PageRenderTime 41ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/jEdit/tags/jedit-4-0-pre5/org/gjt/sp/jedit/textarea/Gutter.java

#
Java | 880 lines | 539 code | 110 blank | 231 comment | 85 complexity | 0cdc119c4fa4bfb9b242a16f9654b81a MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * Gutter.java
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 1999, 2000 mike dillon
  7. * Portions copyright (C) 2001, 2002 Slava Pestov
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22. */
  23. package org.gjt.sp.jedit.textarea;
  24. //{{{ Imports
  25. import java.awt.*;
  26. import java.awt.event.*;
  27. import java.util.ArrayList;
  28. import javax.swing.*;
  29. import javax.swing.border.*;
  30. import javax.swing.event.*;
  31. import org.gjt.sp.jedit.*;
  32. import org.gjt.sp.util.Log;
  33. //}}}
  34. /**
  35. * The gutter is the component that displays folding triangles and line
  36. * numbers to the left of the text area. The only methods in this class
  37. * that should be called by plugins are those for adding and removing
  38. * text area extensions.
  39. *
  40. * @see #addExtension(TextAreaExtension)
  41. * @see #addExtension(int,TextAreaExtension)
  42. * @see #removeExtension(TextAreaExtension)
  43. * @see TextAreaExtension
  44. * @see JEditTextArea
  45. *
  46. * @author Mike Dillon and Slava Pestov
  47. * @version $Id: Gutter.java 4004 2002-02-01 07:40:23Z spestov $
  48. */
  49. public class Gutter extends JComponent implements SwingConstants
  50. {
  51. //{{{ Layers
  52. /**
  53. * The lowest possible layer.
  54. * @see #addExtension(int,TextAreaExtension)
  55. * @since jEdit 4.0pre4
  56. */
  57. public static final int LOWEST_LAYER = Integer.MIN_VALUE;
  58. /**
  59. * Default extension layer. This is above the wrap guide but below the
  60. * bracket highlight.
  61. * @since jEdit 4.0pre4
  62. */
  63. public static final int DEFAULT_LAYER = 0;
  64. /**
  65. * Highest possible layer.
  66. * @since jEdit 4.0pre4
  67. */
  68. public static final int HIGHEST_LAYER = Integer.MAX_VALUE;
  69. //}}}
  70. //{{{ Gutter constructor
  71. public Gutter(View view, JEditTextArea textArea)
  72. {
  73. this.view = view;
  74. this.textArea = textArea;
  75. extensionMgr = new ExtensionManager();
  76. MouseHandler ml = new MouseHandler();
  77. addMouseListener(ml);
  78. addMouseMotionListener(ml);
  79. addExtension(new MarkerHighlight());
  80. } //}}}
  81. //{{{ paintComponent() method
  82. public void paintComponent(Graphics _gfx)
  83. {
  84. Graphics2D gfx = (Graphics2D)_gfx;
  85. // fill the background
  86. Rectangle clip = gfx.getClipBounds();
  87. gfx.setColor(getBackground());
  88. gfx.fillRect(clip.x, clip.y, clip.width, clip.height);
  89. // if buffer is loading, don't paint anything
  90. if (!textArea.getBuffer().isLoaded())
  91. return;
  92. // paint highlights and line numbers
  93. int lineHeight = textArea.getPainter().getFontMetrics()
  94. .getHeight();
  95. int firstLine = clip.y / lineHeight;
  96. int lastLine = (clip.y + clip.height - 1) / lineHeight;
  97. FontMetrics pfm = textArea.getPainter().getFontMetrics();
  98. Color fg = getForeground();
  99. int baseline = (int)((this.baseline + lineHeight
  100. - pfm.getDescent()) / 2.0);
  101. boolean highlightCurrentLine = currentLineHighlightEnabled
  102. && textArea.selection.size() == 0;
  103. int y = (clip.y - clip.y % lineHeight);
  104. Buffer buffer = textArea.getBuffer();
  105. textArea.chunkCache.updateChunksUpTo(lastLine);
  106. for (int line = firstLine; line <= lastLine;
  107. line++, y += lineHeight)
  108. {
  109. ChunkCache.LineInfo info = textArea.chunkCache.getLineInfo(line);
  110. if(!info.chunksValid)
  111. System.err.println("gutter paint: not valid");
  112. int physicalLine = info.physicalLine;
  113. //{{{ Paint text area extensions
  114. if(physicalLine != -1)
  115. {
  116. int start = textArea.getScreenLineStartOffset(line);
  117. int end = textArea.getScreenLineEndOffset(line);
  118. extensionMgr.paintValidLine(gfx,line,physicalLine,start,end,y);
  119. }
  120. else
  121. extensionMgr.paintInvalidLine(gfx,line,y);
  122. //}}}
  123. // Skip lines beyond EOF
  124. if(physicalLine == -1)
  125. return;
  126. //{{{ Paint fold triangles
  127. if(info.firstSubregion
  128. && physicalLine != buffer.getLineCount() - 1
  129. && buffer.isFoldStart(physicalLine))
  130. {
  131. int _y = y + lineHeight / 2;
  132. gfx.setColor(foldColor);
  133. if(textArea.getFoldVisibilityManager()
  134. .isLineVisible(physicalLine + 1))
  135. {
  136. gfx.drawLine(1,_y - 3,10,_y - 3);
  137. gfx.drawLine(2,_y - 2,9,_y - 2);
  138. gfx.drawLine(3,_y - 1,8,_y - 1);
  139. gfx.drawLine(4,_y,7,_y);
  140. gfx.drawLine(5,_y + 1,6,_y + 1);
  141. }
  142. else
  143. {
  144. gfx.drawLine(4,_y - 5,4,_y + 4);
  145. gfx.drawLine(5,_y - 4,5,_y + 3);
  146. gfx.drawLine(6,_y - 3,6,_y + 2);
  147. gfx.drawLine(7,_y - 2,7,_y + 1);
  148. gfx.drawLine(8,_y - 1,8,_y);
  149. }
  150. } //}}}
  151. //{{{ Paint bracket scope
  152. else if(bracketHighlight)
  153. {
  154. if(textArea.isBracketHighlightVisible())
  155. {
  156. int bracketLine = textArea.getBracketLine();
  157. int caretLine = textArea.getCaretLine();
  158. if(caretLine != bracketLine)
  159. {
  160. if(caretLine > bracketLine)
  161. {
  162. int tmp = caretLine;
  163. caretLine = bracketLine;
  164. bracketLine = tmp;
  165. }
  166. gfx.setColor(bracketHighlightColor);
  167. if(physicalLine == caretLine)
  168. {
  169. gfx.fillRect(5,
  170. y
  171. + lineHeight / 2,
  172. 5,
  173. 2);
  174. gfx.fillRect(5,
  175. y
  176. + lineHeight / 2,
  177. 2,
  178. lineHeight - lineHeight / 2);
  179. }
  180. else if(physicalLine == bracketLine)
  181. {
  182. gfx.fillRect(5,
  183. y,
  184. 2,
  185. lineHeight / 2);
  186. gfx.fillRect(5,
  187. y + lineHeight / 2,
  188. 5,
  189. 2);
  190. }
  191. else if(physicalLine > caretLine
  192. && physicalLine < bracketLine)
  193. {
  194. gfx.fillRect(5,
  195. y,
  196. 2,
  197. lineHeight);
  198. }
  199. }
  200. }
  201. } //}}}
  202. //{{{ Paint line numbers
  203. if(info.firstSubregion && expanded)
  204. {
  205. String number = Integer.toString(physicalLine + 1);
  206. int offset;
  207. switch (alignment)
  208. {
  209. case RIGHT:
  210. offset = gutterSize.width - collapsedSize.width
  211. - (fm.stringWidth(number) + 1);
  212. break;
  213. case CENTER:
  214. offset = ((gutterSize.width - collapsedSize.width)
  215. - fm.stringWidth(number)) / 2;
  216. break;
  217. case LEFT: default:
  218. offset = 0;
  219. break;
  220. }
  221. if (physicalLine == textArea.getCaretLine() && highlightCurrentLine)
  222. {
  223. gfx.setColor(currentLineHighlight);
  224. }
  225. else if (interval > 1 && (line
  226. + textArea.getFirstLine() + 1)
  227. % interval == 0)
  228. gfx.setColor(intervalHighlight);
  229. else
  230. gfx.setColor(fg);
  231. gfx.drawString(number, FOLD_MARKER_SIZE + offset,
  232. baseline + y);
  233. } //}}}
  234. }
  235. } //}}}
  236. //{{{ addCustomHighlight() method
  237. /**
  238. * @deprecated Write a <code>TextAreaExtension</code> instead.
  239. */
  240. public void addCustomHighlight(TextAreaHighlight highlight)
  241. {
  242. Log.log(Log.WARNING,this,"Old highlighter API not supported: "
  243. + highlight);
  244. } //}}}
  245. //{{{ removeCustomHighlight() method
  246. /**
  247. * @deprecated Write a <code>TextAreaExtension</code> instead.
  248. */
  249. public void removeCustomHighlight(TextAreaHighlight highlight)
  250. {
  251. Log.log(Log.WARNING,this,"Old highlighter API not supported: "
  252. + highlight);
  253. } //}}}
  254. //{{{ addExtension() method
  255. /**
  256. * Adds a text area extension, which can perform custom painting and
  257. * tool tip handling.
  258. * @param extension The extension
  259. * @since jEdit 4.0pre4
  260. */
  261. public void addExtension(TextAreaExtension extension)
  262. {
  263. extensionMgr.addExtension(DEFAULT_LAYER,extension);
  264. repaint();
  265. } //}}}
  266. //{{{ addExtension() method
  267. /**
  268. * Adds a text area extension, which can perform custom painting and
  269. * tool tip handling.
  270. * @param layer The layer to add the extension to. Note that more than
  271. * extension can share the same layer.
  272. * @param extension The extension
  273. * @since jEdit 4.0pre4
  274. */
  275. public void addExtension(int layer, TextAreaExtension extension)
  276. {
  277. extensionMgr.addExtension(layer,extension);
  278. repaint();
  279. } //}}}
  280. //{{{ removeExtension() method
  281. /**
  282. * Removes a text area extension. It will no longer be asked to
  283. * perform custom painting and tool tip handling.
  284. * @param extension The extension
  285. * @since jEdit 4.0pre4
  286. */
  287. public void removeExtension(TextAreaExtension extension)
  288. {
  289. extensionMgr.removeExtension(extension);
  290. repaint();
  291. } //}}}
  292. //{{{ getToolTipText() method
  293. /**
  294. * Returns the tool tip to display at the specified location.
  295. * @param evt The mouse event
  296. */
  297. public String getToolTipText(MouseEvent evt)
  298. {
  299. if(!textArea.getBuffer().isLoaded())
  300. return null;
  301. return extensionMgr.getToolTipText(evt.getX(),evt.getY());
  302. } //}}}
  303. //{{{ setBorder() method
  304. /**
  305. * Convenience method for setting a default matte border on the right
  306. * with the specified border width and color
  307. * @param width The border width (in pixels)
  308. * @param color1 The focused border color
  309. * @param color2 The unfocused border color
  310. * @param color3 The gutter/text area gap color
  311. */
  312. public void setBorder(int width, Color color1, Color color2, Color color3)
  313. {
  314. this.borderWidth = width;
  315. focusBorder = new CompoundBorder(new MatteBorder(0,0,0,width,color3),
  316. new MatteBorder(0,0,0,width,color1));
  317. noFocusBorder = new CompoundBorder(new MatteBorder(0,0,0,width,color3),
  318. new MatteBorder(0,0,0,width,color2));
  319. updateBorder();
  320. } //}}}
  321. //{{{ updateBorder() method
  322. /**
  323. * Sets the border differently if the text area has focus or not.
  324. */
  325. public void updateBorder()
  326. {
  327. // because we are called from the text area's focus handler,
  328. // we do an invokeLater() so that the view's focus handler
  329. // has a chance to execute and set the edit pane properly
  330. SwingUtilities.invokeLater(new Runnable()
  331. {
  332. public void run()
  333. {
  334. if(view.getEditPane() == null)
  335. return;
  336. if(view.getEditPane().getTextArea() == textArea)
  337. setBorder(focusBorder);
  338. else
  339. setBorder(noFocusBorder);
  340. }
  341. });
  342. } //}}}
  343. //{{{ setBorder() method
  344. /*
  345. * JComponent.setBorder(Border) is overridden here to cache the left
  346. * inset of the border (if any) to avoid having to fetch it during every
  347. * repaint.
  348. */
  349. public void setBorder(Border border)
  350. {
  351. super.setBorder(border);
  352. if (border == null)
  353. {
  354. collapsedSize.width = 0;
  355. collapsedSize.height = 0;
  356. }
  357. else
  358. {
  359. Insets insets = border.getBorderInsets(this);
  360. collapsedSize.width = FOLD_MARKER_SIZE + insets.right;
  361. collapsedSize.height = gutterSize.height
  362. = insets.top + insets.bottom;
  363. gutterSize.width = FOLD_MARKER_SIZE + insets.right
  364. + fm.stringWidth("12345");
  365. }
  366. revalidate();
  367. } //}}}
  368. //{{{ setFont() method
  369. /*
  370. * JComponent.setFont(Font) is overridden here to cache the baseline for
  371. * the font. This avoids having to get the font metrics during every
  372. * repaint.
  373. */
  374. public void setFont(Font font)
  375. {
  376. super.setFont(font);
  377. fm = getFontMetrics(font);
  378. baseline = fm.getAscent();
  379. Border border = getBorder();
  380. if(border != null)
  381. {
  382. gutterSize.width = FOLD_MARKER_SIZE
  383. + border.getBorderInsets(this).right
  384. + fm.stringWidth("12345");
  385. revalidate();
  386. }
  387. } //}}}
  388. //{{{ Getters and setters
  389. //{{{ getHighlightedForeground() method
  390. /**
  391. * Get the foreground color for highlighted line numbers
  392. * @return The highlight color
  393. */
  394. public Color getHighlightedForeground()
  395. {
  396. return intervalHighlight;
  397. } //}}}
  398. //{{{ setHighlightedForeground() method
  399. public void setHighlightedForeground(Color highlight)
  400. {
  401. intervalHighlight = highlight;
  402. } //}}}
  403. //{{{ getCurrentLineForeground() method
  404. public Color getCurrentLineForeground()
  405. {
  406. return currentLineHighlight;
  407. } //}}}
  408. //{{{ setCurrentLineForeground() method
  409. public void setCurrentLineForeground(Color highlight)
  410. {
  411. currentLineHighlight = highlight;
  412. } //}}}
  413. //{{{ getFoldColor() method
  414. public Color getFoldColor()
  415. {
  416. return foldColor;
  417. } //}}}
  418. //{{{ setFoldColor() method
  419. public void setFoldColor(Color foldColor)
  420. {
  421. this.foldColor = foldColor;
  422. } //}}}
  423. //{{{ getPreferredSize() method
  424. /*
  425. * Component.getPreferredSize() is overridden here to support the
  426. * collapsing behavior.
  427. */
  428. public Dimension getPreferredSize()
  429. {
  430. if (expanded)
  431. return gutterSize;
  432. else
  433. return collapsedSize;
  434. } //}}}
  435. //{{{ getMinimumSize() method
  436. public Dimension getMinimumSize()
  437. {
  438. return getPreferredSize();
  439. } //}}}
  440. //{{{ getLineNumberAlignment() method
  441. /**
  442. * Identifies whether the horizontal alignment of the line numbers.
  443. * @return Gutter.RIGHT, Gutter.CENTER, Gutter.LEFT
  444. */
  445. public int getLineNumberAlignment()
  446. {
  447. return alignment;
  448. } //}}}
  449. //{{{ setLineNumberAlignment() method
  450. /**
  451. * Sets the horizontal alignment of the line numbers.
  452. * @param alignment Gutter.RIGHT, Gutter.CENTER, Gutter.LEFT
  453. */
  454. public void setLineNumberAlignment(int alignment)
  455. {
  456. if (this.alignment == alignment) return;
  457. this.alignment = alignment;
  458. repaint();
  459. } //}}}
  460. //{{{ isExpanded() method
  461. /**
  462. * Identifies whether the gutter is collapsed or expanded.
  463. * @return true if the gutter is expanded, false if it is collapsed
  464. */
  465. public boolean isExpanded()
  466. {
  467. return expanded;
  468. } //}}}
  469. //{{{ setExpanded() method
  470. /**
  471. * Sets whether the gutter is collapsed or expanded and force the text
  472. * area to update its layout if there is a change.
  473. * @param collapsed true if the gutter is expanded,
  474. * false if it is collapsed
  475. */
  476. public void setExpanded(boolean expanded)
  477. {
  478. if (this.expanded == expanded) return;
  479. this.expanded = expanded;
  480. textArea.revalidate();
  481. } //}}}
  482. //{{{ toggleExpanded() method
  483. /**
  484. * Toggles whether the gutter is collapsed or expanded.
  485. */
  486. public void toggleExpanded()
  487. {
  488. setExpanded(!expanded);
  489. } //}}}
  490. //{{{ getHighlightInterval() method
  491. /**
  492. * Sets the number of lines between highlighted line numbers.
  493. * @return The number of lines between highlighted line numbers or
  494. * zero if highlighting is disabled
  495. */
  496. public int getHighlightInterval()
  497. {
  498. return interval;
  499. } //}}}
  500. //{{{ setHighlightInterval() method
  501. /**
  502. * Sets the number of lines between highlighted line numbers. Any value
  503. * less than or equal to one will result in highlighting being disabled.
  504. * @param interval The number of lines between highlighted line numbers
  505. */
  506. public void setHighlightInterval(int interval)
  507. {
  508. if (interval <= 1) interval = 0;
  509. this.interval = interval;
  510. repaint();
  511. } //}}}
  512. //{{{ isCurrentLineHighlightEnabled() method
  513. public boolean isCurrentLineHighlightEnabled()
  514. {
  515. return currentLineHighlightEnabled;
  516. } //}}}
  517. //{{{ setCurrentLineHighlightEnabled() method
  518. public void setCurrentLineHighlightEnabled(boolean enabled)
  519. {
  520. if (currentLineHighlightEnabled == enabled) return;
  521. currentLineHighlightEnabled = enabled;
  522. repaint();
  523. } //}}}
  524. //{{{ getBracketHighlightColor() method
  525. /**
  526. * Returns the bracket highlight color.
  527. */
  528. public final Color getBracketHighlightColor()
  529. {
  530. return bracketHighlightColor;
  531. } //}}}
  532. //{{{ setBracketHighlightColor() method
  533. /**
  534. * Sets the bracket highlight color.
  535. * @param bracketHighlightColor The bracket highlight color
  536. * @since jEdit 4.0pre1
  537. */
  538. public final void setBracketHighlightColor(Color bracketHighlightColor)
  539. {
  540. this.bracketHighlightColor = bracketHighlightColor;
  541. repaint();
  542. } //}}}
  543. //{{{ isBracketHighlightEnabled() method
  544. /**
  545. * Returns true if bracket highlighting is enabled, false otherwise.
  546. * When bracket highlighting is enabled, the bracket matching the
  547. * one before the caret (if any) is highlighted.
  548. * @since jEdit 4.0pre1
  549. */
  550. public final boolean isBracketHighlightEnabled()
  551. {
  552. return bracketHighlight;
  553. } //}}}
  554. //{{{ setBracketHighlightEnabled() method
  555. /**
  556. * Enables or disables bracket highlighting.
  557. * When bracket highlighting is enabled, the bracket matching the
  558. * one before the caret (if any) is highlighted.
  559. * @param bracketHighlight True if bracket highlighting should be
  560. * enabled, false otherwise
  561. * @since jEdit 4.0pre1
  562. */
  563. public final void setBracketHighlightEnabled(boolean bracketHighlight)
  564. {
  565. this.bracketHighlight = bracketHighlight;
  566. repaint();
  567. } //}}}
  568. //{{{ getMarkerHighlightColor() method
  569. public Color getMarkerHighlightColor()
  570. {
  571. return markerHighlightColor;
  572. } //}}}
  573. //{{{ setMarkerHighlightColor() method
  574. public void setMarkerHighlightColor(Color markerHighlightColor)
  575. {
  576. this.markerHighlightColor = markerHighlightColor;
  577. } //}}}
  578. //{{{ isMarkerHighlightEnabled() method
  579. public boolean isMarkerHighlightEnabled()
  580. {
  581. return markerHighlight;
  582. } //}}}
  583. //{{{ isMarkerHighlightEnabled()
  584. public void setMarkerHighlightEnabled(boolean markerHighlight)
  585. {
  586. this.markerHighlight = markerHighlight;
  587. } //}}}
  588. //}}}
  589. //{{{ Private members
  590. private static final int FOLD_MARKER_SIZE = 12;
  591. private View view;
  592. private JEditTextArea textArea;
  593. private ExtensionManager extensionMgr;
  594. private int baseline;
  595. private Dimension gutterSize = new Dimension(0,0);
  596. private Dimension collapsedSize = new Dimension(0,0);
  597. private Color intervalHighlight;
  598. private Color currentLineHighlight;
  599. private Color foldColor;
  600. private FontMetrics fm;
  601. private int alignment;
  602. private int interval;
  603. private boolean currentLineHighlightEnabled;
  604. private boolean expanded;
  605. private boolean bracketHighlight;
  606. private Color bracketHighlightColor;
  607. private boolean markerHighlight;
  608. private Color markerHighlightColor;
  609. private int borderWidth;
  610. private Border focusBorder, noFocusBorder;
  611. //}}}
  612. //{{{ MouseHandler class
  613. class MouseHandler extends MouseInputAdapter
  614. {
  615. boolean drag;
  616. int toolTipInitialDelay, toolTipReshowDelay;
  617. //{{{ mouseEntered() method
  618. public void mouseEntered(MouseEvent e)
  619. {
  620. ToolTipManager ttm = ToolTipManager.sharedInstance();
  621. toolTipInitialDelay = ttm.getInitialDelay();
  622. toolTipReshowDelay = ttm.getReshowDelay();
  623. ttm.setInitialDelay(0);
  624. ttm.setReshowDelay(0);
  625. } //}}}
  626. //{{{ mouseExited() method
  627. public void mouseExited(MouseEvent evt)
  628. {
  629. ToolTipManager ttm = ToolTipManager.sharedInstance();
  630. ttm.setInitialDelay(toolTipInitialDelay);
  631. ttm.setReshowDelay(toolTipReshowDelay);
  632. } //}}}
  633. //{{{ mousePressed() method
  634. public void mousePressed(MouseEvent e)
  635. {
  636. if(GUIUtilities.isPopupTrigger(e)
  637. || e.getX() >= getWidth() - borderWidth * 2)
  638. {
  639. e.translatePoint(-getWidth(),0);
  640. textArea.mouseHandler.mousePressed(e);
  641. drag = true;
  642. }
  643. else
  644. {
  645. Buffer buffer = textArea.getBuffer();
  646. int screenLine = e.getY() / textArea.getPainter()
  647. .getFontMetrics().getHeight();
  648. textArea.chunkCache.updateChunksUpTo(screenLine);
  649. int line = textArea.chunkCache.getLineInfo(screenLine)
  650. .physicalLine;
  651. if(line == -1)
  652. return;
  653. FoldVisibilityManager foldVisibilityManager
  654. = textArea.getFoldVisibilityManager();
  655. //{{{ Clicking on fold triangle does various things
  656. if(buffer.isFoldStart(line))
  657. {
  658. if(e.isControlDown())
  659. {
  660. foldVisibilityManager
  661. .expandFold(line,true);
  662. textArea.selectFold(line);
  663. }
  664. else if(foldVisibilityManager
  665. .isLineVisible(line + 1))
  666. {
  667. foldVisibilityManager
  668. .collapseFold(line);
  669. }
  670. else
  671. {
  672. foldVisibilityManager
  673. .expandFold(line,
  674. e.isShiftDown());
  675. }
  676. } //}}}
  677. //{{{ Clicking in bracket scope locates matching bracket
  678. else if(bracketHighlight)
  679. {
  680. if(textArea.isBracketHighlightVisible())
  681. {
  682. int bracketLine = textArea.getBracketLine();
  683. int caretLine = textArea.getCaretLine();
  684. if(caretLine != bracketLine)
  685. {
  686. if(caretLine > bracketLine)
  687. {
  688. int tmp = caretLine;
  689. caretLine = bracketLine;
  690. bracketLine = tmp;
  691. }
  692. if(line >= caretLine
  693. && line <= bracketLine)
  694. {
  695. if(e.isControlDown())
  696. textArea.selectToMatchingBracket();
  697. else
  698. textArea.goToMatchingBracket();
  699. }
  700. }
  701. }
  702. } //}}}
  703. }
  704. } //}}}
  705. //{{{ mouseDragged() method
  706. public void mouseDragged(MouseEvent e)
  707. {
  708. if(drag /* && e.getX() >= getWidth() - borderWidth * 2 */)
  709. {
  710. e.translatePoint(-getWidth(),0);
  711. textArea.mouseHandler.mouseDragged(e);
  712. }
  713. } //}}}
  714. //{{{ mouseReleased() method
  715. public void mouseReleased(MouseEvent e)
  716. {
  717. if(drag && e.getX() >= getWidth() - borderWidth * 2)
  718. {
  719. e.translatePoint(-getWidth(),0);
  720. textArea.mouseHandler.mouseReleased(e);
  721. }
  722. drag = false;
  723. } //}}}
  724. } //}}}
  725. //{{{ MarkerHighlight class
  726. class MarkerHighlight extends TextAreaExtension
  727. {
  728. //{{{ paintValidLine() method
  729. public void paintValidLine(Graphics2D gfx, int screenLine,
  730. int physicalLine, int start, int end, int y)
  731. {
  732. if(isMarkerHighlightEnabled())
  733. {
  734. Buffer buffer = textArea.getBuffer();
  735. if(buffer.getMarkerInRange(start,end) != null)
  736. {
  737. gfx.setColor(getMarkerHighlightColor());
  738. FontMetrics fm = textArea.getPainter().getFontMetrics();
  739. gfx.fillRect(0,y,textArea.getGutter()
  740. .getWidth(),fm.getHeight());
  741. }
  742. }
  743. } //}}}
  744. //{{{ getToolTipText() method
  745. public String getToolTipText(int x, int y)
  746. {
  747. if(isMarkerHighlightEnabled())
  748. {
  749. int start = textArea.xyToOffset(0,y);
  750. if(start == -1)
  751. return null;
  752. int end = textArea.getScreenLineEndOffset(
  753. textArea.getScreenLineOfOffset(start));
  754. Marker marker = textArea.getBuffer().getMarkerInRange(start,end);
  755. if(marker != null)
  756. {
  757. char shortcut = marker.getShortcut();
  758. if(shortcut == '\0')
  759. return jEdit.getProperty("view.gutter.marker.no-name");
  760. else
  761. {
  762. String[] args = { String.valueOf(shortcut) };
  763. return jEdit.getProperty("view.gutter.marker",args);
  764. }
  765. }
  766. }
  767. return null;
  768. } //}}}
  769. } //}}}
  770. }