【聚杰网数据库编程】拖放 Eclipse Workbench 标签
下面让我们来看一下如何捕获存放编辑器的 CTabFolder 容器。通过对编辑器平铺行为的观察,我们注意到不管在何时平铺显示编辑器,都会创建一个新的 Tab 文件夹。另外,当一个标签组中的所有编辑器全部关闭或被移动到一个不同的 Tab 文件夹上时,原来的 Tab 文件夹就会被销毁。这意味着 CTabFolder 容器的创建和销毁都是动态的,因此 CTabFolder 容器的拖放源的创建也应该是动态完成的。
要实现这种功能,需要能够对 CTabFolder 容器的创建进行控制。但是 Eclipse 并没有提供任何可以在创建 CTabFolder 容器时进行回调的功能。另外一种方法是对 CTabFolders 进行特殊化 (specialize) 处理(继承),继承这些 specialized CTabFolders(继承类,而不是基类 CTabFolder),并在这些 specialized CTabFolders 的 constructors 中创建拖放源。然而,在 Eclipse 中实例化这些 specialized CTabFolders 是一项非常繁杂的任务,因此我们需要寻找一种新的解决方案。
一种创建拖放源的新方法
下面让我们为 Display 添加一个拖放检测监听器(用来监听 SWT.DragDetect 类型的事件),如下所示:
清单 2. 为 Display 添加拖放监听器
PlatformUI.getWorkbench().getDisplay().addFilter(SWT.DragDetect, new Listener() { public void handleEvent(Event event) { } }); |
不论何时发生拖放操作时,都会调用这个监听器的 handleEvent() 方法,其中 event.widget 指向产生这个事件的控件。在拖动编辑器标签时,event.widget 指向存放这个拖放编辑器标签的 CTabFolder 容器。这样我们现在就可以为这个 CTabFolder 容器创建一个拖放源,如下所示:
清单 3. 捕获存放编辑器的 Tab 文件夹
PlatformUI.getWorkbench().getDisplay().addFilter(SWT.DragDetect, new Listener() { public void handleEvent(Event event) { //ignore drag of widgets other than tab-folders (which host editor and view tabs) if(!(event.widget instanceof CTabFolder)) return; CTabFolder draggedFolder = (CTabFolder)event.widget; int operations = DND.DROP_COPY | DND.DROP_DEFAULT; final DragSource dragSource = new DragSource(draggedFolder, operations); Transfer[] transferTypes = new Transfer[] {EditorInputTransfer.getInstance()}; dragSource.setTransfer(transferTypes); dragSource.addDragListener(new DragSourceListener() { public void dragStart(DragSourceEvent dsEvent) { } public void dragSetData(DragSourceEvent dsEvent) { //code to perform operation-1 and operation-2 } public void dragFinished(DragSourceEvent dsEvent) { dragSource.dispose(); } }); } }); |
现在我们主要关心的是在开始拖放操作之后创建了一个新的拖放源。在开始拖放操作之后创建一个拖放源,这样做是否能够确保这个新的拖放源可以接收现在发生的拖放操作的通知?
为了寻找答案,首先让我们来了解一下 Eclipse 的事件分发行为。
当控件上产生某种类型的事件时,首先将是那些为相同事件类型注册的 Display 的所有过滤器 收到发生该事件的通知(使用 Display.addFilter() 方法添加的监听器),接收顺序是过滤器在 Display 上的注册顺序。然后发生该事件的通知会发送给控件中为该事件类型注册的所有监听器,发送顺序是这些监听器在控件上的注册顺序。
例如,假设 Listener 1 是在某个控件上为 t1 类型的事件注册的第一个监听器,而 Listener 2 是在这个控件上为相同的 t1 类型的事件注册的第二个监听器。另外假设 Filter 1 是在 Display 上为相同的 t1 类型的事件注册的过滤器。现在,当这个控件上产生一个 t1 类型的事件时,第一个接收到发生该事件的通知的是 Filter 1,然后是 Listener 1,最后是 Listener 2。




