cc.alcina.framework.gwt.client.ide.widget.Toolbar.java Source code

Java tutorial

Introduction

Here is the source code for cc.alcina.framework.gwt.client.ide.widget.Toolbar.java

Source

/* 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package cc.alcina.framework.gwt.client.ide.widget;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.dom.client.Document;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

import cc.alcina.framework.common.client.actions.ActionGroup;
import cc.alcina.framework.common.client.actions.PermissibleAction;
import cc.alcina.framework.common.client.actions.PermissibleAction.HasPermissibleActionChildren;
import cc.alcina.framework.common.client.actions.PermissibleAction.HasPermissibleActionDelegate;
import cc.alcina.framework.common.client.actions.PermissibleAction.PermissibleActionWithDelegate;
import cc.alcina.framework.common.client.actions.PermissibleActionEvent;
import cc.alcina.framework.common.client.actions.PermissibleActionListener;
import cc.alcina.framework.common.client.logic.permissions.Permissible;
import cc.alcina.framework.common.client.logic.permissions.PermissionsManager;
import cc.alcina.framework.common.client.util.CommonUtils;
import cc.alcina.framework.common.client.util.LooseContext;
import cc.alcina.framework.gwt.client.logic.HasHref;
import cc.alcina.framework.gwt.client.stdlayout.image.StandardDataImageProvider;
import cc.alcina.framework.gwt.client.util.RelativePopupPositioning;
import cc.alcina.framework.gwt.client.util.RelativePopupPositioning.RelativePopupAxis;
import cc.alcina.framework.gwt.client.util.WidgetUtils;
import cc.alcina.framework.gwt.client.widget.SpanPanel;
import cc.alcina.framework.gwt.client.widget.StyledAWidget;
import cc.alcina.framework.gwt.client.widget.dialog.RelativePopupPanel;
import cc.alcina.framework.gwt.client.widget.handlers.HasChildHandlers;
import cc.alcina.framework.gwt.client.widget.handlers.HasChildHandlersSupport;

/**
 * 
 * @author Nick Reddel
 */
