com.extjs.gxt.ui.client.widget.layout.ToolBarLayout.java Source code

Java tutorial

Introduction

Here is the source code for com.extjs.gxt.ui.client.widget.layout.ToolBarLayout.java

Source

/*
 * Sencha GXT 2.3.1 - Sencha for GWT
 * Copyright(c) 2007-2013, Sencha, Inc.
 * licensing@sencha.com
 * 
 * http://www.sencha.com/products/gxt/license/
 */
package com.extjs.gxt.ui.client.widget.layout;

import java.util.ArrayList;
import java.util.List;

import com.extjs.gxt.ui.client.GXT;
import com.extjs.gxt.ui.client.core.El;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MenuEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.util.SafeGxt;
import com.extjs.gxt.ui.client.widget.Component;
import com.extjs.gxt.ui.client.widget.ComponentHelper;
import com.extjs.gxt.ui.client.widget.Container;
import com.extjs.gxt.ui.client.widget.Layout;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.button.ButtonGroup;
import com.extjs.gxt.ui.client.widget.button.SplitButton;
import com.extjs.gxt.ui.client.widget.menu.HeaderMenuItem;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.menu.MenuItem;
import com.extjs.gxt.ui.client.widget.menu.SeparatorMenuItem;
import com.extjs.gxt.ui.client.widget.toolbar.FillToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;

public class ToolBarLayout extends Layout {

    protected Button more;
    protected Menu moreMenu;

    private Listener<ComponentEvent> containerListener;
    private El extrasTr;
    private List<Component> hiddens;
    private boolean lastOverflow = false;
    private int lastWidth = 0;
    private El leftTr;
    private SafeHtml noItemsMenuText = SafeHtmlUtils
            .fromSafeConstant("<div class=\"x-toolbar-no-items\">(None)</div>");
    private El rightTr;
    private int spacing = 0;

    private int triggerWidth = 18;

    public ToolBarLayout() {
        monitorResize = true;
        hiddens = new ArrayList<Component>();
        targetStyleName = "x-toolbar-layout-ct";
    }

    /**
     * Returns the button used when the toolbar has overflow.
     * 
     * @return the button
     */
    public Button getMoreButton() {
        return more;
    }

    /**
     * Returns the no menu item text.
     * 
     * @return the no menu item text
     */
    public SafeHtml getNoItemsMenuText() {
        return noItemsMenuText;
    }

    /**
     * Returns the item spacing.
     * 
     * @return the spacing
     */
    public int getSpacing() {
        return spacing;
    }

    @Override
    public void setContainer(Container<?> ct) {
        if (containerListener == null) {
            containerListener = new Listener<ComponentEvent>() {
                public void handleEvent(ComponentEvent be) {
                    if (be.getType() == Events.Attach && lastOverflow) {
                        ComponentHelper.doAttach(more);
                    } else if (be.getType() == Events.Detach && lastOverflow) {
                        ComponentHelper.doDetach(more);
                    }
                }
            };
        }
        if (this.container != null) {
            this.container.removeListener(Events.Attach, containerListener);
            this.container.removeListener(Events.Detach, containerListener);
        }
        super.setContainer(ct);
        if (this.container != null) {
            this.container.addListener(Events.Attach, containerListener);
            this.container.addListener(Events.Detach, containerListener);
        }
    }

    /**
     * Sets the no menu items text (defaults to '<div
     * class=\"x-toolbar-no-items\">(None)</div>').
     * 
     * @param noItemsMenuText the no menu items text
     */
    public void setNoItemsMenuText(SafeHtml noItemsMenuText) {
        this.noItemsMenuText = noItemsMenuText;
    }

    /**
     * Sets the amount of spacing between items (defaults to 0).
     * 
     * @param spacing the spacing
     */
    public void setSpacing(int spacing) {
        this.spacing = spacing;
    }

