org.rstudio.studio.client.application.ui.impl.WebApplicationHeader.java Source code

Java tutorial

Introduction

Here is the source code for org.rstudio.studio.client.application.ui.impl.WebApplicationHeader.java

Source

/*
 * WebApplicationHeader.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.application.ui.impl;

import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.user.client.ui.*;
import com.google.inject.Inject;
import com.google.inject.Provider;

import org.rstudio.core.client.BrowseCap;
import org.rstudio.core.client.command.*;
import org.rstudio.core.client.command.impl.WebMenuCallback;
import org.rstudio.core.client.theme.res.ThemeResources;
import org.rstudio.core.client.theme.res.ThemeStyles;
import org.rstudio.core.client.widget.HyperlinkLabel;
import org.rstudio.core.client.widget.MessageDialogLabel;
import org.rstudio.core.client.widget.ToolbarButton;
import org.rstudio.core.client.widget.events.GlassVisibilityEvent;
import org.rstudio.studio.client.RStudioGinjector;
import org.rstudio.studio.client.application.events.EventBus;
import org.rstudio.studio.client.application.events.LogoutRequestedEvent;
import org.rstudio.studio.client.application.ui.ApplicationHeader;
import org.rstudio.studio.client.application.ui.GlobalToolbar;
import org.rstudio.studio.client.application.ui.ProjectPopupMenu;
import org.rstudio.studio.client.application.ui.impl.header.HeaderPanel;
import org.rstudio.studio.client.application.ui.impl.header.MenubarPanel;
import org.rstudio.studio.client.common.GlobalDisplay;
import org.rstudio.studio.client.common.dialog.WebDialogBuilderFactory;
import org.rstudio.studio.client.workbench.codesearch.CodeSearch;
import org.rstudio.studio.client.workbench.commands.Commands;
import org.rstudio.studio.client.workbench.events.SessionInitEvent;
import org.rstudio.studio.client.workbench.events.SessionInitHandler;
import org.rstudio.studio.client.workbench.model.Session;
import org.rstudio.studio.client.workbench.model.SessionInfo;

public class WebApplicationHeader extends Composite implements ApplicationHeader {
    public WebApplicationHeader() {
        RStudioGinjector.INSTANCE.injectMembers(this);
    }

    @Inject
    public void initialize(final Commands commands, EventBus eventBus, GlobalDisplay globalDisplay,
            ThemeResources themeResources, final Session session, Provider<CodeSearch> pCodeSearch) {
        eventBus_ = eventBus;
        globalDisplay_ = globalDisplay;

        // Use the outer panel to just aggregate the menu bar/account area,
        // with the logo. The logo can't be inside the HorizontalPanel because
        // it needs to overflow out of the top of the panel, and it was much
        // easier to do this with absolute positioning.
        outerPanel_ = new FlowPanel();
        outerPanel_.getElement().getStyle().setPosition(Position.RELATIVE);

        // large logo
        logoLarge_ = new Image(ThemeResources.INSTANCE.rstudio());
        ((ImageElement) logoLarge_.getElement().cast()).setAlt("RStudio");
        Style style = logoLarge_.getElement().getStyle();
        style.setPosition(Position.ABSOLUTE);
        style.setTop(5, Unit.PX);
        style.setLeft(18, Unit.PX);

        // small logo
        logoSmall_ = new Image(ThemeResources.INSTANCE.rstudio_small());
        ((ImageElement) logoSmall_.getElement().cast()).setAlt("RStudio");
        style = logoSmall_.getElement().getStyle();
        style.setPosition(Position.ABSOLUTE);
        style.setTop(5, Unit.PX);
        style.setLeft(18, Unit.PX);

        // header container
        headerBarPanel_ = new HorizontalPanel();
        headerBarPanel_.setStylePrimaryName(themeResources.themeStyles().header());
        headerBarPanel_.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
        headerBarPanel_.setWidth("100%");

        if (BrowseCap.INSTANCE.suppressBrowserForwardBack())
            suppressBrowserForwardBack();

        // override Cmd+W keybaord shortcut for Chrome
        if (BrowseCap.isChrome()) {
            int modifiers = (BrowseCap.hasMetaKey() ? KeyboardShortcut.META : KeyboardShortcut.CTRL)
                    | KeyboardShortcut.ALT;

            AppCommand closeSourceDoc = commands.closeSourceDoc();
            closeSourceDoc.setShortcut(new KeyboardShortcut(modifiers, 'W'));
            ShortcutManager.INSTANCE.register(modifiers, 'W', closeSourceDoc, "", "", "");
        }

        // main menu
        advertiseEditingShortcuts(globalDisplay, commands);
        WebMenuCallback menuCallback = new WebMenuCallback();
        commands.mainMenu(menuCallback);
        mainMenu_ = menuCallback.getMenu();
        mainMenu_.setAutoHideRedundantSeparators(false);
        fixup(mainMenu_);
        mainMenu_.addStyleName(themeResources.themeStyles().mainMenu());
        AppMenuBar.addSubMenuVisibleChangedHandler(new SubMenuVisibleChangedHandler() {
            public void onSubMenuVisibleChanged(SubMenuVisibleChangedEvent event) {
                // When submenus of the main menu appear, glass over any iframes
                // so that mouse clicks can make the menus disappear
                if (event.isVisible())
                    eventBus_.fireEvent(new GlassVisibilityEvent(true));
                else
                    eventBus_.fireEvent(new GlassVisibilityEvent(false));
            }
        });
        headerBarPanel_.add(mainMenu_);

        HTML spacer = new HTML();
        headerBarPanel_.add(spacer);
        headerBarPanel_.setCellWidth(spacer, "100%");

        // commands panel (no widgets added until after session init)
        headerBarCommandsPanel_ = new HorizontalPanel();
        headerBarPanel_.add(headerBarCommandsPanel_);
        headerBarPanel_.setCellHorizontalAlignment(headerBarCommandsPanel_, HorizontalPanel.ALIGN_RIGHT);

        eventBus.addHandler(SessionInitEvent.TYPE, new SessionInitHandler() {
            public void onSessionInit(SessionInitEvent sie) {
                SessionInfo sessionInfo = session.getSessionInfo();

                // only show the user identity if we are in server mode
                if (sessionInfo.getShowIdentity())
                    initCommandsPanel(sessionInfo);

                // complete toolbar initialization
                toolbar_.completeInitialization(sessionInfo);

                // add project tools to main menu
                projectMenuButton_ = new ProjectPopupMenu(sessionInfo, commands).getToolbarButton();
                projectMenuButton_.addStyleName(ThemeStyles.INSTANCE.webHeaderBarCommandsProjectMenu());
                headerBarPanel_.add(projectMenuButton_);
                showProjectMenu(!toolbar_.isVisible());
            }
        });

        // create toolbar
        toolbar_ = new GlobalToolbar(commands, eventBus, pCodeSearch);
        toolbar_.addStyleName(themeResources.themeStyles().webGlobalToolbar());

        // initialize widget
        initWidget(outerPanel_);
    }

    public void showToolbar(boolean showToolbar) {
        outerPanel_.clear();

        if (showToolbar) {
            HeaderPanel headerPanel = new HeaderPanel(headerBarPanel_, toolbar_);
            outerPanel_.add(headerPanel);
            outerPanel_.add(logoLarge_);
            mainMenu_.getElement().getStyle().setMarginLeft(18, Unit.PX);
            preferredHeight_ = 65;
            showProjectMenu(false);
        } else {
            MenubarPanel menubarPanel = new MenubarPanel(headerBarPanel_);
            outerPanel_.add(menubarPanel);
            outerPanel_.add(logoSmall_);
            mainMenu_.getElement().getStyle().setMarginLeft(0, Unit.PX);
            preferredHeight_ = 45;
            showProjectMenu(true);
        }
    }

    public boolean isToolbarVisible() {
        return !projectMenuButton_.isVisible();
    }

    public void focusGoToFunction() {
        toolbar_.focusGoToFunction();
    }

    private void showProjectMenu(boolean show) {
        projectMenuButton_.setVisible(show);
    }

    private native final void suppressBrowserForwardBack() /*-{
                                                           try {
                                                           var outerWindow = $wnd.parent;
                                                           if (outerWindow.addEventListener) {
                                                           var handler = function(evt) {
                                                           if ((evt.keyCode == 37 || evt.keyCode == 39) && (evt.metaKey && !evt.ctrlKey && !evt.shiftKey && !evt.altKey)) {
                                                           evt.preventDefault();
                                                           evt.stopPropagation();
                                                           }
                                                           };
                                                           outerWindow.addEventListener('keydown', handler, false);
                                                           $wnd.addEventListener('keydown', handler, false);
                                                           }
                                                           } catch(err) {}
                                                           }-*/;

    private void advertiseEditingShortcuts(final GlobalDisplay display, final Commands commands) {
        int mod = BrowseCap.hasMetaKey() ? KeyboardShortcut.META : KeyboardShortcut.CTRL;

        commands.undoDummy().setShortcut(new KeyboardShortcut(mod, 'Z'));
        commands.redoDummy().setShortcut(new KeyboardShortcut(mod | KeyboardShortcut.SHIFT, 'Z'));

        commands.cutDummy().setShortcut(new KeyboardShortcut(mod, 'X'));
        commands.copyDummy().setShortcut(new KeyboardShortcut(mod, 'C'));
        commands.pasteDummy().setShortcut(new KeyboardShortcut(mod, 'V'));

        CommandHandler useKeyboardNotification = new CommandHandler() {
            public void onCommand(AppCommand command) {
                MessageDialogLabel label = new MessageDialogLabel();
                label.setHtml("Your browser does not allow access to your<br/>"
                        + "computer's clipboard. As a result you must<br/>" + "use keyboard shortcuts for:"
                        + "<br/><br/><table cellpadding=0 cellspacing=0 border=0>" + makeRow(commands.undoDummy())
                        + makeRow(commands.redoDummy()) + makeRow(commands.cutDummy())
                        + makeRow(commands.copyDummy()) + makeRow(commands.pasteDummy()) + "</table>");
                new WebDialogBuilderFactory().create(GlobalDisplay.MSG_WARNING, "Use Keyboard Shortcut", label)
                        .showModal();
            }

            private String makeRow(AppCommand cmd) {
                String textAlign = BrowseCap.hasMetaKey() ? "text-align: right" : "";
                return "<tr><td>" + cmd.getMenuLabel(true) + "</td>" + "<td style='padding-left: 12px; " + textAlign
                        + "'>" + cmd.getShortcutPrettyHtml() + "</td></tr>";
            }
        };

        commands.undoDummy().addHandler(useKeyboardNotification);
        commands.redoDummy().addHandler(useKeyboardNotification);
        commands.cutDummy().addHandler(useKeyboardNotification);
        commands.copyDummy().addHandler(useKeyboardNotification);
        commands.pasteDummy().addHandler(useKeyboardNotification);
    }

    public int getPreferredHeight() {
        return preferredHeight_;
    }

    /**
     * Without this fixup, the main menu doesn't properly deselect its items
     * when the mouse takes focus away.
     */
    private void fixup(final AppMenuBar mainMenu) {
        mainMenu.addCloseHandler(new CloseHandler<PopupPanel>() {
            public void onClose(CloseEvent<PopupPanel> popupPanelCloseEvent) {
                // Only dismiss the selection if the panel that just closed belongs
                // to the currently selected item. Otherwise, the selected item
                // has already changed and we don't want to mess with it. (This is
                // NOT an edge case, it is very common.)
                MenuItem menuItem = mainMenu.getSelectedItem();
                if (menuItem != null) {
                    MenuBar subMenu = menuItem.getSubMenu();
                    if (subMenu != null && popupPanelCloseEvent.getTarget() != null
                            && subMenu.equals(popupPanelCloseEvent.getTarget().getWidget())) {
                        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
                            public void execute() {
                                mainMenu.selectItem(null);
                            }
                        });
                    }
                }
            }
        });
    }

    private void initCommandsPanel(final SessionInfo sessionInfo) {
        // add username 
        Label usernameLabel = new Label();
        usernameLabel.setText(sessionInfo.getUserIdentity());
        headerBarCommandsPanel_.add(usernameLabel);
        headerBarCommandsPanel_.add(createCommandSeparator());

        // signout link 
        Widget signoutLink = createCommandLink("Sign Out", new ClickHandler() {
            public void onClick(ClickEvent event) {
                eventBus_.fireEvent(new LogoutRequestedEvent());
            }
        });
        headerBarCommandsPanel_.add(signoutLink);
    }

    private Widget createCommandSeparator() {
        return new HTML("&nbsp;|&nbsp;");
    }

    private Widget createCommandLink(String caption, ClickHandler clickHandler) {
        HyperlinkLabel link = new HyperlinkLabel(caption, clickHandler);
        return link;
    }

    public Widget asWidget() {
        return this;
    }

    private int preferredHeight_;
    private FlowPanel outerPanel_;
    private Image logoLarge_;
    private Image logoSmall_;
    private HorizontalPanel headerBarPanel_;
    private HorizontalPanel headerBarCommandsPanel_;
    private ToolbarButton projectMenuButton_;
    private AppMenuBar mainMenu_;
    private GlobalToolbar toolbar_;
    private EventBus eventBus_;
    private GlobalDisplay globalDisplay_;

}