Java tutorial
/******************************************************************************* * Copyright (c) 2009 EclipseSource and others. 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: * EclipseSource - initial API and implementation *******************************************************************************/ package com.sap.dirigible.ide.ui.rap.managers; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.IMenuCreator; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.internal.provisional.action.CoolBarManager2; import org.eclipse.jface.internal.provisional.action.IToolBarContributionItem; import org.eclipse.rap.rwt.lifecycle.WidgetUtil; import org.eclipse.rap.ui.interactiondesign.layout.ElementBuilder; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; import org.eclipse.swt.widgets.Widget; import org.eclipse.ui.menus.CommandContributionItem; import com.sap.dirigible.ide.ui.rap.builders.CoolbarLayerBuilder; import com.sap.dirigible.ide.ui.rap.builders.DummyBuilder; import com.sap.dirigible.ide.ui.rap.shared.LayoutSetConstants; @SuppressWarnings("restriction") public class CoolBarManager extends CoolBarManager2 { /** * */ private static final long serialVersionUID = 4030411582266976719L; private static final String HEADER_TOOLBAR_VARIANT = "header-toolbar"; //$NON-NLS-1$ private static final String HEADER_OVERFLOW_VARIANT = "header-overflow"; //$NON-NLS-1$ private static final String ACTIVE = "toolbarOverflowActive"; //$NON-NLS-1$ private static final String INACTIVE = "toolbarOverflowInactive"; //$NON-NLS-1$ private static final int WAVE_SPACING = 20; private Composite overflowParent; private Image preservedWave; private ToolBar toolbar; private List<IContributionItem> overflowItems = new ArrayList<IContributionItem>(); private Button overflowOpenButton; private Button overflowCloseButton; private Image newWave; private Composite overflowLayer; private transient ElementBuilder dummyBuilder; private ToolBar overflowToolbar; private ScrolledComposite overflowToolbarParent; private FocusListener focusListener = new FocusAdapter() { /** * */ private static final long serialVersionUID = 2868519802746082967L; public void focusLost(FocusEvent event) { // close the overflow if the toolbar focus is lost closeOverflow(); toggleImages(); } }; /* * Class for accessing a pull down item's menu to set a custom variant. */ private class StylingSelectionAdapter extends SelectionAdapter { /** * */ private static final long serialVersionUID = 7800773962053801640L; private String variant; public StylingSelectionAdapter(final String variant) { this.variant = variant; } @SuppressWarnings("deprecation") private void styleMenuItems(final Menu menu) { MenuItem[] items = menu.getItems(); if (items != null && items.length > 0 && variant != null) { for (int i = 0; i < items.length; i++) { items[i].setData(WidgetUtil.CUSTOM_VARIANT, variant); } } } @SuppressWarnings("deprecation") public void widgetSelected(final SelectionEvent e) { Widget widget = e.widget; if (widget != null && widget instanceof ToolItem && !widget.isDisposed()) { if (widget.getData(WidgetUtil.CUSTOM_VARIANT) != null) { IContributionItem item = (IContributionItem) widget.getData(); if (item instanceof CommandContributionItem) { CommandContributionItem commandItem = (CommandContributionItem) item; MenuManager manager = commandItem.getMenuManager(); if (manager != null) { Menu menu = manager.getMenu(); if (menu != null) { menu.setData(WidgetUtil.CUSTOM_VARIANT, variant); styleMenuItems(menu); } } } else if (item instanceof ActionContributionItem) { ActionContributionItem actionItem = (ActionContributionItem) item; IAction action = actionItem.getAction(); IMenuCreator menuCreator = action.getMenuCreator(); if (menuCreator != null) { Menu menu = menuCreator.getMenu(toolbar); if (menu != null) { menu.setData(WidgetUtil.CUSTOM_VARIANT, variant); styleMenuItems(menu); } } } } } } } public CoolBarManager() { dummyBuilder = new DummyBuilder(null, LayoutSetConstants.SET_ID_COOLBAR); } @SuppressWarnings("deprecation") public Control createControl2(final Composite parent) { toolbar = new ToolBar(parent, SWT.NONE); toolbar.setData(WidgetUtil.CUSTOM_VARIANT, HEADER_TOOLBAR_VARIANT); toolbar.getParent().getParent().addControlListener(new ControlAdapter() { /** * */ private static final long serialVersionUID = 2996664650047931507L; public void controlResized(final ControlEvent e) { // close the overflow and update the ToolBar if the // browser has resized closeOverflow(); update(true); } }); return toolbar; } public Control getControl2() { return toolbar; } public void update(final boolean force) { if ((isDirty() || force) && getControl2() != null) { refresh(); boolean changed = false; /* * Make a list of items including only those items that are visible. * Separators are being removed. Because we use only one Toolbar all * ToolBarContributionItems will be extracted in their IContribution * Items. */ final IContributionItem[] items = getItems(); final List<IContributionItem> visibleItems = new ArrayList<IContributionItem>(items.length); for (int i = 0; i < items.length; i++) { final IContributionItem item = items[i]; if (item.isVisible()) { if (item instanceof IToolBarContributionItem) { IToolBarContributionItem toolbarItem = (IToolBarContributionItem) item; IToolBarManager toolBarManager = toolbarItem.getToolBarManager(); IContributionItem[] toolbarItems = toolBarManager.getItems(); for (int j = 0; j < toolbarItems.length; j++) { final IContributionItem toolItem = toolbarItems[j]; if (toolItem.isVisible() && !toolItem.isSeparator()) { visibleItems.add(toolItem); } } } } } /* * Make a list of ToolItem widgets in the tool bar for which there * is no current visible contribution item. These are the widgets to * be disposed. Dynamic items are also removed. */ ToolItem[] toolItems = toolbar.getItems(); final ArrayList<ToolItem> toolItemsToRemove = new ArrayList<ToolItem>(toolItems.length); for (int i = 0; i < toolItems.length; i++) { final Object data = toolItems[i].getData(); if ((data == null) || (!visibleItems.contains(data)) || ((data instanceof IContributionItem) && ((IContributionItem) data).isDynamic())) { toolItemsToRemove.add(toolItems[i]); } } // Dispose of any items in the list to be removed. for (int i = toolItemsToRemove.size() - 1; i >= 0; i--) { ToolItem toolItem = (ToolItem) toolItemsToRemove.get(i); if (!toolItem.isDisposed()) { Control control = toolItem.getControl(); if (control != null) { toolItem.setControl(null); control.dispose(); } toolItem.dispose(); } } // Add any new items by telling them to fill. toolItems = toolbar.getItems(); IContributionItem sourceItem; IContributionItem destinationItem; int sourceIndex = 0; int destinationIndex = 0; final Iterator<IContributionItem> visibleItemItr = visibleItems.iterator(); while (visibleItemItr.hasNext()) { sourceItem = visibleItemItr.next(); // Retrieve the corresponding contribution item from SWT's // data. if (sourceIndex < toolItems.length) { destinationItem = (IContributionItem) toolItems[sourceIndex].getData(); } else { destinationItem = null; } // The items match if they are equal or both separators. if (destinationItem != null) { if (sourceItem.equals(destinationItem)) { sourceIndex++; destinationIndex++; sourceItem.update(); continue; } else if ((destinationItem.isSeparator()) && (sourceItem.isSeparator())) { toolItems[sourceIndex].setData(sourceItem); sourceIndex++; destinationIndex++; sourceItem.update(); continue; } } // Otherwise, a new item has to be added. final int start = toolbar.getItemCount(); sourceItem.fill(toolbar, destinationIndex); final int newItems = toolbar.getItemCount() - start; // add the selection listener for the styling StylingSelectionAdapter listener = new StylingSelectionAdapter(HEADER_TOOLBAR_VARIANT); for (int i = 0; i < newItems; i++) { ToolItem item = toolbar.getItem(destinationIndex++); item.setData(sourceItem); item.addSelectionListener(listener); } changed = true; } // Remove any old widgets not accounted for. for (int i = toolItems.length - 1; i >= sourceIndex; i--) { final ToolItem item = toolItems[i]; if (!item.isDisposed()) { Control control = item.getControl(); if (control != null) { item.setControl(null); control.dispose(); } item.dispose(); changed = true; } } // Update wrap indices. only needed by a coolbar // updateWrapIndices(); // Update the sizes. for (int i = 0; i < items.length; i++) { IContributionItem item = items[i]; item.update(SIZE); } if (changed) { updateToolbarTabOrder(); } // We are no longer dirty. setDirty(false); styleToolItems(); toolbar.pack(); toolbar.layout(true, true); manageOverflow(); } } /* * This method manages the items which can not be shown in the coolbar * because it is to small. So an overflow will be shown including these * items. */ private void manageOverflow() { int coolbarWidth = toolbar.getParent().getSize().x - WAVE_SPACING; int childrenLength = toolbar.getItemCount() - 1; overflowItems.clear(); for (int i = childrenLength; i >= 0; i--) { int childrenSize = getChildrenSize(toolbar); if (childrenSize > coolbarWidth) { ToolItem toolItem = toolbar.getItem(i); IContributionItem item = (IContributionItem) toolItem.getData(); addOverflowItem(item); activateOverflowOpenButton(); Control control = toolItem.getControl(); toolItem.setControl(null); if (control != null) { control.dispose(); } toolItem.dispose(); } } // check if the overflow button should be activated or not checkOverflowActivation(); } private void checkOverflowActivation() { // If every item has a representation in the toolbar, the overflow // button // should be invisible if (overflowItems.size() > 0) { activateOverflowOpenButton(); } else { deactivateOverflowButton(); } } private void addOverflowItem(final IContributionItem item) { // add the contrib item to the overflow items if it's not allready in if (!overflowItems.contains(item)) { overflowItems.add(item); } } private void deactivateOverflowButton() { if (overflowOpenButton != null) { overflowOpenButton.setVisible(false); } } /* * This method calculates the size of all children of the coolbar. This is * necessary to compare the correct sizes for the overflow. */ private int getChildrenSize(final ToolBar toolbar) { int result = 0; FormData spacing = dummyBuilder.getPosition(LayoutSetConstants.COOLBAR_SPACING); if (spacing != null) { ToolItem[] items = toolbar.getItems(); for (int i = 0; i < items.length; i++) { result += items[i].getWidth() + spacing.width; } } return result; } /* * Creates and activates the overflow button */ @SuppressWarnings("deprecation") private void activateOverflowOpenButton() { if (overflowParent != null && overflowOpenButton == null) { overflowOpenButton = new Button(overflowParent, SWT.PUSH); overflowOpenButton.setData(WidgetUtil.CUSTOM_VARIANT, INACTIVE); overflowOpenButton.setLayoutData(getOverflowButtonLayoutData()); overflowOpenButton.addSelectionListener(new SelectionAdapter() { /** * */ private static final long serialVersionUID = 2870996000104454996L; public void widgetSelected(final SelectionEvent e) { // open the overflow and toggle the chefron icon createOverflowLayer(); toggleImages(); } }); } overflowOpenButton.setVisible(true); // create the close button if (overflowCloseButton == null) { overflowCloseButton = new Button(overflowParent, SWT.PUSH); overflowCloseButton.setData(WidgetUtil.CUSTOM_VARIANT, ACTIVE); overflowCloseButton.setLayoutData(getOverflowButtonLayoutData()); overflowCloseButton.addSelectionListener(new SelectionAdapter() { /** * */ private static final long serialVersionUID = -234350695524707801L; public void widgetSelected(final SelectionEvent e) { closeOverflow(); toggleImages(); }; }); } overflowCloseButton.setVisible(false); } /* * Change the images, this includes the chefron icon and the wave image */ private void toggleImages() { Image wave = null; if (overflowOpenButton.isVisible()) { // The button was inactive so active it overflowOpenButton.setVisible(false); overflowCloseButton.setVisible(true); wave = newWave; overflowLayer.getParent().setVisible(true); overflowLayer.setFocus(); } else { overflowCloseButton.setVisible(false); overflowOpenButton.setVisible(true); overflowLayer.getParent().setVisible(false); wave = preservedWave; } overflowParent.setBackgroundImage(wave); } private FormData getOverflowButtonLayoutData() { String imageId = LayoutSetConstants.COOLBAR_OVERFLOW_ACTIVE; Image image = dummyBuilder.getImage(imageId); FormData fdOverFlowButton = dummyBuilder.getPosition(LayoutSetConstants.COOLBAR_BUTTON_POS); if (image != null) { fdOverFlowButton.width = image.getBounds().width; fdOverFlowButton.height = image.getBounds().height; } return fdOverFlowButton; } private void createOverflowLayer() { ElementBuilder layerBuilder = new CoolbarLayerBuilder(overflowParent.getParent(), LayoutSetConstants.SET_ID_OVERFLOW); if (overflowLayer == null) { layerBuilder.build(); overflowLayer = (Composite) layerBuilder.getControl(); overflowLayer.addFocusListener(focusListener); newWave = layerBuilder.getImage(LayoutSetConstants.OVERFLOW_WAVE); } Object adapter = layerBuilder.getAdapter(CoolBarManager.class); if (adapter != null) { // position the layer FormData fdLayer = (FormData) overflowLayer.getParent().getLayoutData(); Display display = overflowLayer.getDisplay(); Point location = display.map(overflowOpenButton, null, 20, 0); fdLayer.left = new FormAttachment(0, location.x); fdLayer.top = new FormAttachment(0, 37); overflowParent.getParent().getParent().layout(true); } else { FormData fdParent = (FormData) overflowParent.getLayoutData(); FormData fdLayer = (FormData) overflowLayer.getParent().getLayoutData(); fdLayer.left = fdParent.left; } // fill the vertical overflow toolbar with the overflow items fillOverflowToolbar(); overflowParent.getParent().layout(true); overflowLayer.getParent().moveAbove(null); overflowLayer.getParent().moveBelow(overflowParent); } @SuppressWarnings("deprecation") private void closeOverflow() { if (overflowLayer != null && preservedWave != null) { boolean opened = overflowLayer.getParent().isVisible(); if (opened) { overflowLayer.getParent().setVisible(false); overflowParent.setBackgroundImage(preservedWave); overflowOpenButton.setData(WidgetUtil.CUSTOM_VARIANT, INACTIVE); clearOverflowToolbar(); } } } /* * Dispose all Items in the overflow */ private void clearOverflowToolbar() { if (overflowToolbar != null) { ToolItem[] items = overflowToolbar.getItems(); for (int i = 0; i < items.length; i++) { ToolItem toolItem = items[i]; if (toolItem != null && !toolItem.isDisposed()) { toolItem.setData(null); toolItem.dispose(); } } } } /* * Take all overflow items and fill the vertical overflow toolbar. */ @SuppressWarnings("deprecation") private void fillOverflowToolbar() { if (overflowToolbar == null) { // scrolled toolbar parent overflowToolbarParent = new ScrolledComposite(overflowLayer, SWT.V_SCROLL); DummyBuilder builder = new DummyBuilder(null, LayoutSetConstants.SET_ID_OVERFLOW); FormData pos = builder.getPosition(LayoutSetConstants.OVERFLOW_POS); overflowToolbarParent.setLayoutData(pos); // parent for the toolbar Composite parent = new Composite(overflowToolbarParent, SWT.NONE); parent.setLayout(new FillLayout()); // toolbar overflowToolbar = new ToolBar(parent, SWT.VERTICAL); overflowToolbar.setBackgroundMode(SWT.INHERIT_FORCE); overflowToolbar.setData(WidgetUtil.CUSTOM_VARIANT, HEADER_OVERFLOW_VARIANT); overflowLayer.getParent().addFocusListener(focusListener); // configure the ScrolledComposite overflowToolbarParent.setContent(parent); overflowToolbarParent.setExpandVertical(true); overflowToolbarParent.setExpandHorizontal(true); overflowToolbarParent.setOrigin(0, 0); overflowToolbarParent.setAlwaysShowScrollBars(false); } // clear the old overflow if items exist clearOverflowToolbar(); // fill the toolbar int maxWidth = 0; for (int i = 0; i < overflowItems.size(); i++) { IContributionItem item = overflowItems.get(i); item.fill(overflowToolbar, i); final ToolItem toolItem = overflowToolbar.getItem(i); // add a selection listener for the styling StylingSelectionAdapter listener = new StylingSelectionAdapter(HEADER_OVERFLOW_VARIANT); toolItem.addSelectionListener(listener); toolItem.setData(WidgetUtil.CUSTOM_VARIANT, HEADER_OVERFLOW_VARIANT); if (toolItem.getWidth() > maxWidth) { maxWidth = toolItem.getWidth(); } } // layout the controls overflowLayer.getParent().layout(true, true); overflowLayer.getParent().pack(true); overflowToolbarParent.setMinSize(maxWidth, overflowItems.size() * 25); // bring the scroll position back to it's origin every time the overflow // has opened overflowToolbarParent.setOrigin(0, 0); overflowToolbarParent.layout(); overflowToolbarParent.setFocus(); } @SuppressWarnings("deprecation") private void styleToolItems() { if (toolbar != null) { ToolItem[] items = toolbar.getItems(); for (int i = 0; i < items.length; i++) { ToolItem toolItem = items[i]; final IContributionItem item = (IContributionItem) toolItem.getData(); if (toolItem.getText() == "") { //$NON-NLS-1$ modifyModeForceText(item); } toolItem.setData(WidgetUtil.CUSTOM_VARIANT, HEADER_TOOLBAR_VARIANT); } } } /* * This method changes the modes from ActionContributionItems and * CommandContributionItems to display the text within a ToolItem. */ private void modifyModeForceText(final IContributionItem item) { if (item instanceof ActionContributionItem) { ActionContributionItem actionItem = (ActionContributionItem) item; actionItem.setMode(ActionContributionItem.MODE_FORCE_TEXT); } else if (item instanceof CommandContributionItem) { CommandContributionItem commandItem = (CommandContributionItem) item; commandItem.setMode(CommandContributionItem.MODE_FORCE_TEXT); } } private void updateToolbarTabOrder() { if (toolbar != null) { ToolItem[] items = toolbar.getItems(); if (items != null) { ArrayList<Control> children = new ArrayList<Control>(items.length); for (int i = 0; i < items.length; i++) { if ((items[i].getControl() != null) && (!items[i].getControl().isDisposed())) { children.add(items[i].getControl()); } } // Convert array Control[] childrenArray = new Control[0]; childrenArray = (Control[]) children.toArray(childrenArray); if (childrenArray != null) { toolbar.setTabList(childrenArray); } } } } /* * Method to set the parent for the overflow. This method is called within * the WindowComposers. */ public void setOverflowParent(final Composite overflowParent) { this.overflowParent = overflowParent; preservedWave = overflowParent.getBackgroundImage(); } }