gt:          msg.append(" over your ");
context: /*
   * Workbench.java
   *
   * Copyright (C) 2020 by RStudio, PBC
   *
   * 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;
  
  import com.google.gwt.core.client.GWT;
  import com.google.gwt.core.client.Scheduler;
  import com.google.gwt.user.client.Command;
  import com.google.inject.Inject;
  import com.google.inject.Provider;
  
  import org.rstudio.core.client.BrowseCap;
  import org.rstudio.core.client.Size;
  import org.rstudio.core.client.StringUtil;
  import org.rstudio.core.client.TimeBufferedCommand;
  import org.rstudio.core.client.command.AppCommand;
  import org.rstudio.core.client.command.CommandBinder;
  import org.rstudio.core.client.command.Handler;
  import org.rstudio.core.client.files.FileSystemItem;
  import org.rstudio.core.client.files.filedialog.events.OpenFileDialogEvent;
  import org.rstudio.core.client.widget.ModifyKeyboardShortcutsWidget;
  import org.rstudio.core.client.widget.Operation;
  import org.rstudio.core.client.widget.OperationWithInput;
  import org.rstudio.core.client.widget.ProgressIndicator;
  import org.rstudio.core.client.widget.ProgressOperationWithInput;
  import org.rstudio.studio.client.RStudioGinjector;
  import org.rstudio.studio.client.application.ApplicationVisibility;
  import org.rstudio.studio.client.application.Desktop;
  import org.rstudio.studio.client.application.events.DeferredInitCompletedEvent;
  import org.rstudio.studio.client.application.events.EventBus;
  import org.rstudio.studio.client.common.ConsoleDispatcher;
  import org.rstudio.studio.client.common.FileDialogs;
  import org.rstudio.studio.client.common.GlobalDisplay;
  import org.rstudio.studio.client.common.GlobalDisplay.NewWindowOptions;
  import org.rstudio.studio.client.common.GlobalProgressDelayer;
  import org.rstudio.studio.client.common.SimpleRequestCallback;
  import org.rstudio.studio.client.common.dependencies.DependencyManager;
  import org.rstudio.studio.client.common.filetypes.FileTypeRegistry;
  import org.rstudio.studio.client.common.rstudioapi.AskSecretManager;
  import org.rstudio.studio.client.common.vcs.AskPassManager;
  import org.rstudio.studio.client.common.vcs.ShowPublicKeyDialog;
  import org.rstudio.studio.client.common.vcs.VCSConstants;
  import org.rstudio.studio.client.htmlpreview.HTMLPreview;
  import org.rstudio.studio.client.htmlpreview.events.ShowHTMLPreviewEvent;
  import org.rstudio.studio.client.htmlpreview.events.ShowPageViewerEvent;
  import org.rstudio.studio.client.htmlpreview.model.HTMLPreviewParams;
  import org.rstudio.studio.client.pdfviewer.PDFViewer;
  import org.rstudio.studio.client.plumber.PlumberAPI;
  import org.rstudio.studio.client.projects.ProjectOpener;
  import org.rstudio.studio.client.projects.model.ProjectTemplateRegistryProvider;
  import org.rstudio.studio.client.rmarkdown.RmdOutput;
  import org.rstudio.studio.client.rmarkdown.events.ShinyGadgetDialogEvent;
  import org.rstudio.studio.client.server.Server;
  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.server.VoidServerRequestCallback;
  import org.rstudio.studio.client.server.remote.ExecuteUserCommandEvent;
  import org.rstudio.studio.client.shiny.ShinyApplication;
  import org.rstudio.studio.client.shiny.ui.ShinyGadgetDialog;
  import org.rstudio.studio.client.workbench.commands.Commands;
  import org.rstudio.studio.client.workbench.commands.ReportShortcutBindingEvent;
  import org.rstudio.studio.client.workbench.events.*;
  import org.rstudio.studio.client.workbench.events.ShowMainMenuEvent.Menu;
  import org.rstudio.studio.client.workbench.model.*;
  import org.rstudio.studio.client.workbench.prefs.model.UserPrefs;
  import org.rstudio.studio.client.workbench.views.choosefile.ChooseFile;
  import org.rstudio.studio.client.workbench.views.files.events.DirectoryNavigateEvent;
  import org.rstudio.studio.client.workbench.views.source.SourceWindowManager;
  import org.rstudio.studio.client.workbench.views.source.editors.profiler.ProfilerPresenter;
  import org.rstudio.studio.client.workbench.views.terminal.events.ActivateNamedTerminalEvent;
  import org.rstudio.studio.client.workbench.views.tutorial.TutorialPresenter.Tutorial;
  import org.rstudio.studio.client.workbench.views.tutorial.events.TutorialCommandEvent;
  import org.rstudio.studio.client.workbench.views.tutorial.events.TutorialLaunchEvent;
  import org.rstudio.studio.client.workbench.views.vcs.git.model.GitState;
  
  public class Workbench implements BusyEvent.Handler,
                                    ShowErrorMessageEvent.Handler,
                                    UserPromptEvent.Handler,
                                    ShowWarningBarEvent.Handler,
                                    BrowseUrlEvent.Handler,
                                    QuotaStatusEvent.Handler,
                                    WorkbenchLoadedEvent.Handler,
                                    WorkbenchMetricsChangedEvent.Handler,
                                    InstallRtoolsEvent.Handler,
                                    ShinyGadgetDialogEvent.Handler,
                                    ExecuteUserCommandEvent.Handler,
                                    AdminNotificationEvent.Handler,
                                    OpenFileDialogEvent.Handler,
                                    ShowPageViewerEvent.Handler,
                                    TutorialLaunchEvent.Handler,
                                    DeferredInitCompletedEvent.Handler,
                                    ReportShortcutBindingEvent.Handler
  {
     interface Binder extends CommandBinder<Commands, Workbench> {}
  
     @Inject
     public Workbench(WorkbenchMainView view,
                      WorkbenchContext workbenchContext,
                      GlobalDisplay globalDisplay,
                      Commands commands,
                      EventBus eventBus,
                      Session session,
                      Provider<UserPrefs> pPrefs,
                      Server server,
                      RemoteFileSystemContext fsContext,
                      FileDialogs fileDialogs,
                      FileTypeRegistry fileTypeRegistry,
                      ConsoleDispatcher consoleDispatcher,
                      WorkbenchNewSession newSession,
                      ProjectOpener projectOpener,
                      Provider<GitState> pGitState,
                      SourceWindowManager sourceWindowManager,
                      UserInterfaceHighlighter highlighter,       // force gin to create
                      ChooseFile chooseFile,                      // force gin to create
                      AskPassManager askPass,                     // force gin to create
                      PDFViewer pdfViewer,                        // force gin to create
                      HTMLPreview htmlPreview,                    // force gin to create
                      ProfilerPresenter prof,                     // force gin to create
                      ShinyApplication sApp,                      // force gin to create
                      PlumberAPI sAPI,                            // force gin to create
                      DependencyManager dm,                       // force gin to create
                      ApplicationVisibility av,                   // force gin to create
                      RmdOutput rmdOutput,                        // force gin to create
                      ProjectTemplateRegistryProvider provider,   // force gin to create
                      WorkbenchServerOperations serverOperations, // force gin to create
                      AskSecretManager askSecret)                 // force gin to create
    {
        view_ = view;
        workbenchContext_ = workbenchContext;
        projectOpener_ = projectOpener;
        globalDisplay_ = globalDisplay;
        commands_ = commands;
        eventBus_ = eventBus;
        session_ = session;
        pPrefs_ = pPrefs;
        server_ = server;
        fsContext_ = fsContext;
        fileDialogs_ = fileDialogs;
        fileTypeRegistry_ = fileTypeRegistry;
        consoleDispatcher_ = consoleDispatcher;
        pGitState_ = pGitState;
        newSession_ = newSession;
        serverOperations_ = serverOperations;
        sourceWindowManager_ = sourceWindowManager;
  
        ((Binder)GWT.create(Binder.class)).bind(commands, this);
  
        // edit
        eventBus.addHandler(BusyEvent.TYPE, this);
        eventBus.addHandler(ShowErrorMessageEvent.TYPE, this);
        eventBus.addHandler(UserPromptEvent.TYPE, this);
        eventBus.addHandler(ShowWarningBarEvent.TYPE, this);
        eventBus.addHandler(BrowseUrlEvent.TYPE, this);
        eventBus.addHandler(QuotaStatusEvent.TYPE, this);
        eventBus.addHandler(WorkbenchLoadedEvent.TYPE, this);
        eventBus.addHandler(WorkbenchMetricsChangedEvent.TYPE, this);
        eventBus.addHandler(InstallRtoolsEvent.TYPE, this);
        eventBus.addHandler(ShinyGadgetDialogEvent.TYPE, this);
        eventBus.addHandler(ExecuteUserCommandEvent.TYPE, this);
        eventBus.addHandler(AdminNotificationEvent.TYPE, this);
        eventBus.addHandler(OpenFileDialogEvent.TYPE, this);
        eventBus.addHandler(ShowPageViewerEvent.TYPE, this);
        eventBus.addHandler(TutorialLaunchEvent.TYPE, this);
        eventBus.addHandler(DeferredInitCompletedEvent.TYPE, this);
        eventBus.addHandler(ReportShortcutBindingEvent.TYPE, this);
  
        // We don't want to send setWorkbenchMetrics more than once per 1/2-second
        metricsChangedCommand_ = new TimeBufferedCommand(500)
        {
           @Override
           protected void performAction(boolean shouldSchedulePassive)
           {
              assert !shouldSchedulePassive;
  
              server_.setWorkbenchMetrics(lastWorkbenchMetrics_,
                                          new VoidServerRequestCallback());
           }
        };
     }
  
     public WorkbenchMainView getMainView()
     {
        return view_;
     }
  
     public void onWorkbenchLoaded(WorkbenchLoadedEvent event)
     {
        server_.initializeForMainWorkbench();
  
        FileSystemItem defaultDialogDir =
              session_.getSessionInfo().getActiveProjectDir();
        if (defaultDialogDir != null)
           workbenchContext_.setDefaultFileDialogDir(defaultDialogDir);
  
        checkForInitMessages();
        checkForLicenseMessage();
  
        RStudioGinjector.INSTANCE.getFocusVisiblePolyfill().load(null);
  
        if (Desktop.isDesktop() &&
            StringUtil.equals(session_.getSessionInfo().getVcsName(), VCSConstants.GIT_ID))
        {
           pGitState_.get().addVcsRefreshHandler(vcsRefreshEvent ->
           {
              String title = workbenchContext_.createWindowTitle();
              if (title != null)
                 Desktop.getFrame().setWindowTitle(title);
           });
        }
     }
  
     public void onTutorialLaunch(final TutorialLaunchEvent event)
     {
        commands_.activateTutorial().execute();
  
        Tutorial tutorial = event.getTutorial();
        Scheduler.get().scheduleDeferred(() -> {
  
           TutorialCommandEvent commandEvent = new TutorialCommandEvent(
                 TutorialCommandEvent.TYPE_LAUNCH_DEFAULT_TUTORIAL,
                 tutorial.toJsObject());
  
           eventBus_.fireEvent(commandEvent);
  
        });
     }
  
     public void onDeferredInitCompleted(DeferredInitCompletedEvent ev)
     {
        checkForCrashHandlerPermission();
     }
  
     public void onBusy(BusyEvent event)
     {
     }
  
     public void onShowErrorMessage(ShowErrorMessageEvent event)
     {
        ErrorMessage errorMessage = event.getErrorMessage();
        globalDisplay_.showErrorMessage(errorMessage.getTitle(),
                                        errorMessage.getMessage());
  
     }
  
     @Override
     public void onShowWarningBar(ShowWarningBarEvent event)
     {
        globalDisplay_.showWarningBar(event.isSevere(), event.getMessage());
     }
  
     public void onBrowseUrl(BrowseUrlEvent event)
     {
        BrowseUrlInfo urlInfo = event.getUrlInfo();
        NewWindowOptions newWindowOptions = new NewWindowOptions();
        newWindowOptions.setName(urlInfo.getWindow());
        globalDisplay_.openWindow(urlInfo.getUrl(), newWindowOptions);
     }
  
     public void onWorkbenchMetricsChanged(WorkbenchMetricsChangedEvent event)
     {
        lastWorkbenchMetrics_ = event.getWorkbenchMetrics();
        metricsChangedCommand_.nudge();
     }
  
     public void onQuotaStatus(QuotaStatusEvent event)
     {
        QuotaStatus quotaStatus = event.getQuotaStatus();
  
        // always show warning if the user is over quota
        if (quotaStatus.isOverQuota())
        {
           long over = quotaStatus.getUsed() - quotaStatus.getQuota();
           StringBuilder msg = new StringBuilder();
           msg.append("You are ");
           msg.append(StringUtil.formatFileSize(over));
  