    protected void addComponentToMenu(Menu menu, Component c) {
        if (c instanceof SeparatorToolItem) {
            menu.add(new SeparatorMenuItem());
        } else if (c instanceof SplitButton) {
            final SplitButton sb = (SplitButton) c;
            MenuItem item = new MenuItem(sb.getHtml(), sb.getIcon());
            item.setEnabled(c.isEnabled());
            item.setItemId(c.getItemId());
            if (sb.getData("gxt-menutext") != null) {
                item.setText(sb.getData("gxt-menutext").toString());
            }
            if (sb.getMenu() != null) {
                item.setSubMenu(sb.getMenu());
            }
            item.addSelectionListener(new SelectionListener<MenuEvent>() {

                @Override
                public void componentSelected(MenuEvent ce) {
                    ButtonEvent e = new ButtonEvent(sb);
                    e.setEvent(ce.getEvent());
                    sb.fireEvent(Events.Select, e);
                }

            });
            menu.add(item);

        } else if (c instanceof Button) {
            final Button b = (Button) c;
            MenuItem item = new MenuItem(b.getHtml(), b.getIcon());
            item.setItemId(c.getItemId());

            if (b.getData("gxt-menutext") != null) {
                item.setText(b.getData("gxt-menutext").toString());
            }
            if (b.getMenu() != null) {
                item.setHideOnClick(false);
                item.setSubMenu(b.getMenu());
            }
            item.setEnabled(c.isEnabled());
            item.addSelectionListener(new SelectionListener<MenuEvent>() {

                @Override
                public void componentSelected(MenuEvent ce) {
                    ButtonEvent e = new ButtonEvent(b);
                    e.setEvent(ce.getEvent());
                    b.fireEvent(Events.Select, e);
                }

            });
            menu.add(item);
        } else if (c instanceof ButtonGroup) {
            ButtonGroup g = (ButtonGroup) c;
            g.setItemId(c.getItemId());
            menu.add(new SeparatorMenuItem());
            SafeHtml heading = g.getHeadingHtml();
            if (SafeGxt.isNullOrEmpty(heading)) {
                menu.add(new HeaderMenuItem(g.getHeadingHtml()));
            }
            for (Component c2 : g.getItems()) {
                addComponentToMenu(menu, c2);
            }
            menu.add(new SeparatorMenuItem());
        }

        if (menu.getItemCount() > 0) {
            if (menu.getItem(0) instanceof SeparatorMenuItem) {
                menu.remove(menu.getItem(0));
            }
            if (menu.getItemCount() > 0) {
                if (menu.getItem(menu.getItemCount() - 1) instanceof SeparatorMenuItem) {
                    menu.remove(menu.getItem(menu.getItemCount() - 1));
                }
            }
        }
    }

    protected void cleanup(El row) {
        NodeList<Node> cn = row.dom.getChildNodes();
        for (int i = cn.getLength() - 1; i >= 0; i--) {
            Element td = (Element) cn.getItem(i);
            if (!td.hasChildNodes()) {
                row.dom.removeChild(td);
            }
        }
    }

    protected void clearMenu() {
        moreMenu.removeAll();
    }

    protected void fitToSize(El t) {
        if (!((ToolBar) container).isEnableOverflow()) {
            return;
        }
        if (target.getWidth() < 1) {
            return;
        }
        int w = t.getWidth(true);
        int lw = lastWidth;

        lastWidth = w;
        int iw = t.firstChild().getWidth(true);

        int clipWidth = w - triggerWidth;

        if (iw > w || (hiddens != null && hiddens.size() > 0 && w >= lw)) {
            int loopWidth = 0;
            for (Component c : container.getItems()) {
                if (!(c instanceof FillToolItem)) {
                    loopWidth += getComponentWidth(c);
                    if (loopWidth >= clipWidth) {
                        if (!isHidden(c)) {
                            c.setData("gxt-overflow", "true");
                            hideComponent(c);
                        }
                    } else {
                        if (isHidden(c)) {
                            c.setData("gxt-overflow", null);
                            unhideComponent(c);
                        }
                    }
                }
            }
        }
        if (hiddens != null && hiddens.size() > 0) {
            initMore();
            if (!lastOverflow) {
                lastOverflow = true;
            }
        } else if (more != null) {
            ComponentHelper.doDetach(more);
            more.el().removeFromParent();
            if (lastOverflow) {
                lastOverflow = false;
            }
        }
    }

    protected int getComponentWidth(Component c) {
        return (Integer) (c.getData("xtbWidth") != null ? c.getData("xtbWidth") : c.el().getParent().getWidth());
    }

    protected void hideComponent(Component c) {
        c.setData("xtbWidth", c.el().getParent().getWidth());
        c.setData("xtbIsVisible", c.isRendered() && !c.el().isStyleAttribute("display", "none"));
        hiddens.add(c);
        c.hide();
    }

