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.

TextPaneCanvas.java 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  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.swing.textpane;
  23. import com.dmdirc.ui.messages.IRCTextAttribute;
  24. import java.awt.Graphics;
  25. import java.awt.Graphics2D;
  26. import java.awt.Point;
  27. import java.awt.Rectangle;
  28. import java.awt.Shape;
  29. import java.awt.event.ComponentEvent;
  30. import java.awt.event.ComponentListener;
  31. import java.awt.event.MouseEvent;
  32. import java.awt.font.LineBreakMeasurer;
  33. import java.awt.font.TextHitInfo;
  34. import java.awt.font.TextLayout;
  35. import java.text.AttributedCharacterIterator;
  36. import java.util.HashMap;
  37. import java.util.Map;
  38. import javax.swing.JPanel;
  39. import javax.swing.event.MouseInputListener;
  40. /** Canvas object to draw text. */
  41. class TextPaneCanvas extends JPanel implements MouseInputListener,
  42. ComponentListener {
  43. /**
  44. * A version number for this class. It should be changed whenever the
  45. * class structure is changed (or anything else that would prevent
  46. * serialized objects being unserialized with the new class).
  47. */
  48. private static final long serialVersionUID = 6;
  49. /** IRCDocument. */
  50. private final IRCDocument document;
  51. /** parent textpane. */
  52. private final TextPane textPane;
  53. /** Position -> TextLayout. */
  54. private final Map<Rectangle, TextLayout> positions;
  55. /** TextLayout -> Line numbers. */
  56. private final Map<TextLayout, LineInfo> textLayouts;
  57. /** Line height. */
  58. private final int lineHeight;
  59. /** Selection event types. */
  60. private enum MouseEventType {
  61. /** Mouse clicked.*/
  62. CLICK,
  63. /** Mouse dragged.*/
  64. DRAG,
  65. /** Mouse released.*/
  66. RELEASE,
  67. };
  68. /** position of the scrollbar. */
  69. private int scrollBarPosition;
  70. /** Start line of the selection. */
  71. private int selStartLine;
  72. /** Start character of the selection. */
  73. private int selStartChar;
  74. /** End line of the selection. */
  75. private int selEndLine;
  76. /** End character of the selection. */
  77. private int selEndChar;
  78. /** First visible line. */
  79. private int firstVisibleLine;
  80. /** Last visible line. */
  81. private int lastVisibleLine;
  82. /** Line wrapping cache. */
  83. private final Map<Integer, Integer> lineWrap;
  84. /**
  85. * Creates a new text pane canvas.
  86. *
  87. * @param parent parent text pane for the canvas
  88. * @param document IRCDocument to be displayed
  89. */
  90. public TextPaneCanvas(final TextPane parent, final IRCDocument document) {
  91. super();
  92. this.document = document;
  93. scrollBarPosition = 0;
  94. lineHeight = getFont().getSize() + 2;
  95. textPane = parent;
  96. setDoubleBuffered(true);
  97. setOpaque(true);
  98. textLayouts = new HashMap<TextLayout, LineInfo>();
  99. positions = new HashMap<Rectangle, TextLayout>();
  100. lineWrap = new HashMap<Integer, Integer>();
  101. addMouseListener(this);
  102. addMouseMotionListener(this);
  103. addComponentListener(this);
  104. }
  105. /**
  106. * Paints the text onto the canvas.
  107. *
  108. * @param graphics graphics object to draw onto
  109. */
  110. public void paintComponent(final Graphics graphics) {
  111. final Graphics2D g = (Graphics2D) graphics;
  112. final float formatWidth = getWidth() - 6;
  113. final float formatHeight = getHeight();
  114. float drawPosY = formatHeight;
  115. int startLine = scrollBarPosition;
  116. int useStartLine;
  117. int useStartChar;
  118. int useEndLine;
  119. int useEndChar;
  120. int paragraphStart;
  121. int paragraphEnd;
  122. LineBreakMeasurer lineMeasurer;
  123. g.setColor(textPane.getBackground());
  124. g.fill(g.getClipBounds());
  125. textLayouts.clear();
  126. positions.clear();
  127. //check theres something to draw
  128. if (document.getNumLines() == 0) {
  129. return;
  130. }
  131. // Check the start line is in range
  132. if (startLine >= document.getNumLines()) {
  133. startLine = document.getNumLines() - 1;
  134. }
  135. if (startLine <= 0) {
  136. startLine = 0;
  137. }
  138. //sets the last visible line
  139. lastVisibleLine = startLine;
  140. firstVisibleLine = startLine;
  141. if (selStartLine > selEndLine) {
  142. // Swap both
  143. useStartLine = selEndLine;
  144. useStartChar = selEndChar;
  145. useEndLine = selStartLine;
  146. useEndChar = selStartChar;
  147. } else if (selStartLine == selEndLine && selStartChar > selEndChar) {
  148. // Just swap the chars
  149. useStartLine = selStartLine;
  150. useStartChar = selEndChar;
  151. useEndLine = selEndLine;
  152. useEndChar = selStartChar;
  153. } else {
  154. // Swap nothing
  155. useStartLine = selStartLine;
  156. useStartChar = selStartChar;
  157. useEndLine = selEndLine;
  158. useEndChar = selEndChar;
  159. }
  160. // Iterate through the lines
  161. for (int i = startLine; i >= 0; i--) {
  162. float drawPosX;
  163. final AttributedCharacterIterator iterator = document.getLine(i).getIterator();
  164. paragraphStart = iterator.getBeginIndex();
  165. paragraphEnd = iterator.getEndIndex();
  166. lineMeasurer = new LineBreakMeasurer(iterator, g.getFontRenderContext());
  167. lineMeasurer.setPosition(paragraphStart);
  168. final int wrappedLine;
  169. //do we have the line wrapping in the cache?
  170. if (lineWrap.containsKey(i)) {
  171. //use it
  172. wrappedLine = lineWrap.get(i);
  173. } else {
  174. //get it and populate the cache
  175. wrappedLine = getNumWrappedLines(lineMeasurer,
  176. paragraphStart, paragraphEnd, formatWidth);
  177. lineWrap.put(i, wrappedLine);
  178. }
  179. if (wrappedLine > 1) {
  180. drawPosY -= lineHeight * wrappedLine;
  181. }
  182. int j = 0;
  183. int chars = 0;
  184. // Loop through each wrapped line
  185. while (lineMeasurer.getPosition() < paragraphEnd) {
  186. final TextLayout layout;
  187. if (formatWidth < 0) {
  188. layout = lineMeasurer.nextLayout(0);
  189. } else {
  190. layout = lineMeasurer.nextLayout(formatWidth);
  191. }
  192. // Calculate the Y offset
  193. if (wrappedLine == 1) {
  194. drawPosY -= lineHeight;
  195. } else if (j != 0) {
  196. drawPosY += lineHeight;
  197. }
  198. // Calculate the initial X position
  199. if (layout.isLeftToRight()) {
  200. drawPosX = 3;
  201. } else {
  202. drawPosX = formatWidth - layout.getAdvance();
  203. }
  204. // Check if the target is in range
  205. if (drawPosY >= 0 || drawPosY <= formatHeight) {
  206. g.setColor(textPane.getForeground());
  207. layout.draw(g, drawPosX, drawPosY + lineHeight / 2f);
  208. doHighlight(i, useStartLine, useEndLine, useStartChar,
  209. useEndChar, chars, layout, g, drawPosY, drawPosX);
  210. firstVisibleLine = i;
  211. textLayouts.put(layout, new LineInfo(i, j));
  212. positions.put(new Rectangle(0, (int) drawPosY,
  213. (int) formatWidth, lineHeight), layout);
  214. }
  215. j++;
  216. chars += layout.getCharacterCount();
  217. }
  218. if (j > 1) {
  219. drawPosY -= lineHeight * (wrappedLine - 1);
  220. }
  221. if (drawPosY <= 0) {
  222. break;
  223. }
  224. }
  225. }
  226. /**
  227. * Returns the number of timesa line will wrap.
  228. *
  229. * @param lineMeasurer LineBreakMeasurer to work out wrapping for
  230. * @param paragraphStart Start index of the paragraph
  231. * @param paragraphEnd End index of the paragraph
  232. * @param formatWidth Width to wrap at
  233. *
  234. * @return Number of times the line wraps
  235. */
  236. private int getNumWrappedLines(final LineBreakMeasurer lineMeasurer,
  237. final int paragraphStart, final int paragraphEnd,
  238. final float formatWidth) {
  239. int wrappedLine = 0;
  240. while (lineMeasurer.getPosition() < paragraphEnd) {
  241. if (formatWidth < 0) {
  242. lineMeasurer.nextLayout(0);
  243. } else {
  244. lineMeasurer.nextLayout(formatWidth);
  245. }
  246. wrappedLine++;
  247. }
  248. lineMeasurer.setPosition(paragraphStart);
  249. return wrappedLine;
  250. }
  251. /**
  252. * Redraws the text that has been highlighted.
  253. *
  254. * @param line Line number
  255. * @param startLine Selection start line
  256. * @param endLine Selection end line
  257. * @param startChar Selection start char
  258. * @param endChar Selection end char
  259. * @param chars Number of characters so far in the line
  260. * @param layout Current line textlayout
  261. * @param g Graphics surface to draw highlight on
  262. * @param drawPosY current y location of the line
  263. * @param drawPosX current x location of the line
  264. */
  265. private void doHighlight(final int line, final int startLine,
  266. final int endLine, final int startChar, final int endChar,
  267. final int chars, final TextLayout layout, final Graphics2D g,
  268. final float drawPosY, final float drawPosX) {
  269. //Does this line need highlighting?
  270. if (startLine <= line && endLine >= line) {
  271. int firstChar;
  272. int lastChar;
  273. // Determine the first char we care about
  274. if (startLine < line || startChar < chars) {
  275. firstChar = chars;
  276. } else {
  277. firstChar = startChar;
  278. }
  279. // ... And the last
  280. if (endLine > line || endChar > chars + layout.getCharacterCount()) {
  281. lastChar = chars + layout.getCharacterCount();
  282. } else {
  283. lastChar = endChar;
  284. }
  285. // If the selection includes the chars we're showing
  286. if (lastChar > chars && firstChar < chars + layout.getCharacterCount()) {
  287. final int trans = (int) (lineHeight / 2f + drawPosY);
  288. final Shape shape = layout.getLogicalHighlightShape(firstChar - chars, lastChar - chars);
  289. final String text = textPane.getTextFromLine(line).substring(firstChar, lastChar);
  290. g.setColor(textPane.getForeground());
  291. g.translate(3, trans);
  292. g.fill(shape);
  293. g.translate(-3, -1 * trans);
  294. g.setColor(textPane.getBackground());
  295. if (firstChar == 0) {
  296. g.translate(0, trans);
  297. } else {
  298. g.translate(shape.getBounds().getX(), trans);
  299. }
  300. g.drawString(text, drawPosX, 0);
  301. if (firstChar == 0) {
  302. g.translate(0, -1 * trans);
  303. } else {
  304. g.translate(-1 * shape.getBounds().getX(), -1 * trans);
  305. }
  306. }
  307. }
  308. }
  309. /**
  310. * sets the position of the scroll bar, and repaints if required.
  311. * @param position scroll bar position
  312. */
  313. protected void setScrollBarPosition(final int position) {
  314. if (scrollBarPosition != position) {
  315. scrollBarPosition = position;
  316. if (textPane.isVisible()) {
  317. repaint();
  318. }
  319. }
  320. }
  321. /** {@inheritDoc}. */
  322. public void mouseClicked(final MouseEvent e) {
  323. String clickedText = "";
  324. final int start;
  325. final int end;
  326. final int[] info = getClickPosition(this.getMousePosition());
  327. if (info[0] != -1) {
  328. final AttributedCharacterIterator iterator = document.getLine(info[0]).getIterator();
  329. iterator.setIndex(info[2]);
  330. final Object linkattr = iterator.getAttributes().get(IRCTextAttribute.HYPERLINK);
  331. if (linkattr instanceof String) {
  332. fireHyperlinkClicked((String) linkattr);
  333. return;
  334. }
  335. clickedText = textPane.getTextFromLine(info[0]);
  336. if (info[2] == -1) {
  337. start = -1;
  338. end = -1;
  339. } else {
  340. final int[] extent = getSurroundingWordIndexes(clickedText, info[2]);
  341. start = extent[0];
  342. end = extent[1];
  343. }
  344. if (e.getClickCount() == 2) {
  345. selStartLine = info[0];
  346. selEndLine = info[0];
  347. selStartChar = start;
  348. selEndChar = end;
  349. } else if (e.getClickCount() == 3) {
  350. selStartLine = info[0];
  351. selEndLine = info[0];
  352. selStartChar = 0;
  353. selEndChar = clickedText.length();
  354. } else if (start != -1 && end != -1) {
  355. checkClickedText(clickedText.substring(start, end));
  356. }
  357. }
  358. e.setSource(textPane);
  359. textPane.dispatchEvent(e);
  360. }
  361. /**
  362. * Returns the indexes for the word surrounding the index in the specified
  363. * string.
  364. *
  365. * @param text Text to get word from
  366. * @param index Index to get surrounding word
  367. *
  368. * @return Indexes of the word surrounding the index (start, end)
  369. */
  370. private int[] getSurroundingWordIndexes(final String text, final int index) {
  371. final int start = getSurroundingWordStart(text, index);
  372. final int end = getSurroundingWordEnd(text, index);
  373. if (start < 0 || end > text.length() || start > end) {
  374. return new int[]{0, 0};
  375. }
  376. return new int[]{start, end};
  377. }
  378. /**
  379. * Returns the start index for the word surrounding the index in the
  380. * specified string.
  381. *
  382. * @param text Text to get word from
  383. * @param index Index to get surrounding word
  384. *
  385. * @return Start index of the word surrounding the index
  386. */
  387. private int getSurroundingWordStart(final String text, final int index) {
  388. int start = index;
  389. // Traverse backwards
  390. while (start > 0 && start < text.length() && text.charAt(start) != ' ') {
  391. start--;
  392. }
  393. if (start + 1 < text.length() && text.charAt(start) == ' ') {
  394. start++;
  395. }
  396. return start;
  397. }
  398. /**
  399. * Returns the end index for the word surrounding the index in the
  400. * specified string.
  401. *
  402. * @param text Text to get word from
  403. * @param index Index to get surrounding word
  404. *
  405. * @return End index of the word surrounding the index
  406. */
  407. private int getSurroundingWordEnd(final String text, final int index) {
  408. int end = index;
  409. // And forwards
  410. while (end < text.length() && end > 0 && text.charAt(end) != ' ') {
  411. end++;
  412. }
  413. return end;
  414. }
  415. /** {@inheritDoc}. */
  416. public void mousePressed(final MouseEvent e) {
  417. if (e.getButton() == e.BUTTON1) {
  418. highlightEvent(MouseEventType.CLICK, e);
  419. }
  420. e.setSource(textPane);
  421. textPane.dispatchEvent(e);
  422. }
  423. /** {@inheritDoc}. */
  424. public void mouseReleased(final MouseEvent e) {
  425. if (e.getButton() == e.BUTTON1) {
  426. highlightEvent(MouseEventType.RELEASE, e);
  427. }
  428. e.setSource(textPane);
  429. textPane.dispatchEvent(e);
  430. }
  431. /** {@inheritDoc}. */
  432. public void mouseDragged(final MouseEvent e) {
  433. if (e.getModifiersEx() == e.BUTTON1_DOWN_MASK) {
  434. highlightEvent(MouseEventType.DRAG, e);
  435. }
  436. e.setSource(textPane);
  437. textPane.dispatchEvent(e);
  438. }
  439. /** {@inheritDoc}. */
  440. public void mouseEntered(final MouseEvent e) {
  441. //Ignore
  442. }
  443. /** {@inheritDoc}. */
  444. public void mouseExited(final MouseEvent e) {
  445. //Ignore
  446. }
  447. /** {@inheritDoc}. */
  448. public void mouseMoved(final MouseEvent e) {
  449. //Ignore
  450. }
  451. /**
  452. * Sets the selection for the given event.
  453. *
  454. * @param type mouse event type
  455. * @param e responsible mouse event
  456. */
  457. private void highlightEvent(final MouseEventType type, final MouseEvent e) {
  458. final Point point = this.getMousePosition();
  459. if (point == null) {
  460. if (e.getXOnScreen() > getLocationOnScreen().getX()
  461. && e.getXOnScreen() < (getLocationOnScreen().getX() + getWidth())) {
  462. if (getLocationOnScreen().getY() > e.getYOnScreen()) {
  463. textPane.setScrollBarPosition(scrollBarPosition - 1);
  464. } else {
  465. textPane.setScrollBarPosition(scrollBarPosition + 1);
  466. }
  467. }
  468. } else {
  469. final int[] info = getClickPosition(point);
  470. if (info[0] != -1 && info[1] != -1) {
  471. if (type == MouseEventType.CLICK) {
  472. selStartLine = info[0];
  473. selStartChar = info[2];
  474. }
  475. selEndLine = info[0];
  476. selEndChar = info[2];
  477. this.repaint();
  478. }
  479. }
  480. }
  481. /**
  482. * Checks the clicked text and fires the appropriate events.
  483. *
  484. * @param clickedText Text clicked
  485. */
  486. public void checkClickedText(final String clickedText) {
  487. if (textPane.isValidChannel(clickedText)) {
  488. fireChannelClicked(clickedText);
  489. }
  490. }
  491. /**
  492. *
  493. * Returns the line information from a mouse click inside the textpane.
  494. *
  495. * @param point mouse position
  496. *
  497. * @return line number, line part, position in whole line
  498. */
  499. public int[] getClickPosition(final Point point) {
  500. int lineNumber = -1;
  501. int linePart = -1;
  502. int pos = 0;
  503. if (point != null) {
  504. for (Map.Entry<Rectangle, TextLayout> entry : positions.entrySet()) {
  505. if (entry.getKey().contains(point)) {
  506. lineNumber = textLayouts.get(entry.getValue()).getLine();
  507. linePart = textLayouts.get(entry.getValue()).getPart();
  508. }
  509. }
  510. for (Map.Entry<Rectangle, TextLayout> entry : positions.entrySet()) {
  511. if (textLayouts.get(entry.getValue()).getLine() == lineNumber) {
  512. if (textLayouts.get(entry.getValue()).getPart() < linePart) {
  513. pos += entry.getValue().getCharacterCount();
  514. } else if (textLayouts.get(entry.getValue()).getPart() == linePart) {
  515. final TextHitInfo hit = entry.getValue().hitTestChar(
  516. (int) point.getX(), (int) point.getY());
  517. if (hit.isLeadingEdge() || hit.getCharIndex() == 0) {
  518. pos += hit.getCharIndex();
  519. } else {
  520. pos += hit.getCharIndex() + 1;
  521. }
  522. }
  523. }
  524. }
  525. }
  526. return new int[]{lineNumber, linePart, pos};
  527. }
  528. /**
  529. * Informs listeners when a word has been clicked on.
  530. * @param text word clicked on
  531. */
  532. private void fireHyperlinkClicked(final String text) {
  533. textPane.fireHyperlinkClicked(text);
  534. }
  535. /**
  536. * Informs listeners when a word has been clicked on.
  537. * @param text word clicked on
  538. */
  539. private void fireChannelClicked(final String text) {
  540. textPane.fireChannelClicked(text);
  541. }
  542. /**
  543. * Returns the selected range info.
  544. * <ul>
  545. * <li>0 = start line</li>
  546. * <li>1 = start char</li>
  547. * <li>2 = end line</li>
  548. * <li>3 = end char</li>
  549. * </ul>
  550. *
  551. * @return Selected range info
  552. */
  553. protected int[] getSelectedRange() {
  554. if (selStartLine > selEndLine) {
  555. // Swap both
  556. return new int[]{selEndLine, selEndChar, selStartLine, selStartChar, };
  557. } else if (selStartLine == selEndLine && selStartChar > selEndChar) {
  558. // Just swap the chars
  559. return new int[]{selStartLine, selEndChar, selEndLine, selStartChar, };
  560. } else {
  561. // Swap nothing
  562. return new int[]{selStartLine, selStartChar, selEndLine, selEndChar, };
  563. }
  564. }
  565. /** Clears the selection. */
  566. protected void clearSelection() {
  567. selEndLine = selStartLine;
  568. selEndChar = selStartChar;
  569. if (isVisible()) {
  570. repaint();
  571. }
  572. }
  573. /**
  574. * Selects the specified region of text.
  575. *
  576. * @param startLine Start line
  577. * @param startChar Start char
  578. * @param endLine End line
  579. * @param endChar End char
  580. */
  581. public void setSelectedRange(final int startLine, final int startChar,
  582. final int endLine, final int endChar) {
  583. selStartLine = startLine;
  584. selStartChar = startChar;
  585. selEndLine = endLine;
  586. selEndChar = endChar;
  587. if (isVisible()) {
  588. repaint();
  589. }
  590. }
  591. /**
  592. * Returns the first visible line.
  593. *
  594. * @return the line number of the first visible line
  595. */
  596. public int getFirstVisibleLine() {
  597. return firstVisibleLine;
  598. }
  599. /**
  600. * Returns the last visible line.
  601. *
  602. * @return the line number of the last visible line
  603. */
  604. public int getLastVisibleLine() {
  605. return lastVisibleLine;
  606. }
  607. /** {@inheritDoc}. */
  608. public void componentResized(final ComponentEvent e) {
  609. //line wrap cache now invalid, clear and repaint
  610. lineWrap.clear();
  611. if (isVisible()) {
  612. repaint();
  613. }
  614. }
  615. /** {@inheritDoc}. */
  616. public void componentMoved(final ComponentEvent e) {
  617. //Ignore
  618. }
  619. /** {@inheritDoc}. */
  620. public void componentShown(final ComponentEvent e) {
  621. //Ignore
  622. }
  623. /** {@inheritDoc}. */
  624. public void componentHidden(final ComponentEvent e) {
  625. //Ignore
  626. }
  627. }