/******************************************************************************* * Copyright (c) 2015 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Pivotal, Inc. - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.boot.dash.views; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuCreator; 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.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IActionBars; import org.eclipse.ui.views.properties.IPropertySheetPage; import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor; import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; import org.springframework.ide.eclipse.boot.dash.BootDashActivator; import org.springframework.ide.eclipse.boot.dash.livexp.MultiSelection; import org.springframework.ide.eclipse.boot.dash.livexp.MultiSelectionSource; import org.springframework.ide.eclipse.boot.dash.model.BootDashElement; import org.springframework.ide.eclipse.boot.dash.model.BootDashViewModel; import org.springframework.ide.eclipse.boot.dash.model.UserInteractions; import org.springframework.ide.eclipse.boot.dash.util.ToolbarPulldownContributionItem; import org.springframework.ide.eclipse.boot.dash.views.sections.BootDashUnifiedTreeSection; import org.springframework.ide.eclipse.boot.dash.views.sections.TagSearchSection; import org.springframework.ide.eclipse.boot.dash.views.sections.ViewPartWithSections; import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression; import org.springsource.ide.eclipse.commons.livexp.core.ValueListener; import org.springsource.ide.eclipse.commons.livexp.ui.IPageSection; import com.google.common.collect.ImmutableSet; /** * @author Kris De Volder */ public class BootDashTreeView extends ViewPartWithSections implements ITabbedPropertySheetPageContributor, ISelectionProvider { /** * The ID of the view as specified by the extension. */ public static final String ID = "org.springframework.ide.eclipse.boot.dash.views.BootDashView"; /** * Adds scroll support to the whole view. You probably want to disable this * if view is broken into pieces that have their own scrollbars */ private static final boolean ENABLE_SCROLLING = false; private BootDashViewModel model = BootDashActivator.getDefault().getModel(); // private Action refreshAction; // private Action doubleClickAction; private BootDashActions actions; private UserInteractions ui = new DefaultUserInteractions(this); private MultiSelection<BootDashElement> selection = null; // lazy init private List<ISelectionChangedListener> selectionListeners = new ArrayList<>(); /* * The content provider class is responsible for providing objects to the * view. It can wrap existing objects in adapters or simply return objects * as-is. These objects may be sensitive to the current input of the view, * or ignore it and always show the same content (like Task List, for * example). */ /** * The constructor. */ public BootDashTreeView() { super(ENABLE_SCROLLING); } @Override public void dispose() { super.dispose(); if (actions != null) { actions.dispose(); } } /** * This is a callback that will allow us to create the viewer and initialize * it. */ public void createPartControl(Composite parent) { super.createPartControl(parent); getSite().setSelectionProvider(this); // Create the help context id for the viewer's control // PlatformUI.getWorkbench().getHelpSystem().setHelp(tv.getControl(), // "org.springframework.ide.eclipse.boot.dash.viewer"); actions = new BootDashActions(model, getRawSelection(), ui); // hookContextMenu(); // hookDoubleClickAction(); contributeToActionBars(); } public synchronized MultiSelection<BootDashElement> getRawSelection() { if (this.selection == null) { MultiSelection<BootDashElement> selection = MultiSelection.empty(BootDashElement.class); for (IPageSection section : getSections()) { if (section instanceof MultiSelectionSource) { MultiSelectionSource source = (MultiSelectionSource) section; MultiSelection<BootDashElement> subSelection = source.getSelection().filter(BootDashElement.class); selection = MultiSelection.union(selection, subSelection); } } this.selection = selection; selection.getElements().addListener(new ValueListener<ImmutableSet<BootDashElement>>() { @Override public void gotValue(LiveExpression<ImmutableSet<BootDashElement>> exp, ImmutableSet<BootDashElement> value) { ISelection selection = getSelection(); for (ISelectionChangedListener selectionListener : selectionListeners) { selectionListener.selectionChanged(new SelectionChangedEvent(BootDashTreeView.this, selection)); } } }); } return this.selection; } public List<BootDashElement> getSelectedElements() { ArrayList<BootDashElement> elements = new ArrayList<>(); for (Object e : getRawSelection().getValue()) { if (e instanceof BootDashElement) { elements.add((BootDashElement) e); } } return Collections.unmodifiableList(elements); } private void contributeToActionBars() { IActionBars bars = getViewSite().getActionBars(); fillLocalPullDown(bars.getMenuManager()); fillLocalToolBar(bars.getToolBarManager()); } /** * Fills the pull-down menu for this view (accessible from the toolbar) */ private void fillLocalPullDown(IMenuManager manager) { for (RunStateAction a : actions.getRunStateActions()) { manager.add(a); } manager.add(actions.getOpenBrowserAction()); manager.add(actions.getOpenNgrokAdminUi()); manager.add(actions.getOpenConsoleAction()); manager.add(actions.getOpenInPackageExplorerAction()); manager.add(actions.getOpenConfigAction()); manager.add(actions.getShowPropertiesViewAction()); manager.add(new Separator()); manager.add(actions.getExposeRunAppAction()); manager.add(actions.getExposeDebugAppAction()); manager.add(new Separator()); addAddRunTargetMenuActions(manager); manager.add(new Separator()); //manager.add(actions.getToggleFiltersDialogAction()); for (ToggleFilterAction a : actions.getToggleFilterActions()) { manager.add(a); } manager.add(new Separator()); manager.add(actions.getOpenFilterPreferencesAction()); // manager.add(refreshAction); // manager.add(new Separator()); // manager.add(action2); } private void fillLocalToolBar(IToolBarManager manager) { for (RunStateAction a : actions.getRunStateActions()) { manager.add(a); } manager.add(actions.getOpenBrowserAction()); manager.add(actions.getOpenConsoleAction()); manager.add(actions.getOpenConfigAction()); manager.add(actions.getShowPropertiesViewAction()); manager.add(actions.getToggleFiltersDialogAction()); // This ought to work, but it doesn't. // manager.add(createAddRunTargetMenuManager()); // Must write specific code to create toolbar pull-down button / menu: createAddRunTargetPulldown(manager); // manager.add(refreshAction); // manager.add(action2); } private void addAddRunTargetMenuActions(IMenuManager manager) { if (actions.getAddRunTargetActions().length==1) { //Special case. Creationg a pulldown for just one item isn't very logical. AddRunTargetAction action = actions.getAddRunTargetActions()[0]; manager.add(action); } else { MenuManager menu = createAddRunTargetMenuManager(); manager.add(menu); } } private MenuManager createAddRunTargetMenuManager() { final MenuManager menu = new MenuManager("Add Run Target...", BootDashActivator.getImageDescriptor("icons/add_target.png"), null); for (AddRunTargetAction a : actions.getAddRunTargetActions()) { menu.add(a); } return menu; } public void createAddRunTargetPulldown(IToolBarManager toolbar) { if (actions.getAddRunTargetActions().length==1) { //Special case. Creationg a pulldown for just one item isn't very logical. AddRunTargetAction action = actions.getAddRunTargetActions()[0]; toolbar.add(action); } else { Action dropdownAction=new Action("Create Target",SWT.DROP_DOWN){}; dropdownAction.setImageDescriptor(BootDashActivator.getImageDescriptor("icons/add_target.png")); dropdownAction.setMenuCreator(new IMenuCreator() { Menu theMenu; @Override public Menu getMenu(Menu parent) { return null; } @Override public Menu getMenu(Control parent) { if (theMenu==null) { final MenuManager menu = createAddRunTargetMenuManager(); theMenu = menu.createContextMenu(parent); theMenu.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { menu.dispose(); } }); } return theMenu; } @Override public void dispose() { } }); toolbar.add(new ToolbarPulldownContributionItem(dropdownAction)); } } /** * Passing the focus request to the viewer's control. */ public void setFocus() { if (page != null) { page.setFocus(); } } public UserInteractions getUserInteractions() { return ui; } @Override public Shell getShell() { return getSite().getShell(); } @Override protected List<IPageSection> createSections() throws CoreException { List<IPageSection> sections = new ArrayList<>(); sections.add(new TagSearchSection(BootDashTreeView.this, model.getFilterBox().getText(), model)); sections.add(new BootDashUnifiedTreeSection(this, model, ui)); return sections; } @Override public String getContributorId() { return "org.springframework.ide.eclipse.boot.dash.propertyContributor"; } @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public Object getAdapter(Class adapter) { if (adapter == IPropertySheetPage.class) { return new TabbedPropertySheetPage(this); } return super.getAdapter(adapter); } @Override public void addSelectionChangedListener(ISelectionChangedListener listener) { selectionListeners.add(listener); } @Override public ISelection getSelection() { return new StructuredSelection(getRawSelection().getValue().toArray()); } @Override public void removeSelectionChangedListener(ISelectionChangedListener listener) { selectionListeners.remove(listener); } @Override public void setSelection(ISelection selection) { //This method isn't implemented. Probably this is okay, nobody needs to set our selection. // If the need arises to do this in the future, then the 'setSelection' needs to be distributed to // our subsections so each subsection can select whichever elements in the selection apply to them. } }