From 0802bb8e9535c516a0454691beb909c98717ee15 Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Tue, 20 Oct 2015 16:36:28 +0100 Subject: [PATCH] LANG: EventSource and refactor Navigator bundle actions. --- .../melnorme/lang/ide/core/LangCore.java | 6 +- .../lang/ide/core/LangCoreMessages.java | 5 ++ .../core/engine/StructureModelManager.java | 2 +- .../core/operations/AbstractToolManager.java | 4 +- .../project_model/BundleModelManager.java | 10 +++ .../core/project_model/ProjectBasedModel.java | 2 +- .../LANGUAGE_BundleModelManager.java | 8 +- .../ide/ui/actions/RunUIOperationAction.java | 30 +++++++ .../structure/AbstractContentOutlinePage.java | 2 +- .../LangNavigatorActionProvider.java | 57 ++++++++++++ .../ide/ui/operations/RunToolOperation.java | 89 +++++++++++++++++++ .../melnorme/lang/utils/EventSource.java | 40 +++++++++ .../melnorme/utilbox/fields/DomainField.java | 17 +--- .../IEventSource.java} | 11 +-- .../{misc => fields}/ListenerListHelper.java | 5 +- 15 files changed, 253 insertions(+), 35 deletions(-) create mode 100644 plugin_ide.ui/src-lang/melnorme/lang/ide/ui/actions/RunUIOperationAction.java create mode 100644 plugin_ide.ui/src-lang/melnorme/lang/ide/ui/operations/RunToolOperation.java create mode 100644 plugin_tooling/src-lang/melnorme/lang/utils/EventSource.java rename plugin_tooling/src-util/melnorme/utilbox/{misc/IListenerList.java => fields/IEventSource.java} (77%) rename plugin_tooling/src-util/melnorme/utilbox/{misc => fields}/ListenerListHelper.java (91%) diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/LangCore.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/LangCore.java index 79e9cf4ed..815a410bb 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/LangCore.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/LangCore.java @@ -19,7 +19,7 @@ import melnorme.lang.ide.core.engine.EngineClient; import melnorme.lang.ide.core.operations.AbstractToolManager; import melnorme.lang.ide.core.operations.build.BuildManager; -import melnorme.lang.ide.core.project_model.IBundleModelManager; +import melnorme.lang.ide.core.project_model.BundleModelManager; import melnorme.lang.ide.core.project_model.LangBundleModel; import melnorme.lang.ide.core.utils.EclipseUtils; import melnorme.lang.tooling.data.StatusException; @@ -44,7 +44,7 @@ public static LangCore getInstance() { protected static final AbstractToolManager toolManager = LangCore_Actual.createToolManagerSingleton(); protected static final EngineClient engineClient = LangCore_Actual.createEngineClient(); - protected static final IBundleModelManager bundleManager = LangCore_Actual.createBundleModelManager(); + protected static final BundleModelManager bundleManager = LangCore_Actual.createBundleModelManager(); protected static final BuildManager buildManager = LangCore_Actual.createBuildManager(); public static AbstractToolManager getToolManager() { @@ -53,7 +53,7 @@ public static AbstractToolManager getToolManager() { public static EngineClient getEngineClient() { return engineClient; } - public static IBundleModelManager getBundleModelManager() { + public static BundleModelManager getBundleModelManager() { return bundleManager; } public static LangBundleModel getBundleModel() { diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/LangCoreMessages.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/LangCoreMessages.java index bbd3eecd5..ed887b327 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/LangCoreMessages.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/LangCoreMessages.java @@ -20,4 +20,9 @@ public class LangCoreMessages implements ProcessHelperMessages { public static final String BUILD_ClearingProblemMarkers = "Clearing problem markers"; + /* ----------------- ----------------- */ + + public static final String RunningCommand = + "Running command: "; + } \ No newline at end of file diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/engine/StructureModelManager.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/engine/StructureModelManager.java index b1069fd44..4107744c5 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/engine/StructureModelManager.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/engine/StructureModelManager.java @@ -24,7 +24,7 @@ import melnorme.utilbox.concurrency.ICancelMonitor; import melnorme.utilbox.concurrency.NamingThreadFactory; import melnorme.utilbox.concurrency.OperationCancellation; -import melnorme.utilbox.misc.ListenerListHelper; +import melnorme.utilbox.fields.ListenerListHelper; import melnorme.utilbox.misc.Location; import melnorme.utilbox.misc.SimpleLogger; diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/AbstractToolManager.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/AbstractToolManager.java index 62397dfef..8914af931 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/AbstractToolManager.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/AbstractToolManager.java @@ -30,18 +30,18 @@ import melnorme.lang.tooling.data.StatusLevel; import melnorme.lang.tooling.ops.IOperationHelper; import melnorme.lang.tooling.ops.util.PathValidator; +import melnorme.lang.utils.EventSource; import melnorme.lang.utils.ProcessUtils; import melnorme.utilbox.concurrency.ICancelMonitor; import melnorme.utilbox.concurrency.OperationCancellation; import melnorme.utilbox.core.CommonException; -import melnorme.utilbox.misc.ListenerListHelper; import melnorme.utilbox.misc.Location; import melnorme.utilbox.process.ExternalProcessHelper.ExternalProcessResult; /** * Abstract class for running external tools and notifying interested listeners (normally the UI only). */ -public abstract class AbstractToolManager extends ListenerListHelper { +public abstract class AbstractToolManager extends EventSource { public AbstractToolManager() { } diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/project_model/BundleModelManager.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/project_model/BundleModelManager.java index a0b681c93..8d745789b 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/project_model/BundleModelManager.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/project_model/BundleModelManager.java @@ -12,7 +12,9 @@ import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; +import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.Path; import melnorme.lang.ide.core.BundleInfo; import melnorme.lang.ide.core.utils.CoreTaskAgent; @@ -74,6 +76,14 @@ protected void doShutdown() { /* ----------------- ----------------- */ + public boolean isBundleManifestFile(IFile file) { + return file.getProjectRelativePath().equals(getDefaultBundleManifestPath()); + } + + protected abstract Path getDefaultBundleManifestPath(); + + /* ----------------- ----------------- */ + @Override public BUNDLE_MODEL getModel() { return model; diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/project_model/ProjectBasedModel.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/project_model/ProjectBasedModel.java index 73d746155..9df92c08f 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/project_model/ProjectBasedModel.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/project_model/ProjectBasedModel.java @@ -18,7 +18,7 @@ import org.eclipse.core.resources.IProject; -import melnorme.utilbox.misc.ListenerListHelper; +import melnorme.utilbox.fields.ListenerListHelper; import melnorme.utilbox.misc.SimpleLogger; public abstract class ProjectBasedModel { diff --git a/plugin_ide.core/src/LANG_PROJECT_ID/ide/core/bundle_model/LANGUAGE_BundleModelManager.java b/plugin_ide.core/src/LANG_PROJECT_ID/ide/core/bundle_model/LANGUAGE_BundleModelManager.java index dcd775f77..2d9f36c2f 100644 --- a/plugin_ide.core/src/LANG_PROJECT_ID/ide/core/bundle_model/LANGUAGE_BundleModelManager.java +++ b/plugin_ide.core/src/LANG_PROJECT_ID/ide/core/bundle_model/LANGUAGE_BundleModelManager.java @@ -11,6 +11,7 @@ package LANG_PROJECT_ID.ide.core.bundle_model; import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.Path; import melnorme.lang.ide.core.BundleInfo; import melnorme.lang.ide.core.LangCore_Actual.LANGUAGE_BundleModel; @@ -25,7 +26,12 @@ public LANGUAGE_BundleModelManager() { @Override protected BundleManifestResourceListener init_createResourceListener() { - return new ManagerResourceListener(new org.eclipse.core.runtime.Path("lang.bundle")); + return new ManagerResourceListener(getDefaultBundleManifestPath()); + } + + @Override + protected Path getDefaultBundleManifestPath() { + return new Path("lang.bundle"); } @Override diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/actions/RunUIOperationAction.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/actions/RunUIOperationAction.java new file mode 100644 index 000000000..fc5db22b8 --- /dev/null +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/actions/RunUIOperationAction.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Bruno Medeiros and other Contributors. + * 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: + * Bruno Medeiros - initial API and implementation + *******************************************************************************/ +package melnorme.lang.ide.ui.actions; + +import org.eclipse.jface.action.Action; + +public class RunUIOperationAction extends Action { + + protected final AbstractUIOperation operation; + + public RunUIOperationAction(AbstractUIOperation operation) { + this.operation = operation; + + setText(operation.getOperationName()); + } + + @Override + public void run() { + operation.executeAndHandle(); + } + +} \ No newline at end of file diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/editor/structure/AbstractContentOutlinePage.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/editor/structure/AbstractContentOutlinePage.java index 095e8c462..4b3611afb 100644 --- a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/editor/structure/AbstractContentOutlinePage.java +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/editor/structure/AbstractContentOutlinePage.java @@ -12,7 +12,7 @@ import melnorme.lang.ide.ui.LangUIPlugin; -import melnorme.utilbox.misc.ListenerListHelper; +import melnorme.utilbox.fields.ListenerListHelper; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/navigator/LangNavigatorActionProvider.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/navigator/LangNavigatorActionProvider.java index 9986d9b21..eca4857b1 100644 --- a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/navigator/LangNavigatorActionProvider.java +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/navigator/LangNavigatorActionProvider.java @@ -11,7 +11,10 @@ package melnorme.lang.ide.ui.navigator; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.Shell; @@ -21,8 +24,14 @@ import org.eclipse.ui.actions.ActionGroup; import org.eclipse.ui.navigator.CommonActionProvider; import org.eclipse.ui.navigator.ICommonActionExtensionSite; +import org.eclipse.ui.navigator.ICommonMenuConstants; import org.eclipse.ui.navigator.ICommonViewerWorkbenchSite; +import melnorme.lang.ide.core.LangCore; +import melnorme.lang.ide.core.project_model.view.DependenciesContainer; +import melnorme.lang.ide.ui.LangImages; +import melnorme.lang.ide.ui.actions.AbstractUIOperation; +import melnorme.lang.ide.ui.actions.RunUIOperationAction; import melnorme.utilbox.collections.ArrayList2; public abstract class LangNavigatorActionProvider extends CommonActionProvider { @@ -96,4 +105,52 @@ protected Object getSelectionFirstElement() { } } + + public static abstract class BundleOperationsActionGroup extends ViewPartActionGroup { + + public BundleOperationsActionGroup(IViewPart viewPart) { + super(viewPart); + } + + public IProject getBundleProjectFromSelection() { + Object selElement = getSelectionFirstElement(); + if(selElement instanceof IProject) { + return (IProject) selElement; + } + if(selElement instanceof DependenciesContainer) { + DependenciesContainer dependenciesContainer = (DependenciesContainer) selElement; + return dependenciesContainer.getParent(); + } + if(selElement instanceof IFile) { + IFile file = (IFile) selElement; + if(LangCore.getBundleModelManager().isBundleManifestFile(file)) { + return file.getProject(); + } + } + return null; + } + + @Override + public void fillContextMenu(IMenuManager menu) { + IProject project = getBundleProjectFromSelection(); + if(project == null) + return; + + MenuManager bundleOpsMenu = new MenuManager(getMenuName(), LangImages.NAV_Library, "bundleMenu"); + + initActions(bundleOpsMenu, project); + + menu.prependToGroup(ICommonMenuConstants.GROUP_BUILD, bundleOpsMenu); + } + + protected abstract String getMenuName(); + + protected abstract void initActions(MenuManager bundleOpsMenu, IProject project); + + protected void addRunOperationAction(MenuManager bundleOpsMenu, AbstractUIOperation operation) { + bundleOpsMenu.add(new RunUIOperationAction(operation)); + } + + } + } \ No newline at end of file diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/operations/RunToolOperation.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/operations/RunToolOperation.java new file mode 100644 index 000000000..07876587d --- /dev/null +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/operations/RunToolOperation.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2015 Bruno Medeiros and other Contributors. + * 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: + * Bruno Medeiros - initial API and implementation + *******************************************************************************/ +package melnorme.lang.ide.ui.operations; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; + +import melnorme.lang.ide.core.LangCore; +import melnorme.lang.ide.core.LangCoreMessages; +import melnorme.lang.ide.core.operations.AbstractToolManager; +import melnorme.lang.ide.core.operations.AbstractToolManager.RunProcessTask; +import melnorme.lang.ide.core.operations.MessageEventInfo; +import melnorme.lang.ide.core.operations.OperationInfo; +import melnorme.lang.ide.core.utils.TextMessageUtils; +import melnorme.lang.ide.ui.actions.AbstractUIOperation; +import melnorme.utilbox.collections.Indexable; +import melnorme.utilbox.concurrency.OperationCancellation; +import melnorme.utilbox.core.CommonException; + +public abstract class RunToolOperation extends AbstractUIOperation { + + protected final IProject project; + protected final Indexable commands; + + public RunToolOperation(String operationName, IProject project, Indexable commands) { + super(operationName); + this.project = project; + this.commands = commands; + } + + protected AbstractToolManager getToolManager() { + return LangCore.getToolManager(); + } + + @Override + protected void doBackgroundComputation(IProgressMonitor monitor) + throws CoreException, CommonException, OperationCancellation { + ProcessBuilder pb = createProcessBuilder(); + + OperationInfo opInfo = getToolManager().startNewToolOperation(); + + getToolManager().notifyMessageEvent(new MessageEventInfo(opInfo, + TextMessageUtils.headerBIG(getOperationStartMessage()))); + + RunProcessTask runToolTask = getToolManager().newRunToolTask(opInfo, pb, monitor); + runProcessTask(runToolTask); + } + + protected String getOperationStartMessage() { + return LangCoreMessages.RunningCommand; + } + + protected ProcessBuilder createProcessBuilder() throws CoreException, CommonException { + return AbstractToolManager.createProcessBuilder(project, getCommands()); + } + + protected void runProcessTask(RunProcessTask runToolTask) throws CommonException, OperationCancellation { + runToolTask.runProcess(); + } + + protected String[] getCommands() { + return commands.toArray(String.class); + } + + /* ----------------- ----------------- */ + + public abstract static class RunSDKToolOperation extends RunToolOperation { + + public RunSDKToolOperation(String operationName, IProject project, Indexable commands) { + super(operationName, project, commands); + } + + @Override + protected ProcessBuilder createProcessBuilder() throws CoreException, CommonException { + return getToolManager().createSDKProcessBuilder(project, getCommands()); + } + + } + +} \ No newline at end of file diff --git a/plugin_tooling/src-lang/melnorme/lang/utils/EventSource.java b/plugin_tooling/src-lang/melnorme/lang/utils/EventSource.java new file mode 100644 index 000000000..01200e52b --- /dev/null +++ b/plugin_tooling/src-lang/melnorme/lang/utils/EventSource.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2015 Bruno Medeiros and other Contributors. + * 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: + * Bruno Medeiros - initial API and implementation + *******************************************************************************/ +package melnorme.lang.utils; + + +import melnorme.utilbox.collections.Indexable; +import melnorme.utilbox.fields.IEventSource; +import melnorme.utilbox.fields.ListenerListHelper; + +public class EventSource implements IEventSource { + + protected final ListenerListHelper listeners = new ListenerListHelper<>(); + + public EventSource() { + super(); + } + + @Override + public void addListener(T listener) { + listeners.addListener(listener); + } + + @Override + public void removeListener(T listener) { + listeners.removeListener(listener); + } + + protected Indexable getListeners() { + return listeners.getListeners(); + } + +} \ No newline at end of file diff --git a/plugin_tooling/src-util/melnorme/utilbox/fields/DomainField.java b/plugin_tooling/src-util/melnorme/utilbox/fields/DomainField.java index 5870e8a0b..0617bc622 100644 --- a/plugin_tooling/src-util/melnorme/utilbox/fields/DomainField.java +++ b/plugin_tooling/src-util/melnorme/utilbox/fields/DomainField.java @@ -10,12 +10,12 @@ *******************************************************************************/ package melnorme.utilbox.fields; -import melnorme.utilbox.misc.ListenerListHelper; +import melnorme.lang.utils.EventSource; /** * A value that listener/observer can connect to and listen for modification. */ -public class DomainField implements IModelField { +public class DomainField extends EventSource implements IModelField { private VALUE value; // private to prevent direct modifications. @@ -33,19 +33,6 @@ protected VALUE getDefaultFieldValue() { /* ----------------- listeners ----------------- */ - protected final ListenerListHelper listeners = new ListenerListHelper<>(); - - @Override - public void addListener(IFieldValueListener listener) { - listeners.addListener(listener); - } - - @Override - public void removeListener(IFieldValueListener listener) { - listeners.removeListener(listener); - } - - public void fireFieldValueChanged() { fieldValueChanged(); for (IFieldValueListener listener : listeners.getListeners()) { diff --git a/plugin_tooling/src-util/melnorme/utilbox/misc/IListenerList.java b/plugin_tooling/src-util/melnorme/utilbox/fields/IEventSource.java similarity index 77% rename from plugin_tooling/src-util/melnorme/utilbox/misc/IListenerList.java rename to plugin_tooling/src-util/melnorme/utilbox/fields/IEventSource.java index fcbbcfa1a..9bbd3dfba 100644 --- a/plugin_tooling/src-util/melnorme/utilbox/misc/IListenerList.java +++ b/plugin_tooling/src-util/melnorme/utilbox/fields/IEventSource.java @@ -8,17 +8,12 @@ * Contributors: * Bruno Medeiros - initial API and implementation *******************************************************************************/ -package melnorme.utilbox.misc; +package melnorme.utilbox.fields; -import melnorme.utilbox.collections.Indexable; - - -public interface IListenerList { +public interface IEventSource { - public Indexable getListeners(); + public void addListener(LISTENER listener); public void removeListener(LISTENER listener); - public void addListener(LISTENER listener); - } \ No newline at end of file diff --git a/plugin_tooling/src-util/melnorme/utilbox/misc/ListenerListHelper.java b/plugin_tooling/src-util/melnorme/utilbox/fields/ListenerListHelper.java similarity index 91% rename from plugin_tooling/src-util/melnorme/utilbox/misc/ListenerListHelper.java rename to plugin_tooling/src-util/melnorme/utilbox/fields/ListenerListHelper.java index a11d67d7d..4cd81f172 100644 --- a/plugin_tooling/src-util/melnorme/utilbox/misc/ListenerListHelper.java +++ b/plugin_tooling/src-util/melnorme/utilbox/fields/ListenerListHelper.java @@ -8,7 +8,7 @@ * Contributors: * Bruno Medeiros - initial API and implementation *******************************************************************************/ -package melnorme.utilbox.misc; +package melnorme.utilbox.fields; import java.util.Iterator; @@ -20,7 +20,7 @@ * This class is designed to be thread safe. * @see also {@link org.eclipse.core.runtime.ListenerList} */ -public class ListenerListHelper implements IListenerList { +public class ListenerListHelper implements IEventSource { private volatile Indexable listeners; @@ -33,7 +33,6 @@ protected ListenerListHelper(Indexable listeners) { } - @Override public synchronized Indexable getListeners() { return listeners; }