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.

MainFrame.java 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. /*
  2. * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes
  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.addons.ui_swing.components.MenuBar;
  24. import com.dmdirc.addons.ui_swing.components.LoggingSwingWorker;
  25. import com.dmdirc.addons.ui_swing.components.SplitPane;
  26. import com.dmdirc.addons.ui_swing.components.desktopPane.DMDircDesktopPane;
  27. import com.dmdirc.addons.ui_swing.components.statusbar.SwingStatusBar;
  28. import com.dmdirc.addons.ui_swing.framemanager.tree.TreeFrameManager;
  29. import com.dmdirc.FrameContainer;
  30. import com.dmdirc.Main;
  31. import com.dmdirc.ServerManager;
  32. import com.dmdirc.actions.ActionManager;
  33. import com.dmdirc.actions.CoreActionType;
  34. import com.dmdirc.config.IdentityManager;
  35. import com.dmdirc.interfaces.ConfigChangeListener;
  36. import com.dmdirc.ui.IconManager;
  37. import com.dmdirc.ui.WindowManager;
  38. import com.dmdirc.ui.interfaces.FrameManager;
  39. import com.dmdirc.ui.interfaces.FramemanagerPosition;
  40. import com.dmdirc.ui.interfaces.MainWindow;
  41. import com.dmdirc.ui.interfaces.Window;
  42. import com.dmdirc.ui.CoreUIUtils;
  43. import com.dmdirc.ui.interfaces.FrameListener;
  44. import com.dmdirc.util.ReturnableThread;
  45. import java.awt.Dimension;
  46. import java.awt.event.WindowEvent;
  47. import java.awt.event.WindowFocusListener;
  48. import java.awt.event.WindowListener;
  49. import javax.swing.ImageIcon;
  50. import javax.swing.JDesktopPane;
  51. import javax.swing.JFrame;
  52. import javax.swing.JInternalFrame;
  53. import javax.swing.JOptionPane;
  54. import javax.swing.JPanel;
  55. import javax.swing.JSplitPane;
  56. import javax.swing.MenuSelectionManager;
  57. import javax.swing.WindowConstants;
  58. import net.miginfocom.swing.MigLayout;
  59. /**
  60. * The main application frame.
  61. */
  62. public final class MainFrame extends JFrame implements WindowListener,
  63. MainWindow, ConfigChangeListener, FrameListener {
  64. /** Logger to use. */
  65. private static final java.util.logging.Logger LOGGER =
  66. java.util.logging.Logger.getLogger(MainFrame.class.getName());
  67. /**
  68. * A version number for this class. It should be changed whenever the class
  69. * structure is changed (or anything else that would prevent serialized
  70. * objects being unserialized with the new class).
  71. */
  72. private static final long serialVersionUID = 9;
  73. /** The main application icon. */
  74. private ImageIcon imageIcon;
  75. /** The frame manager that's being used. */
  76. private FrameManager mainFrameManager;
  77. /** Dekstop pane. */
  78. private DMDircDesktopPane desktopPane;
  79. /** Main panel. */
  80. private JPanel frameManagerPanel;
  81. /** Frame manager position. */
  82. private FramemanagerPosition position;
  83. /** Show version? */
  84. private boolean showVersion;
  85. /** Menu bar. */
  86. private MenuBar menu;
  87. /** Exit code. */
  88. private int exitCode = 0;
  89. /** Swing Controller. */
  90. private SwingController controller;
  91. /** Status bar. */
  92. private SwingStatusBar statusBar;
  93. /**
  94. * Creates new form MainFrame.
  95. *
  96. * @param controller Swing controller
  97. */
  98. protected MainFrame(final SwingController controller) {
  99. super();
  100. this.controller = controller;
  101. initComponents();
  102. imageIcon =
  103. new ImageIcon(IconManager.getIconManager().getImage("icon"));
  104. setIconImage(imageIcon.getImage());
  105. CoreUIUtils.centreWindow(this);
  106. setVisible(true);
  107. addWindowListener(this);
  108. showVersion = IdentityManager.getGlobalConfig().getOptionBool("ui",
  109. "showversion");
  110. IdentityManager.getGlobalConfig().addChangeListener("ui", "lookandfeel",
  111. this);
  112. IdentityManager.getGlobalConfig().addChangeListener("ui", "showversion",
  113. this);
  114. IdentityManager.getGlobalConfig().addChangeListener("icon", "icon", this);
  115. addWindowFocusListener(new WindowFocusListener() {
  116. /** {@inheritDoc} */
  117. @Override
  118. public void windowGainedFocus(WindowEvent e) {
  119. ActionManager.processEvent(CoreActionType.CLIENT_FOCUS_GAINED,
  120. null);
  121. }
  122. /** {@inheritDoc} */
  123. @Override
  124. public void windowLostFocus(WindowEvent e) {
  125. ActionManager.processEvent(CoreActionType.CLIENT_FOCUS_LOST,
  126. null);
  127. //TODO: Remove me when we switch to java7
  128. MenuSelectionManager.defaultManager().clearSelectedPath();
  129. }
  130. });
  131. setTitle(getTitlePrefix());
  132. }
  133. /**
  134. * Returns the status bar for this frame.
  135. *
  136. * @return Status bar
  137. */
  138. public SwingStatusBar getStatusBar() {
  139. return statusBar;
  140. }
  141. /**
  142. * Returns the size of the frame manager.
  143. *
  144. * @return Frame manager size.
  145. */
  146. public int getFrameManagerSize() {
  147. return UIUtilities.invokeAndWait(new ReturnableThread<Integer>() {
  148. /** {@inheritDoc} */
  149. @Override
  150. public void run() {
  151. if (position == FramemanagerPosition.LEFT ||
  152. position == FramemanagerPosition.RIGHT) {
  153. setObject(frameManagerPanel.getWidth());
  154. } else {
  155. setObject(frameManagerPanel.getHeight());
  156. }
  157. }
  158. });
  159. }
  160. /** {@inheritDoc}. */
  161. @Override
  162. public ImageIcon getIcon() {
  163. return UIUtilities.invokeAndWait(new ReturnableThread<ImageIcon>() {
  164. /** {@inheritDoc} */
  165. @Override
  166. public void run() {
  167. setObject(imageIcon);
  168. }
  169. });
  170. }
  171. /**
  172. * Returns the window that is currently active.
  173. *
  174. * @return The active window
  175. */
  176. public Window getActiveFrame() {
  177. return UIUtilities.invokeAndWait(new ReturnableThread<Window>() {
  178. /** {@inheritDoc} */
  179. @Override
  180. public void run() {
  181. setObject(desktopPane.getSelectedWindow());
  182. }
  183. });
  184. }
  185. /** {@inheritDoc}. */
  186. @Override
  187. public void setMaximised(final boolean max) {
  188. //Ignore
  189. }
  190. /** {@inheritDoc}. */
  191. @Override
  192. public void setTitle(final String title) {
  193. if (title != null && getActiveFrame() != null && getActiveFrame().isMaximum()) {
  194. super.setTitle(getTitlePrefix() + " - " + title);
  195. } else {
  196. super.setTitle(getTitlePrefix());
  197. }
  198. }
  199. /** {@inheritDoc}. */
  200. @Override
  201. public String getTitlePrefix() {
  202. if (showVersion) {
  203. return "DMDirc " + IdentityManager.getGlobalConfig().getOption(
  204. "version", "version");
  205. } else {
  206. return "DMDirc";
  207. }
  208. }
  209. /** {@inheritDoc}. */
  210. @Override
  211. public boolean getMaximised() {
  212. return UIUtilities.invokeAndWait(new ReturnableThread<Boolean>() {
  213. /** {@inheritDoc}. */
  214. @Override
  215. public void run() {
  216. final Window window = getActiveFrame();
  217. if (window == null) {
  218. setObject(false);
  219. } else {
  220. setObject(getActiveFrame().isMaximum());
  221. }
  222. }
  223. });
  224. }
  225. /**
  226. * Returns the desktop pane for the frame.
  227. *
  228. * @return JDesktopPane for the frame
  229. */
  230. public JDesktopPane getDesktopPane() {
  231. return desktopPane;
  232. }
  233. /**
  234. * {@inheritDoc}.
  235. *
  236. * @param windowEvent Window event
  237. */
  238. @Override
  239. public void windowOpened(final WindowEvent windowEvent) {
  240. //ignore
  241. }
  242. /**
  243. * {@inheritDoc}.
  244. *
  245. * @param windowEvent Window event
  246. */
  247. @Override
  248. public void windowClosing(final WindowEvent windowEvent) {
  249. quit(exitCode);
  250. }
  251. /**
  252. * {@inheritDoc}.
  253. *
  254. * @param windowEvent Window event
  255. */
  256. @Override
  257. public void windowClosed(final WindowEvent windowEvent) {
  258. new Thread(new Runnable() {
  259. /** {@inheritDoc} */
  260. @Override
  261. public void run() {
  262. Main.quit(exitCode);
  263. }
  264. }, "Quit thread").start();
  265. }
  266. /**
  267. * {@inheritDoc}.
  268. *
  269. * @param windowEvent Window event
  270. */
  271. @Override
  272. public void windowIconified(final WindowEvent windowEvent) {
  273. ActionManager.processEvent(CoreActionType.CLIENT_MINIMISED, null);
  274. }
  275. /**
  276. * {@inheritDoc}.
  277. *
  278. * @param windowEvent Window event
  279. */
  280. @Override
  281. public void windowDeiconified(final WindowEvent windowEvent) {
  282. ActionManager.processEvent(CoreActionType.CLIENT_UNMINIMISED, null);
  283. }
  284. /**
  285. * {@inheritDoc}.
  286. *
  287. * @param windowEvent Window event
  288. */
  289. @Override
  290. public void windowActivated(final WindowEvent windowEvent) {
  291. //ignore
  292. }
  293. /**
  294. * {@inheritDoc}.
  295. *
  296. * @param windowEvent Window event
  297. */
  298. @Override
  299. public void windowDeactivated(final WindowEvent windowEvent) {
  300. //ignore
  301. }
  302. /** Initialiases the frame managers. */
  303. private void initFrameManagers() {
  304. UIUtilities.invokeAndWait(new Runnable() {
  305. /** {@inheritDoc} */
  306. @Override
  307. public void run() {
  308. final String manager = IdentityManager.getGlobalConfig().
  309. getOption("ui",
  310. "framemanager");
  311. try {
  312. mainFrameManager = (FrameManager) Class.forName(manager).
  313. getConstructor().newInstance();
  314. } catch (Exception ex) {
  315. // Throws craploads of exceptions and we want to handle them all
  316. // the same way, so we might as well catch Exception
  317. mainFrameManager = new TreeFrameManager();
  318. }
  319. WindowManager.addFrameListener(mainFrameManager);
  320. mainFrameManager.setParent(frameManagerPanel);
  321. WindowManager.addFrameListener(MainFrame.this);
  322. }
  323. });
  324. }
  325. /**
  326. * Initialises the components for this frame.
  327. */
  328. private void initComponents() {
  329. statusBar = new SwingStatusBar(controller, this);
  330. frameManagerPanel = new JPanel();
  331. desktopPane = new DMDircDesktopPane(this);
  332. initFrameManagers();
  333. menu = new MenuBar(controller, this);
  334. Apple.getApple().setMenuBar(menu);
  335. setJMenuBar(menu);
  336. setPreferredSize(new Dimension(800, 600));
  337. getContentPane().setLayout(new MigLayout(
  338. "fill, ins rel, wrap 1, hidemode 2"));
  339. getContentPane().add(initSplitPane(), "grow, push");
  340. getContentPane().add(statusBar,
  341. "hmax 20, wmax 100%-2*rel, wmin 100%-2*rel");
  342. setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
  343. pack();
  344. }
  345. /**
  346. * Initialises the split pane.
  347. *
  348. * @return Returns the initialised split pane
  349. */
  350. private JSplitPane initSplitPane() {
  351. final JSplitPane mainSplitPane =
  352. new SplitPane(SplitPane.Orientation.HORIZONTAL);
  353. position =
  354. FramemanagerPosition.getPosition(IdentityManager.getGlobalConfig().
  355. getOption("ui", "framemanagerPosition"));
  356. if (position == FramemanagerPosition.UNKNOWN) {
  357. position = FramemanagerPosition.LEFT;
  358. }
  359. if (!mainFrameManager.canPositionVertically() &&
  360. (position == FramemanagerPosition.LEFT ||
  361. position == FramemanagerPosition.RIGHT)) {
  362. position = FramemanagerPosition.BOTTOM;
  363. }
  364. if (!mainFrameManager.canPositionHorizontally() &&
  365. (position == FramemanagerPosition.TOP ||
  366. position == FramemanagerPosition.BOTTOM)) {
  367. position = FramemanagerPosition.LEFT;
  368. }
  369. switch (position) {
  370. case TOP:
  371. mainSplitPane.setTopComponent(frameManagerPanel);
  372. mainSplitPane.setBottomComponent(desktopPane);
  373. mainSplitPane.setResizeWeight(0.0);
  374. mainSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
  375. frameManagerPanel.setPreferredSize(new Dimension(
  376. Integer.MAX_VALUE,
  377. IdentityManager.getGlobalConfig().
  378. getOptionInt("ui", "frameManagerSize")));
  379. break;
  380. case LEFT:
  381. mainSplitPane.setLeftComponent(frameManagerPanel);
  382. mainSplitPane.setRightComponent(desktopPane);
  383. mainSplitPane.setResizeWeight(0.0);
  384. mainSplitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
  385. frameManagerPanel.setPreferredSize(new Dimension(
  386. IdentityManager.getGlobalConfig().getOptionInt("ui",
  387. "frameManagerSize"), Integer.MAX_VALUE));
  388. break;
  389. case BOTTOM:
  390. mainSplitPane.setTopComponent(desktopPane);
  391. mainSplitPane.setBottomComponent(frameManagerPanel);
  392. mainSplitPane.setResizeWeight(1.0);
  393. mainSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
  394. frameManagerPanel.setPreferredSize(new Dimension(
  395. Integer.MAX_VALUE,
  396. IdentityManager.getGlobalConfig().
  397. getOptionInt("ui", "frameManagerSize")));
  398. break;
  399. case RIGHT:
  400. mainSplitPane.setLeftComponent(desktopPane);
  401. mainSplitPane.setRightComponent(frameManagerPanel);
  402. mainSplitPane.setResizeWeight(1.0);
  403. mainSplitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
  404. frameManagerPanel.setPreferredSize(new Dimension(
  405. IdentityManager.getGlobalConfig().getOptionInt("ui",
  406. "frameManagerSize"), Integer.MAX_VALUE));
  407. break;
  408. default:
  409. break;
  410. }
  411. return mainSplitPane;
  412. }
  413. /** {@inheritDoc}. */
  414. @Override
  415. public void quit() {
  416. quit(0);
  417. }
  418. /**
  419. * Exit code call to quit.
  420. *
  421. * @param exitCode Exit code
  422. */
  423. public void quit(final int exitCode) {
  424. if (exitCode == 0 && IdentityManager.getGlobalConfig().getOptionBool(
  425. "ui", "confirmQuit") && JOptionPane.showConfirmDialog(this,
  426. "You are about to quit DMDirc, are you sure?", "Quit confirm",
  427. JOptionPane.YES_NO_OPTION,
  428. JOptionPane.WARNING_MESSAGE) !=
  429. JOptionPane.YES_OPTION) {
  430. return;
  431. }
  432. this.exitCode = exitCode;
  433. new LoggingSwingWorker() {
  434. /** {@inheritDoc} */
  435. @Override
  436. protected Object doInBackground() throws Exception {
  437. ActionManager.processEvent(CoreActionType.CLIENT_CLOSING, null);
  438. ServerManager.getServerManager().closeAll(IdentityManager.
  439. getGlobalConfig().getOption("general", "closemessage"));
  440. IdentityManager.getConfigIdentity().setOption("ui",
  441. "frameManagerSize",
  442. String.valueOf(getFrameManagerSize()));
  443. return null;
  444. }
  445. /** {@inheritDoc} */
  446. @Override
  447. protected void done() {
  448. super.done();
  449. dispose();
  450. }
  451. }.execute();
  452. }
  453. /** {@inheritDoc} */
  454. @Override
  455. public void configChanged(final String domain, final String key) {
  456. if ("ui".equals(domain)) {
  457. if ("lookandfeel".equals(key)) {
  458. controller.updateLookAndFeel();
  459. } else {
  460. showVersion = IdentityManager.getGlobalConfig().getOptionBool(
  461. "ui",
  462. "showversion");
  463. }
  464. } else {
  465. imageIcon = new ImageIcon(IconManager.getIconManager().getImage(
  466. "icon"));
  467. setIconImage(imageIcon.getImage());
  468. }
  469. }
  470. /** {@inheritDoc}. */
  471. @Override
  472. public void addWindow(final FrameContainer window) {
  473. UIUtilities.invokeAndWait(new Runnable() {
  474. /** {@inheritDoc} */
  475. @Override
  476. public void run() {
  477. addWindow(window, desktopPane.getAllFrames().length - 1);
  478. }
  479. });
  480. }
  481. /**
  482. * Adds a window to this frame manager.
  483. *
  484. * @param window The server to be added
  485. * @param index Index of the window to be added
  486. */
  487. public void addWindow(final FrameContainer window, final int index) {
  488. UIUtilities.invokeAndWait(new Runnable() {
  489. /** {@inheritDoc} */
  490. @Override
  491. public void run() {
  492. final JInternalFrame frame = (JInternalFrame) window.getFrame();
  493. // Add the frame
  494. desktopPane.add(frame, index);
  495. }
  496. });
  497. }
  498. /** {@inheritDoc}. */
  499. @Override
  500. public void delWindow(final FrameContainer window) {
  501. UIUtilities.invokeAndWait(new Runnable() {
  502. /** {@inheritDoc} */
  503. @Override
  504. public void run() {
  505. final JInternalFrame frame = (JInternalFrame) window.getFrame();
  506. desktopPane.remove(frame);
  507. }
  508. });
  509. }
  510. /** {@inheritDoc}. */
  511. @Override
  512. public void addWindow(final FrameContainer parent,
  513. final FrameContainer window) {
  514. addWindow(window);
  515. }
  516. /** {@inheritDoc}. */
  517. @Override
  518. public void delWindow(final FrameContainer parent,
  519. final FrameContainer window) {
  520. delWindow(window);
  521. }
  522. }