package org.nightlabs.jfire.trade.quicksale.ui; import javax.security.auth.login.LoginException; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IEditorReference; import org.eclipse.ui.IFolderLayout; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.IPerspectiveDescriptor; import org.eclipse.ui.IPerspectiveFactory; import org.eclipse.ui.IPerspectiveListener4; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PerspectiveAdapter; import org.nightlabs.base.ui.editor.Editor2PerspectiveRegistry; import org.nightlabs.base.ui.login.LoginState; import org.nightlabs.base.ui.notification.NotificationAdapterSWTThreadAsync; import org.nightlabs.base.ui.notification.SelectionManager; import org.nightlabs.base.ui.util.RCPUtil; import org.nightlabs.jfire.base.login.ui.Login; import org.nightlabs.jfire.store.ProductType; import org.nightlabs.jfire.trade.ui.TradePlugin; import org.nightlabs.jfire.trade.ui.articlecontainer.detail.ArticleContainerEditorInput; import org.nightlabs.jfire.trade.ui.detail.ProductTypeDetailView; import org.nightlabs.jfire.trade.ui.producttype.quicklist.ProductTypeQuickListView; import org.nightlabs.jfire.trade.ui.transfer.deliver.DeliveryQueueBrowsingView; import org.nightlabs.notification.NotificationEvent; import org.nightlabs.notification.NotificationListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Daniel.Mazurek [at] NightLabs [dot] de */ public class QuickSalePerspective implements IPerspectiveFactory { /** * LOG4J logger used by this class */ private static final Logger logger = LoggerFactory.getLogger(QuickSalePerspective.class); public static final String ID_PERSPECTIVE = QuickSalePerspective.class.getName(); private static boolean perspectiveListenerAdded = false; private static IPerspectiveListener4 quickSalePerspectiveListener = new PerspectiveAdapter() { @Override public void perspectiveActivated(IWorkbenchPage page, final IPerspectiveDescriptor perspective) { logger.info("perspectiveActivated "+perspective.getId()); //$NON-NLS-1$ // perform "checkOrderOpen" in the next event loop cycle, in order to ensure that the perspective switch // is completely finished. Otherwise, the page.getActiveEditor() will still return the last active editor // (from the last page). Marco. Display.getDefault().asyncExec(new Runnable() { public void run() { checkOrderOpen(perspective.getId()); } }); } @Override public void perspectiveOpened(IWorkbenchPage page, IPerspectiveDescriptor perspective) { } }; private static boolean selectionListenerAdded = false; private static NotificationListener selectionListener = new NotificationAdapterSWTThreadAsync() { public void notify(NotificationEvent notificationEvent) { checkOrderOpen(RCPUtil.getActivePerspectiveID()); } }; static { if (Display.getCurrent() == null) { Display.getDefault().asyncExec(new Runnable() { public void run() { checkPerspectiveListenerAdded(); checkSelectionListenerAdded(); } }); } else { checkPerspectiveListenerAdded(); checkSelectionListenerAdded(); } } public void createInitialLayout(IPageLayout layout) { layout.setEditorAreaVisible(true); layout.addView(ProductTypeDetailView.ID_VIEW, IPageLayout.TOP, 0.2f, IPageLayout.ID_EDITOR_AREA); // layout.addView(ProductTypeQuickListView.ID_VIEW, IPageLayout.RIGHT, 0.7f, // IPageLayout.ID_EDITOR_AREA); IFolderLayout folder = layout.createFolder("right_bottom", IPageLayout.RIGHT, 0.7f, IPageLayout.ID_EDITOR_AREA); //$NON-NLS-1$ folder.addView(ProductTypeQuickListView.ID_VIEW); // The DeliveryQueueBrowsingView is not required in the quick sale perspective and doesn't have sufficient space here anyway! // Commented it out. 2008-10-02 Marco. // folder.addView(DeliveryQueueBrowsingView.ID_VIEW); layout.addPerspectiveShortcut(ID_PERSPECTIVE); layout.addShowViewShortcut(ProductTypeDetailView.ID_VIEW); layout.addShowViewShortcut(ProductTypeQuickListView.ID_VIEW); layout.addShowViewShortcut(DeliveryQueueBrowsingView.ID_VIEW); RCPUtil.addAllPerspectiveShortcuts(layout); } private static void openEditor(final ArticleContainerEditorInput editorInput, final boolean editor2Perspective) { if (Display.getCurrent() == null) throw new IllegalStateException("Wrong thread!!! This method must be called on the UI thread!"); //$NON-NLS-1$ try { if (editor2Perspective) { Editor2PerspectiveRegistry.sharedInstance().openEditor(editorInput, ArticleContainerQuickSaleEditor.ID_EDITOR); } else { if (RCPUtil.getActiveWorkbenchPage() != null) RCPUtil.openEditor(editorInput, ArticleContainerQuickSaleEditor.ID_EDITOR); } } catch (Exception x) { throw new RuntimeException(x); } logger.info("openEditor: editor opened for input="+editorInput); //$NON-NLS-1$ } private static void checkPerspectiveListenerAdded() { if (Display.getCurrent() == null) throw new IllegalStateException("Wrong thread!!! This method must be called on the UI thread!"); //$NON-NLS-1$ if (!perspectiveListenerAdded) { try { RCPUtil.getActiveWorkbenchWindow().addPerspectiveListener(quickSalePerspectiveListener); perspectiveListenerAdded = true; logger.info("perspectiveListener added"); //$NON-NLS-1$ } catch (Exception e) { perspectiveListenerAdded = false; logger.error("adding perspectiveListener failed", e); //$NON-NLS-1$ return; } } } /** * This method checks whether there is exactly one editor open in the <code>QuickSalePerspective</code>. If there are multiple * open, all except one will be closed. If there is no editor open, one will be opened. * <p> * This method has no effect, if the passed <code>perspectiveID</code> does not equal the {@link QuickSalePerspective#ID_PERSPECTIVE}. * </p> * * @param perspectiveID The current perspective's ID. If this method is used in a perspective-listener, this identifier is passed to the listener method. * If it is not known in the current context, it can be obtained by {@link RCPUtil#getActivePerspectiveID()}. Note, that you should always use the * identifier passed to your listener instead of the <code>RCPUtil</code>'s method, since during boot-up or transitions the listener's perspective-id * is likely more correct and reliable. */ public static void checkOrderOpen(String perspectiveID) { if (Display.getCurrent() == null) throw new IllegalStateException("Wrong thread!!! This method must be called on the UI thread!"); //$NON-NLS-1$ if (perspectiveID != null && perspectiveID.equals(QuickSalePerspective.ID_PERSPECTIVE)) { final IWorkbenchPage page = RCPUtil.getActiveWorkbenchPage(); // open editor if necessary if (page != null) { IEditorReference[] references = page.getEditorReferences(); if (references.length == 0) { openQuickSaleEditor(); } else { boolean articleContainerFound = false; for (IEditorReference reference : references) { if (ArticleContainerQuickSaleEditor.ID_EDITOR.equals(reference.getId())) { articleContainerFound = true; break; } } if (!articleContainerFound) { openQuickSaleEditor(); } } } // commented because now with reverse product action additional editor can be opened in QuickSalePerspective // if (page != null) { // // close additional editors if more than one is open // IEditorReference[] references = page.getEditorReferences(); // if (references.length > 1) { // IEditorInput activeInput = null; // if (page.getActiveEditor() != null) { // activeInput = page.getActiveEditor().getEditorInput(); // } // for (int i=0; i<references.length; i++) { // IEditorReference reference = references[i]; // String editorID = reference.getId(); // if (!editorID.equals(ArticleContainerQuickSaleEditor.ID_EDITOR)) { // logger.info("Closing editor (because it is no ArticleContainerQuickSaleEditor): editorID=" + editorID); //$NON-NLS-1$ // page.closeEditor(reference.getEditor(false), true); // } // try { // IEditorInput input = reference.getEditorInput(); // if (activeInput != null && !activeInput.equals(input)) { // logger.info("Closing editor (because it is not showing the active one): input=" + input); //$NON-NLS-1$ // page.closeEditor(reference.getEditor(false), true); // } // } catch (PartInitException e) { // logger.error("PartInitException: " + e.getLocalizedMessage(), e); //$NON-NLS-1$ // } // } // } // } } } private static void openQuickSaleEditor() { try { Login.getLogin(); } catch (LoginException e) { throw new RuntimeException(e); } ArticleContainerEditorInput input = ArticleContainerQuickSaleEditorPage.createEditorInput(); if (input != null) { logger.info("Opening QuickSaleEditor: input=" + input); //$NON-NLS-1$ openEditor(input, false); } else logger.warn("Opening QuickSaleEditor not possible, because input is null!"); //$NON-NLS-1$ } private static void checkSelectionListenerAdded() { if (!selectionListenerAdded) { try { if (Login.sharedInstance().getLoginState() == LoginState.LOGGED_IN) { // sometimes causes a ClassNotFoundException for ProductType // when trying to switch open the perspective SelectionManager.sharedInstance().addNotificationListener(TradePlugin.ZONE_SALE, ProductType.class, selectionListener); selectionListenerAdded = true; logger.info("selectionListener added"); //$NON-NLS-1$ } else { selectionListenerAdded = false; logger.info("adding selectionListener failed, because not logined in"); //$NON-NLS-1$ } } catch (Exception e) { selectionListenerAdded = false; logger.info("adding selectionListener failed"); //$NON-NLS-1$ return; } } } }