| /******************************************************************************* |
| * 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.rt.ui.swt; |
| |
| import java.beans.PropertyChangeEvent; |
| import java.beans.PropertyChangeListener; |
| import java.beans.PropertyChangeSupport; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.concurrent.TimeUnit; |
| |
| 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.jface.resource.ImageDescriptor; |
| import org.eclipse.scout.commons.CompareUtility; |
| import org.eclipse.scout.commons.EventListenerList; |
| import org.eclipse.scout.commons.HTMLUtility; |
| import org.eclipse.scout.commons.HTMLUtility.DefaultFont; |
| import org.eclipse.scout.commons.ITypeWithClassId; |
| import org.eclipse.scout.commons.StringUtility; |
| import org.eclipse.scout.commons.beans.AbstractPropertyObserver; |
| import org.eclipse.scout.commons.exception.IProcessingStatus; |
| import org.eclipse.scout.commons.exception.ProcessingException; |
| import org.eclipse.scout.commons.holders.Holder; |
| import org.eclipse.scout.commons.holders.IHolder; |
| import org.eclipse.scout.commons.job.JobEx; |
| import org.eclipse.scout.commons.logger.IScoutLogger; |
| import org.eclipse.scout.commons.logger.ScoutLogManager; |
| import org.eclipse.scout.rt.client.ClientAsyncJob; |
| import org.eclipse.scout.rt.client.ClientSyncJob; |
| import org.eclipse.scout.rt.client.IClientSession; |
| import org.eclipse.scout.rt.client.busy.IBusyManagerService; |
| import org.eclipse.scout.rt.client.services.common.exceptionhandler.ErrorHandler; |
| import org.eclipse.scout.rt.client.services.common.session.IClientSessionRegistryService; |
| import org.eclipse.scout.rt.client.ui.action.IActionFilter; |
| import org.eclipse.scout.rt.client.ui.action.keystroke.IKeyStroke; |
| import org.eclipse.scout.rt.client.ui.action.menu.IMenu; |
| import org.eclipse.scout.rt.client.ui.basic.filechooser.IFileChooser; |
| import org.eclipse.scout.rt.client.ui.desktop.DesktopEvent; |
| import org.eclipse.scout.rt.client.ui.desktop.DesktopListener; |
| import org.eclipse.scout.rt.client.ui.desktop.IDesktop; |
| import org.eclipse.scout.rt.client.ui.form.IForm; |
| import org.eclipse.scout.rt.client.ui.form.fields.IFormField; |
| import org.eclipse.scout.rt.client.ui.form.fields.htmlfield.IHtmlField; |
| import org.eclipse.scout.rt.client.ui.messagebox.IMessageBox; |
| import org.eclipse.scout.rt.client.ui.wizard.IWizard; |
| import org.eclipse.scout.rt.shared.data.basic.FontSpec; |
| import org.eclipse.scout.rt.shared.ui.UiDeviceType; |
| import org.eclipse.scout.rt.shared.ui.UiLayer; |
| import org.eclipse.scout.rt.shared.ui.UserAgent; |
| import org.eclipse.scout.rt.ui.swt.action.menu.ISwtScoutMenuItem; |
| import org.eclipse.scout.rt.ui.swt.action.menu.SwtScoutMenuItem; |
| import org.eclipse.scout.rt.ui.swt.basic.WidgetPrinter; |
| import org.eclipse.scout.rt.ui.swt.busy.SwtBusyHandler; |
| import org.eclipse.scout.rt.ui.swt.concurrency.SwtScoutSynchronizer; |
| import org.eclipse.scout.rt.ui.swt.form.ISwtScoutForm; |
| import org.eclipse.scout.rt.ui.swt.form.SwtScoutForm; |
| import org.eclipse.scout.rt.ui.swt.form.fields.ISwtScoutFormField; |
| import org.eclipse.scout.rt.ui.swt.internal.debug.layout.spy.LogicalGridLayoutSpy; |
| import org.eclipse.scout.rt.ui.swt.keystroke.ISwtKeyStroke; |
| import org.eclipse.scout.rt.ui.swt.keystroke.ISwtKeyStrokeFilter; |
| import org.eclipse.scout.rt.ui.swt.keystroke.KeyStrokeManager; |
| import org.eclipse.scout.rt.ui.swt.util.ColorFactory; |
| import org.eclipse.scout.rt.ui.swt.util.FontRegistry; |
| import org.eclipse.scout.rt.ui.swt.util.ISwtIconLocator; |
| import org.eclipse.scout.rt.ui.swt.util.ScoutFormToolkit; |
| import org.eclipse.scout.rt.ui.swt.util.SwtIconLocator; |
| import org.eclipse.scout.rt.ui.swt.util.SwtUtility; |
| import org.eclipse.scout.rt.ui.swt.window.ISwtScoutPart; |
| import org.eclipse.scout.rt.ui.swt.window.desktop.editor.AbstractScoutEditorPart; |
| import org.eclipse.scout.rt.ui.swt.window.desktop.editor.ScoutFormEditorInput; |
| import org.eclipse.scout.rt.ui.swt.window.desktop.tray.ISwtScoutTray; |
| import org.eclipse.scout.rt.ui.swt.window.desktop.tray.SwtScoutTray; |
| import org.eclipse.scout.rt.ui.swt.window.desktop.view.AbstractScoutView; |
| import org.eclipse.scout.rt.ui.swt.window.dialog.SwtScoutDialog; |
| import org.eclipse.scout.rt.ui.swt.window.filechooser.SwtScoutFileChooser; |
| import org.eclipse.scout.rt.ui.swt.window.messagebox.SwtScoutMessageBoxDialog; |
| import org.eclipse.scout.rt.ui.swt.window.popup.SwtScoutPopup; |
| import org.eclipse.scout.service.SERVICES; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.dnd.Clipboard; |
| import org.eclipse.swt.dnd.TextTransfer; |
| import org.eclipse.swt.dnd.Transfer; |
| import org.eclipse.swt.events.ShellAdapter; |
| import org.eclipse.swt.events.ShellEvent; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.Font; |
| import org.eclipse.swt.graphics.FontData; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.RGB; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Listener; |
| import org.eclipse.swt.widgets.Menu; |
| import org.eclipse.swt.widgets.MessageBox; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.ToolTip; |
| import org.eclipse.swt.widgets.TrayItem; |
| import org.eclipse.swt.widgets.Widget; |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.IPerspectiveDescriptor; |
| import org.eclipse.ui.IViewPart; |
| import org.eclipse.ui.IViewReference; |
| import org.eclipse.ui.IWorkbench; |
| import org.eclipse.ui.IWorkbenchListener; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.IWorkbenchPart; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.PartInitException; |
| import org.eclipse.ui.PerspectiveAdapter; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.forms.widgets.Form; |
| import org.eclipse.ui.forms.widgets.FormToolkit; |
| import org.eclipse.ui.views.IViewDescriptor; |
| import org.osgi.framework.Bundle; |
| |
| /** |
| * <h3>SwtEnvironment</h3> ... |
| * |
| * @since 1.0.0 06.03.2008 |
| */ |
| public abstract class AbstractSwtEnvironment extends AbstractPropertyObserver implements ISwtEnvironment { |
| private static final IScoutLogger LOG = ScoutLogManager.getLogger(AbstractSwtEnvironment.class); |
| public static final String PROP_WIDGET_IDS_ENABLED = "org.eclipse.scout.rt.widgetIdsEnabled"; |
| public static final String WIDGET_ID_KEY = "TEST_COMP_NAME"; |
| |
| private final Bundle m_applicationBundle; |
| |
| private final String m_perspectiveId; |
| private final Class<? extends IClientSession> m_clientSessionClass; |
| private IClientSession m_clientSession; |
| private IDesktop m_desktop; |
| |
| private int m_status; |
| |
| private SwtScoutSynchronizer m_synchronizer; |
| |
| private final Object m_immediateSwtJobsLock = new Object(); |
| private final List<Runnable> m_immediateSwtJobs = new ArrayList<Runnable>(); |
| |
| private Clipboard m_clipboard; |
| private ColorFactory m_colorFactory; |
| private FontRegistry m_fontRegistry; |
| private ISwtIconLocator m_iconLocator; |
| private ISwtScoutTray m_trayComposite; |
| |
| private List<ISwtKeyStroke> m_desktopKeyStrokes; |
| private KeyStrokeManager m_keyStrokeManager; |
| |
| private Control m_popupOwner; |
| private Rectangle m_popupOwnerBounds; |
| |
| private ScoutFormToolkit m_formToolkit; |
| private FormFieldFactory m_formFieldFactory; |
| |
| private PropertyChangeSupport m_propertySupport; |
| |
| private boolean m_startDesktopCalled; |
| private boolean m_activateDesktopCalled; |
| |
| private EventListenerList m_environmentListeners; |
| |
| private Map<String, String> m_scoutPartIdToUiPartId; |
| private Map<IForm, ISwtScoutPart> m_openForms; |
| private P_ScoutDesktopListener m_scoutDesktopListener; |
| private P_ScoutDesktopPropertyListener m_desktopPropertyListener; |
| |
| private P_PerspectiveListener m_perspectiveListener; |
| private P_WorkbenchListener m_workbenchListener; |
| |
| public AbstractSwtEnvironment(Bundle applicationBundle, String perspectiveId, Class<? extends IClientSession> clientSessionClass) { |
| m_applicationBundle = applicationBundle; |
| m_perspectiveId = perspectiveId; |
| m_clientSessionClass = clientSessionClass; |
| // |
| m_environmentListeners = new EventListenerList(); |
| m_scoutPartIdToUiPartId = new HashMap<String, String>(); |
| m_openForms = new HashMap<IForm, ISwtScoutPart>(); |
| m_propertySupport = new PropertyChangeSupport(this); |
| m_status = SwtEnvironmentEvent.INACTIVE; |
| m_desktopKeyStrokes = new ArrayList<ISwtKeyStroke>(); |
| m_startDesktopCalled = false; |
| } |
| |
| public Bundle getApplicationBundle() { |
| return m_applicationBundle; |
| } |
| |
| private void stopScout() throws CoreException { |
| final IClientSession localSession = m_clientSession; |
| try { |
| if (m_desktopKeyStrokes != null) { |
| for (ISwtKeyStroke swtKeyStroke : m_desktopKeyStrokes) { |
| removeGlobalKeyStroke(swtKeyStroke); |
| } |
| m_desktopKeyStrokes.clear(); |
| } |
| if (m_iconLocator != null) { |
| m_iconLocator.dispose(); |
| m_iconLocator = null; |
| } |
| if (m_colorFactory != null) { |
| m_colorFactory.dispose(); |
| m_colorFactory = null; |
| } |
| m_keyStrokeManager = null; |
| if (m_fontRegistry != null) { |
| m_fontRegistry.dispose(); |
| m_fontRegistry = null; |
| } |
| if (m_formToolkit != null) { |
| m_formToolkit.dispose(); |
| m_formToolkit = null; |
| } |
| if (m_trayComposite != null) { |
| m_trayComposite.disposeTray(); |
| m_trayComposite = null; |
| } |
| detachScoutListeners(); |
| detachSWTListeners(); |
| if (m_synchronizer != null) { |
| m_synchronizer = null; |
| } |
| m_clientSession = null; |
| |
| m_status = SwtEnvironmentEvent.STOPPED; |
| // remove workbench listener to avoid recursive calls |
| PlatformUI.getWorkbench().removeWorkbenchListener(m_workbenchListener); |
| setStartDesktopCalled(false); |
| } |
| finally { |
| if (m_status == SwtEnvironmentEvent.STOPPED) { |
| JobEx sendShutdownEventJob = new JobEx("wait for shutdown state lock job.") { |
| @Override |
| protected IStatus run(IProgressMonitor monitor) { |
| // we are stopping. wait until the session has released the state lock |
| Object stateLock = localSession.getStateLock(); |
| while (localSession.isActive()) { |
| synchronized (stateLock) { |
| try { |
| stateLock.wait(); |
| } |
| catch (InterruptedException e) { |
| LOG.warn("Interrupted while waiting for model thread."); |
| } |
| } |
| } |
| getDisplay().asyncExec(new Runnable() { |
| @Override |
| public void run() { |
| fireEnvironmentChanged(new SwtEnvironmentEvent(this, SwtEnvironmentEvent.STOPPED)); |
| } |
| }); |
| return Status.OK_STATUS; |
| } |
| }; |
| sendShutdownEventJob.schedule(); |
| } |
| } |
| } |
| |
| /** |
| * @param scoutPartLocation |
| * the location id defined in {@link IForm} or additional. |
| * @param uiPartId |
| * the id of the {@link IViewPart} registered in the plugin.xml as a |
| * view extension. |
| */ |
| @Override |
| public void registerPart(String scoutPartLocation, String uiPartId) { |
| m_scoutPartIdToUiPartId.put(scoutPartLocation, uiPartId); |
| } |
| |
| @Override |
| public void unregisterPart(String scoutPartLocation) { |
| m_scoutPartIdToUiPartId.remove(scoutPartLocation); |
| } |
| |
| @Override |
| public final String[] getAllPartIds() { |
| HashSet<String> partIds = new HashSet<String>(m_scoutPartIdToUiPartId.values()); |
| return partIds.toArray(new String[partIds.size()]); |
| } |
| |
| @Override |
| public final String getSwtPartIdForScoutPartId(String scoutPartLocation) { |
| return m_scoutPartIdToUiPartId.get(scoutPartLocation); |
| } |
| |
| @Override |
| public final String getScoutPartIdForSwtPartId(String partId) { |
| if (partId == null) { |
| return ""; |
| } |
| for (Entry<String, String> entry : m_scoutPartIdToUiPartId.entrySet()) { |
| if (entry.getValue().equals(partId)) { |
| return entry.getKey(); |
| } |
| } |
| return ""; |
| } |
| |
| public IViewPart findViewPart(String viewId) { |
| if (viewId != null) { |
| IViewDescriptor viewRef = PlatformUI.getWorkbench().getViewRegistry().find(viewId); |
| if (viewRef != null && !viewRef.getAllowMultiple()) { |
| return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(viewId); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public AbstractScoutView getViewPart(String viewId) { |
| if (viewId != null) { |
| String secondaryId = null; |
| IViewDescriptor viewRef = PlatformUI.getWorkbench().getViewRegistry().find(viewId); |
| if (viewRef.getAllowMultiple()) { |
| secondaryId = "" + System.currentTimeMillis(); |
| } |
| try { |
| IViewPart view = null; |
| if (secondaryId == null) { |
| view = findViewPart(viewId); |
| |
| if (view == null) { |
| view = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(viewId, null, IWorkbenchPage.VIEW_VISIBLE); |
| } |
| } |
| else { |
| view = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(viewId, secondaryId, IWorkbenchPage.VIEW_VISIBLE); |
| } |
| if (!(view instanceof AbstractScoutView)) { |
| LOG.warn("views used in scout's enviromnent must be extensions of AbstractScoutView"); |
| } |
| else { |
| return (AbstractScoutView) view; |
| } |
| } |
| catch (PartInitException e) { |
| LOG.error("could not inizialize view", e); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public AbstractScoutEditorPart getEditorPart(IEditorInput editorInput, String editorId) { |
| if (editorInput != null && editorId != null) { |
| try { |
| IEditorPart editor = null; |
| editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findEditor(editorInput); |
| |
| if (editor == null) { |
| editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().openEditor(editorInput, editorId); |
| } |
| if (!(editor instanceof AbstractScoutEditorPart)) { |
| LOG.warn("editors used in scout's enviromnent must be extensions of AbstractScoutEditorPart"); |
| } |
| else { |
| return (AbstractScoutEditorPart) editor; |
| } |
| } |
| catch (PartInitException e) { |
| LOG.error("could not inizialize editor", e); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public boolean isInitialized() { |
| return m_status == SwtEnvironmentEvent.STARTED; |
| } |
| |
| @Override |
| public final void ensureInitialized() { |
| if (m_status == SwtEnvironmentEvent.INACTIVE |
| || m_status == SwtEnvironmentEvent.STOPPED) { |
| try { |
| init(); |
| } |
| catch (CoreException e) { |
| LOG.error("could not initialize Environment", e); |
| } |
| } |
| } |
| |
| private synchronized void init() throws CoreException { |
| if (m_status == SwtEnvironmentEvent.STARTING |
| || m_status == SwtEnvironmentEvent.STARTED |
| || m_status == SwtEnvironmentEvent.STOPPING) { |
| return; |
| } |
| m_status = SwtEnvironmentEvent.INACTIVE; |
| // must be called in display thread |
| if (Thread.currentThread() != getDisplay().getThread()) { |
| throw new IllegalStateException("must be called in display thread"); |
| } |
| // workbench must exist |
| if (PlatformUI.getWorkbench().getActiveWorkbenchWindow() == null) { |
| throw new IllegalStateException("workbench must be active"); |
| } |
| |
| try { |
| m_status = SwtEnvironmentEvent.STARTING; |
| m_clipboard = new Clipboard(getDisplay()); |
| fireEnvironmentChanged(new SwtEnvironmentEvent(this, m_status)); |
| |
| IClientSession tempClientSession = createAndStartClientSession(); |
| if (!tempClientSession.isActive()) { |
| showClientSessionLoadError(tempClientSession.getLoadError()); |
| LOG.error("ClientSession is not active, there must be a problem with loading or starting"); |
| m_status = SwtEnvironmentEvent.INACTIVE; |
| return; |
| } |
| else { |
| m_clientSession = tempClientSession; |
| } |
| m_desktop = m_clientSession.getDesktop(); |
| SwtUtility.setNlsTextsOnDisplay(getDisplay(), m_clientSession.getTexts()); |
| if (m_synchronizer == null) { |
| m_synchronizer = new SwtScoutSynchronizer(this); |
| } |
| // |
| m_iconLocator = createIconLocator(); |
| m_colorFactory = new ColorFactory(getDisplay()); |
| m_keyStrokeManager = new KeyStrokeManager(this); |
| m_fontRegistry = new FontRegistry(getDisplay()); |
| attachScoutListeners(); |
| attachSWTListeners(); |
| IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); |
| if (activePage != null) { |
| IPerspectiveDescriptor activePerspective = activePage.getPerspective(); |
| if (activePerspective != null) { |
| String perspectiveId = activePerspective.getId(); |
| if (handlePerspectiveOpened(perspectiveId)) { |
| handlePerspectiveActivated(perspectiveId); |
| } |
| } |
| } |
| // desktop keystokes |
| for (IKeyStroke scoutKeyStroke : getClientSession().getDesktop().getKeyStrokes()) { |
| ISwtKeyStroke[] swtStrokes = SwtUtility.getKeyStrokes(scoutKeyStroke, this); |
| for (ISwtKeyStroke swtStroke : swtStrokes) { |
| m_desktopKeyStrokes.add(swtStroke); |
| addGlobalKeyStroke(swtStroke); |
| } |
| } |
| |
| // developmentKeyStroke |
| initGlobalKeyStrokes(); |
| // environment shutdownhook |
| m_workbenchListener = new P_WorkbenchListener(); |
| PlatformUI.getWorkbench().addWorkbenchListener(m_workbenchListener); |
| |
| // notify ui available |
| Runnable job = new Runnable() { |
| @Override |
| public void run() { |
| getScoutDesktop().getUIFacade().fireDesktopOpenedFromUI(); |
| } |
| }; |
| invokeScoutLater(job, 0); |
| |
| // init scout props |
| updateWindowTitle(); |
| updateStatusFromScout(); |
| |
| m_status = SwtEnvironmentEvent.STARTED; |
| fireEnvironmentChanged(new SwtEnvironmentEvent(this, m_status)); |
| attachBusyHandler(); |
| } |
| finally { |
| if (m_status == SwtEnvironmentEvent.STARTING) { |
| m_status = SwtEnvironmentEvent.STOPPED; |
| fireEnvironmentChanged(new SwtEnvironmentEvent(this, m_status)); |
| } |
| } |
| } |
| |
| protected void initGlobalKeyStrokes() { |
| if (Platform.inDevelopmentMode()) { |
| addGlobalKeyStroke(new ISwtKeyStroke() { |
| |
| @Override |
| public void handleSwtAction(Event e) { |
| new LogicalGridLayoutSpy(getDisplay().getActiveShell()).activate(); |
| |
| } |
| |
| @Override |
| public int getStateMask() { |
| return SWT.ALT | SWT.SHIFT; |
| } |
| |
| @Override |
| public int getKeyCode() { |
| return SWT.F2; |
| } |
| }); |
| } |
| } |
| |
| /** |
| * Creates and starts a new client session. <br/> |
| * This is done in a separate thread to make sure that no client code is |
| * running in the ui thread. |
| */ |
| private IClientSession createAndStartClientSession() { |
| final IHolder<IClientSession> holder = new Holder<IClientSession>(IClientSession.class); |
| JobEx job = new JobEx("Creating and starting client session") { |
| |
| @Override |
| protected IStatus run(IProgressMonitor monitor) { |
| holder.setValue(SERVICES.getService(IClientSessionRegistryService.class).newClientSession(m_clientSessionClass, initUserAgent())); |
| |
| return Status.OK_STATUS; |
| } |
| |
| }; |
| job.schedule(); |
| try { |
| job.join(); |
| } |
| catch (InterruptedException e) { |
| LOG.error("Client session startup interrupted.", e); |
| } |
| |
| return holder.getValue(); |
| } |
| |
| protected UserAgent initUserAgent() { |
| return UserAgent.create(UiLayer.SWT, UiDeviceType.DESKTOP); |
| } |
| |
| protected SwtBusyHandler attachBusyHandler() { |
| IBusyManagerService service = SERVICES.getService(IBusyManagerService.class); |
| if (service == null) { |
| return null; |
| } |
| SwtBusyHandler handler = createBusyHandler(); |
| getDisplay().addListener(SWT.Dispose, new P_BusyHandlerDisposeListener(service)); |
| service.register(getClientSession(), handler); |
| return handler; |
| } |
| |
| private class P_BusyHandlerDisposeListener implements Listener { |
| private IBusyManagerService m_busyManagerService; |
| |
| public P_BusyHandlerDisposeListener(IBusyManagerService busyManagerService) { |
| m_busyManagerService = busyManagerService; |
| } |
| |
| @Override |
| public void handleEvent(Event event) { |
| m_busyManagerService.unregister(getClientSession()); |
| } |
| } |
| |
| protected SwtBusyHandler createBusyHandler() { |
| return new SwtBusyHandler(getClientSession(), this); |
| } |
| |
| protected void showClientSessionLoadError(Throwable error) { |
| ErrorHandler handler = new ErrorHandler(error); |
| MessageBox mbox = new MessageBox(getParentShellIgnoringPopups(SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.MODELESS), SWT.OK); |
| mbox.setText("" + handler.getTitle()); |
| mbox.setMessage(StringUtility.join("\n\n", handler.getText(), handler.getDetail())); |
| mbox.open(); |
| } |
| |
| // hide ScoutViews with no Forms |
| private class P_HideScoutViews implements Runnable { |
| |
| @Override |
| public void run() { |
| IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); |
| if (activePage != null) { |
| for (IViewReference viewReference : activePage.getViewReferences()) { |
| IViewPart view = viewReference.getView(false); |
| if (view != null && view instanceof AbstractScoutView) { |
| if (((AbstractScoutView) view).getForm() == null) { |
| activePage.hideView(viewReference); |
| } |
| } |
| else if (m_scoutPartIdToUiPartId.containsValue(viewReference.getId())) { |
| activePage.hideView(viewReference); |
| } |
| } |
| } |
| } |
| } |
| |
| private void fireGuiAttachedFromUI() { |
| if (getScoutDesktop() != null) { |
| getScoutDesktop().getUIFacade().fireGuiAttached(); |
| } |
| getDisplay().asyncExec(new P_HideScoutViews()); |
| } |
| |
| private void fireGuiDetachedFromUI() { |
| if (getScoutDesktop() != null) { |
| getScoutDesktop().getUIFacade().fireGuiDetached(); |
| } |
| } |
| |
| private void fireDesktopActivatedFromUI() { |
| if (getScoutDesktop() != null) { |
| getScoutDesktop().ensureViewStackVisible(); |
| } |
| } |
| |
| @Override |
| public String styleHtmlText(ISwtScoutFormField<?> uiComposite, String rawHtml) { |
| String cleanHtml = rawHtml; |
| if (cleanHtml == null) { |
| cleanHtml = ""; |
| } |
| |
| if (uiComposite.getScoutObject() instanceof IHtmlField) { |
| IHtmlField htmlField = (IHtmlField) uiComposite.getScoutObject(); |
| if (htmlField.isHtmlEditor()) { |
| /* |
| * In HTML editor mode, the HTML is not styled except that an empty HTML skeleton is created in case the given HTML is empty. |
| * In general no extra styling should be applied because the HTML installed in the editor should be the very same as |
| * provided. Otherwise, if the user did some modifications in the HTML source and reloads the HTML in the editor anew, |
| * unwanted auto-corrections would be applied. |
| */ |
| if (!StringUtility.hasText(cleanHtml)) { |
| cleanHtml = "<html><head></head><body></body></html>"; |
| } |
| } |
| else { |
| /* |
| * Because @{link SwtScoutHtmlField} is file based, it is crucial to set the content-type and charset appropriately. |
| * Also, the CSS needs not to be cleaned as the native browser is used. |
| */ |
| cleanHtml = HTMLUtility.cleanupHtml(cleanHtml, true, false, createDefaultFontSettings(uiComposite.getSwtField())); |
| } |
| } |
| return cleanHtml; |
| } |
| |
| /** |
| * Get SWT specific default font settings |
| */ |
| protected DefaultFont createDefaultFontSettings(Control control) { |
| DefaultFont defaultFont = new DefaultFont(); |
| defaultFont.setSize(8); |
| defaultFont.setSizeUnit("pt"); |
| defaultFont.setForegroundColor(0x000000); |
| defaultFont.setFamilies(new String[]{"sans-serif"}); |
| |
| if (control != null) { |
| FontData[] fontData = control.getFont().getFontData(); |
| if (fontData != null && fontData.length > 0) { |
| int height = fontData[0].getHeight(); |
| if (height > 0) { |
| defaultFont.setSize(height); |
| } |
| String fontFamily = fontData[0].getName(); |
| if (StringUtility.hasText(fontFamily)) { |
| defaultFont.setFamilies(new String[]{fontFamily, "sans-serif"}); |
| } |
| } |
| Color color = control.getForeground(); |
| if (color != null) { |
| defaultFont.setForegroundColor(color.getRed() * 0x10000 + color.getGreen() * 0x100 + color.getBlue()); |
| } |
| } |
| return defaultFont; |
| } |
| |
| @Override |
| public void setClipboardText(String text) { |
| m_clipboard.setContents(new Object[]{text}, new Transfer[]{TextTransfer.getInstance()}); |
| } |
| |
| @Override |
| public void addPropertyChangeListener(PropertyChangeListener listener) { |
| m_propertySupport.addPropertyChangeListener(listener); |
| } |
| |
| @Override |
| public void removePropertyChangeListener(PropertyChangeListener listener) { |
| m_propertySupport.removePropertyChangeListener(listener); |
| } |
| |
| @Override |
| public final void addEnvironmentListener(ISwtEnvironmentListener listener) { |
| m_environmentListeners.add(ISwtEnvironmentListener.class, listener); |
| } |
| |
| @Override |
| public final void removeEnvironmentListener(ISwtEnvironmentListener listener) { |
| m_environmentListeners.remove(ISwtEnvironmentListener.class, listener); |
| } |
| |
| private void fireEnvironmentChanged(SwtEnvironmentEvent event) { |
| for (ISwtEnvironmentListener l : m_environmentListeners.getListeners(ISwtEnvironmentListener.class)) { |
| l.environmentChanged(event); |
| } |
| } |
| |
| // icon handling |
| |
| @Override |
| public Image getIcon(String name) { |
| return getIcon(name, ICON_DECORATION_NONE); |
| } |
| |
| @Override |
| public Image getIcon(String name, int iconDecoration) { |
| return m_iconLocator.getIcon(name, iconDecoration); |
| } |
| |
| @Override |
| public ImageDescriptor getImageDescriptor(String iconId) { |
| return m_iconLocator.getImageDescriptor(iconId); |
| } |
| |
| // key stoke handling |
| @Override |
| public void addGlobalKeyStroke(ISwtKeyStroke stroke) { |
| m_keyStrokeManager.addGlobalKeyStroke(stroke); |
| } |
| |
| @Override |
| public boolean removeGlobalKeyStroke(ISwtKeyStroke stroke) { |
| return m_keyStrokeManager.removeGlobalKeyStroke(stroke); |
| } |
| |
| @Override |
| public void addKeyStroke(Widget widget, ISwtKeyStroke stoke) { |
| m_keyStrokeManager.addKeyStroke(widget, stoke); |
| } |
| |
| @Override |
| public boolean removeKeyStroke(Widget widget, ISwtKeyStroke stoke) { |
| return m_keyStrokeManager.removeKeyStroke(widget, stoke); |
| } |
| |
| @Override |
| public void addKeyStrokeFilter(Widget c, ISwtKeyStrokeFilter filter) { |
| m_keyStrokeManager.addKeyStrokeFilter(c, filter); |
| } |
| |
| @Override |
| public boolean removeKeyStrokeFilter(Widget c, ISwtKeyStrokeFilter filter) { |
| return m_keyStrokeManager.removeKeyStrokeFilter(c, filter); |
| } |
| |
| // color handling |
| @Override |
| public Color getColor(String scoutColor) { |
| return m_colorFactory.getColor(scoutColor); |
| } |
| |
| @Override |
| public Color getColor(RGB rgb) { |
| return m_colorFactory.getColor(rgb); |
| } |
| |
| // font handling |
| @Override |
| public Font getFont(FontSpec scoutFont, Font templateFont) { |
| return m_fontRegistry.getFont(scoutFont, templateFont); |
| } |
| |
| @Override |
| public Font getFont(Font templateFont, String newName, Integer newStyle, Integer newSize) { |
| return m_fontRegistry.getFont(templateFont, newName, newStyle, newSize); |
| } |
| |
| // form toolkit handling |
| @Override |
| public ScoutFormToolkit getFormToolkit() { |
| if (m_formToolkit == null) { |
| m_formToolkit = createScoutFormToolkit(getDisplay()); |
| } |
| return m_formToolkit; |
| } |
| |
| // desktop handling |
| @Override |
| public final IDesktop getScoutDesktop() { |
| return m_desktop; |
| } |
| |
| protected void attachScoutListeners() { |
| if (m_scoutDesktopListener == null) { |
| m_scoutDesktopListener = new P_ScoutDesktopListener(); |
| getScoutDesktop().addDesktopListener(m_scoutDesktopListener); |
| } |
| if (m_desktopPropertyListener == null) { |
| m_desktopPropertyListener = new P_ScoutDesktopPropertyListener(); |
| getScoutDesktop().addPropertyChangeListener(m_desktopPropertyListener); |
| } |
| } |
| |
| protected void detachScoutListeners() { |
| IDesktop desktop = getScoutDesktop(); |
| if (desktop == null) { |
| LOG.warn("Desktop is null, cannot remove listeners."); |
| return; |
| } |
| |
| if (m_scoutDesktopListener != null) { |
| desktop.removeDesktopListener(m_scoutDesktopListener); |
| m_scoutDesktopListener = null; |
| } |
| if (m_desktopPropertyListener != null) { |
| desktop.removePropertyChangeListener(m_desktopPropertyListener); |
| m_desktopPropertyListener = null; |
| } |
| } |
| |
| protected void attachSWTListeners() { |
| if (m_perspectiveListener == null) { |
| m_perspectiveListener = new P_PerspectiveListener(); |
| PlatformUI.getWorkbench().getActiveWorkbenchWindow().addPerspectiveListener(m_perspectiveListener); |
| } |
| } |
| |
| protected void detachSWTListeners() { |
| if (m_perspectiveListener != null && PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null) { |
| PlatformUI.getWorkbench().getActiveWorkbenchWindow().removePerspectiveListener(m_perspectiveListener); |
| m_perspectiveListener = null; |
| } |
| } |
| |
| protected void applyScoutState() { |
| IDesktop desktop = getScoutDesktop(); |
| // load state of internal frames and dialogs |
| for (IForm form : desktop.getViewStack()) { |
| if (form.isAutoAddRemoveOnDesktop()) { |
| showStandaloneForm(form); |
| } |
| } |
| //tray icon |
| if (desktop.isTrayVisible()) { |
| m_trayComposite = createTray(desktop); |
| } |
| // dialogs |
| for (IForm dialog : desktop.getDialogStack()) { |
| showStandaloneForm(dialog); |
| } |
| for (IMessageBox messageBoxe : desktop.getMessageBoxStack()) { |
| showMessageBoxFromScout(messageBoxe); |
| } |
| } |
| |
| public IForm findActiveForm() { |
| Shell activeShell = getDisplay().getActiveShell(); |
| if (activeShell == null) { |
| return null; |
| } |
| |
| Object data = activeShell.getData(); |
| if (data instanceof ISwtScoutPart) { |
| return ((ISwtScoutPart) data).getForm(); |
| } |
| else if (data instanceof IWorkbenchWindow) { |
| IWorkbenchPage activePage = ((IWorkbenchWindow) data).getActivePage(); |
| if (activePage == null) { |
| return null; |
| } |
| |
| IWorkbenchPart activePart = activePage.getActivePart(); |
| if (activePart instanceof ISwtScoutPart) { |
| return ((ISwtScoutPart) activePart).getForm(); |
| } |
| } |
| return null; |
| } |
| |
| public IFormField findFocusOwnerField() { |
| Control comp = getDisplay().getFocusControl(); |
| while (comp != null) { |
| Object o = comp.getData(ISwtScoutFormField.CLIENT_PROPERTY_SCOUT_OBJECT); |
| if (o instanceof IFormField) { |
| return (IFormField) o; |
| } |
| // next |
| comp = comp.getParent(); |
| } |
| return null; |
| } |
| |
| @Override |
| public void showFileChooserFromScout(IFileChooser fileChooser) { |
| SwtScoutFileChooser sfc = new SwtScoutFileChooser(getParentShellIgnoringPopups(SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.MODELESS), fileChooser, this); |
| sfc.showFileChooser(); |
| } |
| |
| private final HashMap<IMessageBox, SwtScoutMessageBoxDialog> m_openMessageBoxes = new HashMap<>(); |
| |
| @Override |
| public void showMessageBoxFromScout(IMessageBox messageBox) { |
| SwtScoutMessageBoxDialog box = m_openMessageBoxes.get(messageBox); |
| if (box == null) { |
| box = new SwtScoutMessageBoxDialog(getParentShellIgnoringPopups(SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.MODELESS), messageBox, this); |
| box.open(); |
| m_openMessageBoxes.put(messageBox, box); |
| } |
| } |
| |
| public void removeMessageBoxFromScout(IMessageBox messageBox) { |
| m_openMessageBoxes.remove(messageBox); |
| } |
| |
| @Override |
| public void ensureStandaloneFormVisible(IForm form) { |
| ISwtScoutPart part = m_openForms.get(form); |
| if (part != null) { |
| part.activate(); |
| } |
| } |
| |
| private Map<String, List<IForm>> openLater = new HashMap<String, List<IForm>>(); |
| |
| @Override |
| public void showStandaloneForm(final IForm form) { |
| if (form == null) { |
| return; |
| } |
| ISwtScoutPart part = m_openForms.get(form); |
| if (part != null) { |
| return; |
| } |
| switch (form.getDisplayHint()) { |
| case IForm.DISPLAY_HINT_DIALOG: { |
| int dialogStyle = SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | (form.isModal() ? SWT.APPLICATION_MODAL : SWT.MODELESS | SWT.MIN); |
| Shell parentShell; |
| if (form.isModal()) { |
| parentShell = getParentShellIgnoringPopups(SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.MODELESS); |
| } |
| else { |
| parentShell = getParentShellIgnoringPopups(SWT.MODELESS); |
| } |
| SwtScoutDialog dialog = createSwtScoutDialog(parentShell, dialogStyle); |
| try { |
| m_openForms.put(form, dialog); |
| dialog.showForm(form); |
| part = dialog; |
| } |
| catch (ProcessingException e) { |
| LOG.error(e.getMessage(), e); |
| } |
| break; |
| } |
| case IForm.DISPLAY_HINT_POPUP_DIALOG: { |
| int dialogStyle = SWT.RESIZE | (form.isModal() ? SWT.APPLICATION_MODAL : SWT.MODELESS); |
| Shell parentShell; |
| if (form.isModal()) { |
| parentShell = getParentShellIgnoringPopups(SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.MODELESS); |
| } |
| else { |
| parentShell = getParentShellIgnoringPopups(0); |
| } |
| SwtScoutDialog popupDialog = createSwtScoutPopupDialog(parentShell, dialogStyle); |
| if (popupDialog == null) { |
| LOG.error("showing popup for " + form + ", but there is neither a focus owner nor the property 'ISwtEnvironment.getPopupOwner()'"); |
| return; |
| } |
| try { |
| m_openForms.put(form, popupDialog); |
| popupDialog.showForm(form); |
| part = popupDialog; |
| } |
| catch (Throwable t) { |
| LOG.error(t.getMessage(), t); |
| } |
| break; |
| } |
| case IForm.DISPLAY_HINT_VIEW: { |
| String scoutViewId = form.getDisplayViewId(); |
| if (scoutViewId == null) { |
| LOG.error("The property displayViewId must not be null if the property displayHint is set to IForm.DISPLAY_HINT_VIEW."); |
| return; |
| } |
| |
| String uiViewId = getSwtPartIdForScoutPartId(scoutViewId); |
| if (uiViewId == null) { |
| LOG.warn("no view defined for scoutViewId: " + form.getDisplayViewId()); |
| return; |
| } |
| IViewPart existingView = findViewPart(uiViewId); |
| |
| String formPerspectiveId = form.getPerspectiveId(); |
| if (formPerspectiveId == null) { |
| formPerspectiveId = ""; |
| } |
| IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); |
| //open form if formPerspectiveId is empty |
| // OR if currentPerspectiveId equals perspecitveId set on form |
| if (StringUtility.hasText(formPerspectiveId) |
| && existingView == null |
| && activePage != null |
| && CompareUtility.notEquals(activePage.getPerspective().getId(), formPerspectiveId)) { |
| |
| synchronized (openLater) { |
| if (!openLater.containsKey(formPerspectiveId) || !openLater.get(formPerspectiveId).contains(form)) { |
| if (openLater.get(formPerspectiveId) == null) { |
| openLater.put(formPerspectiveId, new ArrayList<IForm>()); |
| } |
| openLater.get(formPerspectiveId).add(form); |
| } |
| } |
| return; |
| } |
| |
| //Check if an editor or a view should be opened. |
| //An editor is opened if the scoutViewId starts with IForm.EDITOR_ID or IWizard.EDITOR_ID. |
| //Compared to equals the check with startsWith enables the possibility to link different editors with the forms. |
| if (scoutViewId.startsWith(IForm.EDITOR_ID) || scoutViewId.startsWith(IWizard.EDITOR_ID)) { |
| if (activePage != null) { |
| ScoutFormEditorInput editorInput = new ScoutFormEditorInput(form, this); |
| part = getEditorPart(editorInput, uiViewId); |
| m_openForms.put(form, part); |
| } |
| } |
| else { |
| AbstractScoutView viewPart = getViewPart(uiViewId); |
| try { |
| viewPart.showForm(form); |
| part = viewPart; |
| m_openForms.put(form, viewPart); |
| // activate first view |
| IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); |
| if (page != null && page.getActivePart() == null) { |
| page.activate(viewPart); |
| } |
| } |
| catch (ProcessingException e) { |
| LOG.error(e.getMessage(), e); |
| } |
| } |
| break; |
| } |
| case IForm.DISPLAY_HINT_POPUP_WINDOW: { |
| SwtScoutPopup popupWindow = createSwtScoutPopupWindow(); |
| if (popupWindow == null) { |
| LOG.error("showing popup for " + form + ", but there is neither a focus owner nor the property 'ISwtEnvironment.getPopupOwner()'"); |
| return; |
| } |
| try { |
| m_openForms.put(form, popupWindow); |
| popupWindow.showForm(form); |
| part = popupWindow; |
| } |
| catch (Throwable e1) { |
| LOG.error("Failed opening popup for " + form, e1); |
| try { |
| popupWindow.showForm(form); |
| } |
| catch (Throwable t) { |
| LOG.error(t.getMessage(), t); |
| } |
| } |
| break; |
| } |
| } |
| } |
| |
| protected SwtScoutDialog createSwtScoutDialog(Shell shell, int dialogStyle) { |
| return new SwtScoutDialog(shell, this, dialogStyle); |
| } |
| |
| protected SwtScoutDialog createSwtScoutPopupDialog(Shell shell, int dialogStyle) { |
| Control owner = getPopupOwner(); |
| if (owner == null) { |
| owner = getDisplay().getFocusControl(); |
| } |
| if (owner == null) { |
| return null; |
| } |
| Rectangle ownerBounds = getPopupOwnerBounds(); |
| if (ownerBounds == null) { |
| ownerBounds = owner.getBounds(); |
| Point pDisp = owner.toDisplay(0, 0); |
| ownerBounds.x = pDisp.x; |
| ownerBounds.y = pDisp.y; |
| } |
| SwtScoutDialog dialog = new SwtScoutDialog(shell, this, dialogStyle); |
| dialog.setInitialLocation(new Point(ownerBounds.x, ownerBounds.y + ownerBounds.height)); |
| return dialog; |
| } |
| |
| protected SwtScoutPopup createSwtScoutPopupWindow() { |
| Control owner = getPopupOwner(); |
| if (owner == null) { |
| owner = getDisplay().getFocusControl(); |
| } |
| if (owner == null) { |
| return null; |
| } |
| final SwtScoutPopup popup = new SwtScoutPopup(this, owner, true, SWT.RESIZE); |
| popup.setMaxHeightHint(280); |
| //close popup when PARENT shell is activated or closed |
| owner.getShell().addShellListener(new ShellAdapter() { |
| @Override |
| public void shellClosed(ShellEvent e) { |
| //auto-detach |
| ((Shell) e.getSource()).removeShellListener(this); |
| popup.closePart(); |
| } |
| |
| @Override |
| public void shellActivated(ShellEvent e) { |
| //auto-detach |
| ((Shell) e.getSource()).removeShellListener(this); |
| popup.closePart(); |
| } |
| }); |
| return popup; |
| } |
| |
| @Override |
| public Control getPopupOwner() { |
| return m_popupOwner; |
| } |
| |
| @Override |
| public Rectangle getPopupOwnerBounds() { |
| return m_popupOwnerBounds != null ? new Rectangle(m_popupOwnerBounds.x, m_popupOwnerBounds.y, m_popupOwnerBounds.width, m_popupOwnerBounds.height) : null; |
| } |
| |
| @Override |
| public void setPopupOwner(Control owner, Rectangle ownerBounds) { |
| m_popupOwner = owner; |
| m_popupOwnerBounds = ownerBounds; |
| } |
| |
| @Override |
| public void hideStandaloneForm(IForm form) { |
| if (form == null) { |
| return; |
| } |
| final ISwtScoutPart part = m_openForms.remove(form); |
| if (part != null && part.getForm().equals(form)) { |
| closePart(part); |
| } |
| } |
| |
| private void closePart(ISwtScoutPart part) { |
| try { |
| part.closePart(); |
| } |
| catch (ProcessingException e) { |
| LOG.warn("could not close part.", e); |
| } |
| } |
| |
| protected void handleDesktopPropertyChanged(String propertyName, Object oldVal, Object newValue) { |
| if (IDesktop.PROP_STATUS.equals(propertyName)) { |
| updateStatusFromScout(); |
| } |
| else if (IDesktop.PROP_TITLE.equals(propertyName)) { |
| updateWindowTitle(); |
| } |
| } |
| |
| protected void updateStatusFromScout() { |
| if (getScoutDesktop() != null) { |
| IProcessingStatus newValue = getScoutDesktop().getStatus(); |
| //when a tray item is available, use it, otherwise set status on views/dialogs |
| TrayItem trayItem = null; |
| if (getTrayComposite() != null) { |
| trayItem = getTrayComposite().getSwtTrayItem(); |
| } |
| if (trayItem != null) { |
| String s = newValue != null ? newValue.getMessage() : null; |
| if (newValue != null && s != null) { |
| int iconId; |
| switch (newValue.getSeverity()) { |
| case IProcessingStatus.WARNING: { |
| iconId = SWT.ICON_WARNING; |
| break; |
| } |
| case IProcessingStatus.FATAL: |
| case IProcessingStatus.ERROR: { |
| iconId = SWT.ICON_ERROR; |
| break; |
| } |
| case IProcessingStatus.CANCEL: { |
| iconId = 1 << 8;//SWT.ICON_CANCEL |
| break; |
| } |
| default: { |
| iconId = SWT.ICON_INFORMATION; |
| break; |
| } |
| } |
| ToolTip tip = new ToolTip(getParentShellIgnoringPopups(SWT.MODELESS), SWT.BALLOON | iconId); |
| tip.setMessage(s); |
| trayItem.setToolTip(tip); |
| tip.setVisible(true); |
| } |
| else { |
| ToolTip tip = new ToolTip(getParentShellIgnoringPopups(SWT.MODELESS), SWT.NONE); |
| trayItem.setToolTip(tip); |
| tip.setVisible(true); |
| } |
| } |
| else { |
| String message = null; |
| if (newValue != null) { |
| message = newValue.getMessage(); |
| } |
| setStatusLineMessage(null, message); |
| } |
| } |
| } |
| |
| protected void updateWindowTitle() { |
| if (getScoutDesktop() != null) { |
| final String title = getScoutDesktop().getTitle(); |
| // title is null when the getConfiguredTitle on AbstractDesktop returns null. |
| // If the title is null the product title will be left in the titlebar. |
| if (title == null) { |
| for (IWorkbenchWindow w : PlatformUI.getWorkbench().getWorkbenchWindows()) { |
| final Shell s = w.getShell(); |
| if (!s.isDisposed()) { |
| s.getDisplay().asyncExec(new Runnable() { |
| @Override |
| public void run() { |
| s.setText(title); |
| } |
| }); |
| } |
| } |
| } |
| } |
| } |
| |
| @Override |
| public void setStatusLineMessage(Image image, String message) { |
| for (ISwtScoutPart part : m_openForms.values()) { |
| part.setStatusLineMessage(image, message); |
| } |
| } |
| |
| @Override |
| public Collection<ISwtScoutPart> getOpenFormParts() { |
| return new ArrayList<ISwtScoutPart>(m_openForms.values()); |
| } |
| |
| private class P_ScoutDesktopPropertyListener implements PropertyChangeListener { |
| @Override |
| public void propertyChange(final PropertyChangeEvent evt) { |
| Runnable job = new Runnable() { |
| @Override |
| public void run() { |
| handleDesktopPropertyChanged(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); |
| } |
| }; |
| invokeSwtLater(job); |
| } |
| } // end class P_ScoutDesktopPropertyListener |
| |
| private class P_ScoutDesktopListener implements DesktopListener { |
| @Override |
| public void desktopChanged(final DesktopEvent e) { |
| switch (e.getType()) { |
| case DesktopEvent.TYPE_FORM_ADDED: { |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| showStandaloneForm(e.getForm()); |
| } |
| }; |
| invokeSwtLater(t); |
| break; |
| } |
| case DesktopEvent.TYPE_FORM_REMOVED: { |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| hideStandaloneForm(e.getForm()); |
| } |
| }; |
| invokeSwtLater(t); |
| break; |
| } |
| case DesktopEvent.TYPE_FORM_ENSURE_VISIBLE: { |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| ensureStandaloneFormVisible(e.getForm()); |
| } |
| }; |
| invokeSwtLater(t); |
| break; |
| } |
| case DesktopEvent.TYPE_MESSAGE_BOX_ADDED: { |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| showMessageBoxFromScout(e.getMessageBox()); |
| } |
| }; |
| invokeSwtLater(t); |
| break; |
| } |
| case DesktopEvent.TYPE_MESSAGE_BOX_REMOVED: { |
| |
| break; |
| } |
| case DesktopEvent.TYPE_FILE_CHOOSER_ADDED: { |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| showFileChooserFromScout(e.getFileChooser()); |
| } |
| }; |
| invokeSwtLater(t); |
| break; |
| } |
| case DesktopEvent.TYPE_DESKTOP_CLOSED: { |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| try { |
| stopScout(); |
| } |
| catch (CoreException ex) { |
| LOG.error("desktop closed", ex); |
| } |
| } |
| }; |
| invokeSwtLater(t); |
| break; |
| } |
| case DesktopEvent.TYPE_PRINT: { |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| handleScoutPrintInSwt(e); |
| } |
| }; |
| invokeSwtLater(t); |
| break; |
| } |
| case DesktopEvent.TYPE_TRAVERSE_FOCUS_NEXT: { |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| handleTraverseFocusFromScout(true); |
| } |
| }; |
| invokeSwtLater(t); |
| break; |
| } |
| case DesktopEvent.TYPE_TRAVERSE_FOCUS_PREVIOUS: { |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| handleTraverseFocusFromScout(false); |
| } |
| }; |
| invokeSwtLater(t); |
| break; |
| } |
| case DesktopEvent.TYPE_FIND_FOCUS_OWNER: { |
| final Object lock = new Object(); |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| try { |
| e.setFocusedField(findFocusOwnerField()); |
| } |
| finally { |
| synchronized (lock) { |
| lock.notifyAll(); |
| } |
| } |
| } |
| }; |
| synchronized (lock) { |
| invokeSwtLater(t); |
| try { |
| lock.wait(TimeUnit.SECONDS.toMillis(2)); |
| } |
| catch (InterruptedException e1) { |
| LOG.warn("Interrupted while waiting for the focus owner to be found.", e1); |
| } |
| } |
| break; |
| } |
| case DesktopEvent.TYPE_FIND_ACTIVE_FORM: { |
| final Object lock = new Object(); |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| try { |
| e.setActiveForm(findActiveForm()); |
| } |
| finally { |
| synchronized (lock) { |
| lock.notifyAll(); |
| } |
| } |
| } |
| }; |
| synchronized (lock) { |
| invokeSwtLater(t); |
| try { |
| lock.wait(TimeUnit.SECONDS.toMillis(2)); |
| } |
| catch (InterruptedException e1) { |
| LOG.warn("Interrupted while waiting for the active form to be found.", e1); |
| } |
| } |
| break; |
| } |
| } |
| } |
| } |
| |
| @Override |
| public void postImmediateSwtJob(Runnable r) { |
| synchronized (m_immediateSwtJobsLock) { |
| m_immediateSwtJobs.add(r); |
| } |
| } |
| |
| @Override |
| public void dispatchImmediateSwtJobs() { |
| List<Runnable> list; |
| synchronized (m_immediateSwtJobsLock) { |
| list = new ArrayList<Runnable>(m_immediateSwtJobs); |
| m_immediateSwtJobs.clear(); |
| } |
| for (Runnable r : list) { |
| try { |
| r.run(); |
| } |
| catch (Throwable t) { |
| LOG.warn("running " + r, t); |
| } |
| } |
| } |
| |
| @Override |
| public JobEx invokeScoutLater(Runnable job, long cancelTimeout) { |
| synchronized (m_immediateSwtJobsLock) { |
| m_immediateSwtJobs.clear(); |
| } |
| if (m_synchronizer != null) { |
| return m_synchronizer.invokeScoutLater(job, cancelTimeout); |
| } |
| else { |
| LOG.warn("synchronizer is null; clientSession did not start"); |
| return null; |
| } |
| } |
| |
| @Override |
| public void invokeSwtLater(Runnable job) { |
| if (m_synchronizer != null) { |
| m_synchronizer.invokeSwtLater(job); |
| } |
| else { |
| LOG.warn("synchronizer is null; clientSession did not start"); |
| } |
| } |
| |
| @Override |
| public Display getDisplay() { |
| if (PlatformUI.isWorkbenchRunning()) { |
| return PlatformUI.getWorkbench().getDisplay(); |
| } |
| else { |
| LOG.warn("Workbench is not yet started, accessing the display is unusual: " + new Exception().getStackTrace()[1]); |
| Display display = Display.getCurrent(); |
| if (display == null) { |
| display = Display.getDefault(); |
| } |
| return display; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public Shell getParentShellIgnoringPopups(int modalities) { |
| return SwtUtility.getParentShellIgnoringPopups(getDisplay(), modalities); |
| } |
| |
| @Override |
| public IClientSession getClientSession() { |
| return m_clientSession; |
| } |
| |
| // GUI FACTORY |
| |
| protected ISwtIconLocator createIconLocator() { |
| return new SwtIconLocator(getClientSession().getIconLocator()); |
| } |
| |
| protected ScoutFormToolkit createScoutFormToolkit(Display display) { |
| return new ScoutFormToolkit(new FormToolkit(display) { |
| @Override |
| public Form createForm(Composite parent) { |
| Form f = super.createForm(parent); |
| decorateFormHeading(f); |
| return f; |
| } |
| }); |
| } |
| |
| @Override |
| public ISwtScoutTray getTrayComposite() { |
| return m_trayComposite; |
| } |
| |
| protected ISwtScoutTray createTray(IDesktop desktop) { |
| SwtScoutTray ui = new SwtScoutTray(); |
| ui.createField(null, desktop, this); |
| return ui; |
| } |
| |
| @Override |
| public ISwtScoutForm createForm(Composite parent, IForm scoutForm) { |
| SwtScoutForm uiForm = new SwtScoutForm(); |
| uiForm.createField(parent, scoutForm, this); |
| assignWidgetId(scoutForm, uiForm.getSwtField(), uiForm.getSwtContainer()); |
| return uiForm; |
| } |
| |
| protected void assignWidgetId(ITypeWithClassId model, Widget swtField, Widget swtContainer) { |
| if (swtField != null) { |
| assignWidgetId(model, swtField); |
| } |
| else { |
| assignWidgetId(model, swtContainer); |
| } |
| } |
| |
| protected void assignWidgetId(ITypeWithClassId model, Widget widget) { |
| if (isWidgetIdsEnabled() && widget != null) { |
| widget.setData(WIDGET_ID_KEY, model.classId()); |
| } |
| } |
| |
| protected boolean isWidgetIdsEnabled() { |
| return StringUtility.parseBoolean(System.getProperty(PROP_WIDGET_IDS_ENABLED)); |
| } |
| |
| @Override |
| public ISwtScoutFormField createFormField(Composite parent, IFormField model) { |
| if (m_formFieldFactory == null) { |
| m_formFieldFactory = new FormFieldFactory(m_applicationBundle); |
| } |
| ISwtScoutFormField<IFormField> uiField = m_formFieldFactory.createFormField(parent, model, this); |
| assignWidgetId(model, uiField.getSwtField(), uiField.getSwtContainer()); |
| return uiField; |
| } |
| |
| @Override |
| public ISwtScoutMenuItem createMenuItem(Menu uiMenu, IMenu scoutMenu, IActionFilter filter) { |
| SwtScoutMenuItem swtScoutMenuItem = new SwtScoutMenuItem(scoutMenu, uiMenu, filter, this); |
| assignWidgetId(scoutMenu, swtScoutMenuItem.getSwtMenuItem(), swtScoutMenuItem.getParentMenu()); |
| return swtScoutMenuItem; |
| } |
| |
| @Override |
| public void checkThread() { |
| if (!(getDisplay().getThread() == Thread.currentThread())) { |
| throw new IllegalStateException("Must be called in swt thread"); |
| } |
| } |
| |
| private class P_PerspectiveListener extends PerspectiveAdapter { |
| @Override |
| public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) { |
| String perspectiveId = perspective.getId(); |
| if (handlePerspectiveOpened(perspectiveId)) { |
| handlePerspectiveActivated(perspectiveId); |
| } |
| } |
| |
| @Override |
| public void perspectiveDeactivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) { |
| // global keystrokes are bound to a perspective so it is necessary to disable the global keystrokes |
| if (m_perspectiveId.equals(perspective.getId())) { |
| m_keyStrokeManager.setGlobalKeyStrokesActivated(false); |
| } |
| } |
| |
| @Override |
| public void perspectiveClosed(IWorkbenchPage page, IPerspectiveDescriptor perspective) { |
| handlePerspectiveClosed(perspective.getId()); |
| } |
| |
| @Override |
| public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String changeId) { |
| String perspectiveId = perspective.getId(); |
| //If perspective is resetted make sure that scout views are open |
| if (IWorkbenchPage.CHANGE_RESET.equals(changeId)) { |
| handlePerspectiveClosed(perspectiveId); |
| } |
| else if (IWorkbenchPage.CHANGE_RESET_COMPLETE.equals(changeId)) { |
| if (handlePerspectiveOpened(perspectiveId)) { |
| handlePerspectiveActivated(perspectiveId); |
| } |
| } |
| } |
| } |
| |
| private synchronized boolean handlePerspectiveOpened(String perspectiveId) { |
| |
| if (m_perspectiveId.equals(perspectiveId)) { |
| //make sure that the desktop is only started once |
| if (!isStartDesktopCalled()) { |
| final P_PerspecitveOpenedJob j = new P_PerspecitveOpenedJob(getDesktopOpenedTaskText(), getClientSession()); |
| j.schedule(); |
| setStartDesktopCalled(true); |
| } |
| |
| m_keyStrokeManager.setGlobalKeyStrokesActivated(true); |
| |
| return isStartDesktopCalled(); |
| } |
| |
| return false; |
| } |
| |
| private synchronized boolean handlePerspectiveActivated(String perspectiveId) { |
| if (openLater.containsKey(perspectiveId)) { |
| List<IForm> list; |
| synchronized (openLater) { |
| list = openLater.remove(perspectiveId); |
| } |
| for (IForm form : list) { |
| showStandaloneForm(form); |
| } |
| setActivateDesktopCalled(CompareUtility.notEquals(m_perspectiveId, perspectiveId)); |
| } |
| |
| if (m_perspectiveId.equals(perspectiveId) && isStartDesktopCalled()) { |
| //make sure that the desktop is only started once |
| if (!isActivateDesktopCalled()) { |
| final P_PerspectiveActivatedJob j = new P_PerspectiveActivatedJob(getDesktopOpenedTaskText(), getClientSession()); |
| j.schedule(); |
| setActivateDesktopCalled(true); |
| } |
| |
| m_keyStrokeManager.setGlobalKeyStrokesActivated(true); |
| |
| return isActivateDesktopCalled(); |
| } |
| return false; |
| } |
| |
| private synchronized boolean handlePerspectiveClosed(String perspectiveId) { |
| boolean called = false; |
| |
| // make sure that the desktop is only started once |
| if (m_perspectiveId.equals(perspectiveId)) { |
| final P_PerspectiveClosedJob j = new P_PerspectiveClosedJob(getDesktopClosedTaskText(), getClientSession()); |
| j.schedule(); |
| called = true; |
| setStartDesktopCalled(false); |
| setActivateDesktopCalled(false); |
| |
| //global keystrokes are bound to a perspective so it is necessary to disable the global keystrokes |
| m_keyStrokeManager.setGlobalKeyStrokesActivated(false); |
| } |
| |
| return called; |
| } |
| |
| protected void handleTraverseFocusFromScout(boolean forward) { |
| Control comp = getDisplay().getFocusControl(); |
| if (comp != null) { |
| if (forward) { |
| comp.traverse(SWT.TRAVERSE_TAB_NEXT); |
| } |
| else { |
| comp.traverse(SWT.TRAVERSE_TAB_PREVIOUS); |
| } |
| } |
| } |
| |
| protected void handleScoutPrintInSwt(DesktopEvent e) { |
| final WidgetPrinter wp = new WidgetPrinter(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());//getParentShellIgnoringPopups(SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.MODELESS)); |
| try { |
| wp.print(e.getPrintDevice(), e.getPrintParameters()); |
| } |
| catch (Throwable ex) { |
| LOG.error(null, ex); |
| } |
| finally { |
| Runnable r = new Runnable() { |
| @Override |
| public void run() { |
| getScoutDesktop().getUIFacade().fireDesktopPrintedFromUI(wp.getOutputFile()); |
| } |
| }; |
| invokeScoutLater(r, 0); |
| } |
| } |
| |
| protected String getDesktopOpenedTaskText() { |
| return SwtUtility.getNlsText(Display.getCurrent(), "ScoutStarting"); |
| } |
| |
| protected String getDesktopClosedTaskText() { |
| return SwtUtility.getNlsText(Display.getCurrent(), "ScoutStoping"); |
| } |
| |
| private final class P_PerspecitveOpenedJob extends ClientAsyncJob { |
| public P_PerspecitveOpenedJob(String name, IClientSession session) { |
| super(name, session); |
| } |
| |
| @Override |
| protected void runVoid(IProgressMonitor monitor) throws Throwable { |
| getDisplay().syncExec(new Runnable() { |
| @Override |
| public void run() { |
| applyScoutState(); |
| } |
| }); |
| ClientSyncJob clienSyncJob = new ClientSyncJob(getDesktopOpenedTaskText(), super.getClientSession()) { |
| @Override |
| protected void runVoid(IProgressMonitor syncMonitor) throws Throwable { |
| fireGuiAttachedFromUI(); |
| } |
| }; |
| clienSyncJob.schedule(); |
| } |
| } |
| |
| private final class P_PerspectiveActivatedJob extends ClientAsyncJob { |
| public P_PerspectiveActivatedJob(String name, IClientSession session) { |
| super(name, session); |
| } |
| |
| @Override |
| protected void runVoid(IProgressMonitor monitor) throws Throwable { |
| ClientSyncJob clienSyncJob = new ClientSyncJob(getDesktopOpenedTaskText(), super.getClientSession()) { |
| @Override |
| protected void runVoid(IProgressMonitor syncMonitor) throws Throwable { |
| fireDesktopActivatedFromUI(); |
| } |
| }; |
| clienSyncJob.schedule(); |
| } |
| } |
| |
| private final class P_PerspectiveClosedJob extends ClientAsyncJob { |
| public P_PerspectiveClosedJob(String name, IClientSession session) { |
| super(name, session); |
| } |
| |
| @Override |
| protected void runVoid(IProgressMonitor monitor) throws Throwable { |
| ClientSyncJob clienSyncJob = new ClientSyncJob(getDesktopOpenedTaskText(), super.getClientSession()) { |
| @Override |
| protected void runVoid(IProgressMonitor syncMonitor) throws Throwable { |
| fireGuiDetachedFromUI(); |
| } |
| }; |
| clienSyncJob.schedule(); |
| } |
| } |
| |
| private boolean isStartDesktopCalled() { |
| return m_startDesktopCalled; |
| } |
| |
| private void setStartDesktopCalled(boolean startDesktopCalled) { |
| m_startDesktopCalled = startDesktopCalled; |
| } |
| |
| private boolean isActivateDesktopCalled() { |
| return m_activateDesktopCalled; |
| } |
| |
| private void setActivateDesktopCalled(boolean activateDesktopCalled) { |
| m_activateDesktopCalled = activateDesktopCalled; |
| } |
| |
| @Override |
| public String getPerspectiveId() { |
| return m_perspectiveId; |
| } |
| |
| /** |
| * Delegate the shutdown process to the Scout model. The preShutdown process will always |
| * return @code{false}, meaning that there is a veto so that the UI is not allowed to close |
| * the workbench. |
| * If the desktop gets closed in the Scout model (@link{AbstractSwtEnvironment#stopScout()}, this listener |
| * should be removed to avoid recursive calls. |
| */ |
| private class P_WorkbenchListener implements IWorkbenchListener { |
| @Override |
| public boolean preShutdown(IWorkbench workbench, boolean forced) { |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| getScoutDesktop().getUIFacade().fireDesktopClosingFromUI(false); |
| } |
| }; |
| invokeScoutLater(t, 0); |
| return false; |
| } |
| |
| @Override |
| public void postShutdown(IWorkbench workbench) { |
| // nop |
| } |
| } |
| } |