org.rstudio.studio.client.workbench.ui.PaneConfig.java Source code

Java tutorial

Introduction

Here is the source code for org.rstudio.studio.client.workbench.ui.PaneConfig.java

Source

/*
 * PaneConfig.java
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */
package org.rstudio.studio.client.workbench.ui;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArrayString;
import org.rstudio.core.client.js.JsUtil;

import java.util.*;

public class PaneConfig extends JavaScriptObject {
    public native static PaneConfig create(JsArrayString panes, JsArrayString tabSet1, JsArrayString tabSet2) /*-{
                                                                                                              return { panes: panes, tabSet1: tabSet1, tabSet2: tabSet2 };
                                                                                                              }-*/;

    public static PaneConfig createDefault() {
        JsArrayString panes = createArray().cast();
        panes.push("Source");
        panes.push("Console");
        panes.push("TabSet1");
        panes.push("TabSet2");

        JsArrayString tabSet1 = createArray().cast();
        tabSet1.push("Environment");
        tabSet1.push("History");
        tabSet1.push("Build");
        tabSet1.push("VCS");
        tabSet1.push("Presentation");

        JsArrayString tabSet2 = createArray().cast();
        tabSet2.push("Files");
        tabSet2.push("Plots");
        tabSet2.push("Packages");
        tabSet2.push("Help");
        tabSet2.push("Viewer");

        return create(panes, tabSet1, tabSet2);
    }

    public static String[] getAllPanes() {
        return new String[] { "Source", "Console", "TabSet1", "TabSet2" };
    }

    public static String[] getAllTabs() {
        return new String[] { "Environment", "History", "Files", "Plots", "Packages", "Help", "Build", "VCS",
                "Presentation", "Viewer" };
    }

    public static String[] getAlwaysVisibleTabs() {
        return new String[] { "Environment", "History", "Files", "Plots", "Help", "Viewer" };
    }

    public static String[] getHideableTabs() {
        return new String[] { "Build", "VCS", "Presentation", "Packages" };
    }

    // Any tabs that were added after our first public release.
    public static String[] getAddableTabs() {
        return new String[] { "Build", "VCS", "Presentation", "Viewer" };
    }

    // Tabs that have been replaced by newer versions/replaceable supersets
    public static String[] getReplacedTabs() {
        return new String[] { "Workspace" };
    }

    // The tabs that replace those in getReplacedTabs(), order-matched
    public static String[] getReplacementTabs() {
        return new String[] { "Environment" };
    }

    // Given the name of a tab, return the index of the tab that it should
    // replace it, or -1 if the tab doesn't have a replacement
    public static int indexOfReplacedTab(String tab) {
        String[] replacedTabs = getReplacedTabs();
        int idx;
        for (idx = 0; idx < replacedTabs.length; idx++) {
            if (tab.equals(replacedTabs[idx])) {
                return idx;
            }
        }
        return -1;
    }

    // Given an array of tabs, replace any obsolete entries with their
    // replacements
    public static void replaceObsoleteTabs(JsArrayString tabs) {
        for (int idx = 0; idx < tabs.length(); idx++) {
            if (indexOfReplacedTab(tabs.get(idx)) >= 0) {
                tabs.set(idx, getReplacementTabs()[idx]);
            }
        }
    }

    protected PaneConfig() {
    }

    public native final JsArrayString getPanes() /*-{
                                                 return this.panes;
                                                 }-*/;

    public native final void setPanes(JsArrayString panes) /*-{
                                                           this.panes = panes;
                                                           }-*/;

    public native final JsArrayString getTabSet1() /*-{
                                                   return this.tabSet1;
                                                   }-*/;

    public native final void setTabSet1(JsArrayString tabSet) /*-{
                                                              this.tabSet1 = tabSet;
                                                              }-*/;

    public native final JsArrayString getTabSet2() /*-{
                                                   return this.tabSet2;
                                                   }-*/;

    public native final void setTabSet2(JsArrayString tabSet) /*-{
                                                              this.tabSet2 = tabSet;
                                                              }-*/;

