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

Java tutorial

Introduction

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

Source

/*
 * PaneManager.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.JsArrayString;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.name.Named;

import org.rstudio.core.client.Debug;
import org.rstudio.core.client.Triad;
import org.rstudio.core.client.command.CommandBinder;
import org.rstudio.core.client.command.Handler;
import org.rstudio.core.client.events.WindowStateChangeEvent;
import org.rstudio.core.client.layout.DualWindowLayoutPanel;
import org.rstudio.core.client.layout.LogicalWindow;
import org.rstudio.core.client.layout.WindowState;
import org.rstudio.core.client.theme.MinimizedModuleTabLayoutPanel;
import org.rstudio.core.client.theme.MinimizedWindowFrame;
import org.rstudio.core.client.theme.PrimaryWindowFrame;
import org.rstudio.core.client.theme.WindowFrame;
import org.rstudio.core.client.theme.res.ThemeResources;
import org.rstudio.core.client.widget.ToolbarButton;
import org.rstudio.studio.client.application.events.EventBus;
import org.rstudio.studio.client.workbench.commands.Commands;
import org.rstudio.studio.client.workbench.model.ClientState;
import org.rstudio.studio.client.workbench.model.Session;
import org.rstudio.studio.client.workbench.model.WorkbenchServerOperations;
import org.rstudio.studio.client.workbench.model.helper.IntStateValue;
import org.rstudio.studio.client.workbench.prefs.model.UIPrefs;
import org.rstudio.studio.client.workbench.views.console.ConsoleInterruptButton;
import org.rstudio.studio.client.workbench.views.console.ConsolePane;
import org.rstudio.studio.client.workbench.views.output.find.FindOutputTab;
import org.rstudio.studio.client.workbench.views.output.markers.MarkersOutputTab;
import org.rstudio.studio.client.workbench.views.source.SourceShim;

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

/*
 * TODO: Push client state when selected tab or layout changes
 */

public class PaneManager {
    public interface Binder extends CommandBinder<Commands, PaneManager> {
    }

    public enum Tab {
        History, Files, Plots, Packages, Help, VCS, Build, Presentation, Environment, Viewer
    }

    class SelectedTabStateValue extends IntStateValue {
        SelectedTabStateValue(String name, WorkbenchTabPanel tabPanel) {
            super("workbench-pane", name, ClientState.PROJECT_PERSISTENT,
                    session_.getSessionInfo().getClientState(), true);
            tabPanel_ = tabPanel;
            finishInit(session_.getSessionInfo().getClientState());
        }

        @Override
        protected void onInit(Integer value) {
            if (value != null)
                tabPanel_.selectTab(value);
        }

        @Override
        protected Integer getValue() {
            return tabPanel_.getSelectedIndex();
        }

        private final WorkbenchTabPanel tabPanel_;
    }

