PageRenderTime 56ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/columba-1.0/src/mail/core/org/columba/mail/gui/frame/ThreePaneMailFrameController.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 579 lines | 340 code | 119 blank | 120 comment | 38 complexity | c8ced38abd1f48e6849d9f314b4e5765 MD5 | raw file
  1. // The contents of this file are subject to the Mozilla Public License Version
  2. // 1.1
  3. //(the "License"); you may not use this file except in compliance with the
  4. //License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
  5. //
  6. //Software distributed under the License is distributed on an "AS IS" basis,
  7. //WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  8. //for the specific language governing rights and
  9. //limitations under the License.
  10. //
  11. //The Original Code is "The Columba Project"
  12. //
  13. //The Initial Developers of the Original Code are Frederik Dietz and Timo
  14. // Stich.
  15. //Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
  16. //
  17. //All Rights Reserved.
  18. package org.columba.mail.gui.frame;
  19. import java.awt.BorderLayout;
  20. import java.awt.Color;
  21. import java.awt.Point;
  22. import java.awt.event.KeyEvent;
  23. import java.awt.event.MouseAdapter;
  24. import java.awt.event.MouseEvent;
  25. import java.io.File;
  26. import java.io.FileInputStream;
  27. import java.io.IOException;
  28. import java.io.InputStream;
  29. import javax.swing.JComponent;
  30. import javax.swing.JPanel;
  31. import javax.swing.JScrollPane;
  32. import javax.swing.JSplitPane;
  33. import javax.swing.JTable;
  34. import javax.swing.JViewport;
  35. import javax.swing.KeyStroke;
  36. import javax.swing.SwingUtilities;
  37. import javax.swing.tree.TreePath;
  38. import org.columba.api.gui.frame.IContentPane;
  39. import org.columba.api.selection.ISelectionListener;
  40. import org.columba.api.selection.SelectionChangedEvent;
  41. import org.columba.core.config.ViewItem;
  42. import org.columba.core.gui.base.UIFSplitPane;
  43. import org.columba.core.io.DiskIO;
  44. import org.columba.mail.command.IMailFolderCommandReference;
  45. import org.columba.mail.config.MailConfig;
  46. import org.columba.mail.folder.IMailFolder;
  47. import org.columba.mail.folder.IMailbox;
  48. import org.columba.mail.gui.composer.HeaderController;
  49. import org.columba.mail.gui.infopanel.FolderInfoPanel;
  50. import org.columba.mail.gui.message.action.ViewMessageAction;
  51. import org.columba.mail.gui.table.FilterToolbar;
  52. import org.columba.mail.gui.table.ITableController;
  53. import org.columba.mail.gui.table.TableController;
  54. import org.columba.mail.gui.table.action.DeleteAction;
  55. import org.columba.mail.gui.table.action.OpenMessageWithComposerAction;
  56. import org.columba.mail.gui.table.action.OpenMessageWithMessageFrameAction;
  57. import org.columba.mail.gui.table.action.ViewHeaderListAction;
  58. import org.columba.mail.gui.table.model.HeaderTableModel;
  59. import org.columba.mail.gui.table.model.MessageNode;
  60. import org.columba.mail.gui.table.selection.TableSelectionChangedEvent;
  61. import org.columba.mail.gui.table.selection.TableSelectionHandler;
  62. import org.columba.mail.gui.tree.FolderTreeModel;
  63. import org.columba.mail.gui.tree.ITreeController;
  64. import org.columba.mail.gui.tree.TreeController;
  65. import org.columba.mail.gui.tree.action.MoveDownAction;
  66. import org.columba.mail.gui.tree.action.MoveUpAction;
  67. import org.columba.mail.gui.tree.action.RenameFolderAction;
  68. import org.columba.mail.gui.tree.selection.TreeSelectionChangedEvent;
  69. import org.columba.mail.gui.tree.selection.TreeSelectionHandler;
  70. import org.columba.mail.util.MailResourceLoader;
  71. /**
  72. * @author fdietz
  73. *
  74. */
  75. public class ThreePaneMailFrameController extends AbstractMailFrameController
  76. implements TreeViewOwner, TableViewOwner, IContentPane,
  77. ISelectionListener {
  78. public TreeController treeController;
  79. public TableController tableController;
  80. public HeaderController headerController;
  81. public FilterToolbar filterToolbar;
  82. public JSplitPane mainSplitPane;
  83. public JSplitPane rightSplitPane;
  84. private JPanel tablePanel;
  85. private JPanel messagePanel;
  86. public FolderInfoPanel folderInfoPanel;
  87. /**
  88. * true, if the messagelist table selection event was triggered by a popup
  89. * event. False, otherwise.
  90. */
  91. public boolean isTablePopupEvent;
  92. /**
  93. * true, if the tree selection event was triggered by a popup event. False,
  94. * otherwise.
  95. */
  96. public boolean isTreePopupEvent;
  97. /**
  98. * @param container
  99. */
  100. public ThreePaneMailFrameController(ViewItem viewItem) {
  101. super(viewItem);
  102. treeController = new TreeController(this, FolderTreeModel.getInstance());
  103. tableController = new TableController(this);
  104. // create selection handlers
  105. TableSelectionHandler tableHandler = new TableSelectionHandler(
  106. tableController);
  107. getSelectionManager().addSelectionHandler(tableHandler);
  108. tableHandler.addSelectionListener(this);
  109. TreeSelectionHandler treeHandler = new TreeSelectionHandler(
  110. treeController.getView());
  111. getSelectionManager().addSelectionHandler(treeHandler);
  112. // double-click mouse listener
  113. tableController.getView().addMouseListener(new TableMouseListener());
  114. treeController.getView().addMouseListener(new TreeMouseListener());
  115. folderInfoPanel = new FolderInfoPanel(this);
  116. // table registers interest in tree selection events
  117. treeHandler.addSelectionListener(tableHandler);
  118. // also register interest in tree seleciton events
  119. // for updating the title
  120. treeHandler.addSelectionListener(this);
  121. filterToolbar = new FilterToolbar(tableController);
  122. RenameFolderAction renameFolderAction = new RenameFolderAction(this);
  123. // Register F2 hotkey for renaming folder when the message panel has
  124. // focus
  125. tableController.getView().getActionMap().put("F2", renameFolderAction);
  126. tableController.getView().getInputMap().put(
  127. KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), "F2");
  128. // Register F2 hotkey for renaming folder when the folder tree itself
  129. // has focus
  130. treeController.getView().getActionMap().put("F2", renameFolderAction);
  131. treeController.getView().getInputMap().put(
  132. KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), "F2");
  133. // Register Alt-Up hotkey for moving up folder when folder tree or
  134. // table have focus
  135. MoveUpAction moveUpAction = new MoveUpAction(this);
  136. tableController.getView().getActionMap().put("ALT_UP", moveUpAction);
  137. tableController.getView().getInputMap().put(
  138. KeyStroke.getKeyStroke(KeyEvent.VK_UP, KeyEvent.ALT_MASK),
  139. "ALT_UP");
  140. treeController.getView().getActionMap().put("ALT_UP", moveUpAction);
  141. treeController.getView().getInputMap().put(
  142. KeyStroke.getKeyStroke(KeyEvent.VK_UP, KeyEvent.ALT_MASK),
  143. "ALT_UP");
  144. // Register Alt-Down hotkey for moving up folder when folder tree or
  145. // table have focus
  146. MoveDownAction moveDownAction = new MoveDownAction(this);
  147. tableController.getView().getActionMap()
  148. .put("ALT_DOWN", moveDownAction);
  149. tableController.getView().getInputMap().put(
  150. KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, KeyEvent.ALT_MASK),
  151. "ALT_DOWN");
  152. treeController.getView().getActionMap().put("ALT_DOWN", moveDownAction);
  153. treeController.getView().getInputMap().put(
  154. KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, KeyEvent.ALT_MASK),
  155. "ALT_DOWN");
  156. DeleteAction deleteAction = new DeleteAction(this);
  157. tableController.getView().getActionMap().put("DEL", deleteAction);
  158. tableController.getView().getInputMap().put(
  159. KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "DEL");
  160. }
  161. public void enableMessagePreview(boolean enable) {
  162. getViewItem().setBoolean("header_enabled", enable);
  163. if (enable) {
  164. rightSplitPane = new UIFSplitPane();
  165. rightSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
  166. rightSplitPane.add(tablePanel, JSplitPane.LEFT);
  167. rightSplitPane.add(messagePanel, JSplitPane.RIGHT);
  168. mainSplitPane.add(rightSplitPane, JSplitPane.RIGHT);
  169. } else {
  170. rightSplitPane = null;
  171. mainSplitPane.add(tablePanel, JSplitPane.RIGHT);
  172. }
  173. mainSplitPane.setDividerLocation(viewItem.getIntegerWithDefault(
  174. "splitpanes", "main", 100));
  175. if (enable)
  176. rightSplitPane.setDividerLocation(viewItem.getIntegerWithDefault(
  177. "splitpanes", "header", 100));
  178. getContainer().getFrame().validate();
  179. }
  180. /**
  181. * @return Returns the filterToolbar.
  182. */
  183. public FilterToolbar getFilterToolbar() {
  184. return filterToolbar;
  185. }
  186. /**
  187. * @see org.columba.mail.gui.frame.TreeViewOwner#getTreeController()
  188. */
  189. public ITreeController getTreeController() {
  190. return treeController;
  191. }
  192. /**
  193. * @see org.columba.mail.gui.frame.TableViewOwner#getTableController()
  194. */
  195. public ITableController getTableController() {
  196. return tableController;
  197. }
  198. /**
  199. * @see org.columba.api.gui.frame.IContentPane#getComponent()
  200. */
  201. public JComponent getComponent() {
  202. JPanel panel = new JPanel();
  203. mainSplitPane = new UIFSplitPane();
  204. mainSplitPane.setBorder(null);
  205. panel.setLayout(new BorderLayout());
  206. panel.add(mainSplitPane, BorderLayout.CENTER);
  207. mainSplitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
  208. JScrollPane treeScrollPane = new JScrollPane(treeController.getView());
  209. // treeScrollPane.setBorder(BorderFactory.createEmptyBorder(1, 1, 1,
  210. // 1));
  211. mainSplitPane.add(treeScrollPane, JSplitPane.LEFT);
  212. messagePanel = new JPanel();
  213. messagePanel.setLayout(new BorderLayout());
  214. messagePanel.add(messageController, BorderLayout.CENTER);
  215. tablePanel = new JPanel();
  216. tablePanel.setLayout(new BorderLayout());
  217. ViewItem viewItem = getViewItem();
  218. tablePanel.add(filterToolbar, BorderLayout.NORTH);
  219. JScrollPane tableScrollPane = new JScrollPane(tableController.getView());
  220. tableScrollPane
  221. .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
  222. tableScrollPane.getViewport().setScrollMode(
  223. JViewport.BACKINGSTORE_SCROLL_MODE);
  224. tableScrollPane.getViewport().setBackground(Color.white);
  225. tablePanel.add(tableScrollPane, BorderLayout.CENTER);
  226. if (viewItem
  227. .getBooleanWithDefault("splitpanes", "header_enabled", true)) {
  228. rightSplitPane = new UIFSplitPane();
  229. rightSplitPane.setBorder(null);
  230. rightSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
  231. rightSplitPane.add(tablePanel, JSplitPane.LEFT);
  232. rightSplitPane.add(messagePanel, JSplitPane.RIGHT);
  233. mainSplitPane.add(rightSplitPane, JSplitPane.RIGHT);
  234. } else {
  235. mainSplitPane.add(tablePanel, JSplitPane.RIGHT);
  236. }
  237. getContainer().setInfoPanel(folderInfoPanel);
  238. int count = MailConfig.getInstance().getAccountList().count();
  239. if (count == 0) {
  240. // pack();
  241. rightSplitPane.setDividerLocation(150);
  242. } else {
  243. mainSplitPane.setDividerLocation(viewItem.getIntegerWithDefault(
  244. "splitpanes", "main", 100));
  245. if (viewItem.getBooleanWithDefault("splitpanes", "header_enabled",
  246. true))
  247. rightSplitPane.setDividerLocation(viewItem
  248. .getIntegerWithDefault("splitpanes", "header", 100));
  249. }
  250. try {
  251. InputStream is = DiskIO
  252. .getResourceStream("org/columba/mail/action/menu.xml");
  253. getContainer().extendMenu(this, is);
  254. File configDirectory = MailConfig.getInstance()
  255. .getConfigDirectory();
  256. InputStream is2 = new FileInputStream(new File(configDirectory, "main_toolbar.xml"));
  257. getContainer().extendToolbar(this, is2);
  258. } catch (IOException e) {
  259. e.printStackTrace();
  260. }
  261. tableController.createPopupMenu();
  262. treeController.createPopupMenu();
  263. messageController.createPopupMenu();
  264. // TODO: fixme
  265. // JFrame frame = (JFrame) getContainer().getFrame();
  266. // ColumbaMenu menu = (ColumbaMenu) frame.getJMenuBar();
  267. // menu.addMenuItem("my_reply_action_id", new ReplyAction(this),
  268. // ColumbaMenu.MENU_VIEW, ColumbaMenu.PLACEHOLDER_BOTTOM);
  269. return panel;
  270. }
  271. public void showFilterToolbar() {
  272. tablePanel.add(filterToolbar, BorderLayout.NORTH);
  273. tablePanel.validate();
  274. }
  275. public void hideFilterToolbar() {
  276. tablePanel.remove(filterToolbar);
  277. tablePanel.validate();
  278. }
  279. public void savePositions(ViewItem viewItem) {
  280. super.savePositions(viewItem);
  281. // splitpanes
  282. viewItem.setInteger("splitpanes", "main", mainSplitPane
  283. .getDividerLocation());
  284. if (rightSplitPane != null)
  285. viewItem.setInteger("splitpanes", "header", rightSplitPane
  286. .getDividerLocation());
  287. viewItem.setBoolean("splitpanes", "header_enabled",
  288. rightSplitPane != null);
  289. IMailFolderCommandReference r = getTreeSelection();
  290. if (r != null) {
  291. IMailFolder folder = (IMailFolder) r.getSourceFolder();
  292. // folder-based configuration
  293. if (folder instanceof IMailbox)
  294. getFolderOptionsController().save((IMailbox) folder);
  295. }
  296. }
  297. /**
  298. * @return Returns the folderInfoPanel.
  299. */
  300. public FolderInfoPanel getFolderInfoPanel() {
  301. return folderInfoPanel;
  302. }
  303. /**
  304. * @see org.columba.api.gui.frame.IFrameMediator#getString(java.lang.String,
  305. * java.lang.String, java.lang.String)
  306. */
  307. public String getString(String sPath, String sName, String sID) {
  308. return MailResourceLoader.getString(sPath, sName, sID);
  309. }
  310. /**
  311. * @see org.columba.api.gui.frame.IFrameMediator#getContentPane()
  312. */
  313. public IContentPane getContentPane() {
  314. return this;
  315. }
  316. /**
  317. * @see org.columba.api.selection.ISelectionListener#selectionChanged(org.columba.api.selection.SelectionChangedEvent)
  318. */
  319. public void selectionChanged(SelectionChangedEvent e) {
  320. if (e instanceof TreeSelectionChangedEvent) {
  321. // tree selection event
  322. TreeSelectionChangedEvent event = (TreeSelectionChangedEvent) e;
  323. IMailFolder[] selectedFolders = event.getSelected();
  324. if (isTreePopupEvent == false) {
  325. // view headerlist in message list viewer
  326. new ViewHeaderListAction(this).actionPerformed(null);
  327. getFolderInfoPanel().selectionChanged(e);
  328. // update frame title
  329. if (selectedFolders.length == 1 && selectedFolders[0] != null) {
  330. getContainer().getFrame().setTitle(
  331. selectedFolders[0].getName());
  332. } else {
  333. getContainer().getFrame().setTitle("");
  334. }
  335. }
  336. isTreePopupEvent = false;
  337. } else if (e instanceof TableSelectionChangedEvent) {
  338. // messagelist table selection event
  339. TableSelectionChangedEvent event = (TableSelectionChangedEvent) e;
  340. if (isTablePopupEvent == false)
  341. // show message content
  342. new ViewMessageAction(this).actionPerformed(null);
  343. isTablePopupEvent = false;
  344. } else
  345. throw new IllegalArgumentException(
  346. "unknown selection changed event");
  347. }
  348. /**
  349. * Double-click mouse listener for message list table component.
  350. * <p>
  351. * If message is marked as draft, the composer will be opened to edit the
  352. * message. Otherwise, the message will be viewed in the message frame.
  353. *
  354. * @author Frederik Dietz
  355. */
  356. class TableMouseListener extends MouseAdapter {
  357. /**
  358. * @see java.awt.event.MouseAdapter#mousePressed(java.awt.event.MouseEvent)
  359. */
  360. public void mousePressed(MouseEvent event) {
  361. if (event.isPopupTrigger()) {
  362. processPopup(event);
  363. }
  364. }
  365. /**
  366. * @see java.awt.event.MouseAdapter#mouseReleased(java.awt.event.MouseEvent)
  367. */
  368. public void mouseReleased(MouseEvent event) {
  369. if (event.isPopupTrigger()) {
  370. processPopup(event);
  371. }
  372. }
  373. /**
  374. * @see java.awt.event.MouseAdapter#mouseClicked(java.awt.event.MouseEvent)
  375. */
  376. public void mouseClicked(MouseEvent event) {
  377. // if mouse button was pressed twice times
  378. if (event.getClickCount() == 2) {
  379. // get selected row
  380. int selectedRow = tableController.getView().getSelectedRow();
  381. // get message node at selected row
  382. MessageNode node = (MessageNode) ((HeaderTableModel) tableController
  383. .getHeaderTableModel())
  384. .getMessageNodeAtRow(selectedRow);
  385. // is the message marked as draft ?
  386. boolean markedAsDraft = node.getHeader().getFlags().getDraft();
  387. if (markedAsDraft) {
  388. // edit message in composer
  389. new OpenMessageWithComposerAction(
  390. ThreePaneMailFrameController.this)
  391. .actionPerformed(null);
  392. } else {
  393. // open message in new message-frame
  394. new OpenMessageWithMessageFrameAction(
  395. ThreePaneMailFrameController.this)
  396. .actionPerformed(null);
  397. }
  398. }
  399. }
  400. protected void processPopup(final MouseEvent event) {
  401. isTablePopupEvent = true;
  402. JTable table = tableController.getView();
  403. int selectedRows = table.getSelectedRowCount();
  404. if (selectedRows <= 1) {
  405. // select node
  406. int row = table
  407. .rowAtPoint(new Point(event.getX(), event.getY()));
  408. table.setRowSelectionInterval(row, row);
  409. }
  410. SwingUtilities.invokeLater(new Runnable() {
  411. public void run() {
  412. tableController.getPopupMenu().show(event.getComponent(),
  413. event.getX(), event.getY());
  414. isTablePopupEvent = false;
  415. }
  416. });
  417. }
  418. }
  419. class TreeMouseListener extends MouseAdapter {
  420. /**
  421. * @see java.awt.event.MouseAdapter#mousePressed(java.awt.event.MouseEvent)
  422. */
  423. public void mousePressed(MouseEvent event) {
  424. if (event.isPopupTrigger()) {
  425. processPopup(event);
  426. }
  427. }
  428. /**
  429. * @see java.awt.event.MouseAdapter#mouseReleased(java.awt.event.MouseEvent)
  430. */
  431. public void mouseReleased(MouseEvent event) {
  432. if (event.isPopupTrigger()) {
  433. processPopup(event);
  434. }
  435. }
  436. /**
  437. * @see java.awt.event.MouseAdapter#mouseClicked(java.awt.event.MouseEvent)
  438. */
  439. public void mouseClicked(MouseEvent event) {
  440. // if mouse button was pressed twice times
  441. if (event.getClickCount() == 2) {
  442. // get selected row
  443. }
  444. }
  445. protected void processPopup(final MouseEvent event) {
  446. isTreePopupEvent = true;
  447. Point point = event.getPoint();
  448. TreePath path = treeController.getView().getClosestPathForLocation(
  449. point.x, point.y);
  450. treeController.getView().setSelectionPath(path);
  451. SwingUtilities.invokeLater(new Runnable() {
  452. public void run() {
  453. treeController.getPopupMenu().show(event.getComponent(),
  454. event.getX(), event.getY());
  455. isTreePopupEvent = false;
  456. }
  457. });
  458. }
  459. }
  460. }