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.

TreeFrameManager.java 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. /*
  2. * Copyright (c) 2006-2007 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.ui.framemanager.tree;
  23. import java.awt.BorderLayout;
  24. import java.awt.Color;
  25. import java.awt.event.ActionEvent;
  26. import java.awt.event.ActionListener;
  27. import java.awt.event.KeyEvent;
  28. import java.awt.event.KeyListener;
  29. import java.awt.event.MouseEvent;
  30. import java.awt.event.MouseListener;
  31. import java.awt.event.MouseMotionListener;
  32. import java.awt.event.MouseWheelEvent;
  33. import java.awt.event.MouseWheelListener;
  34. import java.util.Hashtable;
  35. import java.util.Map;
  36. import javax.swing.BorderFactory;
  37. import javax.swing.JComponent;
  38. import javax.swing.JMenuItem;
  39. import javax.swing.JPopupMenu;
  40. import javax.swing.JScrollPane;
  41. import javax.swing.JTree;
  42. import javax.swing.SwingUtilities;
  43. import javax.swing.event.TreeExpansionEvent;
  44. import javax.swing.event.TreeExpansionListener;
  45. import javax.swing.event.TreeModelEvent;
  46. import javax.swing.event.TreeModelListener;
  47. import javax.swing.event.TreeSelectionEvent;
  48. import javax.swing.event.TreeSelectionListener;
  49. import javax.swing.event.TreeWillExpandListener;
  50. import javax.swing.tree.DefaultMutableTreeNode;
  51. import javax.swing.tree.ExpandVetoException;
  52. import javax.swing.tree.TreePath;
  53. import javax.swing.tree.TreeSelectionModel;
  54. import com.dmdirc.Channel;
  55. import com.dmdirc.Config;
  56. import com.dmdirc.FrameContainer;
  57. import com.dmdirc.Query;
  58. import com.dmdirc.Raw;
  59. import com.dmdirc.Server;
  60. import com.dmdirc.logger.ErrorLevel;
  61. import com.dmdirc.logger.Logger;
  62. import com.dmdirc.ui.framemanager.FrameManager;
  63. import static com.dmdirc.ui.UIUtilities.SMALL_BORDER;
  64. /**
  65. * Manages open windows in the application in a tree style view.
  66. */
  67. public final class TreeFrameManager implements FrameManager, TreeModelListener,
  68. TreeSelectionListener, TreeExpansionListener, TreeWillExpandListener,
  69. MouseListener, ActionListener, MouseMotionListener, MouseWheelListener,
  70. KeyListener {
  71. /**
  72. * display tree.
  73. */
  74. private final transient JTree tree;
  75. /**
  76. * root node.
  77. */
  78. private final transient DefaultMutableTreeNode root;
  79. /**
  80. * data model.
  81. */
  82. private final transient TreeViewModel model;
  83. /**
  84. * node storage, used for adding and deleting nodes correctly.
  85. */
  86. private final transient Map<FrameContainer, DefaultMutableTreeNode> nodes;
  87. /**
  88. * stores colour associated with a node, cheap hack till i rewrite the model.
  89. */
  90. private final transient Map<FrameContainer, Color> nodeColours;
  91. /**
  92. * stores background colour associated with a node,
  93. * cheap hack till i rewrite the model.
  94. */
  95. private transient DefaultMutableTreeNode rolloverNode;
  96. /**
  97. * popup menu for menu items on nodes.
  98. */
  99. private final transient JPopupMenu popup;
  100. /**
  101. * close menu item used in popup menus.
  102. */
  103. private final transient JMenuItem closeMenuItem;
  104. /**
  105. * The object that is currently selected.
  106. */
  107. private FrameContainer selected;
  108. /**
  109. *node under right click operation.
  110. */
  111. private transient DefaultMutableTreeNode popupNode;
  112. /**
  113. * creates a new instance of the TreeFrameManager.
  114. */
  115. public TreeFrameManager() {
  116. final TreeViewTreeCellRenderer renderer = new TreeViewTreeCellRenderer();
  117. nodes = new Hashtable<FrameContainer, DefaultMutableTreeNode>();
  118. nodeColours = new Hashtable<FrameContainer, Color>();
  119. popup = new JPopupMenu();
  120. closeMenuItem = new JMenuItem("Close window");
  121. root = new DefaultMutableTreeNode("DMDirc");
  122. model = new TreeViewModel(root);
  123. tree = new JTree(model);
  124. closeMenuItem.setActionCommand("Close");
  125. popup.add(closeMenuItem);
  126. popup.setOpaque(true);
  127. popup.setLightWeightPopupEnabled(true);
  128. tree.putClientProperty("JTree.lineStyle", "Angled");
  129. tree.setUI(new javax.swing.plaf.metal.MetalTreeUI());
  130. tree.getSelectionModel().
  131. setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
  132. tree.setCellRenderer(renderer);
  133. tree.setRootVisible(false);
  134. tree.setRowHeight(0);
  135. tree.setShowsRootHandles(false);
  136. tree.setOpaque(true);
  137. tree.setBorder(BorderFactory.createEmptyBorder(SMALL_BORDER,
  138. SMALL_BORDER, SMALL_BORDER, SMALL_BORDER));
  139. tree.setVisible(true);
  140. closeMenuItem.addActionListener(this);
  141. tree.addTreeSelectionListener(this);
  142. tree.addMouseListener(this);
  143. tree.addMouseMotionListener(this);
  144. tree.addMouseWheelListener(this);
  145. tree.addKeyListener(this);
  146. }
  147. /**
  148. * Indicates whether this frame manager can be positioned vertically
  149. * (i.e., at the side of the screen).
  150. * @return True iff the frame manager can be positioned vertically.
  151. */
  152. public boolean canPositionVertically() {
  153. return true;
  154. }
  155. /**
  156. * Indicates whether this frame manager can be positioned horizontally
  157. * (i.e., at the top or bottom of the screen).
  158. * @return True iff the frame manager can be positioned horizontally.
  159. */
  160. public boolean canPositionHorizontally() {
  161. return false;
  162. }
  163. /**
  164. * Indicates that there is a new active frame.
  165. * @param source The object that now has focus.
  166. */
  167. public void setSelected(final FrameContainer source) {
  168. selected = source;
  169. if (nodes.containsKey(source)) {
  170. final TreePath path = new TreePath(nodes.get(source).getPath());
  171. tree.scrollPathToVisible(path);
  172. if (!path.equals(tree.getSelectionPath())) {
  173. tree.setSelectionPath(path);
  174. }
  175. }
  176. SwingUtilities.invokeLater(new Runnable() {
  177. public void run() {
  178. tree.repaint();
  179. }
  180. });
  181. }
  182. /**
  183. * Retrieves the currently selected object.
  184. * @return The object that is currently selected.
  185. */
  186. public FrameContainer getSelected() {
  187. return selected;
  188. }
  189. /**
  190. * Retrieves the currently selected node.
  191. * @return The node that is currently selected.
  192. */
  193. public DefaultMutableTreeNode getSelectedNode() {
  194. return nodes.get(selected);
  195. }
  196. /**
  197. * Shows an event notification to the user by colouring the corresponding
  198. * element to the source a specific colour.
  199. * @param source The object requesting notification.
  200. * @param colour The colour that should be used to indicate the notification.
  201. */
  202. public void showNotification(final FrameContainer source, final Color colour) {
  203. if (nodeColours != null) {
  204. nodeColours.put(source, colour);
  205. SwingUtilities.invokeLater(new Runnable() {
  206. public void run() {
  207. tree.repaint();
  208. }
  209. });
  210. }
  211. }
  212. /**
  213. * Sets the rollover node and repaints the tree.
  214. * @param node rollover node.
  215. */
  216. public void showRollover(final DefaultMutableTreeNode node) {
  217. rolloverNode = node;
  218. SwingUtilities.invokeLater(new Runnable() {
  219. public void run() {
  220. tree.repaint();
  221. }
  222. });
  223. }
  224. /**
  225. * retrives the rollover node.
  226. * @return rollover node.
  227. */
  228. public DefaultMutableTreeNode getRollover() {
  229. return rolloverNode;
  230. }
  231. /**
  232. * Clears a notification from a frame and its node.
  233. * @param source Frame to remove notification from.
  234. */
  235. public void clearNotification(final FrameContainer source) {
  236. if (nodeColours != null && nodeColours.containsKey(source)) {
  237. nodeColours.remove(source);
  238. }
  239. }
  240. /**
  241. * retrieves the colour of a specific node.
  242. * @param source node to check colour of.
  243. * @return colour of the node.
  244. */
  245. public Color getNodeColour(final FrameContainer source) {
  246. if (nodeColours != null && nodeColours.containsKey(source)) {
  247. return nodeColours.get(source);
  248. }
  249. return null;
  250. }
  251. /**
  252. * Sets the parent component in the main UI.
  253. * @param parent parent component.
  254. */
  255. public void setParent(final JComponent parent) {
  256. final JScrollPane scrollPane = new JScrollPane(tree);
  257. scrollPane.setAutoscrolls(false);
  258. parent.setLayout(new BorderLayout());
  259. parent.add(scrollPane);
  260. tree.setBackground(Config.getOptionColor("treeview", "backgroundcolour",
  261. Config.getOptionColor("ui", "backgroundcolour", Color.WHITE)));
  262. tree.setForeground(Config.getOptionColor("treeview", "foregroundcolour",
  263. Config.getOptionColor("ui", "foregroundcolour", Color.BLACK)));
  264. }
  265. /**
  266. * adds a server to the tree.
  267. * @param server associated server.
  268. */
  269. public void addServer(final Server server) {
  270. final DefaultMutableTreeNode node = new DefaultMutableTreeNode();
  271. nodes.put(server, node);
  272. node.setUserObject(server);
  273. model.insertNodeInto(node, root);
  274. if (root.getChildCount() == 1) {
  275. selected = server;
  276. }
  277. tree.scrollPathToVisible(new TreePath(node.getPath()));
  278. }
  279. /**
  280. * removes a server from the tree.
  281. * @param server associated server.
  282. */
  283. public void delServer(final Server server) {
  284. model.removeNodeFromParent(nodes.get(server));
  285. }
  286. /**
  287. * adds a channel to the tree.
  288. * @param server associated server.
  289. * @param channel associated framecontainer.
  290. */
  291. public void addChannel(final Server server, final Channel channel) {
  292. final DefaultMutableTreeNode node = new DefaultMutableTreeNode();
  293. nodes.put(channel, node);
  294. node.setUserObject(channel);
  295. model.insertNodeInto(node, nodes.get(server));
  296. tree.scrollPathToVisible(new TreePath(node.getPath()));
  297. }
  298. /**
  299. * deletes a channel from the tree.
  300. * @param server associated server.
  301. * @param channel associated framecontainer.
  302. */
  303. public void delChannel(final Server server, final Channel channel) {
  304. model.removeNodeFromParent(nodes.get(channel));
  305. }
  306. /**
  307. * adds a query to the tree.
  308. * @param server associated server.
  309. * @param query associated framecontainer.
  310. */
  311. public void addQuery(final Server server, final Query query) {
  312. final DefaultMutableTreeNode node = new DefaultMutableTreeNode();
  313. nodes.put(query, node);
  314. node.setUserObject(query);
  315. model.insertNodeInto(node, nodes.get(server));
  316. tree.scrollPathToVisible(new TreePath(node.getPath()));
  317. }
  318. /**
  319. * deletes a query from the tree.
  320. * @param server associated server.
  321. * @param query associated framecontainer.
  322. */
  323. public void delQuery(final Server server, final Query query) {
  324. model.removeNodeFromParent(nodes.get(query));
  325. }
  326. /**
  327. * adds a raw to the tree.
  328. * @param server associated server.
  329. * @param raw associated framecontainer.
  330. */
  331. public void addRaw(final Server server, final Raw raw) {
  332. final DefaultMutableTreeNode node = new DefaultMutableTreeNode();
  333. nodes.put(raw, node);
  334. node.setUserObject(raw);
  335. model.insertNodeInto(node, nodes.get(server));
  336. tree.scrollPathToVisible(new TreePath(node.getPath()));
  337. }
  338. /**
  339. * deletes a raw from the tree.
  340. * @param server associated server.
  341. * @param raw associated framecontainer.
  342. */
  343. public void delRaw(final Server server, final Raw raw) {
  344. model.removeNodeFromParent(nodes.get(raw));
  345. }
  346. /**
  347. * valled whenever the value of the selection changes.
  348. * @param event selection event.
  349. */
  350. public void valueChanged(final TreeSelectionEvent event) {
  351. final DefaultMutableTreeNode node =
  352. (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
  353. if (node == null) { return; }
  354. final Object nodeInfo = node.getUserObject();
  355. if (nodeInfo instanceof FrameContainer) {
  356. ((FrameContainer) nodeInfo).activateFrame();
  357. } else {
  358. Logger.error(ErrorLevel.WARNING, "Unknown node type.");
  359. }
  360. }
  361. /**
  362. * Called after the tree has been expanded.
  363. * @param event expansion event.
  364. */
  365. public void treeExpanded(final TreeExpansionEvent event) {
  366. //Do nothing
  367. }
  368. /**
  369. * Called after the tree has been collapsed.
  370. * @param event expansion event.
  371. */
  372. public void treeCollapsed(final TreeExpansionEvent event) {
  373. //Do nothing
  374. }
  375. /**
  376. * Called when the tree is about to expand.
  377. * @param event expansion event.
  378. * @throws javax.swing.tree.ExpandVetoException thrown to prevent.
  379. * node expanding
  380. */
  381. public void treeWillExpand(final TreeExpansionEvent event) throws
  382. ExpandVetoException {
  383. //Do nothing
  384. }
  385. /**
  386. * Called when the tree is about to collapse.
  387. * @param event expansion event.
  388. * @throws javax.swing.tree.ExpandVetoException throw to prevent.
  389. * node collapsing
  390. */
  391. public void treeWillCollapse(final TreeExpansionEvent event) throws
  392. ExpandVetoException {
  393. //Do nothing
  394. }
  395. /**
  396. * called after a node, or set of nodes, changes.
  397. * @param event change event.
  398. */
  399. public void treeNodesChanged(final TreeModelEvent event) {
  400. //Do nothing
  401. }
  402. /**
  403. * called after a node has been inserted into the tree.
  404. * @param event change event.
  405. */
  406. public void treeNodesInserted(final TreeModelEvent event) {
  407. //Do nothing
  408. }
  409. /**
  410. * Called when a node is removed from the tree.
  411. * @param event change event.
  412. */
  413. public void treeNodesRemoved(final TreeModelEvent event) {
  414. //Do nothing
  415. }
  416. /**
  417. * Called when a tree changes structure.
  418. * @param event change event.
  419. */
  420. public void treeStructureChanged(final TreeModelEvent event) {
  421. //Do nothing
  422. }
  423. /**
  424. * Invoked when the mouse button has been clicked (pressed and released)
  425. * on a component.
  426. * @param event mouse event.
  427. */
  428. public void mouseClicked(final MouseEvent event) {
  429. processMouseEvent(event);
  430. }
  431. /**
  432. * Invoked when a mouse button has been pressed on a component.
  433. * @param event mouse event.
  434. */
  435. public void mousePressed(final MouseEvent event) {
  436. processMouseEvent(event);
  437. }
  438. /**
  439. * Invoked when a mouse button has been released on a component.
  440. * @param event mouse event.
  441. */
  442. public void mouseReleased(final MouseEvent event) {
  443. processMouseEvent(event);
  444. }
  445. /**
  446. * Invoked when the mouse enters a component.
  447. * @param event mouse event.
  448. */
  449. public void mouseEntered(final MouseEvent event) {
  450. //Do nothing
  451. }
  452. /**
  453. * Invoked when the mouse exits a component.
  454. * @param event mouse event.
  455. */
  456. public void mouseExited(final MouseEvent event) {
  457. //Do nothing
  458. }
  459. /**
  460. * Processes every mouse button event to check for a popup trigger.
  461. * @param event mouse event
  462. */
  463. public void processMouseEvent(final MouseEvent event) {
  464. if (event.isPopupTrigger()) {
  465. final JTree source = (JTree) event.getSource();
  466. final TreePath path = tree.getPathForLocation(event.getX(),
  467. event.getY());
  468. if (path != null) {
  469. popupNode = (DefaultMutableTreeNode) path.getLastPathComponent();
  470. popup.show(source, event.getX(), event.getY());
  471. }
  472. }
  473. }
  474. /**
  475. * Invoked when an action occurs.
  476. * @param event action event.
  477. */
  478. public void actionPerformed(final ActionEvent event) {
  479. if (event.getSource() == closeMenuItem && popupNode != null) {
  480. ((FrameContainer) popupNode.getUserObject()).close();
  481. }
  482. }
  483. /**
  484. * Invoked when a mouse button is pressed on a component and then dragged.
  485. *
  486. * @param event mouse event.
  487. */
  488. public void mouseDragged(final MouseEvent event) {
  489. final DefaultMutableTreeNode node = getNodeForLocation(event.getX(), event.getY());
  490. this.showRollover(node);
  491. if (node != null) {
  492. ((FrameContainer) node.getUserObject()).activateFrame();
  493. }
  494. }
  495. /**
  496. * Invoked when the mouse cursor has been moved onto a component but no
  497. * buttons have been pushed.
  498. *
  499. * @param event mouse event.
  500. */
  501. public void mouseMoved(final MouseEvent event) {
  502. final DefaultMutableTreeNode node = getNodeForLocation(event.getX(), event.getY());
  503. this.showRollover(node);
  504. }
  505. /**
  506. * Returns the node for the specified location, returning null if rollover
  507. * is disabled or there is no node at the specified location.
  508. *
  509. * @param x x coordiantes
  510. * @param y y coordiantes
  511. *
  512. * @return node or null
  513. */
  514. private DefaultMutableTreeNode getNodeForLocation(final int x, final int y) {
  515. DefaultMutableTreeNode node = null;
  516. if (Config.getOptionBool("ui", "treeviewRolloverEnabled")) {
  517. final TreePath selectedPath = tree.getPathForLocation(x, y);
  518. if (selectedPath == null) {
  519. this.showRollover(null);
  520. } else {
  521. node = (DefaultMutableTreeNode) selectedPath.getLastPathComponent();
  522. this.showRollover((DefaultMutableTreeNode) selectedPath.getLastPathComponent());
  523. }
  524. }
  525. return node;
  526. }
  527. /**
  528. * Invoked when the mouse wheel is rotated.
  529. * @param event mouse event.
  530. */
  531. public void mouseWheelMoved(final MouseWheelEvent event) {
  532. //get the number of notches (used only for direction)
  533. if (event.getWheelRotation() < 0) {
  534. changeFocus(true);
  535. } else {
  536. changeFocus(false);
  537. }
  538. }
  539. /**
  540. * Activates the node above or below the active node in the tree.
  541. *
  542. *@param direction true = up, false = down.
  543. */
  544. private void changeFocus(final boolean direction) {
  545. DefaultMutableTreeNode thisNode, nextNode;
  546. if (getSelectedNode() == null) {
  547. //no selected node, get the root node
  548. thisNode = root;
  549. //are there any servers to select?
  550. if (thisNode.getChildCount() > 0) {
  551. thisNode = (DefaultMutableTreeNode) thisNode.getChildAt(0);
  552. } else {
  553. //then wait till there are
  554. return;
  555. }
  556. } else {
  557. //use the selected node to start from
  558. thisNode = getSelectedNode();
  559. }
  560. //are we going up or down?
  561. if (direction) {
  562. //up
  563. if (thisNode.getUserObject() instanceof Server) {
  564. if (thisNode.getParent().getIndex(thisNode) == 0) {
  565. //first server - last child of parent's last child
  566. nextNode = (DefaultMutableTreeNode)
  567. ((DefaultMutableTreeNode) ((DefaultMutableTreeNode)
  568. thisNode.getParent()).getLastChild()).getLastChild();
  569. } else {
  570. //other servers - last child of previous sibling
  571. nextNode = (DefaultMutableTreeNode)
  572. (thisNode.getPreviousSibling()).getLastChild();
  573. }
  574. } else {
  575. if (thisNode.getParent().getIndex(thisNode) == 0) {
  576. //first frame - parent
  577. nextNode = (DefaultMutableTreeNode) thisNode.getParent();
  578. } else {
  579. //other frame - previous sibling
  580. nextNode = thisNode.getPreviousSibling();
  581. }
  582. }
  583. } else {
  584. //down
  585. if (thisNode.getUserObject() instanceof Server) {
  586. //all servers - get the first child
  587. nextNode = (DefaultMutableTreeNode) thisNode.getFirstChild();
  588. } else {
  589. if (thisNode.getParent().getIndex(thisNode)
  590. == thisNode.getParent().getChildCount() - 1) {
  591. //last frame - get the parents next sibling
  592. nextNode = ((DefaultMutableTreeNode) thisNode.getParent()).getNextSibling();
  593. //parent doesnt have a next sibling, get the first child of the grandparent
  594. if (nextNode == null) {
  595. nextNode = (DefaultMutableTreeNode) ((DefaultMutableTreeNode)
  596. thisNode.getParent().getParent()).getFirstChild();
  597. }
  598. } else {
  599. //other frames - get the next sibling
  600. nextNode = thisNode.getNextSibling();
  601. }
  602. }
  603. }
  604. //activate the nodes frame
  605. //((FrameContainer) nextNode.getUserObject()).activateFrame();
  606. tree.setSelectionPath(new TreePath(nextNode));
  607. }
  608. /**
  609. * Invoked when a key has been typed.
  610. * @param event key event.
  611. */
  612. public void keyTyped(final KeyEvent event) {
  613. //Do nothing
  614. }
  615. /**
  616. * Invoked when a key has been pressed.
  617. * @param event key event.
  618. */
  619. public void keyPressed(final KeyEvent event) {
  620. //Do nothing
  621. }
  622. /**
  623. * Invoked when a key has been released.
  624. * @param event key event.
  625. */
  626. public void keyReleased(final KeyEvent event) {
  627. //Do nothing
  628. }
  629. }