    @Inject
    public PaneManager(Provider<MainSplitPanel> pSplitPanel, WorkbenchServerOperations server, EventBus eventBus,
            Session session, Binder binder, Commands commands, UIPrefs uiPrefs,
            @Named("Console") final Widget consolePane, ConsoleInterruptButton consoleInterrupt, SourceShim source,
            @Named("History") final WorkbenchTab historyTab, @Named("Files") final WorkbenchTab filesTab,
            @Named("Plots") final WorkbenchTab plotsTab, @Named("Packages") final WorkbenchTab packagesTab,
            @Named("Help") final WorkbenchTab helpTab, @Named("VCS") final WorkbenchTab vcsTab,
            @Named("Build") final WorkbenchTab buildTab, @Named("Presentation") final WorkbenchTab presentationTab,
            @Named("Environment") final WorkbenchTab environmentTab, @Named("Viewer") final WorkbenchTab viewerTab,
            @Named("Compile PDF") final WorkbenchTab compilePdfTab,
            @Named("Source Cpp") final WorkbenchTab sourceCppTab,
            @Named("R Markdown") final WorkbenchTab renderRmdTab,
            @Named("Deploy") final WorkbenchTab deployShinyTab, final MarkersOutputTab markersTab,
            final FindOutputTab findOutputTab) {
        eventBus_ = eventBus;
        session_ = session;
        commands_ = commands;
        consolePane_ = (ConsolePane) consolePane;
        consoleInterrupt_ = consoleInterrupt;
        source_ = source;
        historyTab_ = historyTab;
        filesTab_ = filesTab;
        plotsTab_ = plotsTab;
        packagesTab_ = packagesTab;
        helpTab_ = helpTab;
        vcsTab_ = vcsTab;
        buildTab_ = buildTab;
        presentationTab_ = presentationTab;
        environmentTab_ = environmentTab;
        viewerTab_ = viewerTab;
        compilePdfTab_ = compilePdfTab;
        findOutputTab_ = findOutputTab;
        sourceCppTab_ = sourceCppTab;
        renderRmdTab_ = renderRmdTab;
        deployShinyTab_ = deployShinyTab;
        markersTab_ = markersTab;

        binder.bind(commands, this);

        PaneConfig config = validateConfig(uiPrefs.paneConfig().getValue());
        initPanes(config);

        panes_ = createPanes(config);
        left_ = createSplitWindow(panes_.get(0), panes_.get(1), "left", 0.4);
        right_ = createSplitWindow(panes_.get(2), panes_.get(3), "right", 0.6);

        panel_ = pSplitPanel.get();
        panel_.initialize(left_, right_);

        if (session_.getSessionInfo().getSourceDocuments().length() == 0
                && sourceLogicalWindow_.getState() != WindowState.HIDE) {
            sourceLogicalWindow_.onWindowStateChange(new WindowStateChangeEvent(WindowState.HIDE));
        } else if (session_.getSessionInfo().getSourceDocuments().length() > 0
                && sourceLogicalWindow_.getState() == WindowState.HIDE) {
            sourceLogicalWindow_.onWindowStateChange(new WindowStateChangeEvent(WindowState.NORMAL));
        }

        uiPrefs.paneConfig().addValueChangeHandler(new ValueChangeHandler<PaneConfig>() {
            public void onValueChange(ValueChangeEvent<PaneConfig> evt) {
                ArrayList<LogicalWindow> newPanes = createPanes(validateConfig(evt.getValue()));
                panes_ = newPanes;
                left_.replaceWindows(newPanes.get(0), newPanes.get(1));
                right_.replaceWindows(newPanes.get(2), newPanes.get(3));

                tabSet1TabPanel_.clear();
                tabSet2TabPanel_.clear();
                populateTabPanel(tabNamesToTabs(evt.getValue().getTabSet1()), tabSet1TabPanel_, tabSet1MinPanel_);
                populateTabPanel(tabNamesToTabs(evt.getValue().getTabSet2()), tabSet2TabPanel_, tabSet2MinPanel_);
            }
        });
    }

    @Handler
    public void onMaximizeConsole() {
        LogicalWindow consoleWindow = panesByName_.get("Console");
        if (consoleWindow.getState() != WindowState.MAXIMIZE) {
            consoleWindow.onWindowStateChange(new WindowStateChangeEvent(WindowState.MAXIMIZE));
        }
    }

    private ArrayList<LogicalWindow> createPanes(PaneConfig config) {
        ArrayList<LogicalWindow> results = new ArrayList<LogicalWindow>();

        JsArrayString panes = config.getPanes();
        for (int i = 0; i < 4; i++) {
            results.add(panesByName_.get(panes.get(i)));
        }
        return results;
    }

    private void initPanes(PaneConfig config) {
        panesByName_ = new HashMap<String, LogicalWindow>();
        panesByName_.put("Console", createConsole());
        panesByName_.put("Source", createSource());

        Triad<LogicalWindow, WorkbenchTabPanel, MinimizedModuleTabLayoutPanel> ts1 = createTabSet("TabSet1",
                tabNamesToTabs(config.getTabSet1()));
        panesByName_.put("TabSet1", ts1.first);
        tabSet1TabPanel_ = ts1.second;
        tabSet1MinPanel_ = ts1.third;

        Triad<LogicalWindow, WorkbenchTabPanel, MinimizedModuleTabLayoutPanel> ts2 = createTabSet("TabSet2",
                tabNamesToTabs(config.getTabSet2()));
        panesByName_.put("TabSet2", ts2.first);
        tabSet2TabPanel_ = ts2.second;
        tabSet2MinPanel_ = ts2.third;
    }

    private ArrayList<Tab> tabNamesToTabs(JsArrayString tabNames) {
        ArrayList<Tab> tabList = new ArrayList<Tab>();
        for (int j = 0; j < tabNames.length(); j++)
            tabList.add(Enum.valueOf(Tab.class, tabNames.get(j)));
        return tabList;
    }

