PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

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

#
Java | 873 lines | 545 code | 107 blank | 221 comment | 96 complexity | 7be51f6ba0c03eeef5e6af3fbbcb8f23 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 javax.swing.*;
  28. import javax.swing.border.*;
  29. import javax.swing.event.*;
  30. import org.gjt.sp.jedit.View;
  31. import org.gjt.sp.jedit.GUIUtilities;
  32. import org.gjt.sp.jedit.buffer.JEditBuffer;
  33. import org.gjt.sp.util.Log;
  34. //}}}
  35. /**
  36. * The gutter is the component that displays folding triangles and line
  37. * numbers to the left of the text area. The only methods in this class
  38. * that should be called by plugins are those for adding and removing
  39. * text area extensions.
  40. *
  41. * @see #addExtension(TextAreaExtension)
  42. * @see #addExtension(int,TextAreaExtension)
  43. * @see #removeExtension(TextAreaExtension)
  44. * @see TextAreaExtension
  45. * @see JEditTextArea
  46. *
  47. * @author Mike Dillon and Slava Pestov
  48. * @version $Id: Gutter.java 5458 2006-06-20 21:27:24Z kpouer $
  49. */
  50. public class Gutter extends JComponent implements SwingConstants
  51. {
  52. //{{{ Layers
  53. /**
  54. * The lowest possible layer.
  55. * @see #addExtension(int,TextAreaExtension)
  56. * @since jEdit 4.0pre4
  57. */
  58. public static final int LOWEST_LAYER = Integer.MIN_VALUE;
  59. /**
  60. * Default extension layer. This is above the wrap guide but below the
  61. * bracket highlight.
  62. * @since jEdit 4.0pre4
  63. */
  64. public static final int DEFAULT_LAYER = 0;
  65. /**
  66. * Highest possible layer.
  67. * @since jEdit 4.0pre4
  68. */
  69. public static final int HIGHEST_LAYER = Integer.MAX_VALUE;
  70. //}}}
  71. //{{{ Gutter constructor
  72. public Gutter(JEditTextArea textArea)
  73. {
  74. this.textArea = textArea;
  75. setAutoscrolls(true);
  76. setOpaque(true);
  77. setRequestFocusEnabled(false);
  78. extensionMgr = new ExtensionManager();
  79. MouseHandler ml = new MouseHandler();
  80. addMouseListener(ml);
  81. addMouseMotionListener(ml);
  82. updateBorder();
  83. } //}}}
  84. //{{{ paintComponent() method
  85. public void paintComponent(Graphics _gfx)
  86. {
  87. Graphics2D gfx = (Graphics2D)_gfx;
  88. // fill the background
  89. Rectangle clip = gfx.getClipBounds();
  90. gfx.setColor(getBackground());
  91. gfx.fillRect(clip.x, clip.y, clip.width, clip.height);
  92. // if buffer is loading, don't paint anything
  93. if (textArea.getBuffer().isLoading())
  94. return;
  95. int lineHeight = textArea.getPainter().getFontMetrics()
  96. .getHeight();
  97. if(lineHeight == 0)
  98. return;
  99. int firstLine = clip.y / lineHeight;
  100. int lastLine = (clip.y + clip.height - 1) / lineHeight;
  101. if(lastLine - firstLine > textArea.getVisibleLines())
  102. {
  103. Log.log(Log.ERROR,this,"BUG: firstLine=" + firstLine);
  104. Log.log(Log.ERROR,this," lastLine=" + lastLine);
  105. Log.log(Log.ERROR,this," visibleLines=" + textArea.getVisibleLines());
  106. Log.log(Log.ERROR,this," height=" + getHeight());
  107. Log.log(Log.ERROR,this," painter.height=" + textArea.getPainter().getHeight());
  108. Log.log(Log.ERROR,this," clip.y=" + clip.y);
  109. Log.log(Log.ERROR,this," clip.height=" + clip.height);
  110. Log.log(Log.ERROR,this," lineHeight=" + lineHeight);
  111. }
  112. int y = (clip.y - clip.y % lineHeight);
  113. extensionMgr.paintScreenLineRange(textArea,gfx,
  114. firstLine,lastLine,y,lineHeight);
  115. for (int line = firstLine; line <= lastLine;
  116. line++, y += lineHeight)
  117. {
  118. paintLine(gfx,line,y);
  119. }
  120. } //}}}
  121. //{{{ addExtension() method
  122. /**
  123. * Adds a text area extension, which can perform custom painting and
  124. * tool tip handling.
  125. * @param extension The extension
  126. * @since jEdit 4.0pre4
  127. */
  128. public void addExtension(TextAreaExtension extension)
  129. {
  130. extensionMgr.addExtension(DEFAULT_LAYER,extension);
  131. repaint();
  132. } //}}}
  133. //{{{ addExtension() method
  134. /**
  135. * Adds a text area extension, which can perform custom painting and
  136. * tool tip handling.
  137. * @param layer The layer to add the extension to. Note that more than
  138. * extension can share the same layer.
  139. * @param extension The extension
  140. * @since jEdit 4.0pre4
  141. */
  142. public void addExtension(int layer, TextAreaExtension extension)
  143. {
  144. extensionMgr.addExtension(layer,extension);
  145. repaint();
  146. } //}}}
  147. //{{{ removeExtension() method
  148. /**
  149. * Removes a text area extension. It will no longer be asked to
  150. * perform custom painting and tool tip handling.
  151. * @param extension The extension
  152. * @since jEdit 4.0pre4
  153. */
  154. public void removeExtension(TextAreaExtension extension)
  155. {
  156. extensionMgr.removeExtension(extension);
  157. repaint();
  158. } //}}}
  159. //{{{ getExtensions() method
  160. /**
  161. * Returns an array of registered text area extensions. Useful for
  162. * debugging purposes.
  163. * @since jEdit 4.1pre5
  164. */
  165. public TextAreaExtension[] getExtensions()
  166. {
  167. return extensionMgr.getExtensions();
  168. } //}}}
  169. //{{{ getToolTipText() method
  170. /**
  171. * Returns the tool tip to display at the specified location.
  172. * @param evt The mouse event
  173. */
  174. public String getToolTipText(MouseEvent evt)
  175. {
  176. if(textArea.getBuffer().isLoading())
  177. return null;
  178. return extensionMgr.getToolTipText(evt.getX(),evt.getY());
  179. } //}}}
  180. //{{{ setBorder() method
  181. /**
  182. * Convenience method for setting a default matte border on the right
  183. * with the specified border width and color
  184. * @param width The border width (in pixels)
  185. * @param color1 The focused border color
  186. * @param color2 The unfocused border color
  187. * @param color3 The gutter/text area gap color
  188. */
  189. public void setBorder(int width, Color color1, Color color2, Color color3)
  190. {
  191. this.borderWidth = width;
  192. focusBorder = new CompoundBorder(new MatteBorder(0,0,0,width,color3),
  193. new MatteBorder(0,0,0,width,color1));
  194. noFocusBorder = new CompoundBorder(new MatteBorder(0,0,0,width,color3),
  195. new MatteBorder(0,0,0,width,color2));
  196. updateBorder();
  197. } //}}}
  198. //{{{ updateBorder() method
  199. /**
  200. * Sets the border differently if the text area has focus or not.
  201. */
  202. public void updateBorder()
  203. {
  204. if (textArea.hasFocus())
  205. setBorder(focusBorder);
  206. else
  207. setBorder(noFocusBorder);
  208. } //}}}
  209. //{{{ setBorder() method
  210. /*
  211. * JComponent.setBorder(Border) is overridden here to cache the left
  212. * inset of the border (if any) to avoid having to fetch it during every
  213. * repaint.
  214. */
  215. public void setBorder(Border border)
  216. {
  217. super.setBorder(border);
  218. if (border == null)
  219. {
  220. collapsedSize.width = 0;
  221. collapsedSize.height = 0;
  222. }
  223. else
  224. {
  225. Insets insets = border.getBorderInsets(this);
  226. collapsedSize.width = FOLD_MARKER_SIZE + insets.right;
  227. collapsedSize.height = gutterSize.height
  228. = insets.top + insets.bottom;
  229. gutterSize.width = FOLD_MARKER_SIZE + insets.right
  230. + fm.stringWidth("12345");
  231. }
  232. revalidate();
  233. } //}}}
  234. //{{{ setFont() method
  235. /*
  236. * JComponent.setFont(Font) is overridden here to cache the baseline for
  237. * the font. This avoids having to get the font metrics during every
  238. * repaint.
  239. */
  240. public void setFont(Font font)
  241. {
  242. super.setFont(font);
  243. fm = getFontMetrics(font);
  244. baseline = fm.getAscent();
  245. Border border = getBorder();
  246. if(border != null)
  247. {
  248. gutterSize.width = FOLD_MARKER_SIZE
  249. + border.getBorderInsets(this).right
  250. + fm.stringWidth("12345");
  251. revalidate();
  252. }
  253. } //}}}
  254. //{{{ Getters and setters
  255. //{{{ getHighlightedForeground() method
  256. /**
  257. * Get the foreground color for highlighted line numbers
  258. * @return The highlight color
  259. */
  260. public Color getHighlightedForeground()
  261. {
  262. return intervalHighlight;
  263. } //}}}
  264. //{{{ setHighlightedForeground() method
  265. public void setHighlightedForeground(Color highlight)
  266. {
  267. intervalHighlight = highlight;
  268. } //}}}
  269. //{{{ getCurrentLineForeground() method
  270. public Color getCurrentLineForeground()
  271. {
  272. return currentLineHighlight;
  273. } //}}}
  274. //{{{ setCurrentLineForeground() method
  275. public void setCurrentLineForeground(Color highlight)
  276. {
  277. currentLineHighlight = highlight;
  278. } //}}}
  279. //{{{ getFoldColor() method
  280. public Color getFoldColor()
  281. {
  282. return foldColor;
  283. } //}}}
  284. //{{{ setFoldColor() method
  285. public void setFoldColor(Color foldColor)
  286. {
  287. this.foldColor = foldColor;
  288. } //}}}
  289. //{{{ getPreferredSize() method
  290. /*
  291. * Component.getPreferredSize() is overridden here to support the
  292. * collapsing behavior.
  293. */
  294. public Dimension getPreferredSize()
  295. {
  296. if (expanded)
  297. return gutterSize;
  298. else
  299. return collapsedSize;
  300. } //}}}
  301. //{{{ getMinimumSize() method
  302. public Dimension getMinimumSize()
  303. {
  304. return getPreferredSize();
  305. } //}}}
  306. //{{{ getLineNumberAlignment() method
  307. /**
  308. * Identifies whether the horizontal alignment of the line numbers.
  309. * @return Gutter.RIGHT, Gutter.CENTER, Gutter.LEFT
  310. */
  311. public int getLineNumberAlignment()
  312. {
  313. return alignment;
  314. } //}}}
  315. //{{{ setLineNumberAlignment() method
  316. /**
  317. * Sets the horizontal alignment of the line numbers.
  318. * @param alignment Gutter.RIGHT, Gutter.CENTER, Gutter.LEFT
  319. */
  320. public void setLineNumberAlignment(int alignment)
  321. {
  322. if (this.alignment == alignment) return;
  323. this.alignment = alignment;
  324. repaint();
  325. } //}}}
  326. //{{{ isExpanded() method
  327. /**
  328. * Identifies whether the gutter is collapsed or expanded.
  329. * @return true if the gutter is expanded, false if it is collapsed
  330. */
  331. public boolean isExpanded()
  332. {
  333. return expanded;
  334. } //}}}
  335. //{{{ setExpanded() method
  336. /**
  337. * Sets whether the gutter is collapsed or expanded and force the text
  338. * area to update its layout if there is a change.
  339. * @param expanded true if the gutter is expanded,
  340. * false if it is collapsed
  341. */
  342. public void setExpanded(boolean expanded)
  343. {
  344. if (this.expanded == expanded) return;
  345. this.expanded = expanded;
  346. textArea.revalidate();
  347. } //}}}
  348. //{{{ toggleExpanded() method
  349. /**
  350. * Toggles whether the gutter is collapsed or expanded.
  351. */
  352. public void toggleExpanded()
  353. {
  354. setExpanded(!expanded);
  355. } //}}}
  356. //{{{ getHighlightInterval() method
  357. /**
  358. * Sets the number of lines between highlighted line numbers.
  359. * @return The number of lines between highlighted line numbers or
  360. * zero if highlighting is disabled
  361. */
  362. public int getHighlightInterval()
  363. {
  364. return interval;
  365. } //}}}
  366. //{{{ setHighlightInterval() method
  367. /**
  368. * Sets the number of lines between highlighted line numbers. Any value
  369. * less than or equal to one will result in highlighting being disabled.
  370. * @param interval The number of lines between highlighted line numbers
  371. */
  372. public void setHighlightInterval(int interval)
  373. {
  374. if (interval <= 1) interval = 0;
  375. this.interval = interval;
  376. repaint();
  377. } //}}}
  378. //{{{ isCurrentLineHighlightEnabled() method
  379. public boolean isCurrentLineHighlightEnabled()
  380. {
  381. return currentLineHighlightEnabled;
  382. } //}}}
  383. //{{{ setCurrentLineHighlightEnabled() method
  384. public void setCurrentLineHighlightEnabled(boolean enabled)
  385. {
  386. if (currentLineHighlightEnabled == enabled) return;
  387. currentLineHighlightEnabled = enabled;
  388. repaint();
  389. } //}}}
  390. //{{{ getStructureHighlightColor() method
  391. /**
  392. * Returns the structure highlight color.
  393. * @since jEdit 4.2pre3
  394. */
  395. public final Color getStructureHighlightColor()
  396. {
  397. return structureHighlightColor;
  398. } //}}}
  399. //{{{ setStructureHighlightColor() method
  400. /**
  401. * Sets the structure highlight color.
  402. * @param structureHighlightColor The structure highlight color
  403. * @since jEdit 4.2pre3
  404. */
  405. public final void setStructureHighlightColor(Color structureHighlightColor)
  406. {
  407. this.structureHighlightColor = structureHighlightColor;
  408. repaint();
  409. } //}}}
  410. //{{{ isStructureHighlightEnabled() method
  411. /**
  412. * Returns true if structure highlighting is enabled, false otherwise.
  413. * @since jEdit 4.2pre3
  414. */
  415. public final boolean isStructureHighlightEnabled()
  416. {
  417. return structureHighlight;
  418. } //}}}
  419. //{{{ setStructureHighlightEnabled() method
  420. /**
  421. * Enables or disables structure highlighting.
  422. * @param structureHighlight True if structure highlighting should be
  423. * enabled, false otherwise
  424. * @since jEdit 4.2pre3
  425. */
  426. public final void setStructureHighlightEnabled(boolean structureHighlight)
  427. {
  428. this.structureHighlight = structureHighlight;
  429. repaint();
  430. } //}}}
  431. //}}}
  432. //{{{ Private members
  433. //{{{ Instance variables
  434. private static final int FOLD_MARKER_SIZE = 12;
  435. private View view;
  436. private JEditTextArea textArea;
  437. private ExtensionManager extensionMgr;
  438. private int baseline;
  439. private Dimension gutterSize = new Dimension(0,0);
  440. private Dimension collapsedSize = new Dimension(0,0);
  441. private Color intervalHighlight;
  442. private Color currentLineHighlight;
  443. private Color foldColor;
  444. private FontMetrics fm;
  445. private int alignment;
  446. private int interval;
  447. private boolean currentLineHighlightEnabled;
  448. private boolean expanded;
  449. private boolean structureHighlight;
  450. private Color structureHighlightColor;
  451. private int borderWidth;
  452. private Border focusBorder, noFocusBorder;
  453. //}}}
  454. //{{{ paintLine() method
  455. private void paintLine(Graphics2D gfx, int line, int y)
  456. {
  457. JEditBuffer buffer = textArea.getBuffer();
  458. if(buffer.isLoading())
  459. return;
  460. int lineHeight = textArea.getPainter().getFontMetrics()
  461. .getHeight();
  462. ChunkCache.LineInfo info = textArea.chunkCache.getLineInfo(line);
  463. int physicalLine = info.physicalLine;
  464. // Skip lines beyond EOF
  465. if(physicalLine == -1)
  466. return;
  467. //{{{ Paint fold triangles
  468. if(info.firstSubregion && buffer.isFoldStart(physicalLine))
  469. {
  470. int _y = y + lineHeight / 2;
  471. gfx.setColor(foldColor);
  472. if(textArea.displayManager
  473. .isLineVisible(physicalLine + 1))
  474. {
  475. gfx.drawLine(1,_y - 3,10,_y - 3);
  476. gfx.drawLine(2,_y - 2,9,_y - 2);
  477. gfx.drawLine(3,_y - 1,8,_y - 1);
  478. gfx.drawLine(4,_y,7,_y);
  479. gfx.drawLine(5,_y + 1,6,_y + 1);
  480. }
  481. else
  482. {
  483. gfx.drawLine(4,_y - 5,4,_y + 4);
  484. gfx.drawLine(5,_y - 4,5,_y + 3);
  485. gfx.drawLine(6,_y - 3,6,_y + 2);
  486. gfx.drawLine(7,_y - 2,7,_y + 1);
  487. gfx.drawLine(8,_y - 1,8,_y);
  488. }
  489. }
  490. else if(info.lastSubregion && buffer.isFoldEnd(physicalLine))
  491. {
  492. gfx.setColor(foldColor);
  493. int _y = y + lineHeight / 2;
  494. gfx.drawLine(4,_y,4,_y + 3);
  495. gfx.drawLine(4,_y + 3,7,_y + 3);
  496. } //}}}
  497. //{{{ Paint bracket scope
  498. else if(structureHighlight)
  499. {
  500. StructureMatcher.Match match = textArea.getStructureMatch();
  501. int caretLine = textArea.getCaretLine();
  502. if(textArea.isStructureHighlightVisible()
  503. && physicalLine >= Math.min(caretLine,match.startLine)
  504. && physicalLine <= Math.max(caretLine,match.startLine))
  505. {
  506. int caretScreenLine;
  507. if(caretLine > textArea.getLastPhysicalLine())
  508. caretScreenLine = Integer.MAX_VALUE;
  509. else if(textArea.displayManager.isLineVisible(
  510. textArea.getCaretLine()))
  511. {
  512. caretScreenLine = textArea
  513. .getScreenLineOfOffset(
  514. textArea.getCaretPosition());
  515. }
  516. else
  517. {
  518. caretScreenLine = -1;
  519. }
  520. int structScreenLine;
  521. if(match.startLine > textArea.getLastPhysicalLine())
  522. structScreenLine = Integer.MAX_VALUE;
  523. else if(textArea.displayManager.isLineVisible(
  524. match.startLine))
  525. {
  526. structScreenLine = textArea
  527. .getScreenLineOfOffset(
  528. match.start);
  529. }
  530. else
  531. {
  532. structScreenLine = -1;
  533. }
  534. if(caretScreenLine > structScreenLine)
  535. {
  536. int tmp = caretScreenLine;
  537. caretScreenLine = structScreenLine;
  538. structScreenLine = tmp;
  539. }
  540. gfx.setColor(structureHighlightColor);
  541. if(structScreenLine == caretScreenLine)
  542. {
  543. // do nothing
  544. }
  545. // draw |^
  546. else if(line == caretScreenLine)
  547. {
  548. gfx.fillRect(5,
  549. y
  550. + lineHeight / 2,
  551. 5,
  552. 2);
  553. gfx.fillRect(5,
  554. y
  555. + lineHeight / 2,
  556. 2,
  557. lineHeight - lineHeight / 2);
  558. }
  559. // draw |_
  560. else if(line == structScreenLine)
  561. {
  562. gfx.fillRect(5,
  563. y,
  564. 2,
  565. lineHeight / 2);
  566. gfx.fillRect(5,
  567. y + lineHeight / 2,
  568. 5,
  569. 2);
  570. }
  571. // draw |
  572. else if(line > caretScreenLine
  573. && line < structScreenLine)
  574. {
  575. gfx.fillRect(5,
  576. y,
  577. 2,
  578. lineHeight);
  579. }
  580. }
  581. } //}}}
  582. //{{{ Paint line numbers
  583. if(info.firstSubregion && expanded)
  584. {
  585. String number = Integer.toString(physicalLine + 1);
  586. int offset;
  587. switch (alignment)
  588. {
  589. case RIGHT:
  590. offset = gutterSize.width - collapsedSize.width
  591. - (fm.stringWidth(number) + 1);
  592. break;
  593. case CENTER:
  594. offset = ((gutterSize.width - collapsedSize.width)
  595. - fm.stringWidth(number)) / 2;
  596. break;
  597. case LEFT: default:
  598. offset = 0;
  599. break;
  600. }
  601. boolean highlightCurrentLine = currentLineHighlightEnabled
  602. && textArea.getSelectionCount() == 0;
  603. if (physicalLine == textArea.getCaretLine() && highlightCurrentLine)
  604. {
  605. gfx.setColor(currentLineHighlight);
  606. }
  607. else if (interval > 1 && (line
  608. + textArea.getFirstLine() + 1)
  609. % interval == 0)
  610. gfx.setColor(intervalHighlight);
  611. else
  612. gfx.setColor(getForeground());
  613. gfx.drawString(number, FOLD_MARKER_SIZE + offset,
  614. baseline + y);
  615. } //}}}
  616. } //}}}
  617. //}}}
  618. //{{{ MouseHandler class
  619. class MouseHandler extends MouseInputAdapter
  620. {
  621. MouseActions mouseActions = new MouseActions("gutter");
  622. boolean drag;
  623. int toolTipInitialDelay, toolTipReshowDelay;
  624. //{{{ mouseEntered() method
  625. public void mouseEntered(MouseEvent e)
  626. {
  627. ToolTipManager ttm = ToolTipManager.sharedInstance();
  628. toolTipInitialDelay = ttm.getInitialDelay();
  629. toolTipReshowDelay = ttm.getReshowDelay();
  630. ttm.setInitialDelay(0);
  631. ttm.setReshowDelay(0);
  632. } //}}}
  633. //{{{ mouseExited() method
  634. public void mouseExited(MouseEvent evt)
  635. {
  636. ToolTipManager ttm = ToolTipManager.sharedInstance();
  637. ttm.setInitialDelay(toolTipInitialDelay);
  638. ttm.setReshowDelay(toolTipReshowDelay);
  639. } //}}}
  640. //{{{ mousePressed() method
  641. public void mousePressed(MouseEvent e)
  642. {
  643. textArea.requestFocus();
  644. if(GUIUtilities.isPopupTrigger(e)
  645. || e.getX() >= getWidth() - borderWidth * 2)
  646. {
  647. e.translatePoint(-getWidth(),0);
  648. textArea.mouseHandler.mousePressed(e);
  649. drag = true;
  650. }
  651. else
  652. {
  653. JEditBuffer buffer = textArea.getBuffer();
  654. int screenLine = e.getY() / textArea.getPainter()
  655. .getFontMetrics().getHeight();
  656. int line = textArea.chunkCache.getLineInfo(screenLine)
  657. .physicalLine;
  658. if(line == -1)
  659. return;
  660. //{{{ Determine action
  661. String defaultAction;
  662. String variant;
  663. if(buffer.isFoldStart(line))
  664. {
  665. defaultAction = "toggle-fold";
  666. variant = "fold";
  667. }
  668. else if(structureHighlight
  669. && textArea.isStructureHighlightVisible()
  670. && textArea.lineInStructureScope(line))
  671. {
  672. defaultAction = "match-struct";
  673. variant = "struct";
  674. }
  675. else
  676. return;
  677. String action = mouseActions.getActionForEvent(
  678. e,variant);
  679. if(action == null)
  680. action = defaultAction;
  681. //}}}
  682. //{{{ Handle actions
  683. StructureMatcher.Match match = textArea
  684. .getStructureMatch();
  685. if(action.equals("select-fold"))
  686. {
  687. textArea.displayManager.expandFold(line,true);
  688. textArea.selectFold(line);
  689. }
  690. else if(action.equals("narrow-fold"))
  691. {
  692. int[] lines = buffer.getFoldAtLine(line);
  693. textArea.displayManager.narrow(lines[0],lines[1]);
  694. }
  695. else if(action.startsWith("toggle-fold"))
  696. {
  697. if(textArea.displayManager
  698. .isLineVisible(line + 1))
  699. {
  700. textArea.displayManager.collapseFold(line);
  701. }
  702. else
  703. {
  704. if(action.endsWith("-fully"))
  705. {
  706. textArea.displayManager
  707. .expandFold(line,
  708. true);
  709. }
  710. else
  711. {
  712. textArea.displayManager
  713. .expandFold(line,
  714. false);
  715. }
  716. }
  717. }
  718. else if(action.equals("match-struct"))
  719. {
  720. if(match != null)
  721. textArea.setCaretPosition(match.end);
  722. }
  723. else if(action.equals("select-struct"))
  724. {
  725. if(match != null)
  726. {
  727. match.matcher.selectMatch(
  728. textArea);
  729. }
  730. }
  731. else if(action.equals("narrow-struct"))
  732. {
  733. if(match != null)
  734. {
  735. int start = Math.min(
  736. match.startLine,
  737. textArea.getCaretLine());
  738. int end = Math.max(
  739. match.endLine,
  740. textArea.getCaretLine());
  741. textArea.displayManager.narrow(start,end);
  742. }
  743. } //}}}
  744. }
  745. } //}}}
  746. //{{{ mouseDragged() method
  747. public void mouseDragged(MouseEvent e)
  748. {
  749. if(drag /* && e.getX() >= getWidth() - borderWidth * 2 */)
  750. {
  751. e.translatePoint(-getWidth(),0);
  752. textArea.mouseHandler.mouseDragged(e);
  753. }
  754. } //}}}
  755. //{{{ mouseReleased() method
  756. public void mouseReleased(MouseEvent e)
  757. {
  758. if(drag && e.getX() >= getWidth() - borderWidth * 2)
  759. {
  760. e.translatePoint(-getWidth(),0);
  761. textArea.mouseHandler.mouseReleased(e);
  762. }
  763. drag = false;
  764. } //}}}
  765. } //}}}
  766. }