org.eclipse.jface.action.ToolBarManager.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jface.action.ToolBarManager.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *     Andrey Loskutov <loskutov@gmx.de> - Bug 457211
 *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 457214
 *******************************************************************************/
package org.eclipse.jface.action;

import java.util.ArrayList;

import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.accessibility.AccessibleListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.CoolBar;
import org.eclipse.swt.widgets.CoolItem;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;

/**
 * A tool bar manager is a contribution manager which realizes itself and its
 * items in a tool bar control.
 * <p>
 * This class may be instantiated; it may also be subclassed if a more
 * sophisticated layout is required.
 * </p>
 */
public class ToolBarManager extends ContributionManager implements IToolBarManager {

    /**
     * The tool bar items style; <code>SWT.NONE</code> by default.
     */
    private int itemStyle = SWT.NONE;

    /**
     * The tool bar control; <code>null</code> before creation and after
     * disposal.
     */
    private ToolBar toolBar;

    /**
     * The menu manager to the context menu associated with the toolbar.
     *
     * @since 3.0
     */
    private MenuManager contextMenuManager;

    /**
     * Creates a new tool bar manager with the default SWT button style. Use the
     * {@link #createControl(Composite)} method to create the tool bar control.
     */
    public ToolBarManager() {
        //Do nothing if there are no parameters
    }

    /**
     * Creates a tool bar manager with the given SWT button style. Use the
     * <code>createControl</code> method to create the tool bar control.
     *
     * @param style
     *            the tool bar item style
     * @see org.eclipse.swt.widgets.ToolBar for valid style bits
     */
    public ToolBarManager(int style) {
        itemStyle = style;
    }

    /**
     * Creates a tool bar manager for an existing tool bar control. This manager
     * becomes responsible for the control, and will dispose of it when the
     * manager is disposed. <strong>NOTE</strong> When creating a ToolBarManager
     * from an existing {@link ToolBar} you will not get the accessible listener
     * provided by JFace.
     *
     * @see #ToolBarManager()
     * @see #ToolBarManager(int)
     *
     * @param toolbar
     *            the tool bar control
     */
    public ToolBarManager(ToolBar toolbar) {
        this();
        this.toolBar = toolbar;
        if (toolBarExist()) {
            this.itemStyle = toolBar.getStyle();
        }
    }

    /**
     * Sets SWT button style for new tool bar controls created
     * in the {@code createControl(Composite)} method. It does not
     * affect already existing tool bar control.
     *
     * @param style
     *            the tool bar item style
     * @since 3.10
     */
    public void setStyle(int style) {
        itemStyle = style;
    }

    /**
     * Creates and returns this manager's tool bar control. Does not create
     * a new control if one already exists and is not disposed.
     * Also create an {@link AccessibleListener} for the {@link ToolBar}.
     *
     * @param parent
     *            the parent control
     * @return the tool bar control
     */
    public ToolBar createControl(Composite parent) {
        if (!toolBarExist() && parent != null) {
            toolBar = new ToolBar(parent, itemStyle);
            toolBar.setMenu(getContextMenuControl());
            update(true);

            toolBar.getAccessible().addAccessibleListener(getAccessibleListener());
        }

        return toolBar;
    }

    /**
     * Get the accessible listener for the tool bar.
     *
     * @return AccessibleListener
     *
     * @since 3.1
     */
    private AccessibleListener getAccessibleListener() {
        return new AccessibleAdapter() {
            @Override
            public void getName(AccessibleEvent e) {
                if (e.childID != ACC.CHILDID_SELF) {
                    ToolItem item = toolBar.getItem(e.childID);
                    if (item != null) {
                        String toolTip = item.getToolTipText();
                        if (toolTip != null) {
                            e.result = toolTip;
                        }
                    }
                }
            }
        };

    }

    /**
     * Disposes of this tool bar manager and frees all allocated SWT resources.
     * Notifies all contribution items of the dispose. Note that this method
     * does not clean up references between this tool bar manager and its
     * associated contribution items. Use <code>removeAll</code> for that
     * purpose.
     */
    public void dispose() {

        if (toolBarExist()) {
            toolBar.dispose();
        }
        toolBar = null;

        IContributionItem[] items = getItems();
        for (IContributionItem item : items) {
            item.dispose();
        }

        if (getContextMenuManager() != null) {
            getContextMenuManager().dispose();
            setContextMenuManager(null);
        }
    }

    /**
     * Returns the tool bar control for this manager.
     *
     * @return the tool bar control, or <code>null</code> if none (before
     *         creating or after disposal)
     */
    public ToolBar getControl() {
        return toolBar;
    }

    /**
     * Re-lays out the tool bar.
     * <p>
     * The default implementation of this framework method re-lays out the
     * parent when the number of items are different and the new count != 0
     *
     * @param layoutBar
     *            the tool bar control
     * @param oldCount
     *            the old number of items
     * @param newCount
     *            the new number of items
     */
    protected void relayout(ToolBar layoutBar, int oldCount, int newCount) {
        if (oldCount != newCount && newCount != 0) {
            Point beforePack = layoutBar.getSize();
            layoutBar.pack(true);
            Point afterPack = layoutBar.getSize();

            // If the TB didn't change size then we're done
            if (beforePack.equals(afterPack)) {
                return;
            }

            // OK, we need to re-layout the TB
            layoutBar.getParent().layout();

            // Now, if we're in a CoolBar then change the CoolItem size as well
            if (layoutBar.getParent() instanceof CoolBar) {
                CoolBar cb = (CoolBar) layoutBar.getParent();
                CoolItem[] items = cb.getItems();
                for (CoolItem item : items) {
                    if (item.getControl() == layoutBar) {
                        Point curSize = item.getSize();
                        item.setSize(curSize.x + (afterPack.x - beforePack.x),
                                curSize.y + (afterPack.y - beforePack.y));
                        return;
                    }
                }
            }
        }
    }