    private PaneConfig validateConfig(PaneConfig config) {
        if (config == null)
            config = PaneConfig.createDefault();
        if (!config.validateAndAutoCorrect()) {
            Debug.log("Pane config is not valid");
            config = PaneConfig.createDefault();
        }
        return config;
    }

    public MainSplitPanel getPanel() {
        return panel_;
    }

    public WorkbenchTab getTab(Tab tab) {
        switch (tab) {
        case History:
            return historyTab_;
        case Files:
            return filesTab_;
        case Plots:
            return plotsTab_;
        case Packages:
            return packagesTab_;
        case Help:
            return helpTab_;
        case VCS:
            return vcsTab_;
        case Build:
            return buildTab_;
        case Presentation:
            return presentationTab_;
        case Environment:
            return environmentTab_;
        case Viewer:
            return viewerTab_;
        }
        throw new IllegalArgumentException("Unknown tab");
    }

    public WorkbenchTab[] getAllTabs() {
        return new WorkbenchTab[] { historyTab_, filesTab_, plotsTab_, packagesTab_, helpTab_, vcsTab_, buildTab_,
                presentationTab_, environmentTab_, viewerTab_ };
    }

    public void activateTab(Tab tab) {
        tabToPanel_.get(tab).selectTab(tabToIndex_.get(tab));
    }

    public void activateTab(String tabName) {
        Tab tab = tabForName(tabName);
        if (tab != null)
            activateTab(tab);
    }

    public ConsolePane getConsole() {
        return consolePane_;
    }

    public WorkbenchTabPanel getOwnerTabPanel(Tab tab) {
        return tabToPanel_.get(tab);
    }

    public LogicalWindow getSourceLogicalWindow() {
        return sourceLogicalWindow_;
    }

    private DualWindowLayoutPanel createSplitWindow(LogicalWindow top, LogicalWindow bottom, String name,
            double bottomDefaultPct) {
        return new DualWindowLayoutPanel(eventBus_, top, bottom, session_, name, WindowState.NORMAL,
                (int) (Window.getClientHeight() * bottomDefaultPct));
    }

    private LogicalWindow createConsole() {
        PrimaryWindowFrame frame = new PrimaryWindowFrame("Console", null);

        ToolbarButton goToWorkingDirButton = commands_.goToWorkingDir().createToolbarButton();
        goToWorkingDirButton.addStyleName(ThemeResources.INSTANCE.themeStyles().windowFrameToolbarButton());

        @SuppressWarnings("unused")
        ConsoleTabPanel consoleTabPanel = new ConsoleTabPanel(frame, consolePane_, compilePdfTab_, findOutputTab_,
                sourceCppTab_, renderRmdTab_, deployShinyTab_, markersTab_, eventBus_, consoleInterrupt_,
                goToWorkingDirButton);

        return new LogicalWindow(frame, new MinimizedWindowFrame("Console"));
    }

    private LogicalWindow createSource() {
        WindowFrame sourceFrame = new WindowFrame();
        sourceFrame.setFillWidget(source_.asWidget());
        source_.forceLoad();
        return sourceLogicalWindow_ = new LogicalWindow(sourceFrame, new MinimizedWindowFrame("Source"));
    }

    private Triad<LogicalWindow, WorkbenchTabPanel, MinimizedModuleTabLayoutPanel> createTabSet(
            String persisterName, ArrayList<Tab> tabs) {
        final WindowFrame frame = new WindowFrame();
        final WorkbenchTabPanel tabPanel = new WorkbenchTabPanel(frame);
        MinimizedModuleTabLayoutPanel minimized = new MinimizedModuleTabLayoutPanel();

        populateTabPanel(tabs, tabPanel, minimized);

        frame.setFillWidget(tabPanel);

        minimized.addSelectionHandler(new SelectionHandler<Integer>() {
            public void onSelection(SelectionEvent<Integer> integerSelectionEvent) {
                int tab = integerSelectionEvent.getSelectedItem();
                tabPanel.selectTab(tab);
            }
        });

        tabPanel.addSelectionHandler(new SelectionHandler<Integer>() {
            public void onSelection(SelectionEvent<Integer> integerSelectionEvent) {
                session_.persistClientState();
            }
        });

        new SelectedTabStateValue(persisterName, tabPanel);

        return new Triad<LogicalWindow, WorkbenchTabPanel, MinimizedModuleTabLayoutPanel>(
                new LogicalWindow(frame, minimized), tabPanel, minimized);
    }

