| /******************************************************************************* |
| * Copyright (c) 2011 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.rap.window.desktop; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.eclipse.rap.rwt.lifecycle.WidgetUtil; |
| 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.ui.rap.IRwtEnvironment; |
| import org.eclipse.scout.rt.ui.rap.util.BrowserInfo; |
| import org.eclipse.scout.rt.ui.rap.util.RwtUtility; |
| import org.eclipse.scout.rt.ui.rap.window.DefaultFormBoundsProvider; |
| import org.eclipse.scout.rt.ui.rap.window.IFormBoundsProvider; |
| import org.eclipse.scout.rt.ui.rap.window.IRwtScoutPart; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.StackLayout; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.layout.RowData; |
| import org.eclipse.swt.layout.RowLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Listener; |
| |
| /** |
| * @author Andreas Hoegger |
| * @since 3.8.0 |
| */ |
| public class RwtScoutViewStack extends Composite implements IRwtScoutViewStack { |
| private static final long serialVersionUID = 1L; |
| |
| private static final String VARIANT_VIEW_PART = "viewPart"; |
| private static final String VARIANT_VIEW_PART_NO_RADIUS = "viewPartNoRadius"; |
| private static final String VARIANT_VIEW_TAB_AREA = "formTabArea"; |
| |
| private int heightHint = SWT.DEFAULT; |
| private int widthHint = SWT.DEFAULT; |
| private IRwtEnvironment m_uiEnvironment; |
| private HashMap<IForm, RwtScoutDesktopForm> m_openForms; |
| private ArrayList<RwtScoutDesktopForm> m_formStack; |
| private Map<IForm, IFormBoundsProvider> m_formBoundsProviders; |
| private P_DesktopListner m_desktopListener; |
| private Composite m_tabBar; |
| |
| private Composite m_container; |
| |
| public RwtScoutViewStack(Composite parent, IRwtEnvironment uiEnvironment) { |
| super(parent, SWT.NONE); |
| m_uiEnvironment = uiEnvironment; |
| m_openForms = new HashMap<IForm, RwtScoutDesktopForm>(); |
| m_formStack = new ArrayList<RwtScoutDesktopForm>(3); |
| m_formBoundsProviders = new HashMap<IForm, IFormBoundsProvider>(); |
| addListener(SWT.Resize, new P_ResizeListener()); |
| m_desktopListener = new P_DesktopListner(); |
| getUiEnvironment().getScoutDesktop().addDesktopListener(m_desktopListener); |
| setData(WidgetUtil.CUSTOM_VARIANT, getVariant()); |
| createContent(this); |
| } |
| |
| protected String getVariant() { |
| BrowserInfo info = RwtUtility.getBrowserInfo(); |
| if (info != null && info.isMozillaFirefox()) { |
| return VARIANT_VIEW_PART; |
| } |
| else { |
| return VARIANT_VIEW_PART_NO_RADIUS; |
| } |
| } |
| |
| protected void createContent(Composite parent) { |
| if (isTabBarCreationEnabled()) { |
| m_tabBar = getUiEnvironment().getFormToolkit().createComposite(parent); |
| m_tabBar.setData(WidgetUtil.CUSTOM_VARIANT, VARIANT_VIEW_TAB_AREA); |
| } |
| m_container = getUiEnvironment().getFormToolkit().createComposite(parent); |
| |
| // layout |
| GridLayout layout = new GridLayout(1, true); |
| layout.horizontalSpacing = 0; |
| layout.marginHeight = 0; |
| layout.marginTop = 0; |
| layout.marginWidth = 0; |
| layout.verticalSpacing = 0; |
| parent.setLayout(layout); |
| |
| if (m_tabBar != null) { |
| GridData tabBarData = new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL); |
| tabBarData.exclude = false; |
| m_tabBar.setLayoutData(tabBarData); |
| |
| RowLayout tabBarLayout = new RowLayout(); |
| tabBarLayout.marginBottom = 0; |
| tabBarLayout.marginLeft = 0; |
| tabBarLayout.marginTop = 0; |
| m_tabBar.setLayout(tabBarLayout); |
| } |
| |
| GridData containerData = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL); |
| m_container.setLayoutData(containerData); |
| |
| StackLayout containerLayout = new StackLayout(); |
| m_container.setLayout(containerLayout); |
| } |
| |
| @Override |
| public IRwtEnvironment getUiEnvironment() { |
| return m_uiEnvironment; |
| } |
| |
| protected Map<IForm, IFormBoundsProvider> getFormBoundsProviders() { |
| return m_formBoundsProviders; |
| } |
| |
| @Override |
| public IRwtScoutPart addForm(IForm form) { |
| IFormBoundsProvider formBoundsProvider = createFormBoundsProvider(form, getUiEnvironment()); |
| m_formBoundsProviders.put(form, formBoundsProvider); |
| initPreferredSize(formBoundsProvider); |
| |
| RwtScoutDesktopForm ui = createRwtScoutDesktopForm(); |
| ViewStackTabButton button = null; |
| if (m_tabBar != null) { |
| button = new ViewStackTabButton(m_tabBar); |
| button.setLayoutData(new RowData(SWT.DEFAULT, 22)); |
| button.addViewTabListener(new P_ViewTabSelectionListener(ui)); |
| } |
| ui.createPart(this, m_container, button, form, getUiEnvironment()); |
| m_formStack.add(0, ui); |
| m_openForms.put(form, ui); |
| setPartVisibleImpl(form); |
| return ui; |
| } |
| |
| /** |
| * Creates a new instance of {@link RwtScoutDesktopForm}. |
| * <p> |
| * May be overridden to create a custom instance. |
| */ |
| protected RwtScoutDesktopForm createRwtScoutDesktopForm() { |
| return new RwtScoutDesktopForm(); |
| } |
| |
| protected void initPreferredSize(IFormBoundsProvider boundsProvider) { |
| if (boundsProvider == null) { |
| return; |
| } |
| |
| Rectangle formBounds = boundsProvider.getBounds(); |
| if (formBounds != null) { |
| setWidthHint(formBounds.width); |
| setHeightHint(formBounds.height); |
| } |
| else { |
| setWidthHint(-1); |
| setHeightHint(-1); |
| } |
| } |
| |
| protected IFormBoundsProvider createFormBoundsProvider(IForm scoutForm, IRwtEnvironment uiEnvironment) { |
| return new DefaultFormBoundsProvider(scoutForm, uiEnvironment); |
| } |
| |
| @Override |
| public boolean isPartVisible(IRwtScoutPart part) { |
| //resolve |
| part = m_openForms.get(part.getScoutObject()); |
| if (part == null) { |
| return false; |
| } |
| StackLayout stackLayout = (StackLayout) m_container.getLayout(); |
| return RwtUtility.isAncestorOf(stackLayout.topControl, part.getUiContainer()); |
| } |
| |
| @Override |
| public void setPartVisible(IRwtScoutPart part) { |
| //resolve |
| part = m_openForms.get(part.getScoutObject()); |
| if (part == null) { |
| return; |
| } |
| setPartVisibleImpl(part.getScoutObject()); |
| } |
| |
| private void removeForm(IForm form) { |
| RwtScoutDesktopForm uiForm = m_openForms.remove(form); |
| if (uiForm != null) { |
| m_formStack.remove(uiForm); |
| IForm topForm = null; |
| if (m_formStack.size() > 0) { |
| topForm = m_formStack.get(0).getScoutObject(); |
| } |
| setPartVisibleImpl(topForm); |
| } |
| m_formBoundsProviders.remove(form); |
| } |
| |
| protected void setPartVisibleImpl(IForm form) { |
| RwtScoutDesktopForm uiForm = m_openForms.get(form); |
| if (uiForm != null) { |
| StackLayout stackLayout = (StackLayout) m_container.getLayout(); |
| stackLayout.topControl = uiForm.getUiContainer(); |
| if (m_tabBar != null && m_formStack.remove(uiForm)) { |
| GridData tabBarData = (GridData) m_tabBar.getLayoutData(); |
| if (m_formStack.isEmpty()) { |
| m_tabBar.setVisible(false); |
| tabBarData.exclude = true; |
| } |
| else { |
| m_tabBar.setVisible(true); |
| tabBarData.exclude = false; |
| for (RwtScoutDesktopForm f : m_formStack) { |
| f.getTabButton().setActive(false); |
| } |
| uiForm.getTabButton().setActive(true); |
| } |
| m_formStack.add(0, uiForm); |
| } |
| } |
| getParent().layout(true, true); |
| } |
| |
| /** |
| * Controls whether the tab bar should be created at all. May be overridden. |
| * <p> |
| * Default is true. |
| */ |
| protected boolean isTabBarCreationEnabled() { |
| return true; |
| } |
| |
| @Override |
| public boolean getVisible() { |
| return m_container.getChildren().length > 0; |
| } |
| |
| @Override |
| public int getHeightHint() { |
| return heightHint; |
| } |
| |
| @Override |
| public void setHeightHint(int heightHint) { |
| this.heightHint = heightHint; |
| } |
| |
| @Override |
| public int getWidthHint() { |
| return widthHint; |
| } |
| |
| @Override |
| public void setWidthHint(int widthHint) { |
| this.widthHint = widthHint; |
| } |
| |
| private void handleScoutDesktopEvent(DesktopEvent e) { |
| switch (e.getType()) { |
| case DesktopEvent.TYPE_FORM_ENSURE_VISIBLE: |
| setPartVisibleImpl(e.getForm()); |
| break; |
| case DesktopEvent.TYPE_FORM_REMOVED: |
| removeForm(e.getForm()); |
| break; |
| case DesktopEvent.TYPE_DESKTOP_CLOSED: |
| handleDesktopClosed(e.getDesktop()); |
| break; |
| } |
| } |
| |
| private void handleDesktopClosed(IDesktop desktop) { |
| desktop.removeDesktopListener(m_desktopListener); |
| m_desktopListener = null; |
| } |
| |
| private class P_ViewTabSelectionListener implements IViewTabSelectionListener { |
| private final RwtScoutDesktopForm m_form; |
| |
| public P_ViewTabSelectionListener(RwtScoutDesktopForm form) { |
| m_form = form; |
| } |
| |
| @Override |
| public void handleEvent(ViewTabSelectionEvent event) { |
| if (event.getEventType() == ViewTabSelectionEvent.TYPE_VIEW_TAB_SELECTION) { |
| Runnable job = new Runnable() { |
| @Override |
| public void run() { |
| m_form.getScoutObject().getUIFacade().fireFormActivatedFromUI(); |
| } |
| }; |
| getUiEnvironment().invokeScoutLater(job, 0); |
| setPartVisibleImpl(m_form.getScoutObject()); |
| } |
| else if (event.getEventType() == ViewTabSelectionEvent.TYPE_VIEW_TAB_CLOSE_SELECTION) { |
| Runnable job = new Runnable() { |
| @Override |
| public void run() { |
| m_form.getScoutObject().getUIFacade().fireFormClosingFromUI(); |
| } |
| }; |
| getUiEnvironment().invokeScoutLater(job, 0); |
| } |
| |
| } |
| } // end class P_ViewTabSelectionListener |
| |
| private class P_DesktopListner implements DesktopListener { |
| @Override |
| public void desktopChanged(final DesktopEvent e) { |
| if (getUiEnvironment().getDisplay() != null && !getUiEnvironment().getDisplay().isDisposed()) { |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| handleScoutDesktopEvent(e); |
| } |
| }; |
| getUiEnvironment().invokeUiLater(t); |
| } |
| } |
| } |
| |
| private class P_ResizeListener implements Listener { |
| |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| public void handleEvent(Event event) { |
| if (event.type == SWT.Resize) { |
| handleResized(); |
| } |
| } |
| |
| private void handleResized() { |
| if (isDisposed() || m_formBoundsProviders.isEmpty()) { |
| return; |
| } |
| |
| for (IFormBoundsProvider formBoundsProvider : m_formBoundsProviders.values()) { |
| formBoundsProvider.storeBounds(getBounds()); |
| } |
| } |
| |
| } |
| |
| } |