org.rstudio.studio.client.workbench.views.environment.EnvironmentPane.java Source code

Java tutorial

Introduction

Here is the source code for org.rstudio.studio.client.workbench.views.environment.EnvironmentPane.java

Source

/*
 * EnvironmentPane.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.views.environment;

import java.util.ArrayList;
import java.util.List;

import org.rstudio.core.client.DebugFilePosition;
import org.rstudio.core.client.StringUtil;
import org.rstudio.core.client.widget.Operation;
import org.rstudio.core.client.widget.SearchWidget;
import org.rstudio.core.client.widget.SecondaryToolbar;
import org.rstudio.core.client.widget.Toolbar;
import org.rstudio.core.client.widget.ToolbarButton;
import org.rstudio.core.client.widget.ToolbarPopupMenu;
import org.rstudio.studio.client.application.events.EventBus;
import org.rstudio.studio.client.common.GlobalDisplay;
import org.rstudio.studio.client.common.ImageMenuItem;
import org.rstudio.studio.client.common.icons.StandardIcons;
import org.rstudio.studio.client.server.ServerError;
import org.rstudio.studio.client.server.ServerRequestCallback;
import org.rstudio.studio.client.server.Void;
import org.rstudio.studio.client.workbench.commands.Commands;
import org.rstudio.studio.client.workbench.model.Session;
import org.rstudio.studio.client.workbench.prefs.model.UIPrefs;
import org.rstudio.studio.client.workbench.ui.WorkbenchPane;
import org.rstudio.studio.client.workbench.views.console.events.SendToConsoleEvent;
import org.rstudio.studio.client.workbench.views.environment.model.CallFrame;
import org.rstudio.studio.client.workbench.views.environment.model.EnvironmentContextData;
import org.rstudio.studio.client.workbench.views.environment.model.EnvironmentFrame;
import org.rstudio.studio.client.workbench.views.environment.model.EnvironmentServerOperations;
import org.rstudio.studio.client.workbench.views.environment.model.ObjectContents;
import org.rstudio.studio.client.workbench.views.environment.model.RObject;
import org.rstudio.studio.client.workbench.views.environment.view.EnvironmentObjects;
import org.rstudio.studio.client.workbench.views.environment.view.EnvironmentObjectsObserver;
import org.rstudio.studio.client.workbench.views.environment.view.EnvironmentResources;

import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.ui.MenuItem;
import com.google.gwt.user.client.ui.SuggestOracle;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;

public class EnvironmentPane extends WorkbenchPane
        implements EnvironmentPresenter.Display, EnvironmentObjectsObserver {
    @Inject
    public EnvironmentPane(Commands commands, EventBus eventBus, GlobalDisplay globalDisplay,
            EnvironmentServerOperations serverOperations, Session session, UIPrefs prefs) {
        super("Environment");

        commands_ = commands;
        eventBus_ = eventBus;
        server_ = serverOperations;
        globalDisplay_ = globalDisplay;
        prefs_ = prefs;

        expandedObjects_ = new ArrayList<String>();
        scrollPosition_ = 0;
        isClientStateDirty_ = false;
        environments_ = null;
        EnvironmentContextData environmentState = session.getSessionInfo().getEnvironmentState();
        environmentName_ = environmentState.environmentName();
        environmentIsLocal_ = environmentState.environmentIsLocal();

        EnvironmentPaneResources.INSTANCE.environmentPaneStyle().ensureInjected();

        ensureWidget();
    }

    // WorkbenchPane overrides -------------------------------------------------

    @Override
    protected Toolbar createMainToolbar() {
        Toolbar toolbar = new Toolbar();
        toolbar.addLeftWidget(commands_.loadWorkspace().createToolbarButton());
        toolbar.addLeftWidget(commands_.saveWorkspace().createToolbarButton());
        toolbar.addLeftSeparator();
        toolbar.addLeftWidget(createImportMenu());
        toolbar.addLeftSeparator();
        toolbar.addLeftWidget(commands_.clearWorkspace().createToolbarButton());
        toolbar.addLeftSeparator();
        toolbar.addLeftWidget(commands_.refreshEnvironment().createToolbarButton());

        ToolbarPopupMenu menu = new ToolbarPopupMenu();
        menu.addItem(createViewMenuItem(EnvironmentObjects.OBJECT_LIST_VIEW));
        menu.addItem(createViewMenuItem(EnvironmentObjects.OBJECT_GRID_VIEW));
        viewButton_ = new ToolbarButton(nameOfViewType(EnvironmentObjects.OBJECT_LIST_VIEW),
                imageOfViewType(EnvironmentObjects.OBJECT_LIST_VIEW), menu);
        toolbar.addRightWidget(viewButton_);

        return toolbar;
    }

    @Override
    protected SecondaryToolbar createSecondaryToolbar() {
        SecondaryToolbar toolbar = new SecondaryToolbar();

        environmentMenu_ = new EnvironmentPopupMenu();
        environmentButton_ = new ToolbarButton(friendlyEnvironmentName(),
                imageOfEnvironment(environmentName_, environmentIsLocal_), environmentMenu_);
        toolbar.addLeftWidget(environmentButton_);

        SearchWidget searchWidget = new SearchWidget(new SuggestOracle() {
            @Override
            public void requestSuggestions(Request request, Callback callback) {
                // no suggestions
                callback.onSuggestionsReady(request, new Response(new ArrayList<Suggestion>()));
            }
        });
        searchWidget.addValueChangeHandler(new ValueChangeHandler<String>() {
            @Override
            public void onValueChange(ValueChangeEvent<String> event) {
                objects_.setFilterText(event.getValue());
            }
        });

        searchWidget.getElement().getStyle().setMarginTop(1, Unit.PX);
        toolbar.addRightWidget(searchWidget);

        return toolbar;
    }

    @Override
    protected Widget createMainWidget() {
        objects_ = new EnvironmentObjects(this);
        return objects_;
    }

    // EnviromentPresenter.Display implementation ------------------------------

    @Override
    public void addObject(RObject object) {
        objects_.addObject(object);
    }

    @Override
    public void addObjects(JsArray<RObject> objects) {
        objects_.addObjects(objects);
    }

    @Override
    public void removeObject(String objectName) {
        objects_.removeObject(objectName);
    }

    @Override
    public void setContextDepth(int contextDepth) {
        objects_.setContextDepth(contextDepth);

        // if the environment we're about to show is nested, turn off the toolbar
        // commands that act on the global environment
        Boolean commandsEnabled = contextDepth == 0;
        commands_.loadWorkspace().setEnabled(commandsEnabled);
        commands_.saveWorkspace().setEnabled(commandsEnabled);
        commands_.importDatasetFromFile().setEnabled(commandsEnabled);
        commands_.importDatasetFromURL().setEnabled(commandsEnabled);
        dataImportButton_.setEnabled(commandsEnabled);
    }

    @Override
    public void clearObjects() {
        objects_.clearObjects();
        expandedObjects_.clear();
        scrollPosition_ = 0;
        isClientStateDirty_ = true;
    }

    @Override
    public void setEnvironmentName(String environmentName, boolean local) {
        environmentName_ = environmentName;
        environmentButton_.setText(friendlyEnvironmentName());
        environmentButton_.setLeftImage(imageOfEnvironment(environmentName, local));
        objects_.setEnvironmentName(friendlyEnvironmentName());
        if (environmentName.equals("R_GlobalEnv"))
            commands_.clearWorkspace().setEnabled(true);
        else
            commands_.clearWorkspace().setEnabled(false);
    }

    @Override
    public void setCallFrames(JsArray<CallFrame> frameList, boolean autoSize) {
        objects_.setCallFrames(frameList, autoSize);
    }

    @Override
    public int getScrollPosition() {
        return scrollPosition_;
    }

    @Override
    public void setScrollPosition(int scrollPosition) {
        objects_.setScrollPosition(scrollPosition);
    }

    @Override
    public void setExpandedObjects(JsArrayString objects) {
        objects_.setExpandedObjects(objects);
        expandedObjects_.clear();
        for (int idx = 0; idx < objects.length(); idx++) {
            expandedObjects_.add(objects.get(idx));
        }
    }

    @Override
    public String[] getExpandedObjects() {
        return expandedObjects_.toArray(new String[0]);
    }

    @Override
    public List<String> getSelectedObjects() {
        return objects_.getSelectedObjects();
    }

    @Override
    public void clearSelection() {
        objects_.clearSelection();
    }

    @Override
    public void changeContextDepth(int newDepth) {
        server_.setContextDepth(newDepth, new ServerRequestCallback<Void>() {
            @Override
            public void onError(ServerError error) {
                globalDisplay_.showErrorMessage("Error opening call frame", error.getUserMessage());
            }
        });
    }

    public boolean clientStateDirty() {
        return isClientStateDirty_;
    }

    public void setClientStateClean() {
        isClientStateDirty_ = false;
    }

    @Override
    public void resize() {
        objects_.onResize();
    }

    @Override
    public void setBrowserRange(DebugFilePosition range) {
        objects_.updateLineNumber(range.getLine());
    }

    @Override
    public void setObjectDisplayType(int type) {
        viewButton_.setText(nameOfViewType(type));
        viewButton_.setLeftImage(imageOfViewType(type));
        objects_.setObjectDisplay(type);
    }

    @Override
    public int getObjectDisplayType() {
        return objects_.getObjectDisplay();
    }

    @Override
    public int getSortColumn() {
        return objects_.getSortColumn();
    }

    @Override
    public boolean getAscendingSort() {
        return objects_.getAscendingSort();
    }

    @Override
    public void setSort(int sortColumn, boolean sortAscending) {
        objects_.setSort(sortColumn, sortAscending);
    }

    @Override
    public void setViewDirty() {
        isClientStateDirty_ = true;
    }

    // EnviromentObjects.Observer implementation -------------------------------

    public void setPersistedScrollPosition(int scrollPosition) {
        scrollPosition_ = scrollPosition;
        isClientStateDirty_ = true;
    }

    public void setObjectExpanded(String objectName) {
        expandedObjects_.add(objectName);
        isClientStateDirty_ = true;
    }

    public void setObjectCollapsed(String objectName) {
        expandedObjects_.remove(objectName);
        isClientStateDirty_ = true;
    }

    public void viewObject(String objectName) {
        executeFunctionForObject("View", objectName);
    }

    @Override
    public boolean getShowInternalFunctions() {
        return prefs_.showInternalFunctionsInTraceback().getValue();
    }

    @Override
    public void setShowInternalFunctions(boolean show) {
        prefs_.showInternalFunctionsInTraceback().setProjectValue(show);
    }

    public void fillObjectContents(final RObject object, final Operation onCompleted) {
        server_.getObjectContents(object.getName(), new ServerRequestCallback<ObjectContents>() {
            @Override
            public void onResponseReceived(ObjectContents contents) {
                object.setDeferredContents(contents.getContents());
                onCompleted.execute();
            }

            @Override
            public void onError(ServerError error) {
                onCompleted.execute();
            }
        });
    }

    // Private methods ---------------------------------------------------------

    private void executeFunctionForObject(String function, String objectName) {
        String editCode = function + "(" + StringUtil.toRSymbolName(objectName) + ")";
        SendToConsoleEvent event = new SendToConsoleEvent(editCode, true);
        eventBus_.fireEvent(event);
    }

    private Widget createImportMenu() {
        ToolbarPopupMenu menu = new ToolbarPopupMenu();
        menu.addItem(commands_.importDatasetFromFile().createMenuItem(false));
        menu.addItem(commands_.importDatasetFromURL().createMenuItem(false));
        dataImportButton_ = new ToolbarButton("Import Dataset", StandardIcons.INSTANCE.import_dataset(), menu);
        return dataImportButton_;

    }

    private String friendlyEnvironmentName() {
        return friendlyNameOfEnvironment(environmentName_);
    }

    private String friendlyNameOfEnvironment(String name) {
        if (name.equals("R_GlobalEnv"))
            return GLOBAL_ENVIRONMENT_NAME;
        else if (name.equals("base"))
            return "package:base";
        else
            return name;
    }

    private ImageResource imageOfEnvironment(String name, boolean local) {
        if (name.endsWith("()"))
            return EnvironmentResources.INSTANCE.functionEnvironment();
        else if (name.equals("R_GlobalEnv"))
            return EnvironmentResources.INSTANCE.globalEnvironment();
        else if (name.startsWith("package:") || name.equals("base") || local)
            return EnvironmentResources.INSTANCE.packageEnvironment();
        else
            return EnvironmentResources.INSTANCE.attachedEnvironment();
    }

    private void setEnvironments(JsArray<EnvironmentFrame> environments) {
        environments_ = environments;
        rebuildEnvironmentMenu();
    }

    private void rebuildEnvironmentMenu() {
        environmentMenu_.clearItems();
        if (environments_ == null) {
            return;
        }
        for (int i = 0; i < environments_.length(); i++) {
            final EnvironmentFrame frame = environments_.get(i);
            ImageResource img = imageOfEnvironment(frame.getName(), frame.isLocal());
            environmentMenu_.addItem(ImageMenuItem.create(img, friendlyNameOfEnvironment(frame.getName()),
                    new Scheduler.ScheduledCommand() {
                        @Override
                        public void execute() {
                            loadEnvironmentFrame(frame);
                        }
                    }, 2));
        }
    }

    // Called to load a new environment into the environment pane. 
    private void loadEnvironmentFrame(final EnvironmentFrame frame) {
        ServerRequestCallback<Void> callback = new ServerRequestCallback<Void>() {
            @Override
            public void onResponseReceived(Void v) {
                setEnvironmentName(frame.getName(), frame.isLocal());
            }

            @Override
            public void onError(ServerError error) {

            }
        };
        // If the frame's an active call frame, set it by its index 
        if (frame.getFrame() > 0)
            server_.setEnvironmentFrame(frame.getFrame(), callback);
        // Otherwise, set it by its name
        else
            server_.setEnvironment(frame.getName(), callback);
    }

    private String nameOfViewType(int type) {
        if (type == EnvironmentObjects.OBJECT_LIST_VIEW)
            return "List";
        else if (type == EnvironmentObjects.OBJECT_GRID_VIEW)
            return "Grid";
        return "";
    }

    private ImageResource imageOfViewType(int type) {
        if (type == EnvironmentObjects.OBJECT_LIST_VIEW)
            return EnvironmentResources.INSTANCE.objectListView();
        else if (type == EnvironmentObjects.OBJECT_GRID_VIEW)
            return EnvironmentResources.INSTANCE.objectGridView();
        return null;
    }

    private MenuItem createViewMenuItem(final int type) {
        return ImageMenuItem.create(imageOfViewType(type), nameOfViewType(type), new Scheduler.ScheduledCommand() {
            @Override
            public void execute() {
                setObjectDisplayType(type);
            }
        }, 2);
    }

    // An extension of the toolbar popup menu that gets environment names from
    // the server when the menu is invoked. 
    private class EnvironmentPopupMenu extends ToolbarPopupMenu {
        @Override
        public void getDynamicPopupMenu(final ToolbarPopupMenu.DynamicPopupMenuCallback callback) {
            server_.getEnvironmentNames(new ServerRequestCallback<JsArray<EnvironmentFrame>>() {
                @Override
                public void onResponseReceived(JsArray<EnvironmentFrame> response) {
                    setEnvironments(response);
                    callback.onPopupMenu(environmentMenu_);
                }

                @Override
                public void onError(ServerError error) {
                    // Just live with a stale list.
                    callback.onPopupMenu(environmentMenu_);
                }
            });
        }
    }

    public static final String GLOBAL_ENVIRONMENT_NAME = "Global Environment";

    private final Commands commands_;
    private final EventBus eventBus_;
    private final GlobalDisplay globalDisplay_;
    private final EnvironmentServerOperations server_;
    private final UIPrefs prefs_;

    private ToolbarButton dataImportButton_;
    private ToolbarPopupMenu environmentMenu_;
    private ToolbarButton environmentButton_;
    private ToolbarButton viewButton_;
    private EnvironmentObjects objects_;

    private ArrayList<String> expandedObjects_;
    private int scrollPosition_;
    private boolean isClientStateDirty_;
    private JsArray<EnvironmentFrame> environments_;
    private String environmentName_;
    private boolean environmentIsLocal_;
}