    public final boolean validateAndAutoCorrect() {
        JsArrayString panes = getPanes();
        if (panes == null)
            return false;
        if (!sameElements(panes, new String[] { "Source", "Console", "TabSet1", "TabSet2" }))
            return false;

        JsArrayString ts1 = getTabSet1();
        JsArrayString ts2 = getTabSet2();
        if (ts1.length() == 0 || ts2.length() == 0)
            return false;

        // Replace any obsoleted tabs in the config
        replaceObsoleteTabs(ts1);
        replaceObsoleteTabs(ts2);

        // If any of these tabs are missing, then they can be added
        Set<String> addableTabs = makeSet(getAddableTabs());

        // If any of these tabs are missing, then the whole config is invalid
        Set<String> baseTabs = makeSet(getAllTabs());
        baseTabs.removeAll(addableTabs);

        for (String tab : JsUtil.asIterable(concat(ts1, ts2))) {
            if (!baseTabs.remove(tab) && !addableTabs.remove(tab))
                return false; // unknown tab
        }

        // If any baseTabs are still present, they weren't part of the tabsets
        if (baseTabs.size() > 0)
            return false;

        // Were any addable tabs missing? Add them the appropriate tabset
        // (Iterate over original array instead of addableTabs set so that order
        // is well-defined)
        for (String tab : getAddableTabs())
            if (addableTabs.contains(tab))
                if (tab.equals("Viewer"))
                    ts2.push(tab);
                else
                    ts1.push(tab);

        // These tabs can be hidden sometimes; they can't stand alone in a tabset
        Set<String> hideableTabs = makeSet(getHideableTabs());
        if (isSubset(hideableTabs, JsUtil.asIterable(ts1)) || isSubset(hideableTabs, JsUtil.asIterable(ts2))) {
            return false;
        }

        return true;
    }

    private static boolean isSubset(Set<String> set, Iterable<String> possibleSubset) {
        for (String el : possibleSubset)
            if (!set.contains(el))
                return false;
        return true;
    }

    private static Set<String> makeSet(String... values) {
        TreeSet<String> set = new TreeSet<String>();
        for (String val : values)
            set.add(val);
        return set;
    }

    public final PaneConfig copy() {
        return create(copy(getPanes()), copy(getTabSet1()), copy(getTabSet2()));
    }

    public final native boolean isEqualTo(PaneConfig other) /*-{
                                                            return other != null &&
                                                            this.panes.toString() == other.panes.toString() &&
                                                            this.tabSet1.toString() == other.tabSet1.toString() &&
                                                            this.tabSet2.toString() == other.tabSet2.toString();
                                                            }-*/;

    private boolean sameElements(JsArrayString a, String[] b) {
        if (a.length() != b.length)
            return false;

        ArrayList<String> a1 = new ArrayList<String>();
        for (int i = 0; i < a.length(); i++)
            a1.add(a.get(i));
        Collections.sort(a1);

        Arrays.sort(b);

        for (int i = 0; i < b.length; i++)
            if (!a1.get(i).equals(b[i]))
                return false;

        return true;
    }

    private JsArrayString concat(JsArrayString a, JsArrayString b) {
        JsArrayString ab = createArray().cast();
        for (int i = 0; i < a.length(); i++)
            ab.push(a.get(i));
        for (int i = 0; i < b.length(); i++)
            ab.push(b.get(i));
        return ab;
    }

    private static JsArrayString copy(JsArrayString array) {
        if (array == null)
            return null;

        JsArrayString copy = JsArrayString.createArray().cast();
        for (int i = 0; i < array.length(); i++)
            copy.push(array.get(i));
        return copy;
    }

    public static boolean isValidConfig(ArrayList<String> tabs) {
        if (isSubset(makeSet(getHideableTabs()), tabs)) {
            // The proposed tab config only contains hideable tabs (or possibly
            // no tabs at all). Reject.
            return false;
        } else if (isSubset(makeSet(tabs.toArray(new String[tabs.size()])), makeSet(getAlwaysVisibleTabs()))) {
            // The proposed tab config contains all the always-visible tabs,
            // which implies that the other tab config only contains hideable
            // tabs (or possibly no tabs at all). Reject.
            return false;
        } else
            return true;
    }
}