1 /* 2 * GeneralPreferencesPane.java 3 * 4 * Copyright (C) 2021 by RStudio, PBC 5 * 6 * Unless you have received this program directly from RStudio pursuant 7 * to the terms of a commercial license agreement with RStudio, then 8 * this program is licensed to you under the terms of version 3 of the 9 * GNU Affero General Public License. This program is distributed WITHOUT 10 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, 11 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the 12 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details. 13 * 14 */ 15 package org.rstudio.studio.client.workbench.prefs.views; 16 17 import com.google.gwt.event.dom.client.ChangeEvent; 18 import com.google.gwt.event.dom.client.ClickEvent; 19 import com.google.gwt.event.dom.client.ClickHandler; 20 21 import java.util.HashMap; 22 import java.util.Map; 23 24 import org.rstudio.core.client.BrowseCap; 25 import org.rstudio.core.client.ElementIds; 26 import org.rstudio.core.client.StringUtil; 27 import org.rstudio.core.client.files.FileSystemContext; 28 import org.rstudio.core.client.prefs.PreferencesDialogBaseResources; 29 import org.rstudio.core.client.prefs.RestartRequirement; 30 import org.rstudio.core.client.resources.ImageResource2x; 31 import org.rstudio.core.client.theme.DialogTabLayoutPanel; 32 import org.rstudio.core.client.theme.VerticalTabPanel; 33 import org.rstudio.core.client.widget.DirectoryChooserTextBox; 34 import org.rstudio.core.client.widget.MessageDialog; 35 import org.rstudio.core.client.widget.SelectWidget; 36 import org.rstudio.core.client.widget.TextBoxWithButton; 37 import org.rstudio.studio.client.RStudioGinjector; 38 import org.rstudio.studio.client.application.Desktop; 39 import org.rstudio.studio.client.application.model.RVersionSpec; 40 import org.rstudio.studio.client.application.model.RVersionsInfo; 41 import org.rstudio.studio.client.application.ui.RVersionSelectWidget; 42 import org.rstudio.studio.client.common.FileDialogs; 43 import org.rstudio.studio.client.common.GlobalDisplay; 44 import org.rstudio.studio.client.workbench.WorkbenchContext; 45 import org.rstudio.studio.client.workbench.model.RemoteFileSystemContext; 46 import org.rstudio.studio.client.workbench.model.Session; 47 import org.rstudio.studio.client.workbench.prefs.model.UserPrefs; 48 49 import com.google.gwt.core.client.JsArrayString; 50 import com.google.gwt.dom.client.Style; 51 import com.google.gwt.dom.client.Style.Unit; 52 import com.google.gwt.resources.client.ImageResource; 53 import com.google.gwt.user.client.ui.CheckBox; 54 import com.google.gwt.user.client.ui.Label; 55 import com.google.inject.Inject; 56 57 public class GeneralPreferencesPane extends PreferencesPane 58 { 59 @Inject GeneralPreferencesPane(RemoteFileSystemContext fsContext, FileDialogs fileDialogs, UserPrefs prefs, Session session, GlobalDisplay globalDisplay, WorkbenchContext context)60 public GeneralPreferencesPane(RemoteFileSystemContext fsContext, 61 FileDialogs fileDialogs, 62 UserPrefs prefs, 63 Session session, 64 GlobalDisplay globalDisplay, 65 WorkbenchContext context) 66 { 67 fsContext_ = fsContext; 68 fileDialogs_ = fileDialogs; 69 prefs_ = prefs; 70 session_ = session; 71 72 RVersionsInfo versionsInfo = context.getRVersionsInfo(); 73 VerticalTabPanel basic = new VerticalTabPanel(ElementIds.GENERAL_BASIC_PREFS); 74 75 basic.add(headerLabel("R Sessions")); 76 if (BrowseCap.isWindowsDesktop()) 77 { 78 rVersion_ = new TextBoxWithButton( 79 "R version:", 80 "", 81 "Change...", 82 null, 83 ElementIds.TextBoxButtonId.R_VERSION, 84 true, 85 new ClickHandler() 86 { 87 @Override 88 public void onClick(ClickEvent event) 89 { 90 Desktop.getFrame().chooseRVersion(ver -> 91 { 92 if (!StringUtil.isNullOrEmpty(ver)) 93 { 94 rVersion_.setText(ver); 95 96 globalDisplay.showMessage(MessageDialog.INFO, 97 "Change R Version", 98 "You need to quit and re-open RStudio " + 99 "in order for this change to take effect."); 100 } 101 }); 102 } 103 }); 104 rVersion_.setWidth("100%"); 105 rVersion_.setText("Loading..."); 106 rVersion_.getElement().getStyle().setMarginLeft(2, Unit.PX); 107 Desktop.getFrame().getRVersion(version -> { 108 rVersion_.setText(version); 109 }); 110 spaced(rVersion_); 111 basic.add(rVersion_); 112 } 113 if (versionsInfo.isMultiVersion()) 114 { 115 rServerRVersion_ = new RVersionSelectWidget( 116 versionsInfo.getAvailableRVersions()); 117 basic.add(tight(rServerRVersion_)); 118 119 rememberRVersionForProjects_ = 120 new CheckBox("Restore last used R version for projects"); 121 122 rememberRVersionForProjects_.setValue(true); 123 Style style = rememberRVersionForProjects_.getElement().getStyle(); 124 style.setMarginTop(5, Unit.PX); 125 style.setMarginBottom(12, Unit.PX); 126 basic.add(rememberRVersionForProjects_); 127 } 128 129 dirChooser_ = new DirectoryChooserTextBox( 130 "Default working directory (when not in a project):", 131 ElementIds.TextBoxButtonId.DEFAULT_WORKING_DIR, 132 null, 133 fileDialogs_, 134 fsContext_); 135 136 spaced(dirChooser_); 137 nudgeRight(dirChooser_); 138 textBoxWithChooser(dirChooser_); 139 basic.add(dirChooser_); 140 141 restoreLastProject_ = new CheckBox("Restore most recently opened project at startup"); 142 lessSpaced(restoreLastProject_); 143 basic.add(restoreLastProject_); 144 145 basic.add(checkboxPref("Restore previously open source documents at startup", prefs_.restoreSourceDocuments())); 146 147 rProfileOnResume_ = new CheckBox("Run Rprofile when resuming suspended session"); 148 if (!Desktop.isDesktop()) 149 basic.add(rProfileOnResume_); 150 151 basic.add(spacedBefore(headerLabel("Workspace"))); 152 basic.add(loadRData_ = new CheckBox("Restore .RData into workspace at startup")); 153 lessSpaced(loadRData_); 154 155 saveWorkspace_ = new SelectWidget( 156 "Save workspace to .RData on exit:", 157 new String[] 158 { 159 "Always", 160 "Never", 161 "Ask" 162 }, 163 new String[] 164 { 165 UserPrefs.SAVE_WORKSPACE_ALWAYS, 166 UserPrefs.SAVE_WORKSPACE_NEVER, 167 UserPrefs.SAVE_WORKSPACE_ASK 168 }, false, true, false); 169 spaced(saveWorkspace_); 170 basic.add(saveWorkspace_); 171 172 basic.add(headerLabel("History")); 173 alwaysSaveHistory_ = new CheckBox( 174 "Always save history (even when not saving .RData)"); 175 lessSpaced(alwaysSaveHistory_); 176 basic.add(alwaysSaveHistory_); 177 178 removeHistoryDuplicates_ = new CheckBox( 179 "Remove duplicate entries in history"); 180 basic.add(removeHistoryDuplicates_); 181 182 basic.add(spacedBefore(headerLabel("Other"))); 183 184 basic.add(checkboxPref( 185 "Wrap around when navigating to previous/next tab", 186 prefs_.wrapTabNavigation(), 187 true /*defaultSpaced*/)); 188 189 // provide check for updates option in desktop mode when not 190 // already globally disabled 191 if (Desktop.isDesktop() && 192 !session.getSessionInfo().getDisableCheckForUpdates()) 193 { 194 basic.add(checkboxPref("Automatically notify me of updates to RStudio", 195 prefs_.checkForUpdates(), true /*defaultSpaced*/)); 196 } 197 198 // crash reporting - only show in desktop mode 199 enableCrashReporting_ = checkboxPref("Send automated crash reports to RStudio", 200 prefs_.submitCrashReports()); 201 if (Desktop.isDesktop()) 202 { 203 lessSpaced(enableCrashReporting_); 204 enableCrashReporting_.setEnabled(session.getSessionInfo().getCrashHandlerSettingsModifiable()); 205 basic.add(enableCrashReporting_); 206 } 207 208 VerticalTabPanel graphics = new VerticalTabPanel(ElementIds.GENERAL_GRAPHICS_PREFS); 209 210 initializeGraphicsBackendWidget(); 211 graphics.add(headerLabel("Graphics Device")); 212 graphics.add(graphicsBackend_); 213 214 graphicsAntialias_ = new SelectWidget( 215 "Antialiasing:", 216 new String[] { 217 "(Default)", 218 "None", 219 "Gray", 220 "Subpixel" 221 }, 222 new String[] { 223 UserPrefs.GRAPHICS_ANTIALIASING_DEFAULT, 224 UserPrefs.GRAPHICS_ANTIALIASING_NONE, 225 UserPrefs.GRAPHICS_ANTIALIASING_GRAY, 226 UserPrefs.GRAPHICS_ANTIALIASING_SUBPIXEL 227 }, 228 false, 229 true, 230 false); 231 232 graphics.add(graphicsAntialias_); 233 234 VerticalTabPanel advanced = new VerticalTabPanel(ElementIds.GENERAL_ADVANCED_PREFS); 235 236 showServerHomePage_ = new SelectWidget( 237 "Show server home page:", 238 new String[] { 239 "Multiple active sessions", 240 "Always", 241 "Never" 242 }, 243 new String[] { 244 "sessions", 245 "always", 246 "never" 247 }, 248 false, 249 true, 250 false); 251 252 reuseSessionsForProjectLinks_ = new CheckBox("Re-use idle sessions for project links"); 253 lessSpaced(reuseSessionsForProjectLinks_); 254 boolean firstHeader = true; 255 256 if (!Desktop.hasDesktopFrame()) 257 { 258 if (session_.getSessionInfo().getShowUserHomePage() || 259 session_.getSessionInfo().getMultiSession()) 260 { 261 Label homePageLabel = headerLabel("Home Page"); 262 spacedBefore(homePageLabel); 263 advanced.add(homePageLabel); 264 firstHeader = false; 265 } 266 if (session_.getSessionInfo().getShowUserHomePage()) 267 { 268 tight(showServerHomePage_); 269 advanced.add(showServerHomePage_); 270 } 271 if (session_.getSessionInfo().getMultiSession()) 272 advanced.add(reuseSessionsForProjectLinks_); 273 } 274 275 Label debuggingLabel = headerLabel("Debugging"); 276 if (!firstHeader) 277 { 278 spacedBefore(debuggingLabel); 279 firstHeader = false; 280 } 281 advanced.add(debuggingLabel); 282 advanced.add(checkboxPref( 283 "Use debug error handler only when my code contains errors", 284 prefs_.handleErrorsInUserCodeOnly())); 285 286 if (Desktop.hasDesktopFrame()) 287 { 288 Label osLabel = headerLabel("OS Integration"); 289 spacedBefore(osLabel); 290 advanced.add(osLabel); 291 292 renderingEngineWidget_ = new SelectWidget("Rendering engine:", new String[] {}); 293 renderingEngineWidget_.addChoice("Auto-detect (recommended)", ENGINE_AUTO); 294 renderingEngineWidget_.addChoice("Desktop OpenGL", ENGINE_DESKTOP); 295 if (BrowseCap.isLinuxDesktop()) 296 { 297 renderingEngineWidget_.addChoice("OpenGL for Embedded Systems", ENGINE_GLES); 298 } 299 renderingEngineWidget_.addChoice("Software", ENGINE_SOFTWARE); 300 advanced.add(spaced(renderingEngineWidget_)); 301 302 Desktop.getFrame().desktopRenderingEngine((String engine) -> { 303 if (StringUtil.isNullOrEmpty(engine)) 304 return; 305 renderingEngineWidget_.setValue(engine); 306 renderingEngine_ = engine; 307 }); 308 309 useGpuExclusions_ = new CheckBox("Use GPU exclusion list (recommended)"); 310 advanced.add(lessSpaced(useGpuExclusions_)); 311 Desktop.getFrame().getIgnoreGpuExclusionList((Boolean ignore) -> { 312 desktopIgnoreGpuExclusions_ = ignore; 313 useGpuExclusions_.setValue(!ignore); 314 }); 315 316 useGpuDriverBugWorkarounds_ = new CheckBox("Use GPU driver bug workarounds (recommended)"); 317 advanced.add(lessSpaced(useGpuDriverBugWorkarounds_)); 318 Desktop.getFrame().getDisableGpuDriverBugWorkarounds((Boolean disable) -> { 319 desktopDisableGpuDriverBugWorkarounds_ = disable; 320 useGpuDriverBugWorkarounds_.setValue(!disable); 321 }); 322 323 if (BrowseCap.isLinuxDesktop()) 324 { 325 clipboardMonitoring_ = new CheckBox("Enable X11 clipboard monitoring"); 326 advanced.add(lessSpaced(clipboardMonitoring_)); 327 Desktop.getFrame().getClipboardMonitoring(monitoring -> 328 { 329 desktopMonitoring_ = monitoring; 330 clipboardMonitoring_.setValue(monitoring); 331 }); 332 } 333 334 fullPathInTitle_ = new CheckBox("Show full path to project in window title"); 335 advanced.add(lessSpaced(fullPathInTitle_)); 336 } 337 338 Label otherLabel = headerLabel("Other"); 339 spacedBefore(otherLabel); 340 advanced.add(otherLabel); 341 342 showLastDotValue_ = new CheckBox("Show .Last.value in environment listing"); 343 lessSpaced(showLastDotValue_); 344 advanced.add(showLastDotValue_); 345 346 String[] labels = {"7", "8", "9", "10", "11", "12", "13", "14", "16", "18", "24", "36"}; 347 String[] values = new String[labels.length]; 348 for (int i = 0; i < labels.length; i++) 349 values[i] = Double.parseDouble(labels[i]) + ""; 350 351 helpFontSize_ = new SelectWidget("Help panel font size:", 352 labels, 353 values, 354 false, /* Multi select */ 355 true, /* Horizontal label */ 356 false /* List on left */); 357 if (!helpFontSize_.setValue(prefs_.helpFontSizePoints().getValue() + "")) 358 helpFontSize_.getListBox().setSelectedIndex(3); 359 advanced.add(helpFontSize_); 360 361 showServerHomePage_.setEnabled(false); 362 reuseSessionsForProjectLinks_.setEnabled(false); 363 saveWorkspace_.setEnabled(false); 364 loadRData_.setEnabled(false); 365 dirChooser_.setEnabled(false); 366 alwaysSaveHistory_.setEnabled(false); 367 removeHistoryDuplicates_.setEnabled(false); 368 rProfileOnResume_.setEnabled(false); 369 showLastDotValue_.setEnabled(false); 370 restoreLastProject_.setEnabled(false); 371 372 DialogTabLayoutPanel tabPanel = new DialogTabLayoutPanel("General"); 373 tabPanel.setSize("435px", "533px"); 374 tabPanel.add(basic, "Basic", basic.getBasePanelId()); 375 tabPanel.add(graphics, "Graphics", graphics.getBasePanelId()); 376 tabPanel.add(advanced, "Advanced", advanced.getBasePanelId()); 377 tabPanel.selectTab(0); 378 add(tabPanel); 379 } 380 381 @Override initialize(UserPrefs prefs)382 protected void initialize(UserPrefs prefs) 383 { 384 boolean isLauncherSession = session_.getSessionInfo().getLauncherSession(); 385 showServerHomePage_.setEnabled(!isLauncherSession); 386 387 reuseSessionsForProjectLinks_.setEnabled(true); 388 saveWorkspace_.setEnabled(true); 389 loadRData_.setEnabled(true); 390 dirChooser_.setEnabled(true); 391 392 if (!isLauncherSession) 393 showServerHomePage_.setValue(prefs.showUserHomePage().getValue()); 394 else 395 showServerHomePage_.setValue(UserPrefs.SHOW_USER_HOME_PAGE_ALWAYS); 396 397 reuseSessionsForProjectLinks_.setValue(prefs.reuseSessionsForProjectLinks().getValue()); 398 399 int saveWorkspaceIndex; 400 switch (prefs.saveWorkspace().getValue()) 401 { 402 case UserPrefs.SAVE_WORKSPACE_NEVER: 403 saveWorkspaceIndex = 1; 404 break; 405 case UserPrefs.SAVE_WORKSPACE_ALWAYS: 406 saveWorkspaceIndex = 0; 407 break; 408 case UserPrefs.SAVE_WORKSPACE_ASK: 409 default: 410 saveWorkspaceIndex = 2; 411 break; 412 } 413 saveWorkspace_.getListBox().setSelectedIndex(saveWorkspaceIndex); 414 415 loadRData_.setValue(prefs.loadWorkspace().getValue()); 416 417 // NOTE: we intentionally ignore sessionInfo's version of the 418 // initial working directory here as that might reference a 419 // project-specific location, and we don't want that to end up 420 // encoded as part of the user's global preferences 421 String workingDir = prefs.initialWorkingDirectory().getValue(); 422 if (StringUtil.isNullOrEmpty(workingDir)) 423 workingDir = "~"; 424 425 dirChooser_.setText(workingDir); 426 427 alwaysSaveHistory_.setEnabled(true); 428 removeHistoryDuplicates_.setEnabled(true); 429 430 alwaysSaveHistory_.setValue(prefs.alwaysSaveHistory().getValue()); 431 removeHistoryDuplicates_.setValue(prefs.removeHistoryDuplicates().getValue()); 432 433 rProfileOnResume_.setValue(prefs.runRprofileOnResume().getValue()); 434 rProfileOnResume_.setEnabled(true); 435 436 showLastDotValue_.setValue(prefs.showLastDotValue().getValue()); 437 showLastDotValue_.setEnabled(true); 438 439 if (rServerRVersion_ != null) 440 rServerRVersion_.setRVersion(prefs.defaultRVersion().getValue().cast()); 441 442 if (rememberRVersionForProjects_ != null) 443 { 444 rememberRVersionForProjects_.setValue( 445 prefs.restoreProjectRVersion().getValue()); 446 } 447 448 if (fullPathInTitle_ != null) 449 fullPathInTitle_.setValue(prefs.fullProjectPathInWindowTitle().getValue()); 450 451 enableCrashReporting_.setValue(prefs.submitCrashReports().getValue()); 452 453 // projects prefs 454 restoreLastProject_.setEnabled(true); 455 restoreLastProject_.setValue(prefs.restoreLastProject().getValue()); 456 457 // graphics prefs 458 graphicsBackend_.setValue(prefs.graphicsBackend().getValue()); 459 graphicsAntialias_.setValue(prefs.graphicsAntialiasing().getValue()); 460 } 461 462 463 @Override getIcon()464 public ImageResource getIcon() 465 { 466 return new ImageResource2x(PreferencesDialogBaseResources.INSTANCE.iconR2x()); 467 } 468 469 @Override onApply(UserPrefs prefs)470 public RestartRequirement onApply(UserPrefs prefs) 471 { 472 RestartRequirement restartRequirement = super.onApply(prefs); 473 474 { 475 double helpFontSize = Double.parseDouble(helpFontSize_.getValue()); 476 prefs.helpFontSizePoints().setGlobalValue(helpFontSize); 477 } 478 479 if (clipboardMonitoring_ != null && 480 desktopMonitoring_ != clipboardMonitoring_.getValue()) 481 { 482 // set monitoring property if changed 483 restartRequirement.setDesktopRestartRequired(true); 484 boolean desktopMonitoring = clipboardMonitoring_.getValue(); 485 desktopMonitoring_ = desktopMonitoring; 486 Desktop.getFrame().setClipboardMonitoring(desktopMonitoring); 487 } 488 489 if (fullPathInTitle_ != null && 490 fullPathInTitle_.getValue() != prefs.fullProjectPathInWindowTitle().getValue()) 491 { 492 restartRequirement.setDesktopRestartRequired(true); 493 prefs.fullProjectPathInWindowTitle().setGlobalValue(fullPathInTitle_.getValue()); 494 } 495 496 if (renderingEngineWidget_ != null && 497 !StringUtil.equals(renderingEngineWidget_.getValue(), renderingEngine_)) 498 { 499 // set desktop renderer when changed 500 restartRequirement.setDesktopRestartRequired(true); 501 String renderingEngine = renderingEngineWidget_.getValue(); 502 renderingEngine_ = renderingEngine; 503 Desktop.getFrame().setDesktopRenderingEngine(renderingEngine); 504 } 505 506 if (useGpuExclusions_ != null && 507 desktopIgnoreGpuExclusions_ != !useGpuExclusions_.getValue()) 508 { 509 restartRequirement.setDesktopRestartRequired(true); 510 boolean ignore = !useGpuExclusions_.getValue(); 511 desktopIgnoreGpuExclusions_ = ignore; 512 Desktop.getFrame().setIgnoreGpuExclusionList(ignore); 513 } 514 515 if (useGpuDriverBugWorkarounds_ != null && 516 desktopDisableGpuDriverBugWorkarounds_ != !useGpuDriverBugWorkarounds_.getValue()) 517 { 518 restartRequirement.setDesktopRestartRequired(true); 519 boolean disable = !useGpuDriverBugWorkarounds_.getValue(); 520 desktopDisableGpuDriverBugWorkarounds_ = disable; 521 Desktop.getFrame().setDisableGpuDriverBugWorkarounds(disable); 522 } 523 524 if (saveWorkspace_.isEnabled()) 525 { 526 prefs.saveWorkspace().setGlobalValue(saveWorkspace_.getValue()); 527 } 528 529 prefs.loadWorkspace().setGlobalValue(loadRData_.getValue()); 530 prefs.runRprofileOnResume().setGlobalValue(rProfileOnResume_.getValue()); 531 prefs.initialWorkingDirectory().setGlobalValue(dirChooser_.getText()); 532 prefs.showLastDotValue().setGlobalValue(showLastDotValue_.getValue()); 533 prefs.alwaysSaveHistory().setGlobalValue(alwaysSaveHistory_.getValue()); 534 prefs.removeHistoryDuplicates().setGlobalValue(removeHistoryDuplicates_.getValue()); 535 prefs.restoreLastProject().setGlobalValue(restoreLastProject_.getValue()); 536 prefs.graphicsBackend().setGlobalValue(graphicsBackend_.getValue()); 537 prefs.graphicsAntialiasing().setGlobalValue(graphicsAntialias_.getValue()); 538 539 // Pro specific 540 if (showServerHomePage_ != null && showServerHomePage_.isEnabled()) 541 prefs.showUserHomePage().setGlobalValue(showServerHomePage_.getValue()); 542 if (reuseSessionsForProjectLinks_ != null && reuseSessionsForProjectLinks_.isEnabled()) 543 prefs.reuseSessionsForProjectLinks().setGlobalValue(reuseSessionsForProjectLinks_.getValue()); 544 if (rServerRVersion_ != null && rServerRVersion_.isEnabled()) 545 prefs.defaultRVersion().setGlobalValue(rServerRVersion_.getRVersion()); 546 if (rememberRVersionForProjects_ != null && rememberRVersionForProjects_.isEnabled()) 547 prefs.restoreProjectRVersion().setGlobalValue(rememberRVersionForProjects_.getValue()); 548 549 return restartRequirement; 550 } 551 552 @Override getName()553 public String getName() 554 { 555 return "General"; 556 } 557 558 @SuppressWarnings("unused") getDefaultRVersion()559 private RVersionSpec getDefaultRVersion() 560 { 561 if (rServerRVersion_ != null) 562 return rServerRVersion_.getRVersion(); 563 else 564 return RVersionSpec.createEmpty(); 565 } 566 567 @SuppressWarnings("unused") getRestoreProjectRVersion()568 private boolean getRestoreProjectRVersion() 569 { 570 if (rememberRVersionForProjects_ != null) 571 return rememberRVersionForProjects_.getValue(); 572 else 573 return false; 574 } 575 initializeGraphicsBackendWidget()576 private void initializeGraphicsBackendWidget() 577 { 578 Map<String, String> valuesToLabelsMap = new HashMap<>(); 579 valuesToLabelsMap.put(UserPrefs.GRAPHICS_BACKEND_DEFAULT, " (Default)"); 580 valuesToLabelsMap.put(UserPrefs.GRAPHICS_BACKEND_QUARTZ, "Quartz"); 581 valuesToLabelsMap.put(UserPrefs.GRAPHICS_BACKEND_WINDOWS, "Windows"); 582 valuesToLabelsMap.put(UserPrefs.GRAPHICS_BACKEND_CAIRO, "Cairo"); 583 valuesToLabelsMap.put(UserPrefs.GRAPHICS_BACKEND_CAIRO_PNG, "Cairo PNG"); 584 valuesToLabelsMap.put(UserPrefs.GRAPHICS_BACKEND_RAGG, "AGG"); 585 586 JsArrayString supportedBackends = 587 session_.getSessionInfo().getGraphicsBackends(); 588 589 String[] values = new String[supportedBackends.length() + 1]; 590 values[0] = "default"; 591 for (int i = 0; i < supportedBackends.length(); i++) 592 values[i + 1] = supportedBackends.get(i); 593 594 String[] labels = new String[supportedBackends.length() + 1]; 595 for (int i = 0; i < labels.length; i++) 596 labels[i] = valuesToLabelsMap.get(values[i]); 597 598 graphicsBackend_ = 599 new SelectWidget("Backend:", labels, values, false, true, false); 600 601 graphicsBackend_.addChangeHandler((ChangeEvent event) -> 602 { 603 String backend = graphicsBackend_.getValue(); 604 if (StringUtil.equals(backend, UserPrefs.GRAPHICS_BACKEND_RAGG)) 605 { 606 RStudioGinjector.INSTANCE.getDependencyManager().withRagg( 607 "Using the AGG renderer", 608 (Boolean succeeded) -> 609 { 610 if (!succeeded) 611 { 612 graphicsBackend_.setValue(UserPrefs.GRAPHICS_BACKEND_DEFAULT); 613 } 614 }); 615 } 616 }); 617 } 618 619 private static final String ENGINE_AUTO = "auto"; 620 private static final String ENGINE_DESKTOP = "desktop"; 621 private static final String ENGINE_GLES = "gles"; 622 private static final String ENGINE_SOFTWARE = "software"; 623 624 private boolean desktopMonitoring_ = false; 625 private boolean desktopIgnoreGpuExclusions_ = false; 626 private boolean desktopDisableGpuDriverBugWorkarounds_ = false; 627 628 private final FileSystemContext fsContext_; 629 private final FileDialogs fileDialogs_; 630 private RVersionSelectWidget rServerRVersion_ = null; 631 private CheckBox rememberRVersionForProjects_ = null; 632 private CheckBox reuseSessionsForProjectLinks_ = null; 633 private SelectWidget helpFontSize_; 634 private CheckBox clipboardMonitoring_ = null; 635 private CheckBox fullPathInTitle_ = null; 636 private CheckBox useGpuExclusions_ = null; 637 private CheckBox useGpuDriverBugWorkarounds_ = null; 638 private SelectWidget renderingEngineWidget_ = null; 639 private String renderingEngine_ = null; 640 641 private SelectWidget graphicsBackend_; 642 private SelectWidget graphicsAntialias_; 643 644 private SelectWidget showServerHomePage_; 645 private SelectWidget saveWorkspace_; 646 private TextBoxWithButton rVersion_; 647 private TextBoxWithButton dirChooser_; 648 private CheckBox loadRData_; 649 private final CheckBox alwaysSaveHistory_; 650 private final CheckBox removeHistoryDuplicates_; 651 private CheckBox restoreLastProject_; 652 private CheckBox rProfileOnResume_; 653 private CheckBox showLastDotValue_; 654 private CheckBox enableCrashReporting_; 655 private final UserPrefs prefs_; 656 private final Session session_; 657 } 658