    protected void initMore() {
        if (more == null) {
            moreMenu = new Menu();
            moreMenu.addListener(Events.BeforeShow, new Listener<MenuEvent>() {

                public void handleEvent(MenuEvent be) {
                    clearMenu();
                    for (Component c : container.getItems()) {
                        if (isHidden(c)) {
                            addComponentToMenu(be.getContainer(), c);
                        }
                    }
                    // put something so the menu isn't empty
                    // if no compatible items found
                    if (be.getContainer().getItemCount() == 0) {
                        be.getContainer().add(new HeaderMenuItem(noItemsMenuText));
                    }
                }

            });

            more = new Button();
            more.addStyleName("x-toolbar-more");
            more.setIcon(GXT.IMAGES.toolbar_more());
            more.setMenu(moreMenu);
            ComponentHelper.setParent(container, more);
            if (GXT.isAriaEnabled()) {
                more.setTitle("More items...");
            }
        }
        Element td = insertCell(more, extrasTr, 100);
        if (more.isRendered()) {
            td.appendChild(more.el().dom);
        } else {
            more.render(td);
        }
        if (container.isAttached()) {
            ComponentHelper.doAttach(more);
        }
    }

    protected Element insertCell(Component c, El side, int pos) {
        Element td = DOM.createTD();
        td.setClassName("x-toolbar-cell");
        td.setAttribute("role", "presentation");
        Element point;
        if (pos >= side.dom.getChildNodes().getLength()) {
            point = null;
        } else {
            point = side.getChild(pos) != null ? side.getChild(pos).dom : null;
        }
        side.insertBefore(td, point);
        return td;
    }

    protected boolean isHidden(Component c) {
        return hiddens != null && hiddens.contains(c);
    }

    @Override
    protected void onComponentHide(Component component) {
        super.onComponentHide(component);
        if (component.isRendered()) {
            component.el().getParent().addStyleName(component.getHideMode().value());
        }

    }

    @Override
    protected void onComponentShow(Component component) {
        super.onComponentShow(component);
        if (component.isRendered()) {
            component.el().getParent().removeStyleName(component.getHideMode().value());
        }
    }

    protected void onLayout(Container<?> container, El target) {
        if (leftTr == null) {
            target.insertHtml("beforeEnd",
                    "<table cellspacing=\"0\" class=\"x-toolbar-ct\" role=\"presentation\"><tbody><tr><td class=\"x-toolbar-left\" align=\"left\"><table cellspacing=\"0\" role=\"presentation\"><tbody><tr class=\"x-toolbar-left-row\"></tr></tbody></table></td><td class=\"x-toolbar-right\" align=\"right\"><table cellspacing=\"0\" class=\"x-toolbar-right-ct\" role=\"presentation\"><tbody><tr><td><table cellspacing=\"0\" role=\"presentation\"><tbody><tr class=\"x-toolbar-right-row\" role=\"presentation\"></tr></tbody></table></td><td><table cellspacing=\"0\" role=\"presentation\"><tbody><tr class=\"x-toolbar-extras-row\"></tr></tbody></table></td></tr></tbody></table></td></tr></tbody></table>");
            leftTr = target.child("tr.x-toolbar-left-row");
            rightTr = target.child("tr.x-toolbar-right-row");
            extrasTr = target.child("tr.x-toolbar-extras-row");

            leftTr.dom.setAttribute("role", "presentation");
            rightTr.dom.setAttribute("role", "presentation");
            extrasTr.dom.setAttribute("role", "presentation");
        }
        El side = leftTr;
        int pos = 0;

        for (int i = 0, len = container.getItemCount(); i < len; i++, pos++) {
            Component c = container.getItem(i);
            if (c instanceof FillToolItem) {
                side = rightTr;
                pos = -1;
            } else if (!c.isRendered()) {
                c.render(insertCell(c, side, pos));
                if (i < len - 1) {
                    c.el().setStyleAttribute("marginRight", spacing + "px");
                } else {
                    c.el().setStyleAttribute("marginRight", "0px");
                }
            } else {
                if (!isHidden(c) && !isValidParent(c.el().dom, side.getChildElement(pos))) {
                    Element td = insertCell(c, side, pos);
                    td.appendChild(c.el().dom);
                    if (i < len - 1) {
                        c.el().setStyleAttribute("marginRight", spacing + "px");
                    } else {
                        c.el().setStyleAttribute("marginRight", "0px");
                    }
                }
            }
        }
        // strip extra empty cells
        cleanup(leftTr);
        cleanup(rightTr);
        cleanup(extrasTr);
        fitToSize(target);
    }

    protected void unhideComponent(Component c) {
        if (hiddens.remove(c)) {
            Boolean b = c.getData("xtbIsVisible");
            if (b) {
                c.show();
            }
            c.setData("xtbWidth", null);
            c.setData("xtbIsVisible", null);
        }
    }
}