public class Toolbar extends Composite
        implements PermissibleActionEvent.PermissibleActionSource, ClickHandler, HasChildHandlers {
    public static final String CONTEXT_DO_NOT_REMOVE_LISTENERS_ON_DETACH = Toolbar.class.getName()
            + ".CONTEXT_DO_NOT_REMOVE_LISTENERS_ON_DETACH";

    private List<PermissibleAction> actions;

    private Map<Class<? extends PermissibleAction>, ToolbarButton> actionButtons;

    private FlowPanel panel;

    private PermissibleActionEvent.PermissibleActionSupport vetoableActionSupport;

    private List<ActionGroup> actionGroups;

    private boolean hideUnpermittedActions;

    private boolean asButton;

    private Map<PermissibleAction, ToolbarButton> actionButtonsByAction;

    private HasChildHandlersSupport hasChildHandlersSupport;

    private boolean removeListenersOnDetach = true;

    private String buttonStyleName;

    public Toolbar() {
        this.hasChildHandlersSupport = new HasChildHandlersSupport();
        this.panel = new FlowPanel();
        this.actions = new ArrayList<PermissibleAction>();
        panel.setStyleName("toolbar clearfix");
        this.vetoableActionSupport = new PermissibleActionEvent.PermissibleActionSupport();
        initWidget(panel);
        getElement().setId(Document.get().createUniqueId());
        redraw();
    }

    @Override
    public void addHandler(HandlerRegistration registration) {
        this.hasChildHandlersSupport.addHandler(registration);
    }

    @Override
    public void addVetoableActionListener(PermissibleActionListener listener) {
        this.vetoableActionSupport.addVetoableActionListener(listener);
    }

    @Override
    public void detachHandlers() {
        this.hasChildHandlersSupport.detachHandlers();
    }

    public void enableAll(boolean enable) {
        if (actionButtons == null) {
            return;
        }
        Collection<ToolbarButton> buttons = actionButtonsByAction.values();
        for (ToolbarButton toolbarButton : buttons) {
            toolbarButton.setEnabled(enable);
        }
    }

    public List<ActionGroup> getActionGroups() {
        return actionGroups;
    }

    public List<PermissibleAction> getActions() {
        return this.actions;
    }

    public ToolbarButton getButtonForAction(PermissibleAction action) {
        List<Widget> kids = WidgetUtils.allChildren(panel);
        for (Widget widget : kids) {
            if (widget instanceof ToolbarButton) {
                ToolbarButton tb = (ToolbarButton) widget;
                if (tb.getAction() == action) {
                    return tb;
                }
            }
        }
        return null;
    }

    public String getButtonStyleName() {
        return this.buttonStyleName;
    }

    public FlowPanel getPanel() {
        return this.panel;
    }

    public boolean isAsButton() {
        return asButton;
    }

    public boolean isHideUnpermittedActions() {
        return hideUnpermittedActions;
    }

    public boolean isRemoveListenersOnDetach() {
        return removeListenersOnDetach;
    }

    @Override
    public void onClick(ClickEvent event) {
        Widget sender = (Widget) event.getSource();
        if (sender.getParent() instanceof ToolbarButton) {
            ToolbarButton tb = (ToolbarButton) sender.getParent();
            vetoableActionSupport.fireVetoableActionEvent(new PermissibleActionEvent(sender, tb.getAction()));
        }
    }

    public void processAvailableActions(List<Class<? extends PermissibleAction>> avActions) {
        if (actionButtons == null) {
            return;
        }
        Collection<ToolbarButton> buttons = actionButtons.values();
        for (ToolbarButton toolbarButton : buttons) {
            toolbarButton.setEnabled(false);
        }
        for (Class<? extends PermissibleAction> actionClass : avActions) {
            ToolbarButton tb = actionButtons.get(actionClass);
            if (tb != null) {
                tb.setEnabled(true);
            }
        }
    }

    @Override
    public void removeVetoableActionListener(PermissibleActionListener listener) {
        this.vetoableActionSupport.removeVetoableActionListener(listener);
    }

    public void setActionGroup(ActionGroup actionGroup) {
        setActionGroups(Collections.singletonList(actionGroup));
    }

    public void setActionGroups(List<ActionGroup> actionGroups) {
        this.actionGroups = actionGroups;
        redraw();
    }

    public void setActions(List<PermissibleAction> actions) {
        this.actions = actions;
        redraw();
    }

    public void setAsButton(boolean asButton) {
        this.asButton = asButton;
    }

    public void setButtonStyleName(String buttonStyleName) {
        this.buttonStyleName = buttonStyleName;
    }

    public void setHideUnpermittedActions(boolean hideUnpermittedActions) {
        this.hideUnpermittedActions = hideUnpermittedActions;
    }

    public void setRemoveListenersOnDetach(boolean removeListenersOnDetach) {
        this.removeListenersOnDetach = removeListenersOnDetach;
    }

    @Override
    protected void onDetach() {
        super.onDetach();
        if (removeListenersOnDetach && !LooseContext.getBoolean(CONTEXT_DO_NOT_REMOVE_LISTENERS_ON_DETACH)) {
            vetoableActionSupport.removeAllListeners();
        }
    }

    protected void redraw() {
        WidgetUtils.clearChildren(panel);
        hasChildHandlersSupport.detachHandlers();
        actionButtons = new HashMap<Class<? extends PermissibleAction>, ToolbarButton>();
        actionButtonsByAction = new HashMap<PermissibleAction, ToolbarButton>();
        boolean hasActionGroups = actionGroups != null && actionGroups.size() != 0;
        if (hasActionGroups) {
            actions.removeAll(actions);
            for (ActionGroup g : actionGroups) {
                if (g.actions.isEmpty()) {
                    continue;
                }
                FlowPanel fp = new FlowPanel();
                fp.setStyleName("group");
                if (g.isRightAligned()) {
                    fp.addStyleName("float-right");
                }
                for (PermissibleAction action : g.actions) {
                    ToolbarButton button = new ToolbarButton(action, buttonStyleName, asButton);
                    hasChildHandlersSupport.addHandler(button.addClickHandler(this));
                    fp.add(button);
                    actionButtons.put(action.getClass(), button);
                    actionButtonsByAction.put(action, button);
                    actions.add(action);
                    if (isHideUnpermittedActions() && action instanceof Permissible
                            && !PermissionsManager.get().isPermissible((Permissible) action)) {
                        button.setVisible(false);
                    }
                }
                panel.add(fp);
            }
        } else {
            for (PermissibleAction action : actions) {
                ToolbarButton button = new ToolbarButton(action, buttonStyleName, asButton);
                HandlerRegistration registration = button.addClickHandler(this);
                hasChildHandlersSupport.addHandler(registration);
                panel.add(button);
                actionButtons.put(action.getClass(), button);
                actionButtonsByAction.put(action, button);
                if (isHideUnpermittedActions() && action instanceof Permissible
                        && !PermissionsManager.get().isPermissible((Permissible) action)) {
                    button.setVisible(false);
                }
            }
        }
    }

    public static interface HasDropdownPresenter {
        public Widget presentDropdown();

        public void setPopup(RelativePopupPanel rpp);
    }

    public abstract static class PermissibleActionWithDelegateAndDropdown extends PermissibleActionWithDelegate
            implements HasDropdownPresenter {
        public PermissibleActionWithDelegateAndDropdown(PermissibleAction delegate) {
            super(delegate);
        }
    }

    public static class ToolbarButton extends Composite implements HasClickHandlers {
        private final PermissibleAction action;

        private StyledAWidget aWidget;

        private Button button;

        private final boolean asButton;

        private StyledAWidget dropDown;

        public ToolbarButton(PermissibleAction action) {
            this(action, false);
        }

        public ToolbarButton(PermissibleAction action, boolean asButton) {
            this(action, null, asButton);
        }

        public ToolbarButton(PermissibleAction action, String buttonStyleName, boolean asButton) {
            this.asButton = asButton;
            this.action = action;
            Widget w = null;
            String cn = action.getCssClassName();
            if (asButton) {
                button = new Button(SafeHtmlUtils.htmlEscapeAllowEntities(action.getDisplayName()));
                button.setStyleName(buttonStyleName != null ? buttonStyleName : "alcina-Button");
                w = button;
                if (action instanceof ClickHandler) {
                    button.addClickHandler((ClickHandler) action);
                }
            } else {
                aWidget = new StyledAWidget(action.getDisplayName(), false);
                aWidget.setStyleName(buttonStyleName != null ? buttonStyleName : "button-grey");
                aWidget.setWordWrap(false);
                w = aWidget;
                if (action instanceof ClickHandler) {
                    aWidget.addClickHandler((ClickHandler) action);
                }
                refreshHref();
                if (action instanceof PermissibleActionWithDelegate) {
                    PermissibleAction delegate = ((HasPermissibleActionDelegate) action).getDelegate();
                    if (delegate instanceof ClickHandler) {
                        aWidget.addClickHandler((ClickHandler) delegate);
                    }
                }
                if (action instanceof HasPermissibleActionChildren || action instanceof HasDropdownPresenter) {
                    SpanPanel sp = new SpanPanel();
                    w = sp;
                    sp.add(aWidget);
                    if (cn != null) {
                        aWidget.addStyleName(cn);
                    }
                    aWidget.addStyleName("pre-drop-down");
                    AbstractImagePrototype aip = AbstractImagePrototype
                            .create(StandardDataImageProvider.get().getDataImages().downGrey());
                    dropDown = new StyledAWidget(aip.getHTML(), true);
                    dropDown.addStyleName("button-grey drop-down");
                    sp.add(dropDown);
                    dropDown.addClickHandler(new ClickHandler() {
                        @Override
                        public void onClick(ClickEvent event) {
                            showDropDown();
                        }
                    });
                }
            }
            if (cn != null) {
                w.addStyleName(cn);
            }
            initWidget(w);
        }

        @Override
        public HandlerRegistration addClickHandler(ClickHandler handler) {
            if (asButton) {
                return button.addClickHandler(handler);
            } else {
                return aWidget.addClickHandler(handler);
            }
        }

        public PermissibleAction getAction() {
            return this.action;
        }

        public String getHref() {
            return this.aWidget.getHref();
        }

        public String getTarget() {
            return this.aWidget.getTarget();
        }

        public void refreshHref() {
            if (action instanceof HasHref) {
                setHref(((HasHref) action).getHref());
                setTarget(((HasHref) action).getTarget());
            }
        }

        public void setEnabled(boolean enabled) {
            if (asButton) {
                button.setEnabled(enabled);
            } else {
                aWidget.setEnabled(enabled);
            }
        }

        public void setHref(String href) {
            if (CommonUtils.isNotNullOrEmpty(href)) {
                this.aWidget.setHref(href);
                this.aWidget.setPreventDefault(false);
            }
        }

        public void setTarget(String target) {
            this.aWidget.setTarget(target);
        }

        public void setText(String text) {
            if (asButton) {
                button.setText(text);
            } else {
                aWidget.setText(text);
            }
        }

        public void setWordWrap(boolean wordWrap) {
            if (asButton) {
            } else {
                aWidget.setWordWrap(wordWrap);
            }
        }

        public ToolbarButton withCssClassName(String className) {
            aWidget.setStyleName(className);
            return this;
        }

        protected void showDropDown() {
            Widget dropDown = null;
            if (action instanceof HasDropdownPresenter) {
                dropDown = ((HasDropdownPresenter) action).presentDropdown();
            } else {
                VerticalPanel vp = new VerticalPanel();
                dropDown = vp;
                HasPermissibleActionChildren wKids = (HasPermissibleActionChildren) action;
                for (PermissibleAction a : wKids.getChildren()) {
                    vp.add(new ToolbarButton(a));
                }
            }
            RelativePopupPanel rpp = new RelativePopupPanel(true);
            rpp.setAnimationEnabled(false);
            RelativePopupPositioning.showPopup(getWidget(), dropDown, RootPanel.get(),
                    new RelativePopupAxis[] { RelativePopupPositioning.BOTTOM_LTR }, RootPanel.get(), rpp, -6, 6);
            rpp.setAnimationEnabled(false);
            if (action instanceof HasDropdownPresenter) {
                ((HasDropdownPresenter) action).setPopup(rpp);
            } else {
                rpp.addStyleName("child-actions");
            }
            rpp.addStyleName("toolbar-button-dropdown");
        }
    }
}