org.pentaho.mantle.client.solutionbrowser.tabs.MantleTabPanel.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.mantle.client.solutionbrowser.tabs.MantleTabPanel.java

Source

/*
 * This program is free software; you can redistribute it and/or modify it under the 
 * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software 
 * Foundation.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this 
 * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html 
 * or from the Free Software Foundation, Inc., 
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * Copyright 2008 Pentaho Corporation.  All rights reserved.
 *
 * Created Mar 25, 2008
 * @author Michael D'Amour
 */
package org.pentaho.mantle.client.solutionbrowser.tabs;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

import org.pentaho.gwt.widgets.client.utils.string.StringUtils;
import org.pentaho.mantle.client.messages.Messages;
import org.pentaho.mantle.client.objects.SolutionFileInfo;
import org.pentaho.mantle.client.solutionbrowser.SolutionBrowserListener;
import org.pentaho.mantle.client.solutionbrowser.SolutionBrowserPerspective;
import org.pentaho.mantle.client.solutionbrowser.filelist.FileItem;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.event.logical.shared.BeforeSelectionEvent;
import com.google.gwt.event.logical.shared.BeforeSelectionHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Window.ClosingEvent;
import com.google.gwt.user.client.Window.ClosingHandler;
import com.google.gwt.user.client.ui.Frame;
import com.google.gwt.user.client.ui.NamedFrame;
import com.google.gwt.user.client.ui.TabPanel;
import com.google.gwt.user.client.ui.Widget;

public class MantleTabPanel extends TabPanel {

    public static final int CURRENT_SELECTED_TAB = -1;

    private static final String FRAME_ID_PRE = "frame_"; //$NON-NLS-1$
    private static int frameIdCount = 0;

    private HashMap<Widget, TabWidget> contentTabMap = new HashMap<Widget, TabWidget>();

    private int previousIndex;

    public MantleTabPanel() {
        setupNativeHooks(this);
        // add window close listener
        Window.addWindowClosingHandler(new ClosingHandler() {

            public void onWindowClosing(ClosingEvent event) {
                // close only if we have stuff open
                if (getTabBar().getTabCount() > 0) {
                    event.setMessage(Messages.getString("windowCloseWarning")); //$NON-NLS-1$
                }
            }
        });

        addBeforeSelectionHandler(new BeforeSelectionHandler<Integer>() {
            public void onBeforeSelection(BeforeSelectionEvent<Integer> event) {
                previousIndex = getTabBar().getSelectedTab();
            }
        });

        addSelectionHandler(new SelectionHandler<Integer>() {

            public void onSelection(SelectionEvent<Integer> event) {
                int tabIndex = event.getSelectedItem();
                SolutionBrowserPerspective.getInstance().fireSolutionBrowserListenerEvent(
                        SolutionBrowserListener.EventType.DESELECT, previousIndex);
                SolutionBrowserPerspective.getInstance()
                        .fireSolutionBrowserListenerEvent(SolutionBrowserListener.EventType.SELECT, tabIndex);
                if (previousIndex != tabIndex) {
                    Widget tabPanel = getWidget(tabIndex);
                    Window.setTitle(Messages.getString("productName") + " - " + getCurrentTab().getText()); //$NON-NLS-1$ //$NON-NLS-2$

                    if (tabPanel instanceof IFrameTabPanel) {
                        NamedFrame frame = ((IFrameTabPanel) tabPanel).getFrame();
                        frame.setVisible(true);
                        refreshIfPDF();
                    }
                }
                for (int i = 0; i < tabIndex; i++) {
                    hideFrame(i);
                }
                for (int i = tabIndex + 1; i < getTabBar().getTabCount(); i++) {
                    hideFrame(i);
                }
            }
        });
        setHeight("100%"); //$NON-NLS-1$
        setWidth("100%"); //$NON-NLS-1$
    }

    public void add(Widget w, TabWidget tabWidget) {
        super.add(w, tabWidget);
        contentTabMap.put(w, tabWidget);
    }

