1 /* 2 * SpellingPreferencesPane.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 16 package org.rstudio.studio.client.workbench.prefs.views; 17 18 import com.google.gwt.aria.client.Roles; 19 import com.google.gwt.resources.client.ImageResource; 20 import com.google.gwt.user.client.ui.CheckBox; 21 import com.google.gwt.user.client.ui.HasVerticalAlignment; 22 import com.google.gwt.user.client.ui.HorizontalPanel; 23 import com.google.gwt.user.client.ui.Label; 24 import com.google.inject.Inject; 25 26 import java.util.ArrayList; 27 import java.util.Arrays; 28 import java.util.Collections; 29 import java.util.List; 30 import java.util.function.Consumer; 31 import org.rstudio.core.client.Size; 32 import org.rstudio.core.client.StringUtil; 33 import org.rstudio.core.client.prefs.PreferencesDialogBaseResources; 34 import org.rstudio.core.client.prefs.RestartRequirement; 35 import org.rstudio.core.client.resources.ImageResource2x; 36 import org.rstudio.core.client.widget.SmallButton; 37 import org.rstudio.studio.client.common.spelling.SpellingService; 38 import org.rstudio.studio.client.common.spelling.ui.SpellingCustomDictionariesWidget; 39 import org.rstudio.studio.client.common.spelling.ui.SpellingLanguageSelectWidget; 40 import org.rstudio.studio.client.workbench.WorkbenchList; 41 import org.rstudio.studio.client.workbench.WorkbenchListManager; 42 import org.rstudio.studio.client.workbench.prefs.model.SpellingPrefsContext; 43 import org.rstudio.studio.client.workbench.prefs.model.UserPrefs; 44 import org.rstudio.studio.client.workbench.views.edit.ui.EditDialog; 45 46 public class SpellingPreferencesPane extends PreferencesPane 47 { 48 @Inject SpellingPreferencesPane(PreferencesDialogResources res, SpellingService spellingService, WorkbenchListManager workbenchListManager, UserPrefs prefs)49 public SpellingPreferencesPane(PreferencesDialogResources res, 50 SpellingService spellingService, 51 WorkbenchListManager workbenchListManager, 52 UserPrefs prefs) 53 { 54 res_ = res; 55 uiPrefs_ = prefs; 56 57 add(headerLabel("Dictionaries")); 58 59 languageWidget_ = new SpellingLanguageSelectWidget(spellingService); 60 spaced(languageWidget_); 61 add(languageWidget_); 62 63 customDictsWidget_ = new SpellingCustomDictionariesWidget(); 64 mediumSpaced(customDictsWidget_); 65 nudgeRight(customDictsWidget_); 66 add(customDictsWidget_); 67 68 addUserDictionariesEditor(workbenchListManager); 69 70 add(headerLabel("Ignore")); 71 72 add(checkboxPref("Ignore words in UPPERCASE", prefs.ignoreUppercaseWords())); 73 add(mediumSpaced(checkboxPref("Ignore words with numbers", prefs.ignoreWordsWithNumbers(), false))); 74 75 76 add(headerLabel("Checking")); 77 78 realtimeSpellcheckingCheckbox_ = checkboxPref("Use real time spell-checking", prefs.realTimeSpellchecking(), false); 79 spaced(realtimeSpellcheckingCheckbox_); 80 add(realtimeSpellcheckingCheckbox_); 81 82 languageWidget_.addChangeHandler((event) -> 83 { 84 realtimeSpellcheckingCheckbox_.setValue(realtimeSpellcheckingCheckbox_.getValue()); 85 }); 86 } 87 addUserDictionariesEditor(WorkbenchListManager workbenchListManager)88 private void addUserDictionariesEditor(WorkbenchListManager workbenchListManager) 89 { 90 final String kUserDictionary = "User dictionary: "; 91 final Label userDictLabel = new Label(kUserDictionary); 92 final Consumer<Integer> setUserDictLabel = (Integer entries) -> { 93 userDictLabel.setText(kUserDictionary + StringUtil.formatGeneralNumber(entries) + " words"); 94 }; 95 96 final ArrayList<String> userDictWords = new ArrayList<>(); 97 WorkbenchList userDict = workbenchListManager.getUserDictionaryList(); 98 userDict.addListChangedHandler((e) -> { 99 userDictWords.clear(); 100 userDictWords.addAll(e.getList()); 101 Collections.sort(userDictWords, String.CASE_INSENSITIVE_ORDER); 102 setUserDictLabel.accept(userDictWords.size()); 103 }); 104 105 HorizontalPanel userDictPanel = new HorizontalPanel(); 106 userDictPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); 107 userDictPanel.add(userDictLabel); 108 SmallButton editUserDict = new SmallButton("Edit User Dictionary..."); 109 editUserDict.addStyleName(res_.styles().userDictEditButton()); 110 editUserDict.addClickHandler((e) -> { 111 EditDialog editDialog = new EditDialog( 112 "Edit User Dictionary", 113 "Save", 114 String.join("\n", userDictWords), 115 Roles.getDialogRole(), 116 false, 117 true, 118 new Size(400, 425), 119 (dictionary, progress) -> { 120 if (dictionary != null) 121 { 122 List<String> dictSplitItems = Arrays.asList(dictionary.split("\n")); 123 ArrayList<String> dictWords = new ArrayList<>(); 124 for (String item : dictSplitItems) 125 { 126 item = item.trim(); 127 if (!item.isEmpty()) 128 dictWords.add(item); 129 } 130 userDict.setContents(dictWords); 131 setUserDictLabel.accept(dictWords.size()); 132 } 133 progress.onCompleted(); 134 } 135 ); 136 editDialog.showModal(); 137 }); 138 userDictPanel.add(editUserDict); 139 140 mediumSpaced(userDictPanel); 141 add(userDictPanel); 142 } 143 144 145 @Override initialize(UserPrefs rPrefs)146 protected void initialize(UserPrefs rPrefs) 147 { 148 SpellingPrefsContext context = uiPrefs_.spellingPrefsContext().getValue(); 149 languageWidget_.setProgressIndicator(getProgressIndicator()); 150 languageWidget_.setLanguages(context.getAllLanguagesInstalled(), 151 context.getAvailableLanguages()); 152 153 languageWidget_.setSelectedLanguage( 154 uiPrefs_.spellingDictionaryLanguage().getValue()); 155 156 customDictsWidget_.setDictionaries(context.getCustomDictionaries()); 157 customDictsWidget_.setProgressIndicator(getProgressIndicator()); 158 } 159 160 @Override onApply(UserPrefs rPrefs)161 public RestartRequirement onApply(UserPrefs rPrefs) 162 { 163 RestartRequirement restart = super.onApply(rPrefs); 164 165 uiPrefs_.spellingDictionaryLanguage().setGlobalValue( 166 languageWidget_.getSelectedLanguage()); 167 168 restart.setDesktopRestartRequired( 169 restart.getDesktopRestartRequired() || 170 customDictsWidget_.getCustomDictsModified() || 171 !StringUtil.equals( 172 rPrefs.spellingDictionaryLanguage().getValue(), 173 languageWidget_.getSelectedLanguage())); 174 175 return restart; 176 } 177 178 @Override getIcon()179 public ImageResource getIcon() 180 { 181 return new ImageResource2x(PreferencesDialogBaseResources.INSTANCE.iconSpelling2x()); 182 } 183 184 @Override validate()185 public boolean validate() 186 { 187 return true; 188 } 189 190 @Override getName()191 public String getName() 192 { 193 return "Spelling"; 194 } 195 196 197 private final PreferencesDialogResources res_; 198 199 private final UserPrefs uiPrefs_; 200 private final SpellingLanguageSelectWidget languageWidget_; 201 private final SpellingCustomDictionariesWidget customDictsWidget_; 202 private final CheckBox realtimeSpellcheckingCheckbox_; 203 } 204