mat.client.shared.ui.MATTabPanel.java Source code

Java tutorial

Introduction

Here is the source code for mat.client.shared.ui.MATTabPanel.java

Source

package mat.client.shared.ui;

/*
 * Copyright 2008 Google Inc.
 * 
 * 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.
 */

import java.util.Iterator;

import mat.client.Enableable;

import com.google.gwt.event.logical.shared.BeforeSelectionEvent;
import com.google.gwt.event.logical.shared.BeforeSelectionHandler;
import com.google.gwt.event.logical.shared.HasBeforeSelectionHandlers;
import com.google.gwt.event.logical.shared.HasSelectionHandlers;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Accessibility;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DeckPanel;
import com.google.gwt.user.client.ui.HasAnimation;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IndexedPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.SourcesTabEvents;
import com.google.gwt.user.client.ui.TabLayoutPanel;
import com.google.gwt.user.client.ui.TabListener;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * A panel that represents a tabbed set of pages, each of which contains another
 * widget. Its child widgets are shown as the user selects the various tabs
 * associated with them. The tabs can contain arbitrary HTML.
 * 
 * <p>
 * This widget will <em>only</em> work in quirks mode. If your application is in
 * Standards Mode, use {@link TabLayoutPanel} instead.
 * </p>
 * 
 * <p>
 * <img class='gallery' src='doc-files/TabPanel.png'/>
 * </p>
 * 
 * <p>
 * Note that this widget is not a panel per se, but rather a
 * {@link com.google.gwt.user.client.ui.Composite} that aggregates a
 * {@link com.google.gwt.user.client.ui.TabBar} and a
 * {@link com.google.gwt.user.client.ui.DeckPanel}. It does, however, implement
 * {@link com.google.gwt.user.client.ui.HasWidgets}.
 * </p>
 * 
 * <h3>CSS Style Rules</h3> 
 * <ul class='css'> 
 * <li>.gwt-TabPanel { the tab panel itself }</li> 
 * <li>.gwt-TabPanelBottom { the bottom section of the tab panel
 * (the deck containing the widget) }</li> 
 * </ul>
 * 
 * <p>
 * <h3>Example</h3>
 * {@example com.google.gwt.examples.TabPanelExample}
 * </p>
 * 
 * @see TabLayoutPanel
 */