    /*
     * This should only ever get invoked via JSNI now
     */
    @SuppressWarnings("unused")
    private void showNewURLTab(String tabName, String tabTooltip, final String url) {
        showNewURLTab(tabName, tabTooltip, url, false);
    }

    public void showNewURLTab(String tabName, String tabTooltip, final String url, boolean setFileInfoInFrame) {
        final int elementId = getWidgetCount();
        String frameName = getUniqueFrameName();

        // check for other tabs with this name
        if (existingTabMatchesName(tabName)) {
            int counter = 2;
            while (true) {
                // Loop until a unique tab name is not found
                // i.e. get the last counter number and then add 1 to it for the new tab name
                if (existingTabMatchesName(tabName + " (" + counter + ")")) { // unique //$NON-NLS-1$ //$NON-NLS-2$
                    counter++;
                    continue;
                } else {
                    tabName = tabName + " (" + counter + ")"; //$NON-NLS-1$ //$NON-NLS-2$
                    tabTooltip = tabTooltip + " (" + counter + ")"; //$NON-NLS-1$ //$NON-NLS-2$
                    break;
                }
            }
        }

        IFrameTabPanel panel = new IFrameTabPanel(frameName, url);
        add(panel, new TabWidget(tabName, tabTooltip, SolutionBrowserPerspective.getInstance(), this, panel));
        selectTab(elementId);

        final ArrayList<com.google.gwt.dom.client.Element> parentList = new ArrayList<com.google.gwt.dom.client.Element>();
        com.google.gwt.dom.client.Element parent = panel.getFrame().getElement();
        while (parent != getElement()) {
            parentList.add(parent);
            parent = parent.getParentElement();
        }
        Collections.reverse(parentList);
        for (int i = 1; i < parentList.size(); i++) {
            parentList.get(i).getStyle().setProperty("height", "100%"); //$NON-NLS-1$ //$NON-NLS-2$
        }
        SolutionBrowserPerspective.getInstance().showContent();
        SolutionBrowserPerspective.getInstance().fireSolutionBrowserListenerEvent(
                SolutionBrowserListener.EventType.OPEN, getTabBar().getSelectedTab());

        if (setFileInfoInFrame) {
            setFileInfoInFrame(SolutionBrowserPerspective.getInstance().getFilesListPanel().getSelectedFileItem());
        }
    }

    private native void setupNativeHooks(MantleTabPanel tabPanel)
    /*-{  
      $wnd.enableContentEdit = function(enable) { 
        tabPanel.@org.pentaho.mantle.client.solutionbrowser.tabs.MantleTabPanel::enableContentEdit(Z)(enable);      
      }
      $wnd.setContentEditSelected = function(enable) { 
        tabPanel.@org.pentaho.mantle.client.solutionbrowser.tabs.MantleTabPanel::setContentEditSelected(Z)(enable);      
      }
      $wnd.registerContentOverlay = function(id) { 
        tabPanel.@org.pentaho.mantle.client.solutionbrowser.tabs.MantleTabPanel::registerContentOverlay(Ljava/lang/String;)(id);      
      }
      $wnd.registerContentCallback = function(callback) { 
        tabPanel.@org.pentaho.mantle.client.solutionbrowser.tabs.MantleTabPanel::setCurrentTabJSCallback(Lcom/google/gwt/core/client/JavaScriptObject;)(callback);      
      } 
      $wnd.enableAdhocSave = function(enable) {
        tabPanel.@org.pentaho.mantle.client.solutionbrowser.tabs.MantleTabPanel::setCurrentTabSaveEnabled(Z)(enable);
      }
      $wnd.closeTab = function(url) {
        tabPanel.@org.pentaho.mantle.client.solutionbrowser.tabs.MantleTabPanel::closeTab(Ljava/lang/String;)(url);
      }    
      $wnd.mantle_openTab = function(name, title, url) {
        tabPanel.@org.pentaho.mantle.client.solutionbrowser.tabs.MantleTabPanel::showNewURLTab(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)(name, title, url);
      }    
      $wnd.openURL = function(name, tooltip, url){
        tabPanel.@org.pentaho.mantle.client.solutionbrowser.tabs.MantleTabPanel::showNewURLTab(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)(name, tooltip, url);
      }    
        
    }-*/;

