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.

PrefsCategoryLoader.java 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. * Copyright (c) 2006-2015 DMDirc Developers
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. * SOFTWARE.
  21. */
  22. package com.dmdirc.addons.ui_swing.dialogs.prefs;
  23. import com.dmdirc.addons.ui_swing.Apple;
  24. import com.dmdirc.addons.ui_swing.PrefsComponentFactory;
  25. import com.dmdirc.addons.ui_swing.UIUtilities;
  26. import com.dmdirc.addons.ui_swing.components.LoggingSwingWorker;
  27. import com.dmdirc.addons.ui_swing.components.text.TextLabel;
  28. import com.dmdirc.config.prefs.PreferencesCategory;
  29. import com.dmdirc.config.prefs.PreferencesSetting;
  30. import com.dmdirc.config.prefs.PreferencesType;
  31. import com.dmdirc.util.LogUtils;
  32. import java.awt.Component;
  33. import java.awt.MenuContainer;
  34. import java.util.concurrent.ExecutionException;
  35. import javax.swing.BorderFactory;
  36. import javax.swing.JComponent;
  37. import javax.swing.JLabel;
  38. import javax.swing.JPanel;
  39. import javax.swing.UIManager;
  40. import net.miginfocom.layout.PlatformDefaults;
  41. import net.miginfocom.swing.MigLayout;
  42. import org.slf4j.Logger;
  43. import org.slf4j.LoggerFactory;
  44. /**
  45. * Loads a preferences panel for a specified preferences category in the background.
  46. */
  47. public class PrefsCategoryLoader extends LoggingSwingWorker<JPanel, Object> {
  48. private static final Logger LOG = LoggerFactory.getLogger(PrefsCategoryLoader.class);
  49. /** Panel gap. */
  50. private final int padding = (int) PlatformDefaults.getUnitValueX("related").getValue();
  51. /** Panel left padding. */
  52. private final int leftPadding = (int) PlatformDefaults.getPanelInsets(1).getValue();
  53. /** Panel right padding. */
  54. private final int rightPadding = (int) PlatformDefaults.getPanelInsets(3).getValue();
  55. /** Error panel. */
  56. private JPanel errorCategory;
  57. /** Category panel. */
  58. private final CategoryPanel categoryPanel;
  59. /** Category to display. */
  60. private final PreferencesCategory category;
  61. /** Prefs component factory instance. */
  62. private final PrefsComponentFactory factory;
  63. /**
  64. * Instantiates a new preferences category loader.
  65. *
  66. * @param factory Prefs component factory instance
  67. * @param categoryPanel Parent Category panel
  68. * @param category Preferences Category to load
  69. */
  70. public PrefsCategoryLoader(final PrefsComponentFactory factory,
  71. final CategoryPanel categoryPanel,
  72. final PreferencesCategory category) {
  73. this.factory = factory;
  74. this.categoryPanel = categoryPanel;
  75. this.category = category;
  76. UIUtilities.invokeAndWait(() -> {
  77. errorCategory = new JPanel(new MigLayout("fillx"));
  78. errorCategory.add(new TextLabel(
  79. "There was an error loading this category."));
  80. });
  81. }
  82. @Override
  83. protected JPanel doInBackground() {
  84. return addCategory(category);
  85. }
  86. @Override
  87. protected void done() {
  88. categoryPanel.categoryLoaded(this, category);
  89. }
  90. /**
  91. * Returns the panel for this loader.
  92. *
  93. * @return Loaded panel
  94. */
  95. public JPanel getPanel() {
  96. JPanel panel;
  97. try {
  98. panel = get();
  99. } catch (InterruptedException ex) {
  100. panel = errorCategory;
  101. } catch (ExecutionException ex) {
  102. LOG.warn(LogUtils.USER_ERROR, "Error loading prefs panel", ex);
  103. panel = errorCategory;
  104. }
  105. return panel;
  106. }
  107. /**
  108. * Initialises the specified category.
  109. *
  110. * @since 0.6.3m1
  111. * @param category The category that is being initialised
  112. * @param panel The panel to which we're adding its contents
  113. */
  114. private void initCategory(final PreferencesCategory category,
  115. final JPanel panel) {
  116. if (!category.getDescription().isEmpty()) {
  117. UIUtilities.invokeAndWait(() -> panel.add(new TextLabel(category.getDescription()),
  118. "span, growx, pushx, wrap 2*unrel"));
  119. }
  120. for (PreferencesCategory child : category.getSubcats()) {
  121. if (child.isInline() && category.isInlineBefore()) {
  122. addInlineCategory(child, panel);
  123. }
  124. }
  125. if (category.hasObject()) {
  126. if (!(category.getObject() instanceof JPanel)) {
  127. throw new IllegalArgumentException(
  128. "Custom preferences objects" + " for this UI must extend JPanel.");
  129. }
  130. panel.add((Component) category.getObject(), "growx, pushx");
  131. return;
  132. }
  133. for (PreferencesSetting setting : category.getSettings()) {
  134. addComponent(setting, panel);
  135. }
  136. if (!category.isInlineBefore()) {
  137. category.getSubcats().stream().filter(PreferencesCategory::isInline)
  138. .forEach(child -> addInlineCategory(child, panel));
  139. }
  140. }
  141. /**
  142. * Initialises and adds a component to a panel.
  143. *
  144. * @param setting The setting to be used
  145. * @param panel The panel to add the component to
  146. */
  147. private void addComponent(final PreferencesSetting setting,
  148. final JPanel panel) {
  149. final TextLabel label = new TextLabel(setting.getTitle() + ": ", false);
  150. final JComponent option = UIUtilities.invokeAndWait(() -> {
  151. final JComponent option1 = factory.getComponent(setting);
  152. option1.setToolTipText(null);
  153. return option1;
  154. });
  155. categoryPanel.getToolTipPanel().registerTooltipHandler(label,
  156. getTooltipText(setting, categoryPanel));
  157. categoryPanel.getToolTipPanel().registerTooltipHandler(option,
  158. getTooltipText(setting, categoryPanel));
  159. if (setting.getType() != PreferencesType.LABEL) {
  160. if (Apple.isAppleUI()) {
  161. panel.add(label, "align right, wmax 40%");
  162. } else {
  163. panel.add(label, "align left, wmax 40%");
  164. }
  165. }
  166. if (option == null) {
  167. panel.add(new JLabel("Error: See error list."));
  168. } else if (setting.getType() == PreferencesType.LABEL) {
  169. panel.add(option, "growx, pushx, w 100%, span");
  170. } else {
  171. panel.add(option, "growx, pushx, w 60%");
  172. }
  173. }
  174. /**
  175. * Returns the tooltip text for a preferences setting.
  176. *
  177. * @param setting Setting to get text for
  178. * @param component Component tooltip applies to
  179. *
  180. * @return Tooltip text for the setting
  181. */
  182. private String getTooltipText(final PreferencesSetting setting,
  183. final MenuContainer component) {
  184. if (setting.isRestartNeeded()) {
  185. final int size = component.getFont().getSize();
  186. return "<html>" + setting.getHelptext() + "<br>"
  187. + "<img src=\"dmdirc://com/dmdirc/res/restart-needed.png\" " + "width=\"" + size
  188. + "\" height=\"" + size + "\">" + "&nbsp;Restart needed if changed</html>";
  189. }
  190. return setting.getHelptext();
  191. }
  192. /**
  193. * Adds a new inline category.
  194. *
  195. * @param category The category to be added
  196. * @param parent The panel to add the category to
  197. */
  198. private void addInlineCategory(final PreferencesCategory category,
  199. final JPanel parent) {
  200. final JPanel panel = UIUtilities.invokeAndWait(() -> {
  201. final JPanel panel1 = new JPanel(new MigLayout(
  202. "fillx, gap unrel, wrap 2, "
  203. + "hidemode 3, pack, wmax 470-" + leftPadding + '-'
  204. + rightPadding + "-2*"
  205. + padding));
  206. panel1.setName(category.getPath());
  207. panel1.setBorder(BorderFactory.createTitledBorder(UIManager.
  208. getBorder("TitledBorder.border"), category.getTitle()));
  209. return panel1;
  210. });
  211. parent.add(panel, "span, growx, pushx, wrap");
  212. initCategory(category, panel);
  213. }
  214. /**
  215. * Adds the specified category to the preferences dialog.
  216. *
  217. * @since 0.6.3m1
  218. * @param category The category to be added
  219. */
  220. private JPanel addCategory(final PreferencesCategory category) {
  221. final JPanel panel = UIUtilities.invokeAndWait(() -> {
  222. final JPanel panel1 = new JPanel(
  223. new MigLayout("fillx, gap unrel, wrap 2, pack, "
  224. + "hidemode 3, wmax 470-"
  225. + leftPadding + '-' + rightPadding + "-2*" + padding));
  226. panel1.setName(category.getPath());
  227. return panel1;
  228. });
  229. initCategory(category, panel);
  230. return panel;
  231. }
  232. }