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.

SwingController.java 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. /*
  2. * Copyright (c) 2006-2013 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;
  23. import com.dmdirc.Channel;
  24. import com.dmdirc.FrameContainer;
  25. import com.dmdirc.Main;
  26. import com.dmdirc.Server;
  27. import com.dmdirc.actions.ActionManager;
  28. import com.dmdirc.addons.ui_swing.commands.ChannelSettings;
  29. import com.dmdirc.addons.ui_swing.commands.Input;
  30. import com.dmdirc.addons.ui_swing.commands.PopInCommand;
  31. import com.dmdirc.addons.ui_swing.commands.PopOutCommand;
  32. import com.dmdirc.addons.ui_swing.commands.ServerSettings;
  33. import com.dmdirc.addons.ui_swing.components.frames.TextFrame;
  34. import com.dmdirc.addons.ui_swing.components.statusbar.FeedbackNag;
  35. import com.dmdirc.addons.ui_swing.components.statusbar.SwingStatusBar;
  36. import com.dmdirc.addons.ui_swing.dialogs.DialogKeyListener;
  37. import com.dmdirc.addons.ui_swing.dialogs.DialogManager;
  38. import com.dmdirc.addons.ui_swing.dialogs.StandardDialog;
  39. import com.dmdirc.addons.ui_swing.dialogs.StandardMessageDialog;
  40. import com.dmdirc.addons.ui_swing.dialogs.channelsetting.ChannelSettingsDialog;
  41. import com.dmdirc.addons.ui_swing.dialogs.error.ErrorListDialog;
  42. import com.dmdirc.addons.ui_swing.dialogs.prefs.SwingPreferencesDialog;
  43. import com.dmdirc.addons.ui_swing.dialogs.serversetting.ServerSettingsDialog;
  44. import com.dmdirc.addons.ui_swing.dialogs.url.URLDialog;
  45. import com.dmdirc.addons.ui_swing.wizard.WizardListener;
  46. import com.dmdirc.addons.ui_swing.wizard.firstrun.SwingFirstRunWizard;
  47. import com.dmdirc.config.ConfigManager;
  48. import com.dmdirc.config.Identity;
  49. import com.dmdirc.config.IdentityManager;
  50. import com.dmdirc.config.prefs.PluginPreferencesCategory;
  51. import com.dmdirc.config.prefs.PreferencesCategory;
  52. import com.dmdirc.config.prefs.PreferencesDialogModel;
  53. import com.dmdirc.config.prefs.PreferencesSetting;
  54. import com.dmdirc.config.prefs.PreferencesType;
  55. import com.dmdirc.interfaces.ui.UIController;
  56. import com.dmdirc.interfaces.ui.Window;
  57. import com.dmdirc.logger.ErrorLevel;
  58. import com.dmdirc.logger.Logger;
  59. import com.dmdirc.plugins.BasePlugin;
  60. import com.dmdirc.plugins.PluginInfo;
  61. import com.dmdirc.plugins.PluginManager;
  62. import com.dmdirc.ui.IconManager;
  63. import com.dmdirc.ui.WindowManager;
  64. import com.dmdirc.ui.core.components.StatusBarManager;
  65. import com.dmdirc.ui.core.util.URLHandler;
  66. import com.dmdirc.updater.Version;
  67. import com.dmdirc.util.validators.NumericalValidator;
  68. import java.awt.Dialog.ModalityType;
  69. import java.awt.Font;
  70. import java.awt.GraphicsEnvironment;
  71. import java.awt.KeyboardFocusManager;
  72. import java.awt.Toolkit;
  73. import java.net.URI;
  74. import java.util.ArrayList;
  75. import java.util.HashMap;
  76. import java.util.List;
  77. import java.util.Map;
  78. import java.util.concurrent.Callable;
  79. import java.util.concurrent.Semaphore;
  80. import java.util.concurrent.atomic.AtomicBoolean;
  81. import javax.swing.JMenuItem;
  82. import javax.swing.SwingUtilities;
  83. import javax.swing.UIManager;
  84. import javax.swing.UIManager.LookAndFeelInfo;
  85. import javax.swing.UnsupportedLookAndFeelException;
  86. import lombok.Getter;
  87. import net.miginfocom.layout.PlatformDefaults;
  88. /**
  89. * Controls the main swing UI.
  90. */
  91. @SuppressWarnings("PMD.UnusedPrivateField")
  92. public class SwingController extends BasePlugin implements UIController {
  93. /** Window factory. */
  94. @Getter
  95. private final SwingWindowFactory windowFactory =
  96. new SwingWindowFactory(this);
  97. /** Waiting on mainframe creation. */
  98. private final AtomicBoolean mainFrameCreated = new AtomicBoolean(false);
  99. /** URL Handler to use. */
  100. @Getter
  101. private final URLHandler URLHandler = new URLHandler(this);
  102. /** Singleton instance of MainFrame. */
  103. @Getter
  104. private MainFrame mainFrame;
  105. /** Instance of Main. */
  106. @Getter
  107. private final Main main;
  108. /** Status bar. */
  109. @Getter
  110. private SwingStatusBar swingStatusBar;
  111. /** Top level window list. */
  112. private final List<java.awt.Window> windows;
  113. /** Error dialog. */
  114. private ErrorListDialog errorDialog;
  115. /** DMDirc event queue. */
  116. private DMDircEventQueue eventQueue;
  117. /** Key listener to handle dialog key events. */
  118. private DialogKeyListener keyListener;
  119. /** This plugin's plugin info object. */
  120. private final PluginInfo pluginInfo;
  121. /** Global config manager. */
  122. @Getter
  123. private final ConfigManager globalConfig;
  124. /** Identity Manager. */
  125. @Getter
  126. private final IdentityManager identityManager;
  127. /** Global config identity. */
  128. @Getter
  129. private final Identity globalIdentity;
  130. /** Addon config identity. */
  131. @Getter
  132. private final Identity addonIdentity;
  133. /** Global Swing UI Icon manager. */
  134. @Getter
  135. private final IconManager iconManager;
  136. /** Prefs component factory instance. */
  137. @Getter
  138. private final PrefsComponentFactory prefsComponentFactory;
  139. /** Dialog manager. */
  140. @Getter
  141. private final DialogManager dialogManager;
  142. /** Action manager. */
  143. @Getter
  144. private final ActionManager actionManager;
  145. /** Plugin manager. */
  146. @Getter
  147. private final PluginManager pluginManager;
  148. /** Apple handler, deals with Mac specific code. */
  149. @Getter
  150. private final Apple apple;
  151. /**
  152. * Instantiates a new SwingController.
  153. *
  154. * @param pluginInfo Plugin info
  155. * @param identityManager Identity Manager
  156. */
  157. public SwingController(final PluginInfo pluginInfo,
  158. final IdentityManager identityManager,
  159. final PluginManager pluginManager,
  160. final Main main,
  161. final ActionManager actionManager) {
  162. super();
  163. this.main = main;
  164. this.pluginInfo = pluginInfo;
  165. this.identityManager = identityManager;
  166. this.actionManager = actionManager;
  167. this.pluginManager = pluginManager;
  168. globalConfig = identityManager.getGlobalConfiguration();
  169. globalIdentity = identityManager.getGlobalConfigIdentity();
  170. addonIdentity = identityManager.getGlobalAddonIdentity();
  171. apple = new Apple(getGlobalConfig(), this);
  172. iconManager = new IconManager(globalConfig);
  173. prefsComponentFactory = new PrefsComponentFactory(this);
  174. dialogManager = new DialogManager(this);
  175. setAntiAlias();
  176. windows = new ArrayList<java.awt.Window>();
  177. registerCommand(new ServerSettings(), ServerSettings.INFO);
  178. registerCommand(new ChannelSettings(), ChannelSettings.INFO);
  179. registerCommand(new Input(windowFactory), Input.INFO);
  180. registerCommand(new PopOutCommand(this), PopOutCommand.INFO);
  181. registerCommand(new PopInCommand(this), PopInCommand.INFO);
  182. }
  183. /**
  184. * Make swing not use Anti Aliasing if the user doesn't want it.
  185. */
  186. public final void setAntiAlias() {
  187. // For this to work it *HAS* to be before anything else UI related.
  188. final boolean aaSetting = getGlobalConfig()
  189. .getOptionBool("ui", "antialias");
  190. System.setProperty("awt.useSystemAAFontSettings",
  191. Boolean.toString(aaSetting));
  192. System.setProperty("swing.aatext", Boolean.toString(aaSetting));
  193. }
  194. /**
  195. * Does the main frame exist?
  196. *
  197. * @return true iif mainframe exists
  198. */
  199. protected boolean hasMainFrame() {
  200. return mainFrameCreated.get();
  201. }
  202. /** {@inheritDoc} */
  203. @Override
  204. public void showFirstRunWizard() {
  205. final Semaphore semaphore = new Semaphore(0);
  206. UIUtilities.invokeLater(new Runnable() {
  207. /** {@inheritDoc} */
  208. @Override
  209. public void run() {
  210. final WizardListener listener = new WizardListener() {
  211. /** {@inheritDoc} */
  212. @Override
  213. public void wizardFinished() {
  214. semaphore.release();
  215. }
  216. /** {@inheritDoc} */
  217. @Override
  218. public void wizardCancelled() {
  219. semaphore.release();
  220. }
  221. };
  222. final SwingFirstRunWizard wizard = new SwingFirstRunWizard(
  223. getMainFrame(), SwingController.this);
  224. wizard.getWizardDialog().addWizardListener(listener);
  225. wizard.display();
  226. }
  227. });
  228. semaphore.acquireUninterruptibly();
  229. }
  230. /** {@inheritDoc} */
  231. @Override
  232. public void showChannelSettingsDialog(final Channel channel) {
  233. UIUtilities.invokeLater(new Runnable() {
  234. /** {@inheritDoc} */
  235. @Override
  236. public void run() {
  237. showDialog(ChannelSettingsDialog.class, channel,
  238. getWindowFactory().getSwingWindow(channel));
  239. }
  240. });
  241. }
  242. /** {@inheritDoc} */
  243. @Override
  244. public void showServerSettingsDialog(final Server server) {
  245. UIUtilities.invokeLater(new Runnable() {
  246. /** {@inheritDoc} */
  247. @Override
  248. public void run() {
  249. showDialog(ServerSettingsDialog.class,
  250. server, getWindowFactory().getSwingWindow(server));
  251. }
  252. });
  253. }
  254. /**
  255. * Proxy method to {@link DialogManager} that shows a dialog in the client.
  256. * For more details on what parameters might be required see
  257. * {@link DialogManager#getDialog(Class, Object...)}
  258. *
  259. * @see DialogManager#getDialog(Class, Object...) getDialog
  260. *
  261. * @param klass The class of the dialog to show
  262. * @param params Any non standard parameters required
  263. */
  264. public <T extends StandardDialog> void showDialog(final Class<T> klass,
  265. final Object... params) {
  266. dialogManager.showDialog(klass, params);
  267. }
  268. /**
  269. * Updates the look and feel to the current config setting.
  270. */
  271. public void updateLookAndFeel() {
  272. try {
  273. UIManager.setLookAndFeel(UIUtilities.getLookAndFeel(
  274. getGlobalConfig().getOption("ui", "lookandfeel")));
  275. updateComponentTrees();
  276. } catch (final ClassNotFoundException ex) {
  277. Logger.userError(ErrorLevel.LOW,
  278. "Unable to change Look and Feel: " + ex.getMessage());
  279. } catch (final InstantiationException ex) {
  280. Logger.userError(ErrorLevel.LOW,
  281. "Unable to change Look and Feel: " + ex.getMessage());
  282. } catch (final IllegalAccessException ex) {
  283. Logger.userError(ErrorLevel.LOW,
  284. "Unable to change Look and Feel: " + ex.getMessage());
  285. } catch (final UnsupportedLookAndFeelException ex) {
  286. Logger.userError(ErrorLevel.LOW,
  287. "Unable to change Look and Feel: " + ex.getMessage());
  288. }
  289. }
  290. /**
  291. * Updates the component trees of all known windows in the Swing UI.
  292. */
  293. public void updateComponentTrees() {
  294. final int state = UIUtilities.invokeAndWait(
  295. new Callable<Integer>() {
  296. /** {@inheritDoc} */
  297. @Override
  298. public Integer call() {
  299. return getMainFrame().getExtendedState();
  300. }
  301. });
  302. UIUtilities.invokeLater(new Runnable() {
  303. /** {@inheritDoc} */
  304. @Override
  305. public void run() {
  306. SwingUtilities.updateComponentTreeUI(errorDialog);
  307. }
  308. });
  309. for (final java.awt.Window window : getTopLevelWindows()) {
  310. UIUtilities.invokeLater(new Runnable() {
  311. /** {@inheritDoc} */
  312. @Override
  313. public void run() {
  314. SwingUtilities.updateComponentTreeUI(window);
  315. if (window != getMainFrame()) {
  316. window.pack();
  317. }
  318. }
  319. });
  320. }
  321. UIUtilities.invokeLater(new Runnable() {
  322. /** {@inheritDoc} */
  323. @Override
  324. public void run() {
  325. getMainFrame().setExtendedState(state);
  326. }
  327. });
  328. }
  329. /**
  330. * Initialises the global UI settings for the Swing UI.
  331. */
  332. private void initUISettings() {
  333. // This will do nothing on non OS X Systems
  334. if (Apple.isApple()) {
  335. apple.setUISettings();
  336. apple.setListener();
  337. }
  338. final Font defaultFont = new Font(Font.DIALOG, Font.TRUETYPE_FONT, 12);
  339. if (UIManager.getFont("TextField.font") == null) {
  340. UIManager.put("TextField.font", defaultFont);
  341. }
  342. if (UIManager.getFont("TextPane.font") == null) {
  343. UIManager.put("TextPane.font", defaultFont);
  344. }
  345. try {
  346. UIUtilities.initUISettings();
  347. UIManager.setLookAndFeel(UIUtilities.getLookAndFeel(
  348. getGlobalConfig().getOption("ui", "lookandfeel")));
  349. UIUtilities.setUIFont(new Font(getGlobalConfig()
  350. .getOption("ui", "textPaneFontName"), Font.PLAIN, 12));
  351. } catch (final UnsupportedOperationException ex) {
  352. Logger.userError(ErrorLevel.LOW, "Unable to set UI Settings");
  353. } catch (final UnsupportedLookAndFeelException ex) {
  354. Logger.userError(ErrorLevel.LOW, "Unable to set UI Settings");
  355. } catch (final IllegalAccessException ex) {
  356. Logger.userError(ErrorLevel.LOW, "Unable to set UI Settings");
  357. } catch (final InstantiationException ex) {
  358. Logger.userError(ErrorLevel.LOW, "Unable to set UI Settings");
  359. } catch (final ClassNotFoundException ex) {
  360. Logger.userError(ErrorLevel.LOW, "Unable to set UI Settings");
  361. }
  362. if ("Metal".equals(UIManager.getLookAndFeel().getName())
  363. || Apple.isAppleUI()) {
  364. PlatformDefaults.setPlatform(PlatformDefaults.WINDOWS_XP);
  365. }
  366. }
  367. /** {@inheritDoc} */
  368. @Override
  369. public void showURLDialog(final URI url) {
  370. UIUtilities.invokeLater(new Runnable() {
  371. /** {@inheritDoc} */
  372. @Override
  373. public void run() {
  374. showDialog(URLDialog.class, url, getURLHandler());
  375. }
  376. });
  377. }
  378. /** {@inheritDoc} */
  379. @Override
  380. public void showFeedbackNag() {
  381. UIUtilities.invokeLater(new Runnable() {
  382. /** {@inheritDoc} */
  383. @Override
  384. public void run() {
  385. new FeedbackNag(SwingController.this);
  386. }
  387. });
  388. }
  389. /** {@inheritDoc} */
  390. @Override
  391. public void showMessageDialog(final String title, final String message) {
  392. UIUtilities.invokeLater(new Runnable() {
  393. /** {@inheritDoc} */
  394. @Override
  395. public void run() {
  396. new StandardMessageDialog(SwingController.this, getMainFrame(),
  397. ModalityType.MODELESS, title, message).display();
  398. }
  399. });
  400. }
  401. /**
  402. * Shows the error dialog.
  403. */
  404. public void showErrorDialog() {
  405. errorDialog.display();
  406. }
  407. /**
  408. * Returns the current look and feel.
  409. *
  410. * @return Current look and feel
  411. */
  412. public static String getLookAndFeel() {
  413. return UIManager.getLookAndFeel().getName();
  414. }
  415. /** {@inheritDoc} */
  416. @Override
  417. public void onLoad() {
  418. if (GraphicsEnvironment.isHeadless()) {
  419. throw new IllegalStateException(
  420. "Swing UI can't be run in a headless environment");
  421. }
  422. eventQueue = new DMDircEventQueue(this);
  423. keyListener = new DialogKeyListener();
  424. UIUtilities.invokeAndWait(new Runnable() {
  425. /** {@inheritDoc} */
  426. @Override
  427. public void run() {
  428. Toolkit.getDefaultToolkit().getSystemEventQueue()
  429. .push(eventQueue);
  430. }
  431. });
  432. UIUtilities.invokeAndWait(new Runnable() {
  433. /** {@inheritDoc} */
  434. @Override
  435. public void run() {
  436. KeyboardFocusManager.getCurrentKeyboardFocusManager()
  437. .addKeyEventDispatcher(keyListener);
  438. }
  439. });
  440. UIUtilities.invokeAndWait(new Runnable() {
  441. /** {@inheritDoc} */
  442. @Override
  443. public void run() {
  444. initUISettings();
  445. mainFrame = new MainFrame(SwingController.this);
  446. getMainFrame().setVisible(true);
  447. mainFrameCreated.set(true);
  448. swingStatusBar = getMainFrame().getStatusBar();
  449. errorDialog = new ErrorListDialog(SwingController.this);
  450. StatusBarManager.getStatusBarManager().registerStatusBar(
  451. getSwingStatusBar());
  452. }
  453. });
  454. if (!mainFrameCreated.get()) {
  455. throw new IllegalStateException(
  456. "Main frame not created. Unable to continue.");
  457. }
  458. WindowManager.getWindowManager().addListenerAndSync(windowFactory);
  459. super.onLoad();
  460. }
  461. /** {@inheritDoc} */
  462. @Override
  463. public void onUnload() {
  464. errorDialog.dispose();
  465. WindowManager.getWindowManager().removeListener(windowFactory);
  466. mainFrameCreated.set(false);
  467. getMainFrame().dispose();
  468. windowFactory.dispose();
  469. StatusBarManager.getStatusBarManager()
  470. .registerStatusBar(getSwingStatusBar());
  471. eventQueue.pop();
  472. KeyboardFocusManager.getCurrentKeyboardFocusManager().
  473. removeKeyEventDispatcher(keyListener);
  474. for (final java.awt.Window window : getTopLevelWindows()) {
  475. window.dispose();
  476. }
  477. super.onUnload();
  478. }
  479. /** {@inheritDoc} */
  480. @Override
  481. public void domainUpdated() {
  482. getAddonIdentity().setOption("ui", "textPaneFontName",
  483. UIManager.getFont("TextPane.font").getFamily());
  484. getAddonIdentity().setOption("ui", "textPaneFontSize",
  485. UIManager.getFont("TextPane.font").getSize());
  486. }
  487. /**
  488. * Returns the preferences dialog instance creating if required.
  489. *
  490. * @return Swing prefs dialog
  491. */
  492. public SwingPreferencesDialog getPrefsDialog() {
  493. return getDialogManager().getDialog(SwingPreferencesDialog.class);
  494. }
  495. /** {@inheritDoc} */
  496. @Override
  497. public void showConfig(final PreferencesDialogModel manager) {
  498. manager.getCategory("GUI").addSubCategory(createGeneralCategory());
  499. }
  500. /**
  501. * Creates the "Advanced" category.
  502. *
  503. * @return Newly created preferences category
  504. */
  505. private PreferencesCategory createGeneralCategory() {
  506. final PreferencesCategory general = new PluginPreferencesCategory(
  507. pluginInfo, "Swing UI", "These config options apply "
  508. + "only to the swing UI.", "category-gui");
  509. final Map<String, String> lafs = new HashMap<String, String>();
  510. final Map<String, String> framemanagers = new HashMap<String, String>();
  511. final Map<String, String> fmpositions = new HashMap<String, String>();
  512. framemanagers.put(
  513. "com.dmdirc.addons.ui_swing.framemanager.tree.TreeFrameManager",
  514. "Treeview");
  515. framemanagers.put(
  516. "com.dmdirc.addons.ui_swing.framemanager.buttonbar.ButtonBar",
  517. "Button bar");
  518. fmpositions.put("top", "Top");
  519. fmpositions.put("bottom", "Bottom");
  520. fmpositions.put("left", "Left");
  521. fmpositions.put("right", "Right");
  522. final LookAndFeelInfo[] plaf = UIManager.getInstalledLookAndFeels();
  523. lafs.put("Native", "Native");
  524. for (final LookAndFeelInfo laf : plaf) {
  525. lafs.put(laf.getName(), laf.getName());
  526. }
  527. general.addSetting(new PreferencesSetting("ui", "lookandfeel",
  528. "Look and feel", "The Java look and feel to use", lafs,
  529. globalConfig, globalIdentity));
  530. general.addSetting(new PreferencesSetting("ui", "framemanager",
  531. "Window manager", "Which window manager should be used?",
  532. framemanagers,
  533. globalConfig, globalIdentity));
  534. general.addSetting(new PreferencesSetting("ui", "framemanagerPosition",
  535. "Window manager position", "Where should the window "
  536. + "manager be positioned?", fmpositions,
  537. globalConfig, globalIdentity));
  538. general.addSetting(new PreferencesSetting(PreferencesType.FONT,
  539. "ui", "textPaneFontName", "Textpane font",
  540. "Font for the textpane",
  541. globalConfig, globalIdentity));
  542. general.addSetting(new PreferencesSetting(PreferencesType.INTEGER,
  543. "ui", "textPaneFontSize", "Textpane font size",
  544. "Font size for the textpane",
  545. globalConfig, globalIdentity));
  546. general.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  547. "ui", "sortrootwindows", "Sort root windows",
  548. "Sort child windows in the frame managers?",
  549. globalConfig, globalIdentity));
  550. general.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  551. "ui", "sortchildwindows", "Sort child windows",
  552. "Sort root windows in the frame managers?",
  553. globalConfig, globalIdentity));
  554. general.addSubCategory(createNicklistCategory());
  555. general.addSubCategory(createTreeViewCategory());
  556. general.addSubCategory(createAdvancedCategory());
  557. return general;
  558. }
  559. /**
  560. * Creates the "Advanced" category.
  561. *
  562. * @return Newly created preferences category
  563. */
  564. private PreferencesCategory createAdvancedCategory() {
  565. final PreferencesCategory advanced = new PluginPreferencesCategory(
  566. pluginInfo, "Advanced", "");
  567. advanced.addSetting(new PreferencesSetting(
  568. PreferencesType.OPTIONALINTEGER,
  569. new NumericalValidator(10, -1), "ui", "frameBufferSize",
  570. "Window buffer size", "The maximum number of lines in a window"
  571. + " buffer",
  572. globalConfig, globalIdentity));
  573. advanced.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  574. getDomain(), "mdiBarVisibility", "MDI Bar Visibility",
  575. "Controls the visibility of the MDI bar",
  576. globalConfig, globalIdentity));
  577. advanced.addSetting(
  578. new PreferencesSetting(PreferencesType.BOOLEAN, "ui",
  579. "useOneTouchExpandable", "Use one touch expandable split "
  580. + "panes?", "Use one touch expandable arrows for "
  581. + "collapsing/expanding the split panes",
  582. globalConfig, globalIdentity));
  583. advanced.addSetting(new PreferencesSetting(PreferencesType.INTEGER,
  584. getDomain(), "windowMenuItems", "Window menu item count",
  585. "Number of items to show in the window menu",
  586. globalConfig, globalIdentity));
  587. advanced.addSetting(
  588. new PreferencesSetting(PreferencesType.INTEGER, getDomain(),
  589. "windowMenuScrollInterval", "Window menu scroll interval",
  590. "Number of milliseconds to pause when autoscrolling in the "
  591. + "window menu",
  592. globalConfig, globalIdentity));
  593. advanced.addSetting(
  594. new PreferencesSetting(PreferencesType.BOOLEAN, getDomain(),
  595. "showtopicbar", "Show topic bar",
  596. "Shows a graphical topic bar in channels.",
  597. globalConfig, globalIdentity));
  598. advanced.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  599. getDomain(),
  600. "shownicklist", "Show nicklist?",
  601. "Do you want the nicklist visible",
  602. globalConfig, globalIdentity));
  603. advanced.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  604. getDomain(), "showfulltopic", "Show full topic in topic bar?",
  605. "Do you want to show the full topic in the topic bar or just"
  606. + "first line?",
  607. globalConfig, globalIdentity));
  608. advanced.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  609. getDomain(), "hideEmptyTopicBar", "Hide empty topic bar?",
  610. "Do you want to hide the topic bar when there is no topic",
  611. globalConfig, globalIdentity));
  612. advanced.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  613. getDomain(), "textpanelinenotification",
  614. "New line notification", "Do you want to be notified about new "
  615. + "lines whilst scrolled up?",
  616. globalConfig, globalIdentity));
  617. return advanced;
  618. }
  619. /**
  620. * Creates the "Treeview" category.
  621. *
  622. * @return Newly created preferences category
  623. */
  624. private PreferencesCategory createTreeViewCategory() {
  625. final PreferencesCategory treeview = new PluginPreferencesCategory(
  626. pluginInfo, "Treeview", "", "treeview");
  627. treeview.addSetting(new PreferencesSetting(
  628. PreferencesType.OPTIONALCOLOUR,
  629. "treeview", "backgroundcolour", "Treeview background colour",
  630. "Background colour to use for the treeview",
  631. globalConfig, globalIdentity));
  632. treeview.addSetting(new PreferencesSetting(
  633. PreferencesType.OPTIONALCOLOUR,
  634. "treeview", "foregroundcolour", "Treeview foreground colour",
  635. "Foreground colour to use for the treeview",
  636. globalConfig, globalIdentity));
  637. treeview.addSetting(new PreferencesSetting(
  638. PreferencesType.OPTIONALCOLOUR,
  639. "ui", "treeviewRolloverColour", "Treeview rollover colour",
  640. "Background colour to use when the mouse cursor is over a "
  641. + "node",
  642. globalConfig, globalIdentity));
  643. treeview.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  644. "ui", "treeviewActiveBold", "Active node bold",
  645. "Make the active node bold?",
  646. globalConfig, globalIdentity));
  647. treeview.addSetting(new PreferencesSetting(
  648. PreferencesType.OPTIONALCOLOUR,
  649. "ui", "treeviewActiveBackground", "Active node background",
  650. "Background colour to use for active treeview node",
  651. globalConfig, globalIdentity));
  652. treeview.addSetting(new PreferencesSetting(
  653. PreferencesType.OPTIONALCOLOUR,
  654. "ui", "treeviewActiveForeground", "Active node foreground",
  655. "Foreground colour to use for active treeview node",
  656. globalConfig, globalIdentity));
  657. treeview.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  658. getDomain(), "showtreeexpands", "Show expand/collapse handles",
  659. "Do you want to show tree view collapse/expand handles",
  660. globalConfig, globalIdentity));
  661. return treeview;
  662. }
  663. /**
  664. * Creates the "Nicklist" category.
  665. *
  666. * @return Newly created preferences category
  667. */
  668. private PreferencesCategory createNicklistCategory() {
  669. final PreferencesCategory nicklist = new PluginPreferencesCategory(
  670. pluginInfo, "Nicklist", "", "nicklist");
  671. nicklist.addSetting(new PreferencesSetting(
  672. PreferencesType.OPTIONALCOLOUR,
  673. "ui", "nicklistbackgroundcolour", "Nicklist background colour",
  674. "Background colour to use for the nicklist",
  675. globalConfig, globalIdentity));
  676. nicklist.addSetting(new PreferencesSetting(
  677. PreferencesType.OPTIONALCOLOUR,
  678. "ui", "nicklistforegroundcolour", "Nicklist foreground colour",
  679. "Foreground colour to use for the nicklist",
  680. globalConfig, globalIdentity));
  681. nicklist.addSetting(new PreferencesSetting(
  682. PreferencesType.OPTIONALCOLOUR,
  683. "ui", "nickListAltBackgroundColour",
  684. "Alternate background colour",
  685. "Background colour to use for every other nicklist entry",
  686. globalConfig, globalIdentity));
  687. nicklist.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  688. "nicklist", "sortByMode", "Sort nicklist by user mode",
  689. "Sort nicknames by the modes that they have?",
  690. globalConfig, globalIdentity));
  691. nicklist.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  692. "nicklist", "sortByCase", "Sort nicklist by case",
  693. "Sort nicknames in a case-sensitive manner?",
  694. globalConfig, globalIdentity));
  695. return nicklist;
  696. }
  697. /**
  698. * Adds a top level window to the window list.
  699. *
  700. * @param source New window
  701. */
  702. protected void addTopLevelWindow(final java.awt.Window source) {
  703. synchronized (windows) {
  704. windows.add(source);
  705. }
  706. }
  707. /**
  708. * Deletes a top level window to the window list.
  709. *
  710. * @param source Old window
  711. */
  712. protected void delTopLevelWindow(final java.awt.Window source) {
  713. synchronized (windows) {
  714. windows.remove(source);
  715. }
  716. }
  717. /**
  718. * Returns a list of top level windows.
  719. *
  720. * @return Top level window list
  721. */
  722. public List<java.awt.Window> getTopLevelWindows() {
  723. synchronized (windows) {
  724. return new ArrayList<java.awt.Window>(windows);
  725. }
  726. }
  727. /**
  728. * Returns an instance of SwingController. This method is exported for use
  729. * in other plugins.
  730. *
  731. * @return A reference to this SwingController.
  732. */
  733. public UIController getController() {
  734. return this;
  735. }
  736. /**
  737. * Adds the specified menu item to the named parent menu, creating the
  738. * parent menu if required.
  739. *
  740. * @param parentMenu Parent menu name
  741. * @param menuItem Menu item to add
  742. */
  743. public void addMenuItem(final String parentMenu, final JMenuItem menuItem) {
  744. getMainFrame().getJMenuBar().addMenuItem(parentMenu, menuItem);
  745. }
  746. /** {@inheritDoc} */
  747. @Override
  748. public void requestWindowFocus(final Window window) {
  749. if (window instanceof TextFrame) {
  750. getMainFrame().setActiveFrame((TextFrame) window);
  751. }
  752. }
  753. /** {@inheritDoc} */
  754. @Override
  755. public void requestWindowFocus(final FrameContainer container) {
  756. requestWindowFocus(getWindowFactory().getSwingWindow(container));
  757. }
  758. /**
  759. * Returns the version of this swing UI.
  760. *
  761. * @return Swing version
  762. */
  763. public Version getVersion() {
  764. return pluginInfo.getMetaData().getVersion();
  765. }
  766. }