    public Widget getCurrentTab(int tabIndex) {
        Widget tabPanel = null;
        if (tabIndex >= 0 && getWidgetCount() > tabIndex) {
            tabPanel = getWidget(tabIndex);
        } else {
            int selectedTabIndex = getTabBar().getSelectedTab();
            if (selectedTabIndex >= 0) {
                tabPanel = getWidget(selectedTabIndex);
            }
        }
        return tabPanel;
    }

    public TabWidget getCurrentTab() {
        return contentTabMap.get(getWidget(getTabBar().getSelectedTab()));
    }

    public TabWidget getTabForWidget(Widget tabWidget) {
        return contentTabMap.get(getWidget(getWidgetIndex(tabWidget)));
    }

    /**
     * This method returns the current frame element id.
     * 
     * @return
     */
    public String getCurrentFrameElementId() {
        int curpos = getTabBar().getSelectedTab();
        final IFrameTabPanel curPanel = (IFrameTabPanel) getWidget(curpos);
        return curPanel.getFrame().getElement().getAttribute("id"); //$NON-NLS-1$
    }

    public IFrameTabPanel getCurrentFrame() {
        int curpos = getTabBar().getSelectedTab();
        if (curpos == -1) {
            return null;
        }
        final IFrameTabPanel curPanel = (IFrameTabPanel) getWidget(curpos);
        return curPanel;
    }

    public void setCurrentTabSaveEnabled(boolean enabled) {
        IFrameTabPanel panel = getCurrentFrame();
        if (panel != null) {
            panel.setSaveEnabled(enabled);
        }
        SolutionBrowserPerspective.getInstance().fireSolutionBrowserListenerEvent(
                SolutionBrowserListener.EventType.SELECT, getTabBar().getSelectedTab());
    }

    /*
     * registerContentOverlay - register the overlay with the panel. Once the registration is done it fires a soultion browser event passing the current tab index
     * and the type of event
     */
    public void registerContentOverlay(String id) {
        IFrameTabPanel panel = getCurrentFrame();
        panel.addOverlay(id);
        SolutionBrowserPerspective.getInstance().fireSolutionBrowserListenerEvent(
                SolutionBrowserListener.EventType.OPEN, getTabBar().getSelectedTab());
    }

    public void enableContentEdit(boolean enable) {
        IFrameTabPanel panel = getCurrentFrame();
        panel.setEditEnabled(enable);
        SolutionBrowserPerspective.getInstance().fireSolutionBrowserListenerEvent(
                SolutionBrowserListener.EventType.UNDEFINED, getTabBar().getSelectedTab());
    }

    public void setContentEditSelected(boolean selected) {
        IFrameTabPanel panel = getCurrentFrame();
        panel.setEditSelected(selected);
        SolutionBrowserPerspective.getInstance().fireSolutionBrowserListenerEvent(
                SolutionBrowserListener.EventType.UNDEFINED, getTabBar().getSelectedTab());
    }

    // Content frames can register a Javascript object to receive various PUC notifications. We broker that out
    // to the appropriate IFrameTabPanel here.
    public void setCurrentTabJSCallback(JavaScriptObject obj) {
        IFrameTabPanel panel = getCurrentFrame();
        panel.setContentCallback(obj);
    }

    public void hideFrame(int tabIndex) {
        Frame frame = ((IFrameTabPanel) getWidget(tabIndex)).getFrame();
        frame.setVisible(false);
    }

