From 99da8cee74ae665fa2d8f6a2b3cb03b71a66c6e4 Mon Sep 17 00:00:00 2001 From: Alena Laskavaia Date: Mon, 25 Jan 2016 10:23:30 -0500 Subject: [PATCH] launchar: action to invoke new launch target wizard - new extension to contribute a wizard to launchTypeUI extension point - copied bunch of wizards from platform ui since they cannot be extended Change-Id: I45f2801fe04a24e7f8d2bbbd3f31ada1de4a1fc3 --- .../META-INF/MANIFEST.MF | 3 +- bundles/org.eclipse.launchbar.ui/plugin.xml | 9 + .../schema/launchTargetTypeUI.exsd | 95 ++++ .../ui/internal/controls/ConfigSelector.java | 37 +- .../ui/internal/controls/TargetSelector.java | 60 +- .../launchbar/ui/internal/messages.properties | 2 +- .../target/LaunchTargetUIManager.java | 22 +- .../target/NewLaunchTargetWizard.java | 97 ++++ .../target/NewLaunchTargetWizardAction.java | 149 +++++ .../target/NewLaunchTargetWizardNewPage.java | 518 ++++++++++++++++++ .../NewLaunchTargetWizardSelectionPage.java | 120 ++++ .../ui/target/ILaunchTargetUIManager.java | 4 +- 12 files changed, 1078 insertions(+), 38 deletions(-) create mode 100644 bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizard.java create mode 100644 bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizardAction.java create mode 100644 bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizardNewPage.java create mode 100644 bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizardSelectionPage.java diff --git a/bundles/org.eclipse.launchbar.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.launchbar.ui/META-INF/MANIFEST.MF index 0b327d70d39..ea9b0354427 100644 --- a/bundles/org.eclipse.launchbar.ui/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.launchbar.ui/META-INF/MANIFEST.MF @@ -15,7 +15,8 @@ Require-Bundle: org.eclipse.ui, org.eclipse.launchbar.core, org.eclipse.debug.ui, org.eclipse.ui.ide, - org.eclipse.e4.core.contexts + org.eclipse.e4.core.contexts, + org.eclipse.ui.workbench Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy Bundle-Localization: plugin diff --git a/bundles/org.eclipse.launchbar.ui/plugin.xml b/bundles/org.eclipse.launchbar.ui/plugin.xml index 2f0617fd581..7050eeb425c 100644 --- a/bundles/org.eclipse.launchbar.ui/plugin.xml +++ b/bundles/org.eclipse.launchbar.ui/plugin.xml @@ -71,5 +71,14 @@ labelProvider="org.eclipse.launchbar.ui.internal.DefaultDescriptorLabelProvider"> + + + + + + diff --git a/bundles/org.eclipse.launchbar.ui/schema/launchTargetTypeUI.exsd b/bundles/org.eclipse.launchbar.ui/schema/launchTargetTypeUI.exsd index 23a46f9f733..8173b9db2c3 100644 --- a/bundles/org.eclipse.launchbar.ui/schema/launchTargetTypeUI.exsd +++ b/bundles/org.eclipse.launchbar.ui/schema/launchTargetTypeUI.exsd @@ -19,6 +19,7 @@ + @@ -72,6 +73,100 @@ + + + + + + + + + a unique name that can be used to identify this wizard + + + + + + + a translatable name of the wizard that will be used in the dialog box + + + + + + + + + + a relative path of an icon that will be used together with the name to represent the wizard +as one of the choices in the creation dialog box. + + + + + + + + + + a fully qualified name of the Java class implementing <samp>org.eclipse.ui.INewWizard</samp>. + + + + + + + + + + a help url that can describe this wizard in detail. +<p> +Since 3.0 +</p> + + + + + + + a larger image that can help describe this wizard. +<p> +Since 3.0 +</p> + + + + + + + + + + whether the wizard is capable of finishing without ever showing pages to the user. + + + + + + + whether the wizard provides any pages. + + + + + + + + + + + + + an optional subelement whose body contains a short text describing what the wizard will do when started + + + + diff --git a/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/controls/ConfigSelector.java b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/controls/ConfigSelector.java index 9a10dc1c384..ef7712a0cc0 100644 --- a/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/controls/ConfigSelector.java +++ b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/controls/ConfigSelector.java @@ -17,6 +17,8 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.LabelProvider; @@ -36,14 +38,9 @@ import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.MouseTrackAdapter; import org.eclipse.swt.events.MouseTrackListener; -import org.eclipse.swt.events.PaintEvent; -import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; @@ -163,32 +160,16 @@ public class ConfigSelector extends CSelector { @Override public void createActionArea(Composite parent) { - Composite actionArea = new Composite(parent, SWT.NONE); - GridLayout actionLayout = new GridLayout(); - actionLayout.marginWidth = actionLayout.marginHeight = 0; - actionArea.setLayout(actionLayout); - actionArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - - final Composite createButton = new Composite(actionArea, SWT.NONE); - createButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - GridLayout buttonLayout = new GridLayout(); - buttonLayout.marginWidth = buttonLayout.marginHeight = 7; - createButton.setLayout(buttonLayout); + final Composite createButton = new Composite(parent, SWT.BORDER); + GridDataFactory.fillDefaults().grab(true, false).applyTo(createButton); + GridLayoutFactory.fillDefaults().margins(7, 7).applyTo(createButton); createButton.setBackground(getBackground()); - createButton.addPaintListener(new PaintListener() { - @Override - public void paintControl(PaintEvent e) { - Point size = createButton.getSize(); - GC gc = e.gc; - gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW)); - gc.drawLine(0, 0, size.x, 0); - } - }); - final Label createLabel = new Label(createButton, SWT.None); - createLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - createLabel.setText(Messages.ConfigSelector_2); + final Label createLabel = new Label(createButton, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, false).applyTo(createLabel); createLabel.setBackground(getBackground()); + createLabel.setText(Messages.ConfigSelector_2); + MouseListener mouseListener = new MouseAdapter() { @Override diff --git a/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/controls/TargetSelector.java b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/controls/TargetSelector.java index cbbf39ebd6b..305f935c322 100644 --- a/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/controls/TargetSelector.java +++ b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/controls/TargetSelector.java @@ -12,8 +12,9 @@ package org.eclipse.launchbar.ui.internal.controls; import java.util.Comparator; import java.util.List; - import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.resource.CompositeImageDescriptor; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ILabelProvider; @@ -34,11 +35,20 @@ import org.eclipse.launchbar.core.target.TargetStatus.Code; import org.eclipse.launchbar.ui.internal.Activator; import org.eclipse.launchbar.ui.internal.LaunchBarUIManager; import org.eclipse.launchbar.ui.internal.Messages; +import org.eclipse.launchbar.ui.internal.target.NewLaunchTargetWizardAction; import org.eclipse.launchbar.ui.target.ILaunchTargetUIManager; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseTrackAdapter; +import org.eclipse.swt.events.MouseTrackListener; +import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.PropertyDialogAction; @@ -181,6 +191,54 @@ public class TargetSelector extends CSelector implements ILaunchTargetListener { new PropertyDialogAction(new SameShellProvider(getShell()), getSelectionProvider()).run(); } + @Override + public boolean hasActionArea() { + return true; + } + + @Override + public void createActionArea(final Composite parent) { + final Composite createButton = new Composite(parent, SWT.BORDER); + GridDataFactory.fillDefaults().grab(true, false).applyTo(createButton); + GridLayoutFactory.fillDefaults().margins(7, 7).applyTo(createButton); + createButton.setBackground(getBackground()); + + final Label createLabel = new Label(createButton, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, false).applyTo(createLabel); + createLabel.setBackground(getBackground()); + createLabel.setText(Messages.TargetSelector_CreateNewTarget); + + MouseListener mouseListener = new MouseAdapter() { + @Override + public void mouseUp(org.eclipse.swt.events.MouseEvent event) { + NewLaunchTargetWizardAction newWizardAction = new NewLaunchTargetWizardAction( + PlatformUI.getWorkbench().getActiveWorkbenchWindow(), + targetUIManager.getLaunchTargetWizards()); + newWizardAction.run(); + } + }; + + createButton.addMouseListener(mouseListener); + createLabel.addMouseListener(mouseListener); + + MouseTrackListener mouseTrackListener = new MouseTrackAdapter() { + @Override + public void mouseEnter(MouseEvent e) { + Color highlightColor = getHighlightColor(); + createButton.setBackground(highlightColor); + createLabel.setBackground(highlightColor); + } + @Override + public void mouseExit(MouseEvent e) { + Color backgroundColor = getBackground(); + createButton.setBackground(backgroundColor); + createLabel.setBackground(backgroundColor); + } + }; + createButton.addMouseTrackListener(mouseTrackListener); + createLabel.addMouseTrackListener(mouseTrackListener); + } + @Override protected void fireSelectionChanged() { Object selection = getSelection(); diff --git a/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/messages.properties b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/messages.properties index 122b2e13e27..f63a71d1b4d 100644 --- a/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/messages.properties +++ b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/messages.properties @@ -43,7 +43,7 @@ NewLaunchConfigWizard_0=Create Launch Configuration StopActiveCommandHandler_0=Stopping launches StopActiveCommandHandler_1=Stopping build TargetSelector_ToolTipPrefix=Launch Target -TargetSelector_CreateNewTarget=Create New Connection... +TargetSelector_CreateNewTarget=New Launch Target... DescriptorMustNotBeNull=Descriptor must not be null DescriptorMustNotBeNullDesc=The launch descriptor must not be null. diff --git a/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/LaunchTargetUIManager.java b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/LaunchTargetUIManager.java index 751064e6c28..4e15553fcb3 100644 --- a/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/LaunchTargetUIManager.java +++ b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/LaunchTargetUIManager.java @@ -22,14 +22,17 @@ import org.eclipse.launchbar.core.target.ILaunchTarget; import org.eclipse.launchbar.ui.internal.Activator; import org.eclipse.launchbar.ui.target.ILaunchTargetUIManager; import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.internal.dialogs.WizardCollectionElement; +import org.eclipse.ui.internal.registry.WizardsRegistryReader; +import org.eclipse.ui.wizards.IWizardDescriptor; public class LaunchTargetUIManager implements ILaunchTargetUIManager { - private Map typeElements; private Map labelProviders = new HashMap<>(); + private IWizardDescriptor[] wizards; @Override - public ILabelProvider getLabelProvider(ILaunchTarget target) { + public synchronized ILabelProvider getLabelProvider(ILaunchTarget target) { if (typeElements == null) { // Load them up typeElements = new HashMap<>(); @@ -45,7 +48,6 @@ public class LaunchTargetUIManager implements ILaunchTargetUIManager { } } } - String typeId = target.getTypeId(); ILabelProvider labelProvider = labelProviders.get(typeId); if (labelProvider == null) { @@ -57,9 +59,9 @@ public class LaunchTargetUIManager implements ILaunchTargetUIManager { Activator.log(e); } } - if (labelProvider == null) { labelProvider = new LabelProvider() { + @Override public String getText(Object element) { if (element instanceof ILaunchTarget) { return ((ILaunchTarget) element).getName(); @@ -74,12 +76,20 @@ public class LaunchTargetUIManager implements ILaunchTargetUIManager { } return super.getImage(element); } - }; } - } return labelProvider; } + @Override + public synchronized IWizardDescriptor[] getLaunchTargetWizards() { + if (wizards != null) + return wizards; + WizardsRegistryReader reader = new WizardsRegistryReader(Activator.PLUGIN_ID, "launchTargetTypeUI"); //$NON-NLS-1$ + WizardCollectionElement wizardElements = reader.getWizardElements(); + WizardCollectionElement otherCategory = (WizardCollectionElement) wizardElements.getChildren(null)[0]; + wizards = otherCategory.getWizards(); + return wizards; + } } diff --git a/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizard.java b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizard.java new file mode 100644 index 00000000000..0d79e1c0579 --- /dev/null +++ b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizard.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2000, 2015 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.launchbar.ui.internal.target; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.IWizard; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.internal.IWorkbenchGraphicConstants; +import org.eclipse.ui.internal.WorkbenchImages; +import org.eclipse.ui.internal.WorkbenchMessages; +import org.eclipse.ui.internal.WorkbenchPlugin; +import org.eclipse.ui.wizards.IWizardCategory; +import org.eclipse.ui.wizards.IWizardDescriptor; + +/** + * The new wizard is responsible for allowing the user to choose which new + * (nested) wizard to run. The set of available new wizards comes from the new + * extension point. + */ +public class NewLaunchTargetWizard extends Wizard { + private NewLaunchTargetWizardSelectionPage mainPage; + private IWorkbench workbench; + + /** + * Create the wizard pages + */ + @Override + public void addPages() { + mainPage = new NewLaunchTargetWizardSelectionPage(workbench, getWizardDescriptors()); + addPage(mainPage); + } + + public IWizardDescriptor[] getWizardDescriptors() { + IWizardCategory launchCategory = WorkbenchPlugin.getDefault().getNewWizardRegistry() + .findCategory("org.eclipse.launchbar.ui.targetWizards"); //$NON-NLS-1$ + if (launchCategory != null) + return launchCategory.getWizards(); + return new IWizardDescriptor[0]; + } + + /** + * Lazily create the wizards pages + * @param aWorkbench the workbench + * @param currentSelection the current selection + */ + public void init(IWorkbench aWorkbench, + IStructuredSelection currentSelection) { + this.workbench = aWorkbench; + if (getWindowTitle() == null) { + setWindowTitle(WorkbenchMessages.NewWizard_title); + } + setDefaultPageImageDescriptor(WorkbenchImages + .getImageDescriptor(IWorkbenchGraphicConstants.IMG_WIZBAN_NEW_WIZ)); + setNeedsProgressMonitor(true); + } + + /** + * The user has pressed Finish. Instruct self's pages to finish, and answer + * a boolean indicating success. + * + * @return boolean + */ + @Override + public boolean performFinish() { + //save our selection state + mainPage.saveWidgetValues(); + // if we're finishing from the main page then perform finish on the selected wizard. + if (getContainer().getCurrentPage() == mainPage) { + if (mainPage.canFinishEarly()) { + IWizard wizard = mainPage.getSelectedNode().getWizard(); + wizard.setContainer(getContainer()); + return wizard.performFinish(); + } + } + return true; + } + + @Override + public boolean canFinish() { + // we can finish if the first page is current and the the page can finish early. + if (getContainer().getCurrentPage() == mainPage) { + if (mainPage.canFinishEarly()) { + return true; + } + } + return super.canFinish(); + } +} diff --git a/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizardAction.java b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizardAction.java new file mode 100644 index 00000000000..004c8b44b00 --- /dev/null +++ b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizardAction.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (c) 2000, 2015 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.launchbar.ui.internal.target; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.*; +import org.eclipse.ui.internal.IWorkbenchHelpContextIds; +import org.eclipse.ui.internal.WorkbenchMessages; +import org.eclipse.ui.internal.WorkbenchPlugin; +import org.eclipse.ui.wizards.IWizardDescriptor; + +/** + * Invoke the resource creation wizard selection Wizard. + *

+ * This class may be instantiated; it is not intended to be subclassed. + *

+ *

+ * This method automatically registers listeners so that it can keep its + * enablement state up to date. Ordinarily, the window's references to these + * listeners will be dropped automatically when the window closes. However, + * if the client needs to get rid of an action while the window is still open, + * the client must call #dispose() to give the + * action an opportunity to deregister its listeners and to perform any other + * cleanup. + *

+ * @noextend This class is not intended to be subclassed by clients. + */ +public class NewLaunchTargetWizardAction extends Action implements + ActionFactory.IWorkbenchAction { + /** + * The wizard dialog width + */ + private static final int SIZING_WIZARD_WIDTH = 500; + /** + * The wizard dialog height + */ + private static final int SIZING_WIZARD_HEIGHT = 500; + /** + * The title of the wizard window or null to use the default + * wizard window title. + */ + private String windowTitle = null; + /** + * The workbench window; or null if this + * action has been disposed. + */ + private IWorkbenchWindow workbenchWindow; + private IWizardDescriptor[] desc; + + /** + * Create a new instance of this class. + * @param window + * @param iWizardDescriptors + */ + public NewLaunchTargetWizardAction(IWorkbenchWindow window, IWizardDescriptor[] desc) { + super(WorkbenchMessages.NewWizardAction_text); + if (window == null) { + throw new IllegalArgumentException(); + } + this.workbenchWindow = window; + this.desc = desc; + // @issues should be IDE-specific images + ISharedImages images = PlatformUI.getWorkbench().getSharedImages(); + setImageDescriptor(images + .getImageDescriptor(ISharedImages.IMG_TOOL_NEW_WIZARD)); + setDisabledImageDescriptor(images + .getImageDescriptor(ISharedImages.IMG_TOOL_NEW_WIZARD_DISABLED)); + setToolTipText(WorkbenchMessages.NewWizardAction_toolTip); + PlatformUI.getWorkbench().getHelpSystem().setHelp(this, + IWorkbenchHelpContextIds.NEW_ACTION); + } + + /** + *

+ * Sets the title of the wizard window + *

+ * + *

+ * If the title of the wizard window is null, the default + * wizard window title will be used. + *

+ * + * @param windowTitle + * The title of the wizard window, otherwise null + * (default wizard window title). + * + * @since 3.6 + */ + public void setWizardWindowTitle(String windowTitle) { + this.windowTitle = windowTitle; + } + + @Override + public void run() { + if (workbenchWindow == null) { + // action has been disposed + return; + } + NewLaunchTargetWizard wizard = new NewLaunchTargetWizard() { + @Override + public IWizardDescriptor[] getWizardDescriptors() { + return desc; + } + }; + wizard.setWindowTitle(windowTitle); + wizard.init(workbenchWindow.getWorkbench(), null); + IDialogSettings workbenchSettings = WorkbenchPlugin.getDefault() + .getDialogSettings(); + IDialogSettings wizardSettings = workbenchSettings + .getSection("NewLaunchTargetWizardAction"); //$NON-NLS-1$ + if (wizardSettings == null) { + wizardSettings = workbenchSettings.addNewSection("NewLaunchTargetWizardAction"); //$NON-NLS-1$ + } + wizard.setDialogSettings(wizardSettings); + wizard.setForcePreviousAndNextButtons(true); + Shell parent = workbenchWindow.getShell(); + WizardDialog dialog = new WizardDialog(parent, wizard); + dialog.create(); + dialog.getShell().setSize( + Math.max(SIZING_WIZARD_WIDTH, dialog.getShell().getSize().x), + SIZING_WIZARD_HEIGHT); + PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), + IWorkbenchHelpContextIds.NEW_WIZARD); + dialog.open(); + } + + @Override + public void dispose() { + if (workbenchWindow == null) { + // action has already been disposed + return; + } + workbenchWindow = null; + } +} diff --git a/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizardNewPage.java b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizardNewPage.java new file mode 100644 index 00000000000..8cdb42b1811 --- /dev/null +++ b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizardNewPage.java @@ -0,0 +1,518 @@ +/******************************************************************************* + * Copyright (c) 2000, 2015 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.launchbar.ui.internal.target; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.resource.ImageDescriptor; +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.TreeViewer; +import org.eclipse.jface.wizard.IWizardContainer; +import org.eclipse.jface.wizard.IWizardContainer2; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.IWorkbenchWizard; +import org.eclipse.ui.activities.WorkbenchActivityHelper; +import org.eclipse.ui.dialogs.FilteredTree; +import org.eclipse.ui.internal.WorkbenchMessages; +import org.eclipse.ui.internal.dialogs.DialogUtil; +import org.eclipse.ui.internal.dialogs.WizardActivityFilter; +import org.eclipse.ui.internal.dialogs.WizardContentProvider; +import org.eclipse.ui.internal.dialogs.WizardPatternFilter; +import org.eclipse.ui.internal.dialogs.WorkbenchWizardElement; +import org.eclipse.ui.internal.dialogs.WorkbenchWizardNode; +import org.eclipse.ui.model.AdaptableList; +import org.eclipse.ui.model.WorkbenchLabelProvider; +import org.eclipse.ui.wizards.IWizardCategory; +import org.eclipse.ui.wizards.IWizardDescriptor; + +/** + * New wizard selection tab that allows the user to select a registered 'New' + * wizard to be launched. + */ +class NewLaunchTargetWizardNewPage implements ISelectionChangedListener { + // id constants + private static final String DIALOG_SETTING_SECTION_NAME = "NewWizardSelectionPage."; //$NON-NLS-1$ + private final static int SIZING_LISTS_HEIGHT = 200; + private final static int SIZING_VIEWER_WIDTH = 300; + private final static String STORE_EXPANDED_CATEGORIES_ID = DIALOG_SETTING_SECTION_NAME + + "STORE_EXPANDED_CATEGORIES_ID"; //$NON-NLS-1$ + private final static String STORE_SELECTED_ID = DIALOG_SETTING_SECTION_NAME + + "STORE_SELECTED_ID"; //$NON-NLS-1$ + private NewLaunchTargetWizardSelectionPage page; + private FilteredTree filteredTree; + private WizardPatternFilter filteredTreeFilter; + //Keep track of the wizards we have previously selected + private Hashtable selectedWizards = new Hashtable(); + private IDialogSettings settings; + private Button showAllCheck; + private IWizardDescriptor[] primaryWizards; + private CLabel descImageCanvas; + private Map imageTable = new HashMap(); + private IWizardDescriptor selectedElement; + private WizardActivityFilter filter = new WizardActivityFilter(); + private boolean needShowAll; + + /** + * Create an instance of this class + * @param mainPage + * @param wizardCategories + * @param primaryWizards + * @param projectsOnly + */ + public NewLaunchTargetWizardNewPage(NewLaunchTargetWizardSelectionPage mainPage, + IWizardCategory wizardCategories, + IWizardDescriptor[] primaryWizards) { + this.page = mainPage; + this.primaryWizards = primaryWizards; + needShowAll = !allActivityEnabled(primaryWizards); + } + + /** + * @param category the wizard category + * @return whether all of the wizards in the category are enabled via activity filtering + */ + private boolean allActivityEnabled(IWizardDescriptor[] wizards) { + for (int i = 0; i < wizards.length; i++) { + IWizardDescriptor wizard = wizards[i]; + if (WorkbenchActivityHelper.filterItem(wizard)) { + return false; + } + } + return true; + } + + /** + * @since 3.0 + */ + public void activate() { + page.setDescription(WorkbenchMessages.NewWizardNewPage_description); + } + + /** + * Create this tab's visual components + * + * @param parent Composite + * @return Control + */ + protected Control createControl(Composite parent) { + Font wizardFont = parent.getFont(); + // top level group + Composite outerContainer = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + outerContainer.setLayout(layout); + Label wizardLabel = new Label(outerContainer, SWT.NONE); + GridData data = new GridData(SWT.BEGINNING, SWT.FILL, false, true); + outerContainer.setLayoutData(data); + wizardLabel.setFont(wizardFont); + wizardLabel.setText(WorkbenchMessages.NewWizardNewPage_wizardsLabel); + Composite innerContainer = new Composite(outerContainer, SWT.NONE); + layout = new GridLayout(2, false); + layout.marginHeight = 0; + layout.marginWidth = 0; + innerContainer.setLayout(layout); + innerContainer.setFont(wizardFont); + data = new GridData(SWT.FILL, SWT.FILL, true, true); + innerContainer.setLayoutData(data); + filteredTree = createFilteredTree(innerContainer); + createOptionsButtons(innerContainer); + createImage(innerContainer); + updateDescription(null); + // wizard actions pane...create SWT table directly to + // get single selection mode instead of multi selection. + restoreWidgetValues(); + return outerContainer; + } + + /** + * Create a new FilteredTree in the parent. + * + * @param parent the parent Composite. + * @since 3.0 + */ + protected FilteredTree createFilteredTree(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + composite.setLayout(layout); + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.widthHint = SIZING_VIEWER_WIDTH; + data.horizontalSpan = 2; + data.grabExcessHorizontalSpace = true; + data.grabExcessVerticalSpace = true; + boolean needsHint = DialogUtil.inRegularFontMode(parent); + //Only give a height hint if the dialog is going to be too small + if (needsHint) { + data.heightHint = SIZING_LISTS_HEIGHT; + } + composite.setLayoutData(data); + filteredTreeFilter = new WizardPatternFilter(); + FilteredTree filterTree = new FilteredTree(composite, + SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER, filteredTreeFilter, true); + filterTree.setQuickSelectionMode(true); + final TreeViewer treeViewer = filterTree.getViewer(); + treeViewer.setContentProvider(new WizardContentProvider()); + treeViewer.setLabelProvider(new WorkbenchLabelProvider()); + //treeViewer.setComparator(NewWizardCollectionComparator.INSTANCE); + treeViewer.addSelectionChangedListener(this); + ArrayList inputArray = new ArrayList(); + for (int i = 0; i < primaryWizards.length; i++) { + inputArray.add(primaryWizards[i]); + } + boolean expandTop = false; + // ensure the category is expanded. If there is a remembered expansion it will be set later. + if (expandTop) { + treeViewer.setAutoExpandLevel(2); + } + AdaptableList input = new AdaptableList(inputArray); + treeViewer.setInput(input); + filterTree.setBackground(parent.getDisplay().getSystemColor( + SWT.COLOR_WIDGET_BACKGROUND)); + treeViewer.getTree().setFont(parent.getFont()); + treeViewer.addDoubleClickListener(new IDoubleClickListener() { + @Override + public void doubleClick(DoubleClickEvent event) { + IStructuredSelection s = (IStructuredSelection) event + .getSelection(); + selectionChanged(new SelectionChangedEvent(event.getViewer(), s)); + Object element = s.getFirstElement(); + if (treeViewer.isExpandable(element)) { + treeViewer.setExpandedState(element, !treeViewer + .getExpandedState(element)); + } else if (element instanceof WorkbenchWizardElement) { + page.advanceToNextPageOrFinish(); + } + } + }); + treeViewer.addFilter(filter); + Dialog.applyDialogFont(filterTree); + return filterTree; + } + + /** + * Create the Show All and help buttons at the bottom of the page. + * + * @param parent the parent composite on which to create the widgets + */ + private void createOptionsButtons(Composite parent) { + if (needShowAll) { + showAllCheck = new Button(parent, SWT.CHECK); + GridData data = new GridData(); + showAllCheck.setLayoutData(data); + showAllCheck.setFont(parent.getFont()); + showAllCheck.setText(WorkbenchMessages.NewWizardNewPage_showAll); + showAllCheck.setSelection(false); + // flipping tabs updates the selected node + showAllCheck.addSelectionListener(new SelectionAdapter() { + // the delta of expanded elements between the last 'show all' + // and the current 'no show all' + private Object[] delta = new Object[0]; + + @Override + public void widgetSelected(SelectionEvent e) { + boolean showAll = showAllCheck.getSelection(); + if (showAll) { + filteredTree.getViewer().getControl().setRedraw(false); + } else { + // get the inital expanded elements when going from show + // all-> no show all. + // this isnt really the delta yet, we're just reusing + // the variable. + delta = filteredTree.getViewer().getExpandedElements(); + } + try { + if (showAll) { + filteredTree.getViewer().resetFilters(); + filteredTree.getViewer().addFilter(filteredTreeFilter); + // restore the expanded elements that were present + // in the last show all state but not in the 'no + // show all' state. + Object[] currentExpanded = filteredTree.getViewer() + .getExpandedElements(); + Object[] expanded = new Object[delta.length + + currentExpanded.length]; + System.arraycopy(currentExpanded, 0, expanded, 0, + currentExpanded.length); + System.arraycopy(delta, 0, expanded, + currentExpanded.length, delta.length); + filteredTree.getViewer().setExpandedElements(expanded); + } else { + filteredTree.getViewer().addFilter(filter); + } + filteredTree.getViewer().refresh(false); + if (!showAll) { + // if we're going from show all -> no show all + // record the elements that were expanded in the + // 'show all' state but not the 'no show all' state + // (because they didnt exist). + Object[] newExpanded = filteredTree.getViewer().getExpandedElements(); + List deltaList = new ArrayList(Arrays.asList(delta)); + deltaList.removeAll(Arrays.asList(newExpanded)); + } + } finally { + if (showAll) { + filteredTree.getViewer().getControl().setRedraw(true); + } + } + } + }); + } + } + + /** + * Create the image controls. + * + * @param parent the parent Composite. + * @since 3.0 + */ + private void createImage(Composite parent) { + descImageCanvas = new CLabel(parent, SWT.NONE); + GridData data = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING + | GridData.VERTICAL_ALIGN_BEGINNING); + data.widthHint = 0; + data.heightHint = 0; + descImageCanvas.setLayoutData(data); + // hook a listener to get rid of cached images. + descImageCanvas.addDisposeListener(new DisposeListener() { + @Override + public void widgetDisposed(DisposeEvent e) { + for (Iterator i = imageTable.values().iterator(); i.hasNext();) { + ((Image) i.next()).dispose(); + } + imageTable.clear(); + } + }); + } + + /** + * Returns the single selected object contained in the passed + * selectionEvent, or null if the selectionEvent contains + * either 0 or 2+ selected objects. + */ + protected Object getSingleSelection(IStructuredSelection selection) { + return selection.size() == 1 ? selection.getFirstElement() : null; + } + + /** + * Set self's widgets to the values that they held last time this page was + * open + * + */ + protected void restoreWidgetValues() { + //expandPreviouslyExpandedCategories(); + selectPreviouslySelected(); + } + + /** + * Store the current values of self's widgets so that they can be restored + * in the next instance of self + * + */ + public void saveWidgetValues() { + storeSelectedCategoryAndWizard(); + } + + /** + * The user selected either new wizard category(s) or wizard element(s). + * Proceed accordingly. + * + * @param selectionEvent ISelection + */ + @Override + public void selectionChanged(SelectionChangedEvent selectionEvent) { + page.setErrorMessage(null); + page.setMessage(null); + Object selectedObject = getSingleSelection((IStructuredSelection) selectionEvent + .getSelection()); + if (selectedObject instanceof IWizardDescriptor) { + if (selectedObject == selectedElement) { + return; + } + updateWizardSelection((IWizardDescriptor) selectedObject); + } else { + selectedElement = null; + page.setHasPages(false); + page.setCanFinishEarly(false); + page.selectWizardNode(null); + updateDescription(null); + } + } + + /** + * Selects the wizard category and wizard in this page that were selected + * last time this page was used. If a category or wizard that was + * previously selected no longer exists then it is ignored. + */ + protected void selectPreviouslySelected() { + String selectedId = settings.get(STORE_SELECTED_ID); + if (selectedId == null) { + return; + } + Object selected = null; + for (int i = 0; i < primaryWizards.length; i++) { + IWizardDescriptor wizard = primaryWizards[i]; + if (wizard.getId().equals(selectedId)) { + selected = wizard; + break; + } + } + if (selected == null) { + // if we cant find either a category or a wizard, abort. + return; + } + //work around for 62039 + final StructuredSelection selection = new StructuredSelection(selected); + filteredTree.getViewer().getControl().getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + filteredTree.getViewer().setSelection(selection, true); + } + }); + } + + /** + * Set the dialog store to use for widget value storage and retrieval + * + * @param settings IDialogSettings + */ + public void setDialogSettings(IDialogSettings settings) { + this.settings = settings; + } + + + /** + * Stores the currently-selected element in this page's dialog store, in + * order to recreate this page's state in the next instance of this page. + */ + protected void storeSelectedCategoryAndWizard() { + Object selected = getSingleSelection((IStructuredSelection) filteredTree + .getViewer().getSelection()); + if (selected != null) { + if (selected instanceof IWizardCategory) { + settings.put(STORE_SELECTED_ID, + ((IWizardCategory) selected).getPath() + .toString()); + } else { + // else its a wizard + settings.put(STORE_SELECTED_ID, + ((IWizardDescriptor) selected).getId()); + } + } + } + + /** + * Update the current description controls. + * + * @param selectedObject the new wizard + * @since 3.0 + */ + private void updateDescription(IWizardDescriptor selectedObject) { + String string = ""; //$NON-NLS-1$ + if (selectedObject != null) { + string = selectedObject.getDescription(); + } + page.setDescription(string); + if (hasImage(selectedObject)) { + ImageDescriptor descriptor = null; + if (selectedObject != null) { + descriptor = selectedObject.getDescriptionImage(); + } + if (descriptor != null) { + GridData data = (GridData) descImageCanvas.getLayoutData(); + data.widthHint = SWT.DEFAULT; + data.heightHint = SWT.DEFAULT; + Image image = (Image) imageTable.get(descriptor); + if (image == null) { + image = descriptor.createImage(false); + imageTable.put(descriptor, image); + } + descImageCanvas.setImage(image); + } + } else { + GridData data = (GridData) descImageCanvas.getLayoutData(); + data.widthHint = 0; + data.heightHint = 0; + descImageCanvas.setImage(null); + } + descImageCanvas.getParent().layout(true); + filteredTree.getViewer().getTree().showSelection(); + IWizardContainer container = page.getWizard().getContainer(); + if (container instanceof IWizardContainer2) { + ((IWizardContainer2) container).updateSize(); + } + } + + /** + * Tests whether the given wizard has an associated image. + * + * @param selectedObject the wizard to test + * @return whether the given wizard has an associated image + */ + private boolean hasImage(IWizardDescriptor selectedObject) { + if (selectedObject == null) { + return false; + } + if (selectedObject.getDescriptionImage() != null) { + return true; + } + return false; + } + + /** + * @param selectedObject + */ + private void updateWizardSelection(IWizardDescriptor selectedObject) { + selectedElement = selectedObject; + WorkbenchWizardNode selectedNode; + if (selectedWizards.containsKey(selectedObject)) { + selectedNode = (WorkbenchWizardNode) selectedWizards + .get(selectedObject); + } else { + selectedNode = new WorkbenchWizardNode(page, selectedObject) { + @Override + public IWorkbenchWizard createWizard() throws CoreException { + return wizardElement.createWizard(); + } + }; + selectedWizards.put(selectedObject, selectedNode); + } + page.setCanFinishEarly(selectedObject.canFinishEarly()); + page.setHasPages(selectedObject.hasPages()); + page.selectWizardNode(selectedNode); + updateDescription(selectedObject); + } +} diff --git a/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizardSelectionPage.java b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizardSelectionPage.java new file mode 100644 index 00000000000..4e13b15d821 --- /dev/null +++ b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/internal/target/NewLaunchTargetWizardSelectionPage.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2000, 2015 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.launchbar.ui.internal.target; + +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.internal.IWorkbenchHelpContextIds; +import org.eclipse.ui.internal.WorkbenchMessages; +import org.eclipse.ui.internal.activities.ws.WorkbenchTriggerPoints; +import org.eclipse.ui.internal.dialogs.WorkbenchWizardSelectionPage; +import org.eclipse.ui.wizards.IWizardDescriptor; + +/** + * New wizard selection tab that allows the user to either select a + * registered 'New' wizard to be launched, or to select a solution or + * projects to be retrieved from an available server. This page + * contains two visual tabs that allow the user to perform these tasks. + * + * Temporarily has two inner pages. The new format page is used if the system + * is currently aware of activity categories. + */ +class NewLaunchTargetWizardSelectionPage extends WorkbenchWizardSelectionPage { + // widgets + private NewLaunchTargetWizardNewPage newResourcePage; + private IWizardDescriptor[] wizards; + private boolean canFinishEarly = false, hasPages = true; + + /** + * Create an instance of this class. + * + * @param workbench the workbench + * @param wizards the primary wizard elements + */ + public NewLaunchTargetWizardSelectionPage(IWorkbench workbench, + IWizardDescriptor[] wizards) { + super("newWizardSelectionPage", workbench, null, null, WorkbenchTriggerPoints.NEW_WIZARDS);//$NON-NLS-1$ + setTitle(WorkbenchMessages.NewWizardSelectionPage_description); + this.wizards = wizards; + } + + /** + * Makes the next page visible. + */ + public void advanceToNextPageOrFinish() { + if (canFlipToNextPage()) { + getContainer().showPage(getNextPage()); + } else if (canFinishEarly()) { + if (getWizard().performFinish()) { + ((WizardDialog) getContainer()).close(); + } + } + } + + @Override + public void createControl(Composite parent) { + IDialogSettings settings = getDialogSettings(); + newResourcePage = new NewLaunchTargetWizardNewPage(this, null, wizards); + newResourcePage.setDialogSettings(settings); + Control control = newResourcePage.createControl(parent); + getWorkbench().getHelpSystem().setHelp(control, + IWorkbenchHelpContextIds.NEW_WIZARD_SELECTION_WIZARD_PAGE); + setControl(control); + } + + /** + * Since Finish was pressed, write widget values to the dialog store so that they + *will persist into the next invocation of this wizard page + */ + protected void saveWidgetValues() { + newResourcePage.saveWidgetValues(); + } + + @Override + public boolean canFlipToNextPage() { + // if the current page advertises that it does have pages then ask it via the super call + if (hasPages) { + return super.canFlipToNextPage(); + } + return false; + } + + /** + * Sets whether the selected wizard advertises that it does provide pages. + * + * @param newValue whether the selected wizard has pages + * @since 3.1 + */ + public void setHasPages(boolean newValue) { + hasPages = newValue; + } + + /** + * Sets whether the selected wizard advertises that it can finish early. + * + * @param newValue whether the selected wizard can finish early + */ + public void setCanFinishEarly(boolean newValue) { + canFinishEarly = newValue; + } + + /** + * Answers whether the currently selected page, if any, advertises that it may finish early. + * + * @return whether the page can finish early + */ + public boolean canFinishEarly() { + return canFinishEarly; + } +} diff --git a/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/target/ILaunchTargetUIManager.java b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/target/ILaunchTargetUIManager.java index 6cd2a5726d2..f29dde373d9 100644 --- a/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/target/ILaunchTargetUIManager.java +++ b/bundles/org.eclipse.launchbar.ui/src/org/eclipse/launchbar/ui/target/ILaunchTargetUIManager.java @@ -9,6 +9,7 @@ package org.eclipse.launchbar.ui.target; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.launchbar.core.target.ILaunchTarget; +import org.eclipse.ui.wizards.IWizardDescriptor; /** * A manager for the launch target UI. @@ -17,11 +18,12 @@ public interface ILaunchTargetUIManager { /** * Return a label provider that gives the test and image for the target. - * + * * @param target * the launch target * @return the label provider for the launch target */ ILabelProvider getLabelProvider(ILaunchTarget target); + public IWizardDescriptor[] getLaunchTargetWizards(); }