    /**
     * Returns whether the tool bar control is created and not disposed.
     *
     * @return <code>true</code> if the control is created and not disposed,
     *         <code>false</code> otherwise
     */
    private boolean toolBarExist() {
        return toolBar != null && !toolBar.isDisposed();
    }

    @Override
    public void update(boolean force) {

        if (!isDirty() && !force) {
            return;
        }

        if (!toolBarExist()) {
            return;
        }

        int oldCount = toolBar.getItemCount();

        // clean contains all active items without double separators
        IContributionItem[] items = getItems();
        ArrayList<IContributionItem> clean = new ArrayList<>(items.length);
        IContributionItem separator = null;
        for (IContributionItem ci : items) {
            if (!isChildVisible(ci)) {
                continue;
            }
            if (ci.isSeparator()) {
                // delay creation until necessary (handles both adjacent
                // separators, and separator at end)
                separator = ci;
            } else {
                if (separator != null) {
                    if (clean.size() > 0) {
                        clean.add(separator);
                    }
                    separator = null;
                }
                clean.add(ci);
            }
        }

        // determine obsolete items (removed or non active)
        ToolItem[] mi = toolBar.getItems();
        ArrayList<ToolItem> toRemove = new ArrayList<>(mi.length);
        for (ToolItem item : mi) {
            // there may be null items in a toolbar
            if (item == null) {
                continue;
            }

            Object data = item.getData();
            if (data == null || !clean.contains(data)
                    || (data instanceof IContributionItem && ((IContributionItem) data).isDynamic())) {
                toRemove.add(item);
            }
        }

        try {
            toolBar.setRedraw(false);

            // remove obsolete items
            for (int i = toRemove.size(); --i >= 0;) {
                ToolItem item = toRemove.get(i);
                if (!item.isDisposed()) {
                    Control ctrl = item.getControl();
                    if (ctrl != null) {
                        item.setControl(null);
                        ctrl.dispose();
                    }
                    item.dispose();
                }
            }

            // add new items
            IContributionItem dest;
            mi = toolBar.getItems();
            int srcIx = 0;
            int destIx = 0;
            for (IContributionItem src : clean) {

                // get corresponding item in SWT widget
                if (srcIx < mi.length) {
                    dest = (IContributionItem) mi[srcIx].getData();
                } else {
                    dest = null;
                }

                if (dest != null && src.equals(dest)) {
                    srcIx++;
                    destIx++;
                    continue;
                }

                if (dest != null && dest.isSeparator() && src.isSeparator()) {
                    mi[srcIx].setData(src);
                    srcIx++;
                    destIx++;
                    continue;
                }

                int start = toolBar.getItemCount();
                src.fill(toolBar, destIx);
                int newItems = toolBar.getItemCount() - start;
                for (int i = 0; i < newItems; i++) {
                    ToolItem item = toolBar.getItem(destIx++);
                    item.setData(src);
                }
            }

            // remove any old tool items not accounted for
            for (int i = mi.length; --i >= srcIx;) {
                ToolItem item = mi[i];
                if (!item.isDisposed()) {
                    Control ctrl = item.getControl();
                    if (ctrl != null) {
                        item.setControl(null);
                        ctrl.dispose();
                    }
                    item.dispose();
                }
            }

            setDirty(false);

            // turn redraw back on if we turned it off above
        } finally {
            toolBar.setRedraw(true);
        }

        int newCount = toolBar.getItemCount();

        // If we're forcing a change then ensure that we re-layout
        // everything
        if (force) {
            oldCount = newCount + 1;
        }

        relayout(toolBar, oldCount, newCount);

    }

    /**
     * Returns the control of the Menu Manager. If the menu manager does not
     * have a control then one is created.
     *
     * @return menu widget associated with manager
     */
    private Menu getContextMenuControl() {
        if ((contextMenuManager != null) && (toolBar != null)) {
            Menu menuWidget = contextMenuManager.getMenu();
            if ((menuWidget == null) || (menuWidget.isDisposed())) {
                menuWidget = contextMenuManager.createContextMenu(toolBar);
            }
            return menuWidget;
        }
        return null;
    }

    /**
     * Returns the context menu manager for this tool bar manager.
     *
     * @return the context menu manager, or <code>null</code> if none
     * @since 3.0
     */
    public MenuManager getContextMenuManager() {
        return contextMenuManager;
    }

    /**
     * Sets the context menu manager for this tool bar manager to the given menu
     * manager. If the tool bar control exists, it also adds the menu control to
     * the tool bar.
     *
     * @param contextMenuManager
     *            the context menu manager, or <code>null</code> if none
     * @since 3.0
     */
    public void setContextMenuManager(MenuManager contextMenuManager) {
        this.contextMenuManager = contextMenuManager;
        if (toolBar != null) {
            toolBar.setMenu(getContextMenuControl());
        }
    }

    /**
     * Computes real item visibility considering possibly overridden state from
     * manager
     */
    private boolean isChildVisible(IContributionItem item) {
        IContributionManagerOverrides overrides = getOverrides();
        if (overrides == null) {
            return item.isVisible();
        }
        Boolean v = overrides.getVisible(item);
        return v != null ? v.booleanValue() : item.isVisible();
    }
}