選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

MainFrame.java 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. /*
  2. * Copyright (c) 2006-2014 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.FrameContainer;
  24. import com.dmdirc.actions.ActionManager;
  25. import com.dmdirc.actions.CoreActionType;
  26. import com.dmdirc.addons.ui_swing.components.SplitPane;
  27. import com.dmdirc.addons.ui_swing.components.frames.TextFrame;
  28. import com.dmdirc.addons.ui_swing.components.menubar.MenuBar;
  29. import com.dmdirc.addons.ui_swing.components.statusbar.SwingStatusBar;
  30. import com.dmdirc.addons.ui_swing.dialogs.ConfirmQuitDialog;
  31. import com.dmdirc.addons.ui_swing.dialogs.StandardQuestionDialog;
  32. import com.dmdirc.addons.ui_swing.framemanager.FrameManager;
  33. import com.dmdirc.addons.ui_swing.framemanager.FramemanagerPosition;
  34. import com.dmdirc.addons.ui_swing.framemanager.ctrltab.CtrlTabWindowManager;
  35. import com.dmdirc.addons.ui_swing.framemanager.tree.TreeFrameManager;
  36. import com.dmdirc.interfaces.FrameInfoListener;
  37. import com.dmdirc.interfaces.LifecycleController;
  38. import com.dmdirc.interfaces.NotificationListener;
  39. import com.dmdirc.interfaces.config.AggregateConfigProvider;
  40. import com.dmdirc.interfaces.config.ConfigChangeListener;
  41. import com.dmdirc.logger.ErrorLevel;
  42. import com.dmdirc.logger.Logger;
  43. import com.dmdirc.ui.Colour;
  44. import com.dmdirc.ui.CoreUIUtils;
  45. import com.dmdirc.ui.IconManager;
  46. import com.dmdirc.ui.WindowManager;
  47. import com.dmdirc.util.collections.ListenerList;
  48. import com.dmdirc.util.collections.QueuedLinkedHashSet;
  49. import java.awt.Dimension;
  50. import java.awt.Font;
  51. import java.awt.event.WindowEvent;
  52. import java.awt.event.WindowFocusListener;
  53. import java.awt.event.WindowListener;
  54. import javax.inject.Provider;
  55. import javax.swing.ImageIcon;
  56. import javax.swing.JFrame;
  57. import javax.swing.JPanel;
  58. import javax.swing.JSplitPane;
  59. import javax.swing.SwingUtilities;
  60. import javax.swing.WindowConstants;
  61. import net.miginfocom.swing.MigLayout;
  62. import org.slf4j.LoggerFactory;
  63. /**
  64. * The main application frame.
  65. */
  66. public class MainFrame extends JFrame implements WindowListener,
  67. ConfigChangeListener, SwingWindowListener, FrameInfoListener,
  68. NotificationListener {
  69. private static final org.slf4j.Logger log = LoggerFactory.getLogger(MainFrame.class);
  70. /**
  71. * A version number for this class. It should be changed whenever the class structure is changed
  72. * (or anything else that would prevent serialized objects being unserialized with the new
  73. * class).
  74. */
  75. private static final long serialVersionUID = 9;
  76. /** Focus queue. */
  77. private final QueuedLinkedHashSet<TextFrame> focusOrder;
  78. /** Swing Controller. */
  79. private final SwingController controller;
  80. /** Controller to use to end the program. */
  81. private final LifecycleController lifecycleController;
  82. /** The window factory to use to create and listen for windows. */
  83. private final SwingWindowFactory windowFactory;
  84. /** The global config to read settings from. */
  85. private final AggregateConfigProvider globalConfig;
  86. /** The icon manager to use to get icons. */
  87. private final IconManager iconManager;
  88. /** The quit worker to use when quitting the app. */
  89. private final Provider<QuitWorker> quitWorker;
  90. /** Client Version. */
  91. private final String version;
  92. /** Frame manager used for ctrl tab frame switching. */
  93. private CtrlTabWindowManager frameManager;
  94. /** The listeners registered with this class. */
  95. private final ListenerList listeners = new ListenerList();
  96. /** Window management. */
  97. private final WindowManager windowManager;
  98. /** The main application icon. */
  99. private ImageIcon imageIcon;
  100. /** The frame manager that's being used. */
  101. private FrameManager mainFrameManager;
  102. /** Active frame. */
  103. private TextFrame activeFrame;
  104. /** Panel holding frame. */
  105. private JPanel framePanel;
  106. /** Main panel. */
  107. private JPanel frameManagerPanel;
  108. /** Frame manager position. */
  109. private FramemanagerPosition position;
  110. /** Show version? */
  111. private boolean showVersion;
  112. /** Exit code. */
  113. private int exitCode = 0;
  114. /** Status bar. */
  115. private SwingStatusBar statusBar;
  116. /** Main split pane. */
  117. private SplitPane mainSplitPane;
  118. /** Are we quitting or closing? */
  119. private boolean quitting = false;
  120. /**
  121. * Creates new form MainFrame.
  122. *
  123. * @param controller Swing controller
  124. * @param windowFactory The window factory to use to create and listen for windows.
  125. * @param lifecycleController Controller to use to end the application.
  126. * @param globalConfig The config to read settings from.
  127. * @param quitWorker The quit worker to use when quitting the app.
  128. * @param iconManager The icon manager to use to get icons.
  129. * @param windowManager Window management
  130. */
  131. public MainFrame(
  132. final SwingController controller,
  133. final SwingWindowFactory windowFactory,
  134. final LifecycleController lifecycleController,
  135. final AggregateConfigProvider globalConfig,
  136. final Provider<QuitWorker> quitWorker,
  137. final IconManager iconManager,
  138. final WindowManager windowManager) {
  139. super();
  140. this.controller = controller;
  141. this.windowFactory = windowFactory;
  142. this.lifecycleController = lifecycleController;
  143. this.globalConfig = globalConfig;
  144. this.quitWorker = quitWorker;
  145. this.iconManager = iconManager;
  146. this.windowManager = windowManager;
  147. focusOrder = new QueuedLinkedHashSet<>();
  148. imageIcon = new ImageIcon(iconManager.getImage("icon"));
  149. setIconImage(imageIcon.getImage());
  150. CoreUIUtils.centreWindow(this);
  151. addWindowListener(this);
  152. showVersion = globalConfig.getOptionBool("ui", "showversion");
  153. version = globalConfig.getOption("version", "version");
  154. globalConfig.addChangeListener("ui", "lookandfeel", this);
  155. globalConfig.addChangeListener("ui", "showversion", this);
  156. globalConfig.addChangeListener("ui", "framemanager", this);
  157. globalConfig.addChangeListener("ui", "framemanagerPosition", this);
  158. globalConfig.addChangeListener("ui", "textPaneFontName", this);
  159. globalConfig.addChangeListener("icon", "icon", this);
  160. addWindowFocusListener(new WindowFocusListener() {
  161. /** {@inheritDoc} */
  162. @Override
  163. public void windowGainedFocus(final WindowEvent e) {
  164. ActionManager.getActionManager().triggerEvent(
  165. CoreActionType.CLIENT_FOCUS_GAINED, null);
  166. }
  167. /** {@inheritDoc} */
  168. @Override
  169. public void windowLostFocus(final WindowEvent e) {
  170. ActionManager.getActionManager().triggerEvent(
  171. CoreActionType.CLIENT_FOCUS_LOST, null);
  172. }
  173. });
  174. windowFactory.addWindowListener(this);
  175. setTitle(getTitlePrefix());
  176. }
  177. public SwingStatusBar getStatusBar() {
  178. return statusBar;
  179. }
  180. /**
  181. * Returns the size of the frame manager.
  182. *
  183. * @return Frame manager size.
  184. */
  185. public int getFrameManagerSize() {
  186. if (position == FramemanagerPosition.LEFT
  187. || position == FramemanagerPosition.RIGHT) {
  188. return frameManagerPanel.getWidth();
  189. } else {
  190. return frameManagerPanel.getHeight();
  191. }
  192. }
  193. /**
  194. * Returns the window that is currently active.
  195. *
  196. * @return The active window
  197. */
  198. public TextFrame getActiveFrame() {
  199. return activeFrame;
  200. }
  201. /** {@inheritDoc} */
  202. @Override
  203. public MenuBar getJMenuBar() {
  204. return (MenuBar) super.getJMenuBar();
  205. }
  206. /** {@inheritDoc} */
  207. @Override
  208. public void setTitle(final String title) {
  209. UIUtilities.invokeLater(new Runnable() {
  210. /** {@inheritDoc}. */
  211. @Override
  212. public void run() {
  213. if (title == null || activeFrame == null) {
  214. MainFrame.super.setTitle(getTitlePrefix());
  215. } else {
  216. MainFrame.super.setTitle(getTitlePrefix() + " - " + title);
  217. }
  218. }
  219. });
  220. }
  221. /**
  222. * Gets the string which should be prefixed to this frame's title.
  223. *
  224. * @return This frame's title prefix
  225. */
  226. private String getTitlePrefix() {
  227. return "DMDirc" + (showVersion ? " " + version : "");
  228. }
  229. /**
  230. * {@inheritDoc}
  231. *
  232. * @param windowEvent Window event
  233. */
  234. @Override
  235. public void windowOpened(final WindowEvent windowEvent) {
  236. //ignore
  237. }
  238. /**
  239. * {@inheritDoc}
  240. *
  241. * @param windowEvent Window event
  242. */
  243. @Override
  244. public void windowClosing(final WindowEvent windowEvent) {
  245. quit(exitCode);
  246. }
  247. /**
  248. * {@inheritDoc}
  249. *
  250. * @param windowEvent Window event
  251. */
  252. @Override
  253. public void windowClosed(final WindowEvent windowEvent) {
  254. new Thread(new Runnable() {
  255. /** {@inheritDoc} */
  256. @Override
  257. public void run() {
  258. lifecycleController.quit(exitCode);
  259. }
  260. }, "Quit thread").start();
  261. }
  262. /**
  263. * {@inheritDoc}
  264. *
  265. * @param windowEvent Window event
  266. */
  267. @Override
  268. public void windowIconified(final WindowEvent windowEvent) {
  269. ActionManager.getActionManager().triggerEvent(
  270. CoreActionType.CLIENT_MINIMISED, null);
  271. }
  272. /**
  273. * {@inheritDoc}.
  274. *
  275. * @param windowEvent Window event
  276. */
  277. @Override
  278. public void windowDeiconified(final WindowEvent windowEvent) {
  279. ActionManager.getActionManager().triggerEvent(
  280. CoreActionType.CLIENT_UNMINIMISED, null);
  281. }
  282. /**
  283. * {@inheritDoc}.
  284. *
  285. * @param windowEvent Window event
  286. */
  287. @Override
  288. public void windowActivated(final WindowEvent windowEvent) {
  289. //ignore
  290. }
  291. /**
  292. * {@inheritDoc}.
  293. *
  294. * @param windowEvent Window event
  295. */
  296. @Override
  297. public void windowDeactivated(final WindowEvent windowEvent) {
  298. //ignore
  299. }
  300. /** Initialiases the frame managers. */
  301. private void initFrameManagers() {
  302. UIUtilities.invokeAndWait(new Runnable() {
  303. /** {@inheritDoc} */
  304. @Override
  305. public void run() {
  306. frameManagerPanel.removeAll();
  307. if (mainFrameManager != null) {
  308. windowFactory.removeWindowListener(mainFrameManager);
  309. }
  310. final String manager = globalConfig.getOption("ui", "framemanager");
  311. try {
  312. mainFrameManager = (FrameManager) Class.forName(manager)
  313. .getConstructor(WindowManager.class).newInstance(windowManager);
  314. } catch (final ReflectiveOperationException | SecurityException | LinkageError ex) {
  315. Logger.appError(ErrorLevel.MEDIUM, "Unable to load frame "
  316. + "manager, falling back to default.", ex);
  317. } finally {
  318. if (mainFrameManager == null) {
  319. mainFrameManager = new TreeFrameManager(windowManager);
  320. }
  321. }
  322. mainFrameManager.setController(controller);
  323. mainFrameManager.setParent(frameManagerPanel);
  324. addSelectionListener(mainFrameManager);
  325. windowFactory.addWindowListener(mainFrameManager);
  326. }
  327. });
  328. }
  329. /**
  330. * Initialises the components for this frame.
  331. */
  332. public void initComponents() {
  333. UIUtilities.invokeAndWait(new Runnable() {
  334. /** {@inheritDoc} */
  335. @Override
  336. public void run() {
  337. frameManagerPanel = new JPanel();
  338. activeFrame = null;
  339. framePanel = new JPanel(new MigLayout("fill, ins 0"));
  340. initFrameManagers();
  341. mainSplitPane = initSplitPane();
  342. setPreferredSize(new Dimension(800, 600));
  343. getContentPane().setLayout(new MigLayout(
  344. "fill, ins rel, wrap 1, hidemode 2"));
  345. layoutComponents();
  346. setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
  347. pack();
  348. }
  349. });
  350. }
  351. /**
  352. * Sets the menu bar that this frame will use.
  353. *
  354. * <p>Must be called prior to {@link #initComponents()}.
  355. *
  356. * @param menuBar The menu bar to use.
  357. */
  358. public void setMenuBar(final MenuBar menuBar) {
  359. UIUtilities.invokeAndWait(new Runnable() {
  360. /** {@inheritDoc} */
  361. @Override
  362. public void run() {
  363. controller.getApple().setMenuBar(menuBar);
  364. setJMenuBar(menuBar);
  365. }
  366. });
  367. }
  368. /**
  369. * Sets the window manager that this frame will use.
  370. *
  371. * <p>Must be called prior to {@link #initComponents()}.
  372. *
  373. * @param windowManager The window manager to use.
  374. */
  375. public void setWindowManager(final CtrlTabWindowManager windowManager) {
  376. this.frameManager = windowManager;
  377. }
  378. /**
  379. * Sets the status bar that will be used.
  380. *
  381. * <p>Must be called prior to {@link #initComponents()}.
  382. *
  383. * @param statusBar The status bar to be used.
  384. */
  385. public void setStatusBar(final SwingStatusBar statusBar) {
  386. this.statusBar = statusBar;
  387. }
  388. /**
  389. * Lays out the this component.
  390. */
  391. private void layoutComponents() {
  392. getContentPane().add(mainSplitPane, "grow, push");
  393. getContentPane().add(statusBar, "wmax 100%-2*rel, "
  394. + "wmin 100%-2*rel, south, gap rel rel 0 rel");
  395. }
  396. /**
  397. * Initialises the split pane.
  398. *
  399. * @return Returns the initialised split pane
  400. */
  401. private SplitPane initSplitPane() {
  402. final SplitPane splitPane = new SplitPane(globalConfig, SplitPane.Orientation.HORIZONTAL);
  403. position = FramemanagerPosition.getPosition(
  404. globalConfig.getOption("ui", "framemanagerPosition"));
  405. if (position == FramemanagerPosition.UNKNOWN) {
  406. position = FramemanagerPosition.LEFT;
  407. }
  408. if (!mainFrameManager.canPositionVertically() && (position
  409. == FramemanagerPosition.LEFT || position
  410. == FramemanagerPosition.RIGHT)) {
  411. position = FramemanagerPosition.BOTTOM;
  412. }
  413. if (!mainFrameManager.canPositionHorizontally() && (position
  414. == FramemanagerPosition.TOP || position
  415. == FramemanagerPosition.BOTTOM)) {
  416. position = FramemanagerPosition.LEFT;
  417. }
  418. switch (position) {
  419. case TOP:
  420. splitPane.setTopComponent(frameManagerPanel);
  421. splitPane.setBottomComponent(framePanel);
  422. splitPane.setResizeWeight(0.0);
  423. splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
  424. frameManagerPanel.setPreferredSize(new Dimension(
  425. Integer.MAX_VALUE, globalConfig.getOptionInt("ui", "frameManagerSize")));
  426. break;
  427. case LEFT:
  428. splitPane.setLeftComponent(frameManagerPanel);
  429. splitPane.setRightComponent(framePanel);
  430. splitPane.setResizeWeight(0.0);
  431. splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
  432. frameManagerPanel.setPreferredSize(new Dimension(
  433. globalConfig.getOptionInt("ui", "frameManagerSize"), Integer.MAX_VALUE));
  434. break;
  435. case BOTTOM:
  436. splitPane.setTopComponent(framePanel);
  437. splitPane.setBottomComponent(frameManagerPanel);
  438. splitPane.setResizeWeight(1.0);
  439. splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
  440. frameManagerPanel.setPreferredSize(new Dimension(
  441. Integer.MAX_VALUE, globalConfig.getOptionInt("ui", "frameManagerSize")));
  442. break;
  443. case RIGHT:
  444. splitPane.setLeftComponent(framePanel);
  445. splitPane.setRightComponent(frameManagerPanel);
  446. splitPane.setResizeWeight(1.0);
  447. splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
  448. frameManagerPanel.setPreferredSize(new Dimension(
  449. globalConfig.getOptionInt("ui", "frameManagerSize"), Integer.MAX_VALUE));
  450. break;
  451. default:
  452. break;
  453. }
  454. return splitPane;
  455. }
  456. /**
  457. * Exits with an "OK" status code.
  458. */
  459. public void quit() {
  460. quit(0);
  461. }
  462. /**
  463. * Exit code call to quit.
  464. *
  465. * @param exitCode Exit code
  466. */
  467. public void quit(final int exitCode) {
  468. if (exitCode == 0 && globalConfig.getOptionBool("ui", "confirmQuit")) {
  469. final StandardQuestionDialog dialog = new ConfirmQuitDialog(this) {
  470. /** Serial version UID. */
  471. private static final long serialVersionUID = 9;
  472. /** {@inheritDoc} */
  473. @Override
  474. protected void handleQuit() {
  475. doQuit(exitCode);
  476. }
  477. };
  478. dialog.display();
  479. return;
  480. }
  481. doQuit(exitCode);
  482. }
  483. /**
  484. * Exit code call to quit.
  485. *
  486. * @param exitCode Exit code
  487. */
  488. public void doQuit(final int exitCode) {
  489. this.exitCode = exitCode;
  490. quitting = true;
  491. quitWorker.get().executeInExecutor();
  492. }
  493. /** {@inheritDoc} */
  494. @Override
  495. public void configChanged(final String domain, final String key) {
  496. if ("ui".equals(domain)) {
  497. switch (key) {
  498. case "lookandfeel":
  499. controller.updateLookAndFeel();
  500. break;
  501. case "framemanager":
  502. case "framemanagerPosition":
  503. UIUtilities.invokeAndWait(new Runnable() {
  504. /** {@inheritDoc} */
  505. @Override
  506. public void run() {
  507. setVisible(false);
  508. getContentPane().remove(mainSplitPane);
  509. initFrameManagers();
  510. getContentPane().removeAll();
  511. layoutComponents();
  512. setVisible(true);
  513. }
  514. });
  515. break;
  516. case "textPaneFontName":
  517. final String font = globalConfig.getOptionString("ui", "textPaneFontName");
  518. log.debug("Changing textpane font: {}", font);
  519. UIUtilities.setUIFont(new Font(font, Font.PLAIN, 12));
  520. controller.updateComponentTrees();
  521. break;
  522. default:
  523. showVersion = globalConfig.getOptionBool("ui", "showversion");
  524. break;
  525. }
  526. } else {
  527. imageIcon = new ImageIcon(iconManager.getImage("icon"));
  528. UIUtilities.invokeLater(new Runnable() {
  529. /** {@inheritDoc} */
  530. @Override
  531. public void run() {
  532. setIconImage(imageIcon.getImage());
  533. }
  534. });
  535. }
  536. }
  537. /**
  538. * Changes the visible frame.
  539. *
  540. * @param activeFrame The frame to be activated, or null to show none
  541. */
  542. public void setActiveFrame(final TextFrame activeFrame) {
  543. UIUtilities.invokeLater(new Runnable() {
  544. /** {@inheritDoc} */
  545. @Override
  546. public void run() {
  547. focusOrder.offerAndMove(activeFrame);
  548. framePanel.setVisible(false);
  549. framePanel.removeAll();
  550. if (MainFrame.this.activeFrame != null) {
  551. MainFrame.this.activeFrame.getContainer()
  552. .removeNotificationListener(MainFrame.this);
  553. }
  554. MainFrame.this.activeFrame = activeFrame;
  555. if (activeFrame == null) {
  556. framePanel.add(new JPanel(), "grow");
  557. setTitle(null);
  558. } else {
  559. framePanel.add(activeFrame.getDisplayFrame(), "grow");
  560. setTitle(activeFrame.getContainer().getTitle());
  561. activeFrame.getContainer().addNotificationListener(
  562. MainFrame.this);
  563. }
  564. framePanel.setVisible(true);
  565. if (activeFrame != null) {
  566. activeFrame.requestFocus();
  567. activeFrame.requestFocusInWindow();
  568. activeFrame.activateFrame();
  569. }
  570. for (final SelectionListener listener : listeners.get(
  571. SelectionListener.class)) {
  572. listener.selectionChanged(activeFrame);
  573. }
  574. }
  575. });
  576. }
  577. /**
  578. * Registers a new selection listener with this frame. The listener will be notified whenever
  579. * the currently selected frame is changed.
  580. *
  581. * @param listener The listener to be added
  582. *
  583. * @see #setActiveFrame(com.dmdirc.addons.ui_swing.components.frames.TextFrame)
  584. * @see #getActiveFrame()
  585. */
  586. public void addSelectionListener(final SelectionListener listener) {
  587. listeners.add(SelectionListener.class, listener);
  588. }
  589. /**
  590. * Removes a previously registered selection listener.
  591. *
  592. * @param listener The listener to be removed
  593. *
  594. * @see #addSelectionListener(com.dmdirc.addons.ui_swing.SelectionListener)
  595. */
  596. public void removeSelectionListener(final SelectionListener listener) {
  597. listeners.remove(SelectionListener.class, listener);
  598. }
  599. /** {@inheritDoc} */
  600. @Override
  601. public void windowAdded(final TextFrame parent, final TextFrame window) {
  602. if (activeFrame == null) {
  603. setActiveFrame(window);
  604. }
  605. window.getContainer().addFrameInfoListener(this);
  606. }
  607. /** {@inheritDoc} */
  608. @Override
  609. public void windowDeleted(final TextFrame parent, final TextFrame window) {
  610. focusOrder.remove(window);
  611. if (activeFrame.equals(window)) {
  612. activeFrame = null;
  613. framePanel.setVisible(false);
  614. framePanel.removeAll();
  615. framePanel.setVisible(true);
  616. if (focusOrder.peek() == null) {
  617. SwingUtilities.invokeLater(new Runnable() {
  618. /** {@inheritDoc} */
  619. @Override
  620. public void run() {
  621. frameManager.scrollUp();
  622. }
  623. });
  624. } else {
  625. setActiveFrame(focusOrder.peek());
  626. }
  627. }
  628. window.getContainer().removeFrameInfoListener(this);
  629. }
  630. /** {@inheritDoc} */
  631. @Override
  632. public void iconChanged(final FrameContainer window, final String icon) {
  633. //Ignore
  634. }
  635. /** {@inheritDoc} */
  636. @Override
  637. public void nameChanged(final FrameContainer window, final String name) {
  638. //Ignore
  639. }
  640. /** {@inheritDoc} */
  641. @Override
  642. public void titleChanged(final FrameContainer window,
  643. final String title) {
  644. if (activeFrame != null && activeFrame.getContainer().equals(window)) {
  645. setTitle(title);
  646. }
  647. }
  648. /** {@inheritDoc} */
  649. @Override
  650. public void notificationSet(final FrameContainer window,
  651. final Colour colour) {
  652. if (activeFrame != null && activeFrame.getContainer().equals(window)) {
  653. window.clearNotification();
  654. }
  655. }
  656. /** {@inheritDoc} */
  657. @Override
  658. public void notificationCleared(final FrameContainer window) {
  659. //Ignore
  660. }
  661. /** {@inheritDoc} */
  662. @Override
  663. public void dispose() {
  664. if (!quitting) {
  665. removeWindowListener(this);
  666. }
  667. globalConfig.removeListener(this);
  668. super.dispose();
  669. }
  670. }