Java tutorial
/* uDig - User Friendly Desktop Internet GIS client * http://udig.refractions.net * (C) 2012, Refractions Research Inc. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD * License v1.0 (http://udig.refractions.net/files/bsd3-v10.html). */ package net.refractions.udig.project.ui.internal; import java.util.ArrayList; import java.util.List; import net.refractions.udig.internal.ui.IDropTargetProvider; import net.refractions.udig.project.BlackboardEvent; import net.refractions.udig.project.EditManagerEvent; import net.refractions.udig.project.IBlackboard; import net.refractions.udig.project.IBlackboardListener; import net.refractions.udig.project.IEditManager; import net.refractions.udig.project.IEditManagerListener; import net.refractions.udig.project.ILayer; import net.refractions.udig.project.ILegendItem; import net.refractions.udig.project.IMap; import net.refractions.udig.project.command.map.LayerMoveBackCommand; import net.refractions.udig.project.command.map.LayerMoveDownCommand; import net.refractions.udig.project.command.map.LayerMoveFrontCommand; import net.refractions.udig.project.command.map.LayerMoveUpCommand; import net.refractions.udig.project.internal.Folder; import net.refractions.udig.project.internal.Layer; import net.refractions.udig.project.internal.LayerLegendItem; import net.refractions.udig.project.internal.Map; import net.refractions.udig.project.internal.ProjectFactory; import net.refractions.udig.project.internal.ProjectPackage; import net.refractions.udig.project.internal.ProjectPlugin; import net.refractions.udig.project.internal.commands.AddFolderItemCommand; import net.refractions.udig.project.render.IViewportModelListener; import net.refractions.udig.project.render.ViewportModelEvent; import net.refractions.udig.project.ui.AdapterFactoryLabelProviderDecorator; import net.refractions.udig.project.ui.ApplicationGIS; import net.refractions.udig.project.ui.internal.actions.Delete; import net.refractions.udig.project.ui.internal.actions.MylarAction; import net.refractions.udig.project.ui.tool.IToolManager; import net.refractions.udig.ui.PlatformGIS; import net.refractions.udig.ui.UDIGDragDropUtilities; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.impl.AdapterImpl; import org.eclipse.emf.ecore.util.EObjectContainmentEList; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IStatusLineManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeViewerListener; import org.eclipse.jface.viewers.LabelProviderChangedEvent; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeExpansionEvent; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IKeyBindingService; import org.eclipse.ui.IPartListener; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction; import org.eclipse.ui.part.ViewPart; import org.eclipse.ui.views.properties.IPropertySheetPage; /** * The Legend View. This view allows the user to group layers together and set them into different * categories. The view also provides facilities to show/hide map graphics and background layers. * Also, additional layer sorting functionalities (similar to power-point sorting) are implemented. * * @author Naz Chan (LISAsoft) * @since 1.3.1 */ public class LegendView extends ViewPart implements IDropTargetProvider, ISelectionChangedListener { public static final String ID = "net.refractions.udig.project.ui.legendManager"; //$NON-NLS-1$ private Map currentMap; private LegendViewGridHandler gridHandler = new LegendViewGridHandler(); private LegendViewFiltersHandler filtersHandler = new LegendViewFiltersHandler(this); private LayerAction downAction; private LayerAction upAction; private LayerAction frontAction; private LayerAction backAction; private IAction newFolderAction; private LegendViewRenameFolderAction renameFolderAction; private CheckboxTreeViewer viewer; private LegendViewContentProvider contentProvider; private AdapterFactoryLabelProviderDecorator labelProvider; private ILabelProviderListener labelProviderListener = new LabelProviderListerner(); private CheckStateListener checkStateListener = new CheckStateListener(); private CollapseExpandListener collapeExpandListener = new CollapseExpandListener(); private IAction deleteAction; //Listens to changes to selected views/editors private MapEditorListener partServiceListener = new MapEditorListener(); //Listens to changes to current map edit manager private EditManagerListener editManagerListener; private IBlackboardListener mylarListener = new BlackboardListener(); private Adapter mapDeepListener = new MapDeepListener(); private ZoomListener zoomListener = new ZoomListener(); /** * For test case use only * @return LegendViewGridHandler */ public LegendViewGridHandler getGridHandler() { return gridHandler; } /** * For test case use only * @return LegendViewFiltersHandler */ public LegendViewFiltersHandler getFiltersHandler() { return filtersHandler; } /** * For test case use only * @return frontAction */ public LayerAction getFrontAction() { return frontAction; } /** * For test case use only * @return backAction */ public LayerAction getBackAction() { return backAction; } /** * @see org.eclipse.ui.IWorkbenchPart#setFocus() */ public void setFocus() { viewer.getControl().setFocus(); } /** * Returns checkbox tree viewer of the LegendView * @return viewer */ public CheckboxTreeViewer getViewer() { return viewer; } /** * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) */ public void createPartControl(Composite parent) { //Init listerner for the changes/actions on Map Editor getSite().getWorkbenchWindow().getPartService().addPartListener(partServiceListener); initViewer(parent); initContextMenu(viewer); initToobarActions(); setGlobalActions(); UDIGDragDropUtilities.addDragDropSupport(viewer, this); } protected void disposeInternal() { if (PlatformUI.getWorkbench().isClosing()) { ProjectPlugin.getPlugin().turnOffEvents(); } removeViewerListeners(); removeCurrentMapListeners(); gridHandler.disposeHandler(); filtersHandler.disposeHandler(); getSite().getWorkbenchWindow().getPartService().removePartListener(partServiceListener); } /** * Initialises the viewer with necessary properties and listeners. Called on creation of view. * @param parent */ private void initViewer(Composite parent) { //Init viewer object viewer = new CheckboxTreeViewer(parent, SWT.SINGLE); //Set content provider settings contentProvider = new LegendViewContentProvider(this); viewer.setContentProvider(contentProvider); //Set label provider settings labelProvider = new AdapterFactoryLabelProviderDecorator( ProjectExplorer.getProjectExplorer().getAdapterFactory(), viewer); // In dispose() method we need to remove this listener manually! if (labelProviderListener == null) { labelProviderListener = new LabelProviderListerner(); } labelProvider.addListener(labelProviderListener); viewer.setLabelProvider(labelProvider); // Listens to check/uncheck of tree items if (checkStateListener == null) { checkStateListener = new CheckStateListener(); } viewer.addCheckStateListener(checkStateListener); // Listens to expand/collapse of tree items if (collapeExpandListener == null) { collapeExpandListener = new CollapseExpandListener(); } viewer.addTreeListener(collapeExpandListener); //Listens to selection changes of tree items viewer.addSelectionChangedListener(this); //Set filter settings viewer.setFilters(this.filtersHandler.getFilters()); // We need to set the selection provider before creating the global actions // (so ToolManager can hook us up to the global actions like properties and delete) getViewSite().setSelectionProvider(viewer); //Initialises the current map on creation of the view initMapFromEditor(); } /** * Cleans up the viewer of listeners. */ private void removeViewerListeners() { labelProvider.removeListener(labelProviderListener); labelProviderListener = null; labelProvider.dispose(); labelProvider = null; viewer.removeCheckStateListener(checkStateListener); checkStateListener = null; viewer.removeTreeListener(collapeExpandListener); collapeExpandListener = null; viewer.removeSelectionChangedListener(this); } /** * Initialises the current map on creation of the view */ private void initMapFromEditor() { IEditorPart activeEditor = getSite().getPage().getActiveEditor(); if (activeEditor != null && activeEditor instanceof IAdaptable) { Object mapObj = ((IAdaptable) activeEditor).getAdapter(Map.class); if (mapObj != null) { setCurrentMap((Map) mapObj); } } } /** * Creates a context menu * * @param targetViewer */ private void initContextMenu(final Viewer targetViewer) { final MenuManager contextMenu = new MenuManager(); contextMenu.setRemoveAllWhenShown(true); contextMenu.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager mgr) { if (canAddFolder()) { contextMenu.add(newFolderAction()); } if (LegendViewUtils.isFolderSelected(viewer.getSelection())) { contextMenu.add(renameFolderAction()); } if (canDelete()) { contextMenu.add(new Separator()); contextMenu.add(getDeleteAction()); } } }); // Create menu against viewer's control final Control control = targetViewer.getControl(); final Menu menu = contextMenu.createContextMenu(control); control.setMenu(menu); // Register menu for extension getSite().registerContextMenu(contextMenu, targetViewer); } /** * Checks if the current state of the view allows adding a folder. * * @return true if allowed, otherwise false */ private boolean canAddFolder() { return newFolderAction.isEnabled(); } /** * Checks if the current selection allows deletion. * * @return true if allowed, otherwise false */ private boolean canDelete() { final ISelection selection = viewer.getSelection(); if (!selection.isEmpty() && selection instanceof StructuredSelection) { final StructuredSelection structSelection = (StructuredSelection) selection; final Object selectedObj = structSelection.getFirstElement(); if (selectedObj instanceof LayerLegendItem) { return true; } } return false; } /** * Gets an adapted selection from the current selection. This method checks each object in the * selection if they can adapt to an object that can be deleted. * <p> * Example. if LayerLegendItem, return LayerLegendItem.getLayer() * * @return selection to be deleted */ private ISelection getDeleteSelection() { final ISelection selection = viewer.getSelection(); final StructuredSelection strucSelection = (StructuredSelection) selection; final List<Object> adaptedObjs = new ArrayList<Object>(); for (Object obj : strucSelection.toList()) { if (obj instanceof Folder) { adaptedObjs.add(obj); } else if (obj instanceof LayerLegendItem) { final LayerLegendItem layerItem = (LayerLegendItem) obj; adaptedObjs.add(layerItem.getLayer()); } } final StructuredSelection adaptedSelection = new StructuredSelection(adaptedObjs); return adaptedSelection; } private IAction getDeleteAction() { if (deleteAction == null) { deleteAction = new Action() { @Override public void run() { final ISelection selection = getDeleteSelection(); if (!selection.isEmpty()) { final Delete delete = new Delete(false); delete.selectionChanged(this, selection); delete.run(this); } } }; deleteAction.setActionDefinitionId("org.eclipse.ui.edit.delete"); //$NON-NLS-1$ IWorkbenchAction actionTemplate = ActionFactory.DELETE .create(PlatformUI.getWorkbench().getActiveWorkbenchWindow()); deleteAction.setText(actionTemplate.getText()); deleteAction.setToolTipText(actionTemplate.getToolTipText()); deleteAction.setImageDescriptor(actionTemplate.getImageDescriptor()); deleteAction.setDescription(actionTemplate.getDescription()); deleteAction.setDisabledImageDescriptor(actionTemplate.getDisabledImageDescriptor()); } return deleteAction; } private void initToobarActions() { final IToolBarManager mgr = getViewSite().getActionBars().getToolBarManager(); mgr.add(newFolderAction()); // Just to initialise object, will be shown on context menu renameFolderAction(); mgr.add(new Separator()); mgr.add(moveFrontAction()); mgr.add(upAction()); mgr.add(downAction()); mgr.add(moveBackAction()); mgr.add(new Separator()); //Added new functionalities for Legend View mgr.add(filtersHandler.getToggleMgAction()); mgr.add(filtersHandler.getToggleBgAction()); mgr.add(gridHandler.getGridAction()); filtersHandler.setToggleLayersActionState(); } /** * Create an action that moves a layer down in the rendering order */ private LayerAction downAction() { downAction = new LayerAction() { public void run() { getCurrentMap().sendCommandASync(new LayerMoveDownCommand(structSelection)); } }; downAction.setEnabled(false); downAction.setToolTipText(Messages.LegendView_down_tooltip); downAction.setImageDescriptor(ProjectUIPlugin.getDefault().getImageDescriptor(ISharedImages.DOWN_CO)); return downAction; } /** * Create an action that moves a layer up in the rendering order */ private LayerAction upAction() { upAction = new LayerAction() { /** * @see org.eclipse.jface.action.Action#run() */ public void run() { getCurrentMap().sendCommandASync(new LayerMoveUpCommand(structSelection)); } }; upAction.setEnabled(false); upAction.setToolTipText(Messages.LegendView_up_tooltip); upAction.setImageDescriptor(ProjectUIPlugin.getDefault().getImageDescriptor(ISharedImages.UP_CO)); return upAction; } /** * Create an action that moves a layer down in the rendering order */ private LayerAction moveFrontAction() { frontAction = new LayerAction() { public void run() { getCurrentMap().sendCommandASync(new LayerMoveFrontCommand(currentMap, structSelection)); } }; frontAction.setEnabled(false); frontAction.setToolTipText(Messages.LegendView_front_tooltip); frontAction.setImageDescriptor(ProjectUIPlugin.getDefault().getImageDescriptor(ISharedImages.FRONT_CO)); return frontAction; } /** * Create an action that moves a layer up in the rendering order */ private LayerAction moveBackAction() { backAction = new LayerAction() { /** * @see org.eclipse.jface.action.Action#run() */ public void run() { getCurrentMap().sendCommandASync(new LayerMoveBackCommand(currentMap, structSelection)); } }; backAction.setEnabled(false); backAction.setToolTipText(Messages.LegendView_back_tooltip); backAction.setImageDescriptor(ProjectUIPlugin.getDefault().getImageDescriptor(ISharedImages.BACK_CO)); return backAction; } /** * Create an action that creates a new folder */ private IAction newFolderAction() { if (newFolderAction == null) { newFolderAction = new Action() { public void run() { doNewFolderAction(); } }; newFolderAction.setText(Messages.LegendView_new_folder_action_lbl); newFolderAction.setToolTipText(Messages.LegendView_new_folder_tooltip); newFolderAction.setImageDescriptor( ProjectUIPlugin.getDefault().getImageDescriptor(ISharedImages.NEW_FOLDER_CO)); setNewFolderActionState(); } return newFolderAction; } private void doNewFolderAction() { final Folder folder = ProjectFactory.eINSTANCE.createFolder(); folder.setName(Messages.LegendView_new_folder_default_lbl); currentMap.sendCommandSync(new AddFolderItemCommand(folder)); viewer.refresh(); } private void setNewFolderActionState() { if (newFolderAction != null) { if (this.currentMap == null) { newFolderAction.setEnabled(false); } else { newFolderAction.setEnabled(true); } } } /** * Create an action that renames folder */ private IAction renameFolderAction() { if (renameFolderAction == null) { renameFolderAction = new LegendViewRenameFolderAction(viewer); } return renameFolderAction; } /** * @see org.eclipse.ui.IWorkbenchPart#dispose() */ public void dispose() { disposeInternal(); super.dispose(); } /** * @return Returns the currentMap. */ public synchronized Map getCurrentMap() { return currentMap; } /** * @param map The currentMap to set. */ public synchronized void setCurrentMap(final Map map) { // Remove map listeners removeCurrentMapListeners(); // Set new current map this.currentMap = map; // Set current map as viewer's input if (viewer != null) { viewer.setInput(this.currentMap); gridHandler.setMap(this.currentMap); filtersHandler.setMap(this.currentMap); setNewFolderActionState(); } if (this.currentMap != null) { // Add map listeners addCurrentMapListeners(); // Set initial selection Object selectedLayer = this.currentMap.getEditManager().getSelectedLayer(); if (selectedLayer != null && viewer != null) { viewer.setSelection(new StructuredSelection(selectedLayer)); } // Set checkbox state LegendViewCheckboxUtils.updateCheckboxesAsync(this); } } /** * Initialises the current map's listeners */ private void addCurrentMapListeners() { if (this.currentMap != null) { // Add edit manager listener if (editManagerListener == null) { editManagerListener = new EditManagerListener(); } editManagerListener.setCurrentMap(this.currentMap); if (!(this.currentMap.getEditManager()).containsListener(editManagerListener)) { this.currentMap.getEditManager().addListener(editManagerListener); } // Add deep listener if (mapDeepListener == null) { mapDeepListener = new MapDeepListener(); } this.currentMap.addDeepAdapter(mapDeepListener); addLegendListListener(); // Add other listeners if (mylarListener == null) { mylarListener = new BlackboardListener(); } this.currentMap.getBlackboard().addListener(mylarListener); if (zoomListener == null) { zoomListener = new ZoomListener(); } currentMap.getViewportModel().addViewportModelListener(zoomListener); } } private void addLegendListListener() { if (mapDeepListener != null) { EObjectContainmentEList<ILegendItem> legendEObject = (EObjectContainmentEList<ILegendItem>) currentMap .getLegend(); legendEObject.getEObject().eAdapters().add(mapDeepListener); } } /** * Removes the current map's listeners */ private void removeCurrentMapListeners() { if (this.currentMap != null) { // Remove edit manager listener IEditManager editManager = this.currentMap.getEditManager(); if (editManager.containsListener(editManagerListener)) { editManager.removeListener(editManagerListener); editManagerListener = null; } // Remove deep listener this.currentMap.removeDeepAdapter(mapDeepListener); removeLegendListListener(); mapDeepListener = null; // Remove other listeners this.currentMap.getBlackboard().removeListener(mylarListener); mylarListener = null; currentMap.getViewportModel().removeViewportModelListener(zoomListener); zoomListener = null; } } private void removeLegendListListener() { if (mapDeepListener != null) { EObjectContainmentEList<ILegendItem> legendEObject = (EObjectContainmentEList<ILegendItem>) currentMap .getLegend(); legendEObject.getEObject().eAdapters().remove(mapDeepListener); } } /** * We use this method to contribute some global actions from the ToolManager and hook up a * custom delete action that is willing to delete a layer. */ private void setGlobalActions() { IActionBars actionBars = getViewSite().getActionBars(); IToolManager toolManager = ApplicationGIS.getToolManager(); toolManager.contributeGlobalActions(this, actionBars); toolManager.registerActionsWithPart(this); IKeyBindingService keyBindings = getSite().getKeyBindingService(); IAction delAction = getDeleteAction(); actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), delAction); keyBindings.registerAction(delAction); } /** * This is how the framework determines which interfaces we implement. <!-- begin-user-doc --> * <!-- end-user-doc --> * * @param key The desired class * @return An object of type key or null; */ @SuppressWarnings({ "unchecked", "rawtypes" }) public Object getAdapter(Class key) { if (key.equals(IPropertySheetPage.class)) { return ProjectUIPlugin.getDefault().getPropertySheetPage(); } if (key.isAssignableFrom(IMap.class)) { return getCurrentMap(); } return super.getAdapter(key); } /** * Method implemented from IDropTargetProvider. */ @Override public Object getTarget(DropTargetEvent event) { // Add additional processing if needed return null; } /** * Function sets the status message on the bottom left of the application relative to the status * of the currently selected item on the view. */ @Override public void selectionChanged(SelectionChangedEvent event) { final ISelection selection = event.getSelection(); if (!selection.isEmpty() && selection instanceof IStructuredSelection) { final IStructuredSelection structSelection = (IStructuredSelection) selection; final Object obj = structSelection.getFirstElement(); final IStatusLineManager statusLineManager = getViewSite().getActionBars().getStatusLineManager(); if (obj instanceof LayerLegendItem) { final LayerLegendItem layerItem = ((LayerLegendItem) obj); final Layer layer = layerItem.getLayer(); if (layer.getStatus() == ILayer.ERROR) { statusLineManager.setErrorMessage(layer.getStatusMessage()); } else { statusLineManager.setErrorMessage(null); statusLineManager.setMessage(layer.getStatusMessage()); } } else { statusLineManager.setMessage(null); statusLineManager.setErrorMessage(null); } } } /** * Listens to viewport model events such as zoom events, etc. */ private class ZoomListener implements IViewportModelListener { public void changed(ViewportModelEvent event) { viewer.getControl().getDisplay().asyncExec(new Runnable() { public void run() { viewer.refresh(); } }); } } /** * Listens to changes on layer selection of the current map. Updates the viewer when necessary * to reflect the changes. Ex. A new layer is selected. */ private class EditManagerListener implements IEditManagerListener { private Map map; private synchronized void setCurrentMap(final Map currentMap) { this.map = currentMap; } public void changed(final EditManagerEvent event) { // Just in case if (getCurrentMap() != this.map) { this.map.getEditManager().removeListener(this); return; } if (event.getType() == EditManagerEvent.SELECTED_LAYER) { final Runnable runnable = new Runnable() { public void run() { final Object eventObj = event.getNewValue(); final Object selection = ((IStructuredSelection) viewer.getSelection()).getFirstElement(); if (selection != eventObj) { final StructuredSelection structSelection = new StructuredSelection(eventObj); getSite().getSelectionProvider().setSelection(structSelection); } if (mylarOn()) { viewer.refresh(); } } private boolean mylarOn() { final Object mylarValue = map.getBlackboard().get(MylarAction.KEY); if (mylarValue instanceof Boolean) { return ((Boolean) mylarValue).booleanValue(); } return false; } }; if (Display.getCurrent() == null) { Display.getDefault().asyncExec(runnable); } else { runnable.run(); } } } } /** * The abstract class for the sorting actions. This also acts as a selection listener to manage * enabling/disabling of the buttons. */ private abstract class LayerAction extends Action implements ISelectionChangedListener { protected IStructuredSelection structSelection; public LayerAction() { viewer.addSelectionChangedListener(this); } @Override public void selectionChanged(SelectionChangedEvent event) { final ISelection selection = event.getSelection(); if (!selection.isEmpty() && selection instanceof IStructuredSelection) { structSelection = (IStructuredSelection) selection; setEnabled(isValidSelection(structSelection)); } } private boolean isValidSelection(IStructuredSelection selection) { if (selection.size() == 1) { if (selection.getFirstElement() instanceof LayerLegendItem) { return true; } } return false; } } /** * Seems we don't really need that LayersView listens selection changing. To display layers * we need to listen only activating of MapEditor. Also it solves some problems and bugs with * listeners hell during LayersView closing and opening multiple times. * * @author Vitalus */ private class MapEditorListener implements IPartListener { /* * Basically: If an editor is activated, then we ask it if it can turn into a map. If the * selection changes, we ask if the selection can turn into a map. If it can't, we ask the * editor part again. If the editor part cannot serve up a map, blank out the layers view. * (This way editor parts with only one map will still display the layers if something else * is selected. Comment by Vitalus: do we really need? */ private IWorkbenchPart currentPart; /** * @see org.eclipse.ui.IPartListener#partActivated(org.eclipse.ui.IWorkbenchPart) */ public void partActivated(IWorkbenchPart part) { // If newly activated part is different map, set current map to refresh view if (part != currentPart) { if (part instanceof IAdaptable) { IAdaptable adaptable = (IAdaptable) part; Object obj = adaptable.getAdapter(Map.class); if (obj instanceof Map) { currentPart = part; setCurrentMap(((Map) obj)); } } } } /** * @see org.eclipse.ui.IPartListener#partBroughtToTop(org.eclipse.ui.IWorkbenchPart) */ public void partBroughtToTop(IWorkbenchPart part) { partActivated(part); } /** * @see org.eclipse.ui.IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart) */ public void partClosed(IWorkbenchPart part) { // [Naz] This seems to be wrong. if (part == this) { disposeInternal(); return; } //If closed part is current map, set current map to null and refresh viewer if (part == currentPart) { currentPart = null; setCurrentMap(null); viewer.refresh(true); } } /** * @see org.eclipse.ui.IPartListener#partDeactivated(org.eclipse.ui.IWorkbenchPart) */ public void partDeactivated(IWorkbenchPart part) { //Nothing } /** * @see org.eclipse.ui.IPartListener#partOpened(org.eclipse.ui.IWorkbenchPart) */ public void partOpened(IWorkbenchPart part) { //Nothing } } /** * Listens to changes in the blackboard and sets/refreshes the viewer as necessary. */ private class BlackboardListener implements IBlackboardListener { @Override public void blackBoardChanged(BlackboardEvent event) { if (event.getKey() == MylarAction.KEY && event.getOldValue() != event.getNewValue()) { updateViewer(); } } @Override public void blackBoardCleared(IBlackboard source) { updateViewer(); } /** * Updates the viewer due to blackboard changes. See IBlackboardListener mylarListener variable. */ private void updateViewer() { final Runnable runnable = new Runnable() { public void run() { viewer.refresh(); } }; if (Display.getCurrent() == null) { Display.getDefault().asyncExec(runnable); } else { runnable.run(); } } } /** * This listener listens to label provider changes and refreshes the viewer as necessary to * reflect the changes. */ private class LabelProviderListerner implements ILabelProviderListener { @Override public void labelProviderChanged(LabelProviderChangedEvent event) { // Synchronize map variable to view's map attribute final Map currentMap; synchronized (this) { currentMap = LegendView.this.currentMap; } // Refresh the viewer to reflect any change in the labels if (currentMap != null) { PlatformGIS.syncInDisplayThread(new Runnable() { public void run() { if (!PlatformUI.getWorkbench().isClosing()) { if (viewer != null) { viewer.refresh(true); } } } }); } } } /** * This listener is designed to be added as a deep adapter to map and listens to changes both to * the map and its contained layers and updates the checkboxes as necessary to reflect changes. */ private class MapDeepListener extends AdapterImpl { public void notifyChanged(final Notification msg) { // Skip processing if workbench is closing if (PlatformUI.getWorkbench().isClosing()) { return; } final Object notifier = msg.getNotifier(); if (notifier instanceof Map) { if (ProjectPackage.MAP__LEGEND == msg.getFeatureID(Map.class)) { switch (msg.getEventType()) { case Notification.ADD: { addListeners(msg); refreshOnAddAndRemove(msg); break; } case Notification.REMOVE: { removeListeners(msg); refreshOnAddAndRemove(msg); break; } } } } else if (notifier instanceof Folder) { if (ProjectPackage.FOLDER__ITEMS == msg.getFeatureID(Folder.class)) { switch (msg.getEventType()) { case Notification.ADD: { addListeners(msg); refreshOnAddAndRemove(msg); break; } case Notification.REMOVE: { removeListeners(msg); refreshOnAddAndRemove(msg); break; } } } } else if (notifier instanceof Layer) { if (msg.getFeatureID(Layer.class) == ProjectPackage.LAYER__VISIBLE) { // When layer's visibility is changed if (msg.getOldBooleanValue() != msg.getNewBooleanValue()) { LegendViewCheckboxUtils.updateCheckboxesAsync(LegendView.this); } } else if (msg.getFeatureID(Layer.class) == ProjectPackage.LAYER__INTERACTION_MAP) { // When layer's interaction property is changed - note that the event does not // fire properly maybe a bug in the properties page? refreshViewer(); } } } /** * Adds needed listeners to the event object. * * @param msg */ private void addListeners(Notification msg) { if (msg.getNewValue() instanceof Folder) { final Folder folder = (Folder) msg.getNewValue(); folder.eAdapters().add(mapDeepListener); } } /** * Removes needed listeners to the event object. * * @param msg */ private void removeListeners(Notification msg) { if (msg.getOldValue() instanceof Folder) { final Folder folder = (Folder) msg.getOldValue(); folder.eAdapters().remove(mapDeepListener); } } /** * Refresh the handlers and ui elements when a legend item is added/removed. * * @param msg */ private void refreshOnAddAndRemove(Notification msg) { // Refresh handlers' variables filtersHandler.refresh(); gridHandler.refresh(msg); // Refresh viewer final Object notifier = msg.getNotifier(); if (notifier instanceof Folder) { final Folder folder = (Folder) msg.getNotifier(); refreshViewer(folder); } else if (notifier instanceof Map) { refreshViewer(); } } /** * Refreshes the viewer. */ private void refreshViewer() { refreshViewer(null); } /** * Refreshes the viewer and sets the expanded state of the folder. * * @param folder */ private void refreshViewer(final Folder folder) { final Runnable run = new Runnable() { @Override public void run() { viewer.refresh(); LegendViewCheckboxUtils.updateCheckboxes(LegendView.this); } }; if (Display.getCurrent() == null) { Display.getDefault().asyncExec(run); } else { run.run(); } } } /** * Inner-class listens to the expansion/collapsing of tree items * */ private class CollapseExpandListener implements ITreeViewerListener { @Override public void treeCollapsed(TreeExpansionEvent event) { //Do nothing } @Override public void treeExpanded(TreeExpansionEvent event) { LegendViewCheckboxUtils.updateCheckboxesAsync(LegendView.this); } } /** * Inner-class listens to the changes on the check state of tree items */ private class CheckStateListener implements ICheckStateListener { @Override public void checkStateChanged(CheckStateChangedEvent event) { final Object eventObj = event.getElement(); if (eventObj instanceof ILegendItem) { final ILegendItem item = (ILegendItem) eventObj; final boolean isChecked = event.getChecked(); setVisibilityState(item, isChecked); LegendViewCheckboxUtils.updateCheckboxes(LegendView.this); } } private void setVisibilityState(ILegendItem item, boolean isChecked) { if (item instanceof Folder) { final Folder folder = (Folder) item; setVisibilityState(folder, isChecked); } else if (item instanceof LayerLegendItem) { final LayerLegendItem layerItem = (LayerLegendItem) item; setVisibilityState(layerItem, isChecked); } } private void setVisibilityState(Folder folder, boolean isChecked) { for (ILegendItem item : folder.getItems()) { setVisibilityState(item, isChecked); } viewer.setGrayed(folder, false); viewer.setChecked(folder, isChecked); } private void setVisibilityState(LayerLegendItem layerItem, boolean isChecked) { final Layer layer = layerItem.getLayer(); if (layer.isVisible() != isChecked) { layer.setVisible(isChecked); } } } }