//Cannot do anything about tab panel implementing TabListener until next release.
@SuppressWarnings("deprecation")
public class MATTabPanel extends Composite implements TabListener, SourcesTabEvents, HasWidgets, HasAnimation,
        IndexedPanel, HasBeforeSelectionHandlers<Integer>, HasSelectionHandlers<Integer>, Enableable {
    /**
     * This extension of DeckPanel overrides the public mutator methods to prevent
     * external callers from adding to the state of the DeckPanel.
     * <p>
     * Removal of Widgets is supported so that WidgetCollection.WidgetIterator
     * operates as expected.
     * </p>
     * <p>
     * We ensure that the DeckPanel cannot become of of sync with its associated
     * TabBar by delegating all mutations to the TabBar to this implementation of
     * DeckPanel.
     * </p>
     */
    private static class TabbedDeckPanel extends DeckPanel {

        /** The tab bar. */
        private UnmodifiableTabBar tabBar;

        /**
        * Instantiates a new tabbed deck panel.
        * 
        * @param tabBar
        *            the tab bar
        */
        public TabbedDeckPanel(UnmodifiableTabBar tabBar) {
            this.tabBar = tabBar;
        }

        /* (non-Javadoc)
         * @see com.google.gwt.user.client.ui.DeckPanel#add(com.google.gwt.user.client.ui.Widget)
         */
        @Override
        public void add(Widget w) {
            throw new UnsupportedOperationException("Use TabPanel.add() to alter the DeckPanel");
        }

        /* (non-Javadoc)
         * @see com.google.gwt.user.client.ui.Panel#clear()
         */
        @Override
        public void clear() {
            throw new UnsupportedOperationException("Use TabPanel.clear() to alter the DeckPanel");
        }

        /* (non-Javadoc)
         * @see com.google.gwt.user.client.ui.DeckPanel#insert(com.google.gwt.user.client.ui.Widget, int)
         */
        @Override
        public void insert(Widget w, int beforeIndex) {
            throw new UnsupportedOperationException("Use TabPanel.insert() to alter the DeckPanel");
        }

        /* (non-Javadoc)
         * @see com.google.gwt.user.client.ui.DeckPanel#remove(com.google.gwt.user.client.ui.Widget)
         */
        @Override
        public boolean remove(Widget w) {
            // Removal of items from the TabBar is delegated to the DeckPanel
            // to ensure consistency
            int idx = getWidgetIndex(w);
            if (idx != -1) {
                tabBar.removeTabProtected(idx);
                return super.remove(w);
            }

            return false;
        }

        /**
        * Insert protected.
        * 
        * @param w
        *            the w
        * @param tabText
        *            the tab text
        * @param asHTML
        *            the as html
        * @param beforeIndex
        *            the before index
        */
        protected void insertProtected(Widget w, String tabText, boolean asHTML, int beforeIndex) {

            // Check to see if the TabPanel already contains the Widget. If so,
            // remove it and see if we need to shift the position to the left.
            int idx = getWidgetIndex(w);
            if (idx != -1) {
                remove(w);
                if (idx < beforeIndex) {
                    beforeIndex--;
                }
            }

            tabBar.insertTabProtected(tabText, asHTML, beforeIndex);
            super.insert(w, beforeIndex);
        }

        /**
        * Insert protected.
        * 
        * @param w
        *            the w
        * @param tabWidget
        *            the tab widget
        * @param beforeIndex
        *            the before index
        */
        protected void insertProtected(Widget w, Widget tabWidget, int beforeIndex) {

            // Check to see if the TabPanel already contains the Widget. If so,
            // remove it and see if we need to shift the position to the left.
            int idx = getWidgetIndex(w);
            if (idx != -1) {
                remove(w);
                if (idx < beforeIndex) {
                    beforeIndex--;
                }
            }

            tabBar.insertTabProtected(tabWidget, beforeIndex);
            super.insert(w, beforeIndex);
        }
    }

    /**
     * This extension of TabPanel overrides the public mutator methods to prevent
     * external callers from modifying the state of the TabBar.
     */
    private class UnmodifiableTabBar extends MATTabBar {

        /* (non-Javadoc)
         * @see mat.client.shared.ui.MATTabBar#insertTab(java.lang.String, boolean, int)
         */
        @Override
        public void insertTab(String text, boolean asHTML, int beforeIndex) {
            throw new UnsupportedOperationException("Use TabPanel.insert() to alter the TabBar");
        }

        /* (non-Javadoc)
         * @see mat.client.shared.ui.MATTabBar#insertTab(com.google.gwt.user.client.ui.Widget, int)
         */
        @Override
        public void insertTab(Widget widget, int beforeIndex) {
            throw new UnsupportedOperationException("Use TabPanel.insert() to alter the TabBar");
        }

        /**
        * Insert tab protected.
        * 
        * @param text
        *            the text
        * @param asHTML
        *            the as html
        * @param beforeIndex
        *            the before index
        */
        public void insertTabProtected(String text, boolean asHTML, int beforeIndex) {
            super.insertTab(text, asHTML, beforeIndex);
        }

        /**
        * Insert tab protected.
        * 
        * @param widget
        *            the widget
        * @param beforeIndex
        *            the before index
        */
        public void insertTabProtected(Widget widget, int beforeIndex) {
            super.insertTab(widget, beforeIndex);
        }

        /* (non-Javadoc)
         * @see mat.client.shared.ui.MATTabBar#removeTab(int)
         */
        @Override
        public void removeTab(int index) {
            // It's possible for removeTab() to function correctly, but it's
            // preferable to have only TabbedDeckPanel.remove() be operable,
            // especially since TabBar does not export an Iterator over its values.
            throw new UnsupportedOperationException("Use TabPanel.remove() to alter the TabBar");
        }

        /**
        * Removes the tab protected.
        * 
        * @param index
        *            the index
        */
        public void removeTabProtected(int index) {
            super.removeTab(index);
        }

        /* (non-Javadoc)
         * @see mat.client.shared.ui.MATTabBar#createTabTextWrapper()
         */
        @Override
        protected SimplePanel createTabTextWrapper() {
            return MATTabPanel.this.createTabTextWrapper();
        }

    }

    /** The tab bar. */
    private UnmodifiableTabBar tabBar = new UnmodifiableTabBar();

    /** The deck. */
    private TabbedDeckPanel deck = new TabbedDeckPanel(tabBar);

    /**
     * Creates an empty tab panel.
     */
    public MATTabPanel() {
        VerticalPanel panel = new VerticalPanel();
        panel.getElement().setId("panel_VerticalPanel");
        panel.add(tabBar);
        panel.add(deck);

        panel.setCellHeight(deck, "100%");
        tabBar.setWidth("100%");

        tabBar.addTabListener(this);
        initWidget(panel);
        setStyleName("gwt-TabPanel");
        deck.setStyleName("gwt-TabPanelBottom");
        // Add a11y role "tabpanel"
        Accessibility.setRole(deck.getElement(), Accessibility.ROLE_TABPANEL);
    }

    /* (non-Javadoc)
     * @see com.google.gwt.user.client.ui.HasWidgets#add(com.google.gwt.user.client.ui.Widget)
     */
    public void add(Widget w) {
        throw new UnsupportedOperationException("A tabText parameter must be specified with add().");
    }

    /**
     * Adds a widget to the tab panel. If the Widget is already attached to the
     * TabPanel, it will be moved to the right-most index.
     * 
     * @param w the widget to be added
     * @param tabText the text to be shown on its tab
     */
    public void add(Widget w, String tabText) {
        insert(w, tabText, getWidgetCount());
    }

    /**
     * Adds a widget to the tab panel. If the Widget is already attached to the
     * TabPanel, it will be moved to the right-most index.
     * 
     * @param w the widget to be added
     * @param tabText the text to be shown on its tab
     * @param asHTML <code>true</code> to treat the specified text as HTML
     */
    public void add(Widget w, String tabText, boolean asHTML) {
        insert(w, tabText, asHTML, getWidgetCount());
    }

    /**
     * Adds a widget to the tab panel. If the Widget is already attached to the
     * TabPanel, it will be moved to the right-most index.
     * 
     * @param w the widget to be added
     * @param tabWidget the widget to be shown in the tab
     */
    public void add(Widget w, Widget tabWidget) {
        insert(w, tabWidget, getWidgetCount());
    }

    /* (non-Javadoc)
     * @see com.google.gwt.event.logical.shared.HasBeforeSelectionHandlers#addBeforeSelectionHandler(com.google.gwt.event.logical.shared.BeforeSelectionHandler)
     */
    public HandlerRegistration addBeforeSelectionHandler(BeforeSelectionHandler<Integer> handler) {
        return addHandler(handler, BeforeSelectionEvent.getType());
    }

    /* (non-Javadoc)
     * @see com.google.gwt.event.logical.shared.HasSelectionHandlers#addSelectionHandler(com.google.gwt.event.logical.shared.SelectionHandler)
     */
    public HandlerRegistration addSelectionHandler(SelectionHandler<Integer> handler) {
        return addHandler(handler, SelectionEvent.getType());
    }

    /**
      * Adds the tab listener.
      * 
      * @param listener
      *            the listener
      * @deprecated Use {@link #addBeforeSelectionHandler} and
      *             {@link #addSelectionHandler} instead
      */
    @Deprecated
    public void addTabListener(TabListener listener) {
        //ListenerWrapper.WrappedTabListener.add(this, listener);
    }

    /* (non-Javadoc)
     * @see com.google.gwt.user.client.ui.HasWidgets#clear()
     */
    public void clear() {
        while (getWidgetCount() > 0) {
            remove(getWidget(0));
        }
    }

    /**
     * Gets the deck panel within this tab panel. Adding or removing Widgets from
     * the DeckPanel is not supported and will throw
     * UnsupportedOperationExceptions.
     * 
     * @return the deck panel
     */
    public DeckPanel getDeckPanel() {
        return deck;
    }

    /**
     * Gets the tab bar within this tab panel. Adding or removing tabs from from
     * the TabBar is not supported and will throw UnsupportedOperationExceptions.
     * 
     * @return the tab bar
     */
    public MATTabBar getTabBar() {
        return tabBar;
    }

    /* (non-Javadoc)
     * @see com.google.gwt.user.client.ui.IndexedPanel#getWidget(int)
     */
    public Widget getWidget(int index) {
        return deck.getWidget(index);
    }

    /* (non-Javadoc)
     * @see com.google.gwt.user.client.ui.IndexedPanel#getWidgetCount()
     */
    public int getWidgetCount() {
        return deck.getWidgetCount();
    }

    /* (non-Javadoc)
     * @see com.google.gwt.user.client.ui.IndexedPanel#getWidgetIndex(com.google.gwt.user.client.ui.Widget)
     */
    public int getWidgetIndex(Widget widget) {
        return deck.getWidgetIndex(widget);
    }

    /**
     * Inserts a widget into the tab panel. If the Widget is already attached to
     * the TabPanel, it will be moved to the requested index.
     * 
     * @param widget the widget to be inserted
     * @param tabText the text to be shown on its tab
     * @param asHTML <code>true</code> to treat the specified text as HTML
     * @param beforeIndex the index before which it will be inserted
     */
    public void insert(Widget widget, String tabText, boolean asHTML, int beforeIndex) {
        // Delegate updates to the TabBar to our DeckPanel implementation
        deck.insertProtected(widget, tabText, asHTML, beforeIndex);
    }

    /**
     * Inserts a widget into the tab panel. If the Widget is already attached to
     * the TabPanel, it will be moved to the requested index.
     * 
     * @param widget the widget to be inserted.
     * @param tabWidget the widget to be shown on its tab.
     * @param beforeIndex the index before which it will be inserted.
     */
    public void insert(Widget widget, Widget tabWidget, int beforeIndex) {
        // Delegate updates to the TabBar to our DeckPanel implementation
        deck.insertProtected(widget, tabWidget, beforeIndex);
    }

    /**
     * Inserts a widget into the tab panel. If the Widget is already attached to
     * the TabPanel, it will be moved to the requested index.
     * 
     * @param widget the widget to be inserted
     * @param tabText the text to be shown on its tab
     * @param beforeIndex the index before which it will be inserted
     */
    public void insert(Widget widget, String tabText, int beforeIndex) {
        insert(widget, tabText, false, beforeIndex);
    }

    /* (non-Javadoc)
     * @see com.google.gwt.user.client.ui.HasAnimation#isAnimationEnabled()
     */
    public boolean isAnimationEnabled() {
        return deck.isAnimationEnabled();
    }

    /* (non-Javadoc)
     * @see com.google.gwt.user.client.ui.HasWidgets#iterator()
     */
    public Iterator<Widget> iterator() {
        // The Iterator returned by DeckPanel supports removal and will invoke
        // TabbedDeckPanel.remove(), which is an active function.
        return deck.iterator();
    }

    /**
      * On before tab selected.
      * 
      * @param sender
      *            the sender
      * @param tabIndex
      *            the tab index
      * @return true, if successful
      * @deprecated Use {@link BeforeSelectionHandler#onBeforeSelection} instead
      */
    @Deprecated
    public boolean onBeforeTabSelected(SourcesTabEvents sender, int tabIndex) {
        BeforeSelectionEvent<Integer> event = BeforeSelectionEvent.fire(this, tabIndex);
        return event == null || !event.isCanceled();
    }

    /**
      * On tab selected.
      * 
      * @param sender
      *            the sender
      * @param tabIndex
      *            the tab index
      * @deprecated Use {@link SelectionHandler#onSelection} instead
      */
    @Deprecated
    public void onTabSelected(SourcesTabEvents sender, int tabIndex) {
        deck.showWidget(tabIndex);
        SelectionEvent.fire(this, tabIndex);
    }

    /* (non-Javadoc)
     * @see com.google.gwt.user.client.ui.IndexedPanel#remove(int)
     */
    public boolean remove(int index) {
        // Delegate updates to the TabBar to our DeckPanel implementation
        return deck.remove(index);
    }

    /**
      * Removes the given widget, and its associated tab.
      * 
      * @param widget
      *            the widget to be removed
      * @return true, if successful
      */
    public boolean remove(Widget widget) {
        // Delegate updates to the TabBar to our DeckPanel implementation
        return deck.remove(widget);
    }

    /**
      * Removes the tab listener.
      * 
      * @param listener
      *            the listener
      * @deprecated Use the {@link HandlerRegistration#removeHandler} method on
      *             the object returned by and add*Handler method instead
      */
    @Deprecated
    public void removeTabListener(TabListener listener) {
        //ListenerWrapper.WrappedTabListener.remove(this, listener);
    }

    /**
     * Programmatically selects the specified tab.
     * 
     * @param index the index of the tab to be selected
     */
    public void selectTab(int index) {
        tabBar.selectTab(index);
    }

    /* (non-Javadoc)
     * @see com.google.gwt.user.client.ui.HasAnimation#setAnimationEnabled(boolean)
     */
    public void setAnimationEnabled(boolean enable) {
        deck.setAnimationEnabled(enable);
    }

    /**
     * Create a {@link SimplePanel} that will wrap the contents in a tab.
     * Subclasses can use this method to wrap tabs in decorator panels.
     * 
     * @return a {@link SimplePanel} to wrap the tab contents, or null to leave
     *         tabs unwrapped
     */
    protected SimplePanel createTabTextWrapper() {
        return null;
    }

    /**
      * <b>Affected Elements:</b>
      * <ul>
      * <li>-bar = The tab bar.</li>
      * <li>-bar-tab# = The element containing the content of the tab itself.</li>
      * <li>-bar-tab-wrapper# = The cell containing the tab at the index.</li>
      * <li>-bottom = The panel beneath the tab bar.</li>
      * </ul>
      * 
      * @param baseID
      *            the base id
      * @see UIObject#onEnsureDebugId(String)
      */
    @Override
    protected void onEnsureDebugId(String baseID) {
        super.onEnsureDebugId(baseID);
        tabBar.ensureDebugId(baseID + "-bar");
        deck.ensureDebugId(baseID + "-bottom");
    }

    /**
      * implementation if Enableable interface consider setting Enablement of tab
      * bar widgets.
      * 
      * @param enabled
      *            the new enabled
      */
    public void setEnabled(boolean enabled) {
        for (int i = 0; i < tabBar.getTabCount(); i++) {
            tabBar.setTabEnabled(i, enabled);
        }
    }
}