eclipse RCP 模仿win7资源管理器地址栏功能

本文实现效果及其工具下载地址:http://sourceforge.net/projects/filetools/

 

windows7/8的资源管理器个人觉得比较便利的还属地址栏,在定位资源位置时非常方面。见下图:

当窗口大小改变,或地址栏的长度过长时,地址栏会自动隐藏头部。这是一个优点,但同时也是一个缺点。大多数时候,我们需要点击多次才能回到地址头部。而显示出来的那一部分,恰恰是不经常使用的。所以,我想对其进行改进,使地址栏可以达到:

  • 能够显示全部地址栏信息,在长度大导致空间不足时显示尽量多的位置信息,可以隐藏文本信息,但应该显示相应标志指示父文件夹和根目录;

初步实现的效果如图:

 

实现这个效果并不困难。第一种方法是是通过layout来实现。在swt中,常见的rowlayout实现的就是类似的效果,我们可以通过修改rowlayout来达到目的,并达到支持水平和垂直布局。第二种方法是调用jdt里面的BreadcrumbView,做适当修改就可以。

第一种方法的实现(详见附件,里面有源码和测试代码):

Java代码  收藏代码
  1. /* AutoAdjustRowLayout.java
  2.  * Copyright (c) 2013 by Brook Tran
  3.  * All rights reserved.
  4.  *
  5.  * The copyright of this software is own by the authors.
  6.  * You may not use, copy or modify this software, except
  7.  * in accordance with the license agreement you entered into
  8.  * with the copyright holders. For details see accompanying license
  9.  * terms.
  10.  */
  11. package org.jeelee.filemanager.ui.breadcrumb;
  12. import org.eclipse.swt.SWT;
  13. import org.eclipse.swt.graphics.Point;
  14. import org.eclipse.swt.graphics.Rectangle;
  15. import org.eclipse.swt.layout.RowData;
  16. import org.eclipse.swt.widgets.Composite;
  17. import org.eclipse.swt.widgets.Control;
  18. import org.eclipse.swt.widgets.Layout;
  19. /**
  20.  * <B>AutoAdjustRowLayout</B>
  21.  * extends from {@link org.eclipse.swt.layout.RowLayout}
  22.  * @author Brook Tran. Email: <a href=”mailto:Brook.Tran.C@gmail.com”>Brook.Tran.C@gmail.com</a>
  23.  * @since org.jeelee.filemanager 2013-1-9 created
  24.  */
  25. public class BreadcrumbLayout extends Layout{
  26.     /**
  27.      * type specifies whether the layout places controls in rows or
  28.      * columns.
  29.      *
  30.      * The default value is HORIZONTAL.
  31.      *
  32.      * Possible values are: <ul>
  33.      *    <li>HORIZONTAL: Position the controls horizontally from left to right</li>
  34.      *    <li>VERTICAL: Position the controls vertically from top to bottom</li>
  35.      * </ul>
  36.      *
  37.      * @since 2.0
  38.      */
  39.     public int type = SWT.HORIZONTAL | SWT.RIGHT_TO_LEFT;
  40.     /**
  41.      * marginWidth specifies the number of pixels of horizontal margin
  42.      * that will be placed along the left and right edges of the layout.
  43.      *
  44.      * The default value is 0.
  45.      *
  46.      * @since 3.0
  47.      */
  48.     public int marginWidth = 0;
  49.     /**
  50.      * marginHeight specifies the number of pixels of vertical margin
  51.      * that will be placed along the top and bottom edges of the layout.
  52.      *
  53.      * The default value is 0.
  54.      *
  55.      * @since 3.0
  56.      */
  57.     public int marginHeight = 0;
  58.     /**
  59.      * spacing specifies the number of pixels between the edge of one cell
  60.      * and the edge of its neighbouring cell.
  61.      *
  62.      * The default value is 3.
  63.      */
  64.     public int spacing = 3;
  65.     /**
  66.      * pack specifies whether all controls in the layout take
  67.      * their preferred size.  If pack is false, all controls will
  68.      * have the same size which is the size required to accommodate the
  69.      * largest preferred height and the largest preferred width of all
  70.      * the controls in the layout.
  71.      *
  72.      * The default value is true.
  73.      */
  74.     public boolean pack = true;
  75.     /**
  76.      * fill specifies whether the controls in a row should be
  77.      * all the same height for horizontal layouts, or the same
  78.      * width for vertical layouts.
  79.      *
  80.      * The default value is false.
  81.      *
  82.      * @since 3.0
  83.      */
  84.     public boolean fill = false;
  85.     /**
  86.      * marginLeft specifies the number of pixels of horizontal margin
  87.      * that will be placed along the left edge of the layout.
  88.      *
  89.      * The default value is 3.
  90.      */
  91.     public int marginLeft = 3;
  92.     /**
  93.      * marginTop specifies the number of pixels of vertical margin
  94.      * that will be placed along the top edge of the layout.
  95.      *
  96.      * The default value is 3.
  97.      */
  98.     public int marginTop = 3;
  99.     /**
  100.      * marginRight specifies the number of pixels of horizontal margin
  101.      * that will be placed along the right edge of the layout.
  102.      *
  103.      * The default value is 3.
  104.      */
  105.     public int marginRight = 3;
  106.     /**
  107.      * marginBottom specifies the number of pixels of vertical margin
  108.      * that will be placed along the bottom edge of the layout.
  109.      *
  110.      * The default value is 3.
  111.      */
  112.     public int marginBottom = 3;
  113.     public BreadcrumbLayout() {
  114.     }
  115.     public BreadcrumbLayout (int type) {
  116.         this.type = type;
  117.     }
  118.     @Override
  119.     protected void layout (Composite composite, boolean flushCache) {
  120.         Rectangle clientArea = composite.getClientArea ();
  121.         if ((type & SWT.HORIZONTAL) == SWT.HORIZONTAL) {
  122.             layoutHorizontal (composite, true,  clientArea.width, flushCache);
  123.         } else {
  124.             layoutVertical (composite, true, clientArea.height, flushCache);
  125.         }
  126.     }
  127.     @Override
  128.     protected Point computeSize (Composite composite, int wHint, int hHint, boolean flushCache) {
  129.         Point extent;
  130.         if ((type & SWT.HORIZONTAL) == SWT.HORIZONTAL) {
  131.             extent = layoutHorizontal (composite, false,  wHint, flushCache);
  132.         } else {
  133.             extent = layoutVertical (composite, false,  hHint, flushCache);
  134.         }
  135.         if (wHint != SWT.DEFAULT) {
  136.             extent.x = wHint;
  137.         }
  138.         if (hHint != SWT.DEFAULT) {
  139.             extent.y = hHint;
  140.         }
  141.         return extent;
  142.     }
  143.     Point layoutHorizontal (Composite composite, boolean move, int width, boolean flushCache) {
  144.         Control [] children = composite.getChildren ();
  145.         int count = 0;
  146.         for (int i=0; i<children.length; i++) {
  147.             Control control = children [i];
  148.             RowData data = (RowData) control.getLayoutData ();
  149.             if (data == null || !data.exclude) {
  150.                 children [count++] = children [i];
  151.             }
  152.         }
  153.         if (count == 0) {
  154.             return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom);
  155.         }
  156.         int startIndex = 0;
  157.         if( ( type & SWT.RIGHT_TO_LEFT) == SWT.RIGHT_TO_LEFT){
  158.             startIndex = count;
  159.             int maxWidth = marginLeft + marginWidth + marginRight + marginWidth;
  160. //          marginRight + marginLeft +marginWidth  ;
  161.             while(startIndex>0 && maxWidth<width){
  162.                 Control child = children [startIndex-1];
  163.                 Point size = computeSize (child, flushCache);
  164.                 maxWidth += size.x +spacing  + marginWidth;
  165.                 startIndex–;
  166.             }
  167.             startIndex = adjust(move, children, count, startIndex);
  168.         }
  169.         int childWidth = 0, childHeight = 0, maxHeight = 0;
  170.         // get max width & height
  171.         if (!pack) {
  172.             for (int i=startIndex; i<count; i++) {
  173.                 Control child = children [i];
  174.                 Point size = computeSize (child, flushCache);
  175.                 childWidth = Math.max (childWidth, size.x);
  176.                 childHeight = Math.max (childHeight, size.y);
  177.             }
  178.             maxHeight = childHeight;
  179.         }
  180.         int clientX = 0, clientY = 0;
  181.         if (move) {
  182.             Rectangle rect = composite.getClientArea ();
  183.             clientX = rect.x;
  184.             clientY = rect.y;
  185.         }
  186.         Rectangle [] bounds = null;
  187.         if (move && (fill )) {
  188.             bounds = new Rectangle [count];
  189.         }
  190.         int maxX = 0, x = marginLeft + marginWidth, y = marginTop + marginHeight;
  191.         for (int i=startIndex; i<count; i++) {
  192.             Control child = children [i];
  193.             if (pack) {
  194.                 Point size = computeSize (child, flushCache);
  195.                 childWidth = size.x;
  196.                 childHeight = size.y;
  197.             }
  198.             if (pack || fill ) {
  199.                 maxHeight = Math.max (maxHeight, childHeight);
  200.             }
  201.             if (move) {
  202.                 int childX = x + clientX, childY = y + clientY;
  203.                 if ( fill ) {
  204.                     bounds [i] = new Rectangle (childX, childY, childWidth, childHeight);
  205.                 } else {
  206.                     child.setBounds (childX, childY, childWidth, childHeight);
  207.                 }
  208.             }
  209.             x += spacing + childWidth;
  210.             maxX = Math.max (maxX, x);
  211.         }
  212.         maxX = Math.max (clientX + marginLeft + marginWidth, maxX – spacing);
  213.             maxX += marginRight + marginWidth;
  214.         if (move && (fill)) {
  215.             for (int i=startIndex; i<count; i++) {
  216.                     if (fill) {
  217.                         bounds [i].height = maxHeight;
  218.                     }
  219.                 children [i].setBounds (bounds [i]);
  220.             }
  221.         }
  222.         return new Point (maxX, y + maxHeight + marginBottom + marginHeight);
  223.     }
  224.     Point layoutVertical (Composite composite, boolean move,int height, boolean flushCache) {
  225.         Control [] children = composite.getChildren ();
  226.         int count = 0;
  227.         for (int i=0; i<children.length; i++) {
  228.             Control control = children [i];
  229.             RowData data = (RowData) control.getLayoutData ();
  230.             if (data == null || !data.exclude) {
  231.                 children [count++] = children [i];
  232.             }
  233.         }
  234.         if (count == 0) {
  235.             return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom);
  236.         }
  237.         int startIndex = 0;
  238.         if( ( type & SWT.RIGHT_TO_LEFT) == SWT.RIGHT_TO_LEFT){
  239.             startIndex = count;
  240.             int maxHeight = marginTop + marginHeight+ marginBottom +marginHeight  ;
  241.             while(startIndex>0 && maxHeight<height){
  242.                 Control child = children [startIndex-1];
  243.                 Point size = computeSize (child, flushCache);
  244.                 maxHeight += size.y +spacing + marginTop +marginHeight;
  245.                 startIndex–;
  246.             }
  247.             startIndex = adjust(move, children, count, startIndex);
  248.         }
  249.         int childWidth = 0, childHeight = 0, maxWidth = 0;
  250.         if (!pack) {
  251.             for (int i=startIndex; i<count; i++) {
  252.                 Control child = children [i];
  253.                 Point size = computeSize (child, flushCache);
  254.                 childWidth = Math.max (childWidth, size.x);
  255.                 childHeight = Math.max (childHeight, size.y);
  256.             }
  257.             maxWidth = childWidth;
  258.         }
  259.         int clientX = 0, clientY = 0;
  260.         if (move) {
  261.             Rectangle rect = composite.getClientArea ();
  262.             clientX = rect.x;
  263.             clientY = rect.y;
  264.         }
  265.         Rectangle [] bounds = null;
  266.         if (move && (fill)) {
  267.             bounds = new Rectangle [count];
  268.         }
  269.         int maxY = 0, x = marginLeft + marginWidth, y = marginTop + marginHeight;
  270.         for (int i=startIndex; i<count; i++) {
  271.             Control child = children [i];
  272.             if (pack) {
  273.                 Point size = computeSize (child, flushCache);
  274.                 childWidth = size.x;
  275.                 childHeight = size.y;
  276.             }
  277.             if (pack || fill ) {
  278.                 maxWidth = Math.max (maxWidth, childWidth);
  279.             }
  280.             if (move) {
  281.                 int childX = x + clientX, childY = y + clientY;
  282.                 if ( fill ) {
  283.                     bounds [i] = new Rectangle (childX, childY, childWidth, childHeight);
  284.                 } else {
  285.                     child.setBounds (childX, childY, childWidth, childHeight);
  286.                 }
  287.             }
  288.             y += spacing + childHeight;
  289.             maxY = Math.max (maxY, y);
  290.         }
  291.         maxY = Math.max (clientY + marginTop + marginHeight, maxY – spacing);
  292.         if (move && (fill )) {
  293.             for (int i=startIndex; i<count; i++) {
  294.                 children [i].setBounds (bounds [i]);
  295.             }
  296.         }
  297.         return new Point (x + maxWidth + marginRight + marginWidth, maxY);
  298.     }
  299.     private int adjust(boolean move, Control[] children, int count,
  300.             int startIndex) {
  301.         if (startIndex > 0) {
  302.             startIndex++;
  303.         }
  304.         if(startIndex > count){
  305.             startIndex–;
  306.         }
  307.         if(move){
  308.             Rectangle hide = new Rectangle(0, 0, 0, 0);
  309.             for(int i=0;i<startIndex;i++){
  310. //              children[i].setVisible(false);
  311.                 children[i].setBounds(hide);
  312.             }
  313.         }
  314.         return startIndex;
  315.     }
  316.     Point computeSize (Control control, boolean flushCache) {
  317.         int wHint = SWT.DEFAULT, hHint = SWT.DEFAULT;
  318.         RowData data = (RowData) control.getLayoutData ();
  319.         if (data != null) {
  320.             wHint = data.width;
  321.             hHint = data.height;
  322.         }
  323.         return control.computeSize (wHint, hHint, flushCache);
  324.     }
  325.     @Override
  326.     protected boolean flushCache (Control control) {
  327.         return true;
  328.     }
  329.     String getName () {
  330.         String string = getClass ().getName ();
  331.         int index = string.lastIndexOf (‘.’);
  332.         if (index == -1) {
  333.             return string;
  334.         }
  335.         return string.substring (index + 1, string.length ());
  336.     }
  337.     @Override
  338.     public String toString () {
  339.         String string = getName ()+” {“;
  340.         string += “type=”+((type != SWT.HORIZONTAL) ? “SWT.VERTICAL” : “SWT.HORIZONTAL”)+” “;
  341.         if (marginWidth != 0) {
  342.             string += “marginWidth=”+marginWidth+” “;
  343.         }
  344.         if (marginHeight != 0) {
  345.             string += “marginHeight=”+marginHeight+” “;
  346.         }
  347.         if (marginLeft != 0) {
  348.             string += “marginLeft=”+marginLeft+” “;
  349.         }
  350.         if (marginTop != 0) {
  351.             string += “marginTop=”+marginTop+” “;
  352.         }
  353.         if (marginRight != 0) {
  354.             string += “marginRight=”+marginRight+” “;
  355.         }
  356.         if (marginBottom != 0) {
  357.             string += “marginBottom=”+marginBottom+” “;
  358.         }
  359.         if (spacing != 0) {
  360.             string += “spacing=”+spacing+” “;
  361.         }
  362.         string += “pack=”+pack+” “;
  363.         string += “fill=”+fill+” “;
  364.         string = string.trim();
  365.         string += “}”;
  366.         return string;
  367.     }
  368. }

实现效果见下图。其中,第一栏是地址栏的模拟实现,这个会隐藏根目录和父级目录,只显示最多子节点。

第二种方法相对比较简单,像使用普通view一样调用BreadcrumbView,设置LabelProvider和ContentProvider就可以了。

Java代码  收藏代码
  1. class FilePathBreadcrumViewer extends BreadcrumbViewer{
  2.     private FileFilterDelegate fFilter;
  3.     public FilePathBreadcrumViewer(FileFilterDelegate fileFilter,
  4.             Composite parent, int style) {
  5.         super(parent, style);
  6.         fFilter=fileFilter;
  7.     }
  8.     @Override
  9.     protected void configureDropDownViewer(TreeViewer viewer, Object input) {
  10.         viewer.setLabelProvider(new FileDelegateLableProvider());
  11.         viewer.setContentProvider(new FileDelegateTreeContentProvider(fFilter));
  12.     }
  13. }

 

实现的效果:

 

标签