| /******************************************************************************* |
| * Copyright (c) 2010 BSI Business Systems Integration AG. |
| * 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: |
| * BSI Business Systems Integration AG - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.scout.sdk.ui.view.properties.presenter.single; |
| |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.ILaunch; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchListener; |
| import org.eclipse.debug.core.ILaunchManager; |
| import org.eclipse.jface.dialogs.MessageDialogWithToggle; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.pde.internal.ui.IPDEUIConstants; |
| import org.eclipse.pde.ui.launcher.EclipseLaunchShortcut; |
| import org.eclipse.scout.sdk.Texts; |
| import org.eclipse.scout.sdk.extensions.runtime.classes.RuntimeClasses; |
| import org.eclipse.scout.sdk.ui.extensions.bundle.ScoutBundleUiExtension; |
| import org.eclipse.scout.sdk.ui.internal.ScoutSdkUi; |
| import org.eclipse.scout.sdk.ui.internal.extensions.bundle.ScoutBundleExtensionPoint; |
| import org.eclipse.scout.sdk.ui.internal.view.properties.model.links.FileOpenLink; |
| import org.eclipse.scout.sdk.ui.internal.view.properties.model.links.LinksPresenterModel; |
| import org.eclipse.scout.sdk.ui.internal.view.properties.presenter.LinksPresenter; |
| import org.eclipse.scout.sdk.ui.view.properties.PropertyViewFormToolkit; |
| import org.eclipse.scout.sdk.ui.view.properties.presenter.AbstractPresenter; |
| import org.eclipse.scout.sdk.util.pde.ProductFileModelHelper; |
| import org.eclipse.scout.sdk.workspace.IScoutBundle; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.DisposeEvent; |
| import org.eclipse.swt.events.DisposeListener; |
| import org.eclipse.swt.layout.FillLayout; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Group; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.ui.editors.text.EditorsUI; |
| import org.eclipse.ui.forms.events.HyperlinkAdapter; |
| import org.eclipse.ui.forms.events.HyperlinkEvent; |
| import org.eclipse.ui.forms.widgets.ImageHyperlink; |
| |
| /** |
| * <h3>{@link ProductLaunchPresenter}</h3> ... |
| * |
| * @author Andreas Hoegger |
| * @since 1.0.8 31.08.2010 |
| */ |
| @SuppressWarnings("restriction") |
| public class ProductLaunchPresenter extends AbstractPresenter { |
| |
| private String m_productName; |
| private final IFile m_productFile; |
| private final IScoutBundle m_bundle; |
| |
| // internal |
| private ImageHyperlink m_runLink; |
| private ImageHyperlink m_debugLink; |
| private ImageHyperlink m_stopLink; |
| private Group m_mainGroup; |
| |
| private P_LaunchListener m_launchListener; |
| private P_RecomputeLaunchStateJob m_stateUpdateJob; |
| |
| private final static Pattern PATTERN = Pattern.compile("name\\s*\\=\\s*(\\\")?([^\\\"]*)\\\"", Pattern.MULTILINE); |
| private final static String MAC_OS_X_SWING_WARNING_MESSAGE_KEY = "scoutSwingMacOsXWarningKey"; |
| |
| /** |
| * @param toolkit |
| * @param parent |
| */ |
| public ProductLaunchPresenter(PropertyViewFormToolkit toolkit, Composite parent, IFile productFile, IScoutBundle bundle) { |
| super(toolkit, parent); |
| m_productFile = productFile; |
| m_bundle = bundle; |
| String prodName = null; |
| String productFileContent = ""; |
| Matcher m = PATTERN.matcher(productFileContent); |
| if (m.find()) { |
| prodName = m.group(2); |
| } |
| if (prodName == null) { |
| prodName = productFile.getParent().getName() + " " + productFile.getName(); |
| } |
| m_productName = prodName; |
| create(getContainer(), productFile); |
| m_launchListener = new P_LaunchListener(); |
| DebugPlugin.getDefault().getLaunchManager().addLaunchListener(m_launchListener); |
| getContainer().addDisposeListener(new DisposeListener() { |
| @Override |
| public void widgetDisposed(DisposeEvent e) { |
| dispose(); |
| } |
| }); |
| m_stateUpdateJob = new P_RecomputeLaunchStateJob(); |
| m_stateUpdateJob.schedule(); |
| } |
| |
| @Override |
| public void dispose() { |
| super.dispose(); |
| if (m_launchListener != null) { |
| try { |
| DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(m_launchListener); |
| m_launchListener = null; |
| } |
| catch (Exception e) { |
| ScoutSdkUi.logError("could not remove launch listener on debug plugin.", e); |
| } |
| } |
| if (m_stateUpdateJob != null) { |
| m_stateUpdateJob.m_canceled = true; |
| m_stateUpdateJob = null; |
| } |
| } |
| |
| /** |
| * @param container |
| * @param productFile |
| */ |
| protected void create(Composite parent, IFile productFile) { |
| m_mainGroup = new Group(parent, SWT.SHADOW_ETCHED_OUT); |
| m_mainGroup.setText(productFile.getParent().getName()); |
| |
| Label l = getToolkit().createLabel(m_mainGroup, ""); |
| |
| ScoutBundleUiExtension uiExt = ScoutBundleExtensionPoint.getExtension(getBundle().getType()); |
| if (uiExt != null && uiExt.getLauncherIconPath() != null) { |
| l.setImage(ScoutSdkUi.getDefault().getImageRegistry().get(uiExt.getLauncherIconPath())); |
| } |
| |
| Control linkPart = createLinkPart(m_mainGroup); |
| Control actionPart = createActionPart(m_mainGroup); |
| |
| //layout |
| parent.setLayout(new FillLayout()); |
| GridLayout layout = new GridLayout(3, false); |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| layout.verticalSpacing = 0; |
| layout.horizontalSpacing = 0; |
| m_mainGroup.setLayout(layout); |
| l.setLayoutData(new GridData(GridData.FILL_VERTICAL)); |
| linkPart.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL)); |
| GridData actionPartData = new GridData(GridData.FILL_VERTICAL | GridData.FILL_HORIZONTAL); |
| actionPartData.minimumWidth = actionPart.computeSize(SWT.DEFAULT, SWT.DEFAULT).x; |
| actionPartData.horizontalAlignment = SWT.RIGHT; |
| actionPart.setLayoutData(actionPartData); |
| } |
| |
| protected Control createLinkPart(Composite parent) { |
| LinksPresenterModel model = new LinksPresenterModel(); |
| model.addGlobalLink(new FileOpenLink(getProductFile(), 10, IPDEUIConstants.PRODUCT_EDITOR_ID)); |
| |
| try { |
| ProductFileModelHelper pfmh = new ProductFileModelHelper(getProductFile()); |
| IFile configIni = pfmh.ConfigurationFile.getFile(); |
| if (configIni != null) { |
| model.addGlobalLink(new FileOpenLink(configIni, 20, EditorsUI.DEFAULT_TEXT_EDITOR_ID)); |
| } |
| } |
| catch (CoreException e) { |
| ScoutSdkUi.logWarning("Unable to find config.ini file for product '" + getProductFile().getLocation().toOSString() + "'.", e); |
| } |
| |
| LinksPresenter presenter = new LinksPresenter(getToolkit(), parent, model); |
| return presenter.getContainer(); |
| } |
| |
| protected Control createActionPart(Composite parent) { |
| Composite container = getToolkit().createComposite(parent); |
| m_runLink = getToolkit().createImageHyperlink(container, SWT.NONE); |
| m_runLink.setImage(ScoutSdkUi.getImage(ScoutSdkUi.ToolRun)); |
| m_runLink.setToolTipText(Texts.get("StartProduct")); |
| m_runLink.addHyperlinkListener(new HyperlinkAdapter() { |
| @Override |
| public void linkActivated(HyperlinkEvent e) { |
| restartProduct(false); |
| } |
| }); |
| m_debugLink = getToolkit().createImageHyperlink(container, SWT.NONE); |
| m_debugLink.setToolTipText(Texts.get("StartProductInDebugMode")); |
| m_debugLink.setImage(ScoutSdkUi.getImage(ScoutSdkUi.ToolDebug)); |
| m_debugLink.addHyperlinkListener(new HyperlinkAdapter() { |
| @Override |
| public void linkActivated(HyperlinkEvent e) { |
| restartProduct(true); |
| } |
| }); |
| m_stopLink = getToolkit().createImageHyperlink(container, SWT.NONE); |
| m_stopLink.setImage(ScoutSdkUi.getImage(ScoutSdkUi.ToolStop)); |
| m_stopLink.setToolTipText(Texts.get("StopProduct")); |
| m_stopLink.setEnabled(false); |
| m_stopLink.addHyperlinkListener(new HyperlinkAdapter() { |
| @Override |
| public void linkActivated(HyperlinkEvent e) { |
| stopProduct(); |
| } |
| }); |
| |
| //layout |
| GridLayout layout = new GridLayout(1, false); |
| layout.horizontalSpacing = 0; |
| layout.verticalSpacing = 0; |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| |
| container.setLayout(layout); |
| GridData layoutData = new GridData(GridData.FILL_BOTH); |
| |
| m_runLink.setLayoutData(layoutData); |
| layoutData = new GridData(GridData.FILL_BOTH); |
| m_debugLink.setLayoutData(layoutData); |
| layoutData = new GridData(GridData.FILL_BOTH); |
| layoutData.heightHint = 16; |
| m_stopLink.setLayoutData(layoutData); |
| return container; |
| } |
| |
| /** |
| * @return the productFile |
| */ |
| public IFile getProductFile() { |
| return m_productFile; |
| } |
| |
| /** |
| * @return the bundle |
| */ |
| public IScoutBundle getBundle() { |
| return m_bundle; |
| } |
| |
| /** |
| * @return the productName |
| */ |
| public String getProductName() { |
| return m_productName; |
| } |
| |
| private Job startProduct(final boolean debug) { |
| |
| showMacOsXWarnings(); |
| |
| Job job = new Job("starting '" + getProductName() + "' product...") { |
| @Override |
| protected IStatus run(IProgressMonitor monitor) { |
| try { |
| EclipseLaunchShortcut shortCut = new EclipseLaunchShortcut(); |
| shortCut.launch(new StructuredSelection(m_productFile), (debug) ? (ILaunchManager.DEBUG_MODE) : (ILaunchManager.RUN_MODE)); |
| } |
| catch (Exception e) { |
| ScoutSdkUi.logError("could not start product '" + getProductFile().getName() + "'", e); |
| } |
| return Status.OK_STATUS; |
| } |
| }; |
| job.setUser(false); |
| job.setRule(getProductFile()); |
| job.schedule(); |
| return job; |
| } |
| |
| private void showMacOsXWarnings() { |
| if (Platform.OS_MACOSX.equals(Platform.getOS())) { |
| try { |
| IPreferenceStore store = ScoutSdkUi.getDefault().getPreferenceStore(); |
| ProductFileModelHelper pfmh = new ProductFileModelHelper(m_productFile); |
| if (pfmh.ProductFile.existsDependency(RuntimeClasses.ScoutUiSwingBundleId)) { |
| // it is a swing product to be launched on Mac OS X: show help box |
| String doNotShowAgainString = store.getString(MAC_OS_X_SWING_WARNING_MESSAGE_KEY); |
| boolean doNotShowAgain = MessageDialogWithToggle.ALWAYS.equals(doNotShowAgainString); |
| if (!doNotShowAgain) { |
| MessageDialogWithToggle.openWarning(ScoutSdkUi.getShell(), Texts.get("MacOsXSwingWarningTitle"), Texts.get("MacOsXSwingWarningMessage"), |
| Texts.get("DoNotShowAgain"), false, store, MAC_OS_X_SWING_WARNING_MESSAGE_KEY); |
| } |
| } |
| } |
| catch (CoreException e) { |
| ScoutSdkUi.logError(e); |
| } |
| } |
| } |
| |
| private Job stopProduct() { |
| Job job = new Job("stopping '" + getProductName() + "' product...") { |
| @Override |
| protected IStatus run(IProgressMonitor monitor) { |
| try { |
| ILaunchManager lm = DebugPlugin.getDefault().getLaunchManager(); |
| for (ILaunch l : lm.getLaunches()) { |
| ILaunchConfiguration lc = l.getLaunchConfiguration(); |
| if (lc != null && getProductFile().getName().equals(lc.getName())) { |
| l.terminate(); |
| for (int i = 0; i < 50; i++) { |
| if (l.isTerminated()) { |
| break; |
| } |
| else { |
| Thread.sleep(100); |
| } |
| } |
| recomputeLaunchState(); |
| break; |
| } |
| } |
| } |
| catch (Exception e) { |
| ScoutSdkUi.logError("could not stop product '" + getProductFile().getName() + "'", e); |
| } |
| return Status.OK_STATUS; |
| } |
| }; |
| job.setUser(false); |
| job.setRule(getProductFile()); |
| job.schedule(); |
| return job; |
| } |
| |
| private void restartProduct(boolean debug) { |
| Job stopJob = stopProduct(); |
| try { |
| stopJob.join(); |
| startProduct(debug); |
| } |
| catch (InterruptedException e) { |
| ScoutSdkUi.logError("error during stopping product '" + getProductName() + "'", e); |
| } |
| } |
| |
| private void recomputeLaunchState() { |
| if (getContainer() != null && !getContainer().isDisposed()) { |
| getContainer().getDisplay().asyncExec(new Runnable() { |
| @Override |
| public void run() { |
| ILaunch[] launches = DebugPlugin.getDefault().getLaunchManager().getLaunches(); |
| for (ILaunch l : launches) { |
| if (l.getLaunchConfiguration() != null && l.getLaunchConfiguration().getName().equals(getProductFile().getName())) { |
| if (!m_stopLink.isDisposed() && !m_mainGroup.isDisposed()) { |
| if (l.isTerminated()) { |
| m_stopLink.setEnabled(false); |
| m_mainGroup.setText(getProductFile().getParent().getName()); |
| } |
| else { |
| m_stopLink.setEnabled(true); |
| if (l.getLaunchMode().equals(ILaunchManager.DEBUG_MODE)) { |
| m_mainGroup.setText(getProductFile().getParent().getName() + " - " + Texts.get("debugging") + "..."); |
| } |
| else if (l.getLaunchMode().equals(ILaunchManager.RUN_MODE)) { |
| m_mainGroup.setText(getProductFile().getParent().getName() + " - " + Texts.get("Running") + "..."); |
| } |
| else { |
| m_mainGroup.setText(getProductFile().getParent().getName() + " - " + Texts.get("UndefinedState") + "..."); |
| } |
| } |
| } |
| } |
| } |
| } |
| }); |
| } |
| } |
| |
| private class P_LaunchListener implements ILaunchListener { |
| @Override |
| public void launchAdded(ILaunch launch) { |
| recomputeLaunchState(); |
| } |
| |
| @Override |
| public void launchChanged(ILaunch launch) { |
| recomputeLaunchState(); |
| } |
| |
| @Override |
| public void launchRemoved(ILaunch launch) { |
| recomputeLaunchState(); |
| } |
| } // end class P_LaunchListener |
| |
| private class P_RecomputeLaunchStateJob extends Job { |
| |
| private boolean m_canceled = false; |
| |
| public P_RecomputeLaunchStateJob() { |
| super(""); |
| setSystem(true); |
| setPriority(Job.DECORATE); |
| setRule(getProductFile()); |
| } |
| |
| @Override |
| protected IStatus run(IProgressMonitor monitor) { |
| if (!m_canceled) { |
| recomputeLaunchState(); |
| schedule(2500); |
| } |
| return Status.OK_STATUS; |
| } |
| } // end class P_RecomputeLaunchStateJob |
| |
| } |