    public boolean existingTabMatchesName(String name) {
        String key = "title=\"" + name + "\""; //$NON-NLS-1$ //$NON-NLS-2$

        NodeList<com.google.gwt.dom.client.Element> divs = getTabBar().getElement().getElementsByTagName("div"); //$NON-NLS-1$

        for (int i = 0; i < divs.getLength(); i++) {
            String tabHtml = divs.getItem(i).getInnerHTML();
            // TODO: remove once a more elegant tab solution is in place
            if (tabHtml.indexOf(key) > -1) {
                return true;
            }
        }
        return false;
    }

    public String getUniqueFrameName() {
        return FRAME_ID_PRE + frameIdCount++;
    }

    /**
     * Called by JSNI call from parameterized xaction prompt pages to "cancel". The only 'key' to pass up is the URL. To handle the possibility of multiple tabs
     * with the same url, this method first checks the assumption that the current active tab initiates the call. Otherwise it checks from tail up for the first
     * tab with a matching url and closes that one. *
     * 
     * @param url
     */
    @SuppressWarnings("unused")
    private void closeTab(String url) {
        int curpos = getTabBar().getSelectedTab();
        if (StringUtils.isEmpty(url)) {
            // if the url was not provided, simply remove the currently selected tab and then remove
            if (curpos >= 0 && getWidgetCount() > 0) {
                remove(curpos);
            }
            if (getWidgetCount() == 0) {
                allTabsClosed();
            }
            return;
        }
        IFrameTabPanel curPanel = (IFrameTabPanel) getWidget(curpos);
        if (url.contains(curPanel.getUrl())) {
            remove(curpos);
            if (getWidgetCount() == 0) {
                allTabsClosed();
            }
            return;
        }

        for (int i = getWidgetCount() - 1; i >= 0; i--) {
            curPanel = (IFrameTabPanel) getWidget(i);

            if (url.contains(curPanel.getUrl())) {
                remove(i);
                if (getWidgetCount() == 0) {
                    allTabsClosed();
                }
                return;
            }
        }
    }

    private native boolean isPDF(com.google.gwt.dom.client.Element frame)
    /*-{
      return (frame.contentDocument != null && frame.contentDocument.getElementsByTagName('embed').length > 0);
    }-*/;

    public void refreshIfPDF() {
        // There's a bug when re-showing a tab containing a PDF. Under Firefox it doesn't render, so we force a reload
        int selectedTab = getTabBar().getSelectedTab();
        if (selectedTab > -1) {
            final Widget tabContent = getWidget(selectedTab);
            if (tabContent instanceof IFrameTabPanel) {
                Timer t = new Timer() {
                    public void run() {
                        IFrameTabPanel frame = ((IFrameTabPanel) tabContent);
                        if (isPDF(frame.getFrame().getElement())) {
                            frame.reload();
                        }
                    }
                };
                t.schedule(250);
            }
        }
    }

    /**
     * This method will check if the given frame(by id) is jpivot.
     * 
     * @param elementId
     */
    public static native boolean isPivot(String elementId)
    /*-{
      var frame = $doc.getElementById(elementId);
      if (!frame) { 
        return false; 
      }
      frame = frame.contentWindow;
      return true == frame.pivot_initialized;
    }-*/;

    /**
     * Store representation of file in the frame for reference later when save is called
     * 
     * @param selectedFileItem
     */
    public void setFileInfoInFrame(FileItem selectedFileItem) {
        IFrameTabPanel tp = getCurrentFrame();
        if (tp != null && selectedFileItem != null) {
            SolutionFileInfo fileInfo = new SolutionFileInfo();
            fileInfo.setName(selectedFileItem.getName());
            fileInfo.setSolution(selectedFileItem.getSolution());
            fileInfo.setPath(selectedFileItem.getPath());
            tp.setFileInfo(fileInfo);
        }
    }

    public void allTabsClosed() {
        // show the "launch" panel
        SolutionBrowserPerspective.getInstance().showContent();
        SolutionBrowserPerspective.getInstance()
                .fireSolutionBrowserListenerEvent(SolutionBrowserListener.EventType.CLOSE, CURRENT_SELECTED_TAB);
    }

}