    private void populateTabPanel(ArrayList<Tab> tabs, WorkbenchTabPanel tabPanel,
            MinimizedModuleTabLayoutPanel minimized) {
        ArrayList<WorkbenchTab> tabList = new ArrayList<WorkbenchTab>();
        for (int i = 0; i < tabs.size(); i++) {
            Tab tab = tabs.get(i);
            tabList.add(getTab(tab));
            tabToPanel_.put(tab, tabPanel);
            tabToIndex_.put(tab, i);
        }
        tabPanel.setTabs(tabList);

        ArrayList<String> labels = new ArrayList<String>();
        for (Tab tab : tabs) {
            if (!getTab(tab).isSuppressed())
                labels.add(getTabLabel(tab));
        }
        minimized.setTabs(labels.toArray(new String[labels.size()]));
    }

    private String getTabLabel(Tab tab) {
        switch (tab) {
        case History:
            return "History";
        case Files:
            return "Files";
        case Plots:
            return "Plots";
        case Packages:
            return "Packages";
        case Help:
            return "Help";
        case VCS:
            return getTab(tab).getTitle();
        case Build:
            return "Build";
        case Presentation:
            return getTab(tab).getTitle();
        case Environment:
            return "Environment";
        case Viewer:
            return "Viewer";
        }
        return "??";
    }

    private Tab tabForName(String name) {
        if (name.equalsIgnoreCase("history"))
            return Tab.History;
        if (name.equalsIgnoreCase("files"))
            return Tab.Files;
        if (name.equalsIgnoreCase("plots"))
            return Tab.Plots;
        if (name.equalsIgnoreCase("packages"))
            return Tab.Packages;
        if (name.equalsIgnoreCase("help"))
            return Tab.Help;
        if (name.equalsIgnoreCase("vcs"))
            return Tab.VCS;
        if (name.equalsIgnoreCase("build"))
            return Tab.Build;
        if (name.equalsIgnoreCase("presentation"))
            return Tab.Presentation;
        if (name.equalsIgnoreCase("environment"))
            return Tab.Environment;
        if (name.equalsIgnoreCase("viewer"))
            return Tab.Viewer;

        return null;
    }

    private final EventBus eventBus_;
    private final Session session_;
    private final Commands commands_;
    private final FindOutputTab findOutputTab_;
    private final WorkbenchTab compilePdfTab_;
    private final WorkbenchTab sourceCppTab_;
    private final ConsolePane consolePane_;
    private final ConsoleInterruptButton consoleInterrupt_;
    private final SourceShim source_;
    private final WorkbenchTab historyTab_;
    private final WorkbenchTab filesTab_;
    private final WorkbenchTab plotsTab_;
    private final WorkbenchTab packagesTab_;
    private final WorkbenchTab helpTab_;
    private final WorkbenchTab vcsTab_;
    private final WorkbenchTab buildTab_;
    private final WorkbenchTab presentationTab_;
    private final WorkbenchTab environmentTab_;
    private final WorkbenchTab viewerTab_;
    private final WorkbenchTab renderRmdTab_;
    private final WorkbenchTab deployShinyTab_;
    private final MarkersOutputTab markersTab_;
    private MainSplitPanel panel_;
    private LogicalWindow sourceLogicalWindow_;
    private final HashMap<Tab, WorkbenchTabPanel> tabToPanel_ = new HashMap<Tab, WorkbenchTabPanel>();
    private final HashMap<Tab, Integer> tabToIndex_ = new HashMap<Tab, Integer>();
    private HashMap<String, LogicalWindow> panesByName_;
    private DualWindowLayoutPanel left_;
    private DualWindowLayoutPanel right_;
    private ArrayList<LogicalWindow> panes_;
    private WorkbenchTabPanel tabSet1TabPanel_;
    private MinimizedModuleTabLayoutPanel tabSet1MinPanel_;
    private WorkbenchTabPanel tabSet2TabPanel_;
    private MinimizedModuleTabLayoutPanel tabSet2MinPanel_;
}