| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| package org.apache.ivyde.eclipse.resolvevisualizer; |
| |
| import java.awt.Dimension; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.Stack; |
| |
| import org.apache.ivy.core.report.ResolveReport; |
| import org.apache.ivyde.eclipse.cp.IvyClasspathContainer; |
| import org.apache.ivyde.eclipse.resolvevisualizer.label.ILabelDecoratorAlgorithm; |
| import org.apache.ivyde.eclipse.resolvevisualizer.model.IvyNodeElement; |
| import org.apache.ivyde.eclipse.resolvevisualizer.model.IvyNodeElementAdapter; |
| import org.apache.ivyde.eclipse.resolvevisualizer.model.IvyNodeElementFilterAdapter; |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.action.IMenuListener; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.action.IToolBarManager; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.action.Separator; |
| import org.eclipse.jface.viewers.DoubleClickEvent; |
| import org.eclipse.jface.viewers.IDoubleClickListener; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.viewers.ViewerFilter; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.swt.events.ModifyEvent; |
| import org.eclipse.swt.events.ModifyListener; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Menu; |
| import org.eclipse.ui.IActionBars; |
| import org.eclipse.ui.ISharedImages; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.forms.widgets.FormToolkit; |
| import org.eclipse.ui.part.ViewPart; |
| import org.eclipse.zest.core.viewers.AbstractZoomableViewer; |
| import org.eclipse.zest.core.viewers.EntityConnectionData; |
| import org.eclipse.zest.core.viewers.GraphViewer; |
| import org.eclipse.zest.core.viewers.IZoomableWorkbenchPart; |
| import org.eclipse.zest.core.viewers.ZoomContributionViewItem; |
| import org.eclipse.zest.core.widgets.Graph; |
| import org.eclipse.zest.core.widgets.GraphItem; |
| import org.eclipse.zest.core.widgets.GraphNode; |
| import org.eclipse.zest.core.widgets.ZestStyles; |
| import org.eclipse.zest.layouts.LayoutAlgorithm; |
| import org.eclipse.zest.layouts.LayoutStyles; |
| import org.eclipse.zest.layouts.algorithms.CompositeLayoutAlgorithm; |
| import org.eclipse.zest.layouts.algorithms.DirectedGraphLayoutAlgorithm; |
| import org.eclipse.zest.layouts.algorithms.HorizontalShift; |
| |
| public class ResolveVisualizerView extends ViewPart implements IZoomableWorkbenchPart { |
| private GraphViewer viewer; |
| private FormToolkit toolKit; |
| |
| private Action focusDialogAction; |
| private Action focusDialogActionToolbar; |
| private Action focusOnSelectionAction; |
| private Action hideSelectionAction; |
| private Action showHiddenAction; |
| private Action applyDefaultLayoutAction; |
| private Action historyAction; |
| private Action forwardAction; |
| private Action refreshAction; |
| |
| private ZoomContributionViewItem contextZoomContributionViewItem; |
| private ZoomContributionViewItem toolbarZoomContributionViewItem; |
| |
| private Stack/* <IvyNodeElement> */historyStack; |
| private Stack/* <IvyNodeElement> */forwardStack; |
| |
| private IvyNodeElement currentRoot; |
| private IvyNodeElement currentSelection; |
| private IvyClasspathContainer currentContainer; |
| |
| private ResolveVisualizerContentProvider contentProvider = new ResolveVisualizerContentProvider(); |
| private MessageContentProvider messageContentProvider = new MessageContentProvider(); |
| private IvyNodeLabelProvider labelProvider; |
| private ResolveVisualizerForm visualizationForm; |
| |
| private ForceHiddenFilter forceHiddenFilter; |
| |
| public ResolveVisualizerView() { |
| historyStack = new Stack/* <IvyNodeElement> */(); |
| forwardStack = new Stack/* <IvyNodeElement> */(); |
| |
| forceHiddenFilter = new ForceHiddenFilter(); |
| forceHiddenFilter.setEnabled(true); |
| contentProvider.addFilter(forceHiddenFilter); |
| } |
| |
| /** |
| * This is a callback that will allow us to create the viewer and initialize it. |
| */ |
| public void createPartControl(Composite parent) { |
| toolKit = new FormToolkit(parent.getDisplay()); |
| |
| visualizationForm = new ResolveVisualizerForm(parent, toolKit, this); |
| viewer = visualizationForm.getGraphViewer(); |
| |
| this.labelProvider = new IvyNodeLabelProvider(this.viewer); |
| viewer.setLabelProvider(labelProvider); |
| viewer.setContentProvider(contentProvider); |
| viewer.setInput(null); |
| viewer.setConnectionStyle(ZestStyles.CONNECTIONS_DIRECTED); |
| viewer.setLayoutAlgorithm(new CompositeLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING, |
| new LayoutAlgorithm[] { new DirectedGraphLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING), |
| new HorizontalShift(LayoutStyles.NO_LAYOUT_NODE_RESIZING) })); |
| |
| viewer.addSelectionChangedListener(new ISelectionChangedListener() { |
| public void selectionChanged(SelectionChangedEvent event) { |
| Object selectedElement = ((IStructuredSelection) event.getSelection()).getFirstElement(); |
| if (selectedElement instanceof EntityConnectionData) { |
| return; |
| } |
| ResolveVisualizerView.this.selectionChanged((IvyNodeElement) selectedElement); |
| } |
| }); |
| |
| viewer.addDoubleClickListener(new IDoubleClickListener() { |
| public void doubleClick(DoubleClickEvent event) { |
| focusOnSelectionAction.run(); |
| } |
| }); |
| |
| visualizationForm.getSearchBox().addModifyListener(new ModifyListener() { |
| public void modifyText(ModifyEvent e) { |
| String textString = visualizationForm.getSearchBox().getText(); |
| |
| HashMap figureListing = new HashMap(); |
| ArrayList list = new ArrayList(); |
| Iterator iterator = viewer.getGraphControl().getNodes().iterator(); |
| while (iterator.hasNext()) { |
| GraphItem item = (GraphItem) iterator.next(); |
| figureListing.put(item.getText(), item); |
| } |
| iterator = figureListing.keySet().iterator(); |
| if (textString.length() > 0) { |
| while (iterator.hasNext()) { |
| String string = (String) iterator.next(); |
| if (string.toLowerCase().indexOf(textString.toLowerCase()) >= 0) { |
| list.add(figureListing.get(string)); |
| } |
| } |
| } |
| viewer.getGraphControl().setSelection((GraphItem[]) list.toArray(new GraphItem[list.size()])); |
| } |
| }); |
| |
| messageContentProvider.setMessageManager(visualizationForm.getManagedForm().getMessageManager()); |
| contextZoomContributionViewItem = new ZoomContributionViewItem(this); |
| toolbarZoomContributionViewItem = new ZoomContributionViewItem(this); |
| |
| // Create the help context id for the viewer's control |
| makeActions(); |
| hookContextMenu(); |
| contributeToActionBars(); |
| } |
| |
| private void hookContextMenu() { |
| MenuManager menuMgr = new MenuManager("#PopupMenu"); |
| menuMgr.setRemoveAllWhenShown(true); |
| menuMgr.addMenuListener(new IMenuListener() { |
| public void menuAboutToShow(IMenuManager manager) { |
| ResolveVisualizerView.this.fillContextMenu(manager); |
| } |
| }); |
| Menu menu = menuMgr.createContextMenu(viewer.getControl()); |
| viewer.getControl().setMenu(menu); |
| getSite().registerContextMenu(menuMgr, viewer); |
| } |
| |
| private void contributeToActionBars() { |
| IActionBars bars = getViewSite().getActionBars(); |
| bars.getMenuManager().add(toolbarZoomContributionViewItem); |
| fillLocalPullDown(bars.getMenuManager()); |
| fillLocalToolBar(bars.getToolBarManager()); |
| } |
| |
| private void fillLocalPullDown(IMenuManager manager) { |
| } |
| |
| private void fillContextMenu(IMenuManager manager) { |
| manager.add(new Separator()); |
| manager.add(focusDialogAction); |
| manager.add(focusOnSelectionAction); |
| manager.add(new Separator()); |
| manager.add(historyAction); |
| manager.add(forwardAction); |
| manager.add(new Separator()); |
| manager.add(hideSelectionAction); |
| manager.add(showHiddenAction); |
| manager.add(new Separator()); |
| manager.add(refreshAction); |
| manager.add(applyDefaultLayoutAction); |
| manager.add(new Separator()); |
| manager.add(contextZoomContributionViewItem); |
| } |
| |
| private void fillLocalToolBar(IToolBarManager toolBarManager) { |
| toolBarManager.add(refreshAction); |
| toolBarManager.add(focusDialogActionToolbar); |
| toolBarManager.add(new Separator()); |
| toolBarManager.add(historyAction); |
| toolBarManager.add(forwardAction); |
| } |
| |
| private void makeActions() { |
| refreshAction = new Action() { |
| public void run() { |
| final IvyClasspathContainer container = currentContainer; |
| |
| if (container == null) { |
| // nothing as been actually selected |
| return; |
| } |
| |
| ResolveReport report = container.getResolveReport(); |
| if (report == null) { |
| // TODO we might want to launch some resolve here |
| // or at least open a popup inviting the end user to launch one |
| return; |
| } |
| |
| // a resolve report is already saved on the container's state, we will use it |
| focusOnContainer(container); |
| |
| // When a new container is selected, disable the forward action |
| // The forward action only stores history when the back button was used (much like a browser) |
| forwardStack.clear(); |
| forwardAction.setEnabled(false); |
| } |
| }; |
| refreshAction.setText("Resolve"); |
| refreshAction.setEnabled(true); |
| refreshAction.setImageDescriptor(Plugin.getImageDescriptor("icons/refresh.gif")); |
| |
| focusDialogAction = new Action() { |
| public void run() { |
| ClasspathContainerSelectionDialog dialog = new ClasspathContainerSelectionDialog(viewer.getControl() |
| .getShell()); |
| dialog.create(); |
| int dialogStatus = dialog.open(); |
| if (dialogStatus == Window.OK) { |
| currentContainer = (IvyClasspathContainer) dialog.getFirstResult(); |
| refreshAction.run(); |
| } |
| } |
| }; |
| focusDialogAction.setText("Focus on ivy file..."); |
| |
| focusDialogActionToolbar = new Action() { |
| public void run() { |
| focusDialogAction.run(); |
| } |
| }; |
| focusDialogActionToolbar.setToolTipText("Focus on ivy file..."); |
| focusDialogActionToolbar.setImageDescriptor(ResolveVisualizerPlugin.getImageDescriptor("icons/focus.gif")); |
| |
| focusOnSelectionAction = new Action() { |
| public void run() { |
| if (currentSelection != null) { |
| if (currentRoot != currentSelection) { |
| if (currentRoot != null) { |
| historyStack.push(currentRoot); |
| historyAction.setEnabled(true); |
| } |
| focusOn(currentSelection); |
| } |
| } |
| } |
| }; |
| focusOnSelectionAction.setText("Focus on selection"); |
| focusOnSelectionAction.setEnabled(false); |
| |
| historyAction = new Action() { |
| public void run() { |
| if (historyStack.size() > 0) { |
| IvyNodeElement element = (IvyNodeElement) historyStack.pop(); |
| forwardStack.push(currentRoot); |
| forwardAction.setEnabled(true); |
| focusOn(element); |
| if (historyStack.size() <= 0) { |
| historyAction.setEnabled(false); |
| } |
| } |
| } |
| }; |
| historyAction.setText("Back"); |
| historyAction.setToolTipText("Back"); |
| historyAction.setEnabled(false); |
| historyAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages() |
| .getImageDescriptor(ISharedImages.IMG_TOOL_BACK)); |
| |
| forwardAction = new Action() { |
| public void run() { |
| if (forwardStack.size() > 0) { |
| IvyNodeElement element = (IvyNodeElement) forwardStack.pop(); |
| |
| historyStack.push(currentRoot); |
| historyAction.setEnabled(true); |
| |
| focusOn(element); |
| if (forwardStack.size() <= 0) { |
| forwardAction.setEnabled(false); |
| } |
| } |
| } |
| }; |
| |
| forwardAction.setText("Forward"); |
| forwardAction.setToolTipText("Forward"); |
| forwardAction.setEnabled(false); |
| forwardAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages() |
| .getImageDescriptor(ISharedImages.IMG_TOOL_FORWARD)); |
| |
| hideSelectionAction = new Action() { |
| public void run() { |
| forceHiddenFilter.addHidden(currentSelection); |
| refresh(); |
| } |
| }; |
| hideSelectionAction.setText("Hide"); |
| |
| showHiddenAction = new Action() { |
| public void run() { |
| forceHiddenFilter.clearHidden(); |
| refresh(); |
| } |
| }; |
| showHiddenAction.setText("Show hidden"); |
| |
| applyDefaultLayoutAction = new Action() { |
| public void run() { |
| viewer.applyLayout(); |
| } |
| }; |
| applyDefaultLayoutAction.setText("Apply default layout"); |
| } |
| |
| /** |
| * Passing the focus request to the viewer's control. |
| */ |
| public void setFocus() { |
| viewer.getControl().setFocus(); |
| } |
| |
| private final void focusOnContainer(IvyClasspathContainer container) { |
| ResolveReport report = container.getResolveReport(); |
| |
| if (report != null) { |
| forceHiddenFilter.clearHidden(); |
| visualizationForm.getForm().setText( |
| ResolveVisualizerForm.HeaderText + " - " + container.getConf().getIvyXmlPath() + " in \"" |
| + container.getConf().getJavaProject().getProject().getName() + "\""); |
| |
| IvyNodeElement nextRoot = IvyNodeElementAdapter.adapt(report); |
| if (currentRoot != nextRoot) { |
| if (currentRoot != null) { |
| historyStack.push(currentRoot); |
| historyAction.setEnabled(true); |
| } |
| focusOn(nextRoot); |
| } |
| } |
| } |
| |
| /** |
| * Update the view to focus on a particular bundle. If record history is set to true, and bundle does not equal the |
| * current bundle, then the current bundle will be saved on the history stack |
| * |
| * @param focus |
| * @param recordHistory |
| */ |
| public void focusOn(IvyNodeElement focus) { |
| viewer.setSelection(new StructuredSelection(focus)); |
| viewer.setFilters(new ViewerFilter[] {}); |
| viewer.setInput(focus); |
| |
| Iterator nodes = viewer.getGraphControl().getNodes().iterator(); |
| Graph graph = viewer.getGraphControl(); |
| Dimension centre = new Dimension(graph.getBounds().width / 2, graph.getBounds().height / 2); |
| while (nodes.hasNext()) { |
| GraphNode graphNode = (GraphNode) nodes.next(); |
| if (graphNode.getLocation().x <= 1 && graphNode.getLocation().y <= 1) { |
| graphNode.setLocation(centre.width, centre.height); |
| } |
| } |
| |
| currentRoot = focus; |
| |
| if (viewer.getGraphControl().getNodes().size() > 0) { |
| visualizationForm.enableSearchBox(true); |
| } else { |
| visualizationForm.enableSearchBox(false); |
| } |
| visualizationForm.enableSearchBox(true); |
| focusOnSelectionAction.setEnabled(true); |
| |
| selectionChanged(focus); |
| } |
| |
| /** |
| * Handle the select changed. This will update the view whenever a selection occurs. |
| * |
| * @param selectedItem |
| */ |
| private void selectionChanged(IvyNodeElement selectedItem) { |
| currentSelection = selectedItem; |
| labelProvider.setCurrentSelection(currentRoot, selectedItem); |
| messageContentProvider.selectionChanged(currentRoot); |
| viewer.update(contentProvider.getElements(currentRoot), null); |
| } |
| |
| public AbstractZoomableViewer getZoomableViewer() { |
| return viewer; |
| } |
| |
| public void setAutoSelectDecorator(ILabelDecoratorAlgorithm algorithm) { |
| labelProvider.setAutoSelectDecorator(algorithm); |
| |
| if (viewer.getSelection() != null) { |
| Object selected = ((IStructuredSelection) viewer.getSelection()).getFirstElement(); |
| this.selectionChanged((IvyNodeElement) selected); |
| } |
| } |
| |
| public ResolveVisualizerContentProvider getContentProvider() { |
| return contentProvider; |
| } |
| |
| public void refresh() { |
| viewer.refresh(); |
| viewer.applyLayout(); |
| } |
| |
| public IvyNodeElement getCurrentRoot() { |
| return currentRoot; |
| } |
| |
| private class ForceHiddenFilter extends IvyNodeElementFilterAdapter { |
| private Collection/* <IvyNodeElement> */forceHidden = new HashSet/* <IvyNodeElement> */(); |
| |
| public boolean accept(IvyNodeElement unfiltered) { |
| return !forceHidden.contains(unfiltered); |
| } |
| |
| public void addHidden(IvyNodeElement hide) { |
| forceHidden.addAll(Arrays.asList(hide.getDeepDependencies())); |
| } |
| |
| public void clearHidden() { |
| forceHidden.clear(); |
| } |
| } |
| } |