You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PreferencesSetting.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. /*
  2. * Copyright (c) 2006-2017 DMDirc Developers
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  5. * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
  7. * permit persons to whom the Software is furnished to do so, subject to the following conditions:
  8. *
  9. * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
  10. * Software.
  11. *
  12. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  13. * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
  14. * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  15. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  16. */
  17. package com.dmdirc.config.prefs;
  18. import com.dmdirc.config.provider.ConfigProvider;
  19. import com.dmdirc.config.provider.ReadOnlyConfigProvider;
  20. import com.dmdirc.util.validators.PermissiveValidator;
  21. import com.dmdirc.util.validators.Validator;
  22. import com.google.common.collect.Table;
  23. import java.util.ArrayList;
  24. import java.util.Collection;
  25. import java.util.HashMap;
  26. import java.util.Map;
  27. import java.util.Objects;
  28. /**
  29. * Represents a single setting.
  30. */
  31. public class PreferencesSetting {
  32. /** The type of this setting. */
  33. protected final PreferencesType type;
  34. /** The possible options for a multichoice setting. */
  35. protected final Map<String, String> comboOptions;
  36. /** The headers in the table. */
  37. private final Iterable<String> tableHeaders;
  38. /** The possible options for a table setting. */
  39. protected final Table<Integer, Integer, String> tableOptions;
  40. /** The validator to use to validate this setting. */
  41. protected final Validator<String> validator;
  42. /** The domain of the setting. */
  43. protected final String domain;
  44. /** The option name of the setting. */
  45. protected final String option;
  46. /** The title of this setting. */
  47. protected final String title;
  48. /** Text to inform the user what the setting is for. */
  49. protected final String helptext;
  50. /** The current value of the setting. */
  51. protected String value;
  52. /** Whether or not we need a restart. */
  53. protected boolean restartNeeded;
  54. /** The original value of this setting. */
  55. private String original;
  56. /** A list of change listeners. */
  57. private final Collection<SettingChangeListener> listeners = new ArrayList<>();
  58. /** Identity to save settings to. */
  59. private final ConfigProvider identity;
  60. /**
  61. * Creates a new preferences setting for any type except multi-choice.
  62. *
  63. * @param type The type of the setting to create
  64. * @param validator A validator to validate the setting's value
  65. * @param domain The domain of the setting
  66. * @param option The option name of the setting
  67. * @param title The title of this setting
  68. * @param helptext Text to display to help the user
  69. * @param configManager Config Manager
  70. * @param identity Identity to save setting to
  71. */
  72. public PreferencesSetting(final PreferencesType type,
  73. final Validator<String> validator, final String domain,
  74. final String option, final String title, final String helptext,
  75. final ReadOnlyConfigProvider configManager, final ConfigProvider identity) {
  76. if (PreferencesType.MULTICHOICE == type) {
  77. throw new IllegalArgumentException("Multi-choice preferences must "
  78. + "have their options specified.");
  79. }
  80. if (PreferencesType.TABLE == type) {
  81. throw new IllegalArgumentException("Table preferences must "
  82. + "have their table options specified.");
  83. }
  84. this.type = type;
  85. this.comboOptions = null;
  86. this.tableHeaders = null;
  87. this.tableOptions = null;
  88. this.validator = validator;
  89. this.domain = domain;
  90. this.option = option;
  91. this.title = title;
  92. this.helptext = helptext;
  93. this.identity = identity;
  94. value = configManager.getOption(domain, option);
  95. original = value;
  96. }
  97. /**
  98. * Creates a new preferences setting for any type except multi-choice, with a default permissive
  99. * validator.
  100. *
  101. * @param type The type of the setting to create
  102. * @param domain The domain of the setting
  103. * @param option The option name of the setting
  104. * @param title The title of this setting
  105. * @param helptext Text to display to help the user
  106. * @param configManager Config Manager
  107. * @param identity Identity to save setting to
  108. */
  109. public PreferencesSetting(final PreferencesType type, final String domain,
  110. final String option, final String title, final String helptext,
  111. final ReadOnlyConfigProvider configManager, final ConfigProvider identity) {
  112. if (PreferencesType.MULTICHOICE == type) {
  113. throw new IllegalArgumentException("Multi-choice preferences must "
  114. + "have their options specified.");
  115. }
  116. if (PreferencesType.TABLE == type) {
  117. throw new IllegalArgumentException("Table preferences must "
  118. + "have their table options specified.");
  119. }
  120. this.type = type;
  121. this.comboOptions = null;
  122. this.tableHeaders = null;
  123. this.tableOptions = null;
  124. this.validator = new PermissiveValidator<>();
  125. this.domain = domain;
  126. this.option = option;
  127. this.title = title;
  128. this.helptext = helptext;
  129. this.identity = identity;
  130. value = configManager.getOption(domain, option);
  131. original = value;
  132. }
  133. /**
  134. * Creates a new preferences setting for multi-choice preferences.
  135. *
  136. * @param domain The domain of the setting
  137. * @param option The option name of the setting
  138. * @param options A map of setting values to display names for this setting
  139. * @param title The title of this setting
  140. * @param helptext Text to display to help the user
  141. * @param configManager Config Manager
  142. * @param identity Identity to save setting to
  143. */
  144. public PreferencesSetting(final String domain, final String option,
  145. final String title, final String helptext,
  146. final Map<String, String> options,
  147. final ReadOnlyConfigProvider configManager, final ConfigProvider identity) {
  148. this.type = PreferencesType.MULTICHOICE;
  149. this.comboOptions = new HashMap<>(options);
  150. this.tableHeaders = null;
  151. this.tableOptions = null;
  152. this.validator = new PermissiveValidator<>();
  153. this.domain = domain;
  154. this.option = option;
  155. this.title = title;
  156. this.helptext = helptext;
  157. this.identity = identity;
  158. value = configManager.getOption(domain, option);
  159. original = value;
  160. if (!comboOptions.containsKey(value)) {
  161. comboOptions.put(value, "Current (" + value + ')');
  162. }
  163. }
  164. /**
  165. * Creates a new preferences setting for table preferences.
  166. *
  167. * @param domain The domain of the setting
  168. * @param option The option name of the setting
  169. * @param options A map of setting values to display names for this setting
  170. * @param title The title of this setting
  171. * @param helptext Text to display to help the user
  172. * @param configManager Config Manager
  173. * @param identity Identity to save setting to
  174. */
  175. public PreferencesSetting(final String domain, final String option,
  176. final String title, final String helptext,
  177. final Iterable<String> tableHeaders,
  178. final Table<Integer, Integer, String> options,
  179. final ReadOnlyConfigProvider configManager,
  180. final ConfigProvider identity) {
  181. this.type = PreferencesType.TABLE;
  182. this.comboOptions = null;
  183. this.tableHeaders = tableHeaders;
  184. this.tableOptions = options;
  185. this.validator = new PermissiveValidator<>();
  186. this.domain = domain;
  187. this.option = option;
  188. this.title = title;
  189. this.helptext = helptext;
  190. this.identity = identity;
  191. value = configManager.getOption(domain, option);
  192. original = value;
  193. }
  194. public PreferencesType getType() {
  195. return type;
  196. }
  197. public Map<String, String> getComboOptions() {
  198. return comboOptions;
  199. }
  200. public Iterable<String> getTableHeaders() {
  201. return tableHeaders;
  202. }
  203. public Table<Integer, Integer, String> getTableOptions() {
  204. return tableOptions;
  205. }
  206. public Validator<String> getValidator() {
  207. return validator;
  208. }
  209. public String getTitle() {
  210. return title;
  211. }
  212. public String getHelptext() {
  213. return helptext;
  214. }
  215. public String getValue() {
  216. return value;
  217. }
  218. /**
  219. * Sets the current value of this setting. Note that the setting is not saved to the
  220. * configuration file until the save method is called.
  221. *
  222. * @param newValue The new value of the setting
  223. */
  224. public void setValue(final String newValue) {
  225. value = newValue;
  226. for (SettingChangeListener listener : listeners) {
  227. listener.settingChanged(this);
  228. }
  229. }
  230. /**
  231. * Determines whether or not this setting needs a restart when it's changed.
  232. *
  233. * @return True if this setting needs a restart, false otherwise
  234. */
  235. public boolean isRestartNeeded() {
  236. return restartNeeded;
  237. }
  238. /**
  239. * Sets the "restart needed" flag for this setting, indicating a client restart is needed before
  240. * the setting takes effect.
  241. *
  242. * @return A reference to this setting, for convenience
  243. */
  244. public PreferencesSetting setRestartNeeded() {
  245. restartNeeded = true;
  246. return this;
  247. }
  248. /**
  249. * Registers the specified setting change listener.
  250. *
  251. * @param listener The listener to be registered
  252. *
  253. * @return A reference to this setting, for convenience
  254. */
  255. public PreferencesSetting registerChangeListener(final SettingChangeListener listener) {
  256. listeners.add(listener);
  257. return this;
  258. }
  259. /**
  260. * Saves the current value of this setting to the global configuration.
  261. *
  262. * @return True if the setting has changed, false otherwise
  263. */
  264. public boolean save() {
  265. if (!needsSaving()) {
  266. return false;
  267. }
  268. if (value == null) {
  269. identity.unsetOption(domain, option);
  270. } else {
  271. identity.setOption(domain, option, value);
  272. }
  273. original = value;
  274. return true;
  275. }
  276. /**
  277. * Dismisses changes to this setting.
  278. */
  279. public void dismiss() {
  280. if (Objects.equals(original, value)) {
  281. return;
  282. }
  283. value = original;
  284. for (SettingChangeListener listener : listeners) {
  285. listener.settingChanged(this);
  286. }
  287. }
  288. /**
  289. * Does the setting need saving?
  290. *
  291. * @return true iif the setting will be changed if saved
  292. */
  293. public boolean needsSaving() {
  294. return !Objects.equals(value, original)
  295. && (value != null || original != null)
  296. && (validator == null || !validator.validate(value).isFailure());
  297. }
  298. /**
  299. * Does this setting's identity have this setting?
  300. *
  301. * @return true iif the setting is present
  302. */
  303. public boolean isSet() {
  304. return identity.hasOptionString(domain, option, validator);
  305. }
  306. }