PageRenderTime 49ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/bundles/plugins-trunk/SideKick/sidekick/enhanced/SourceTree.java

#
Java | 329 lines | 237 code | 30 blank | 62 comment | 40 complexity | 8e60d4d4752aff64282310457f34036e 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. * SourceTree.java
  3. * :folding=explicit:collapseFolds=1:
  4. *
  5. * Copyright (C) 2005 by Martin Raspe
  6. * (hertzhaft@biblhertz.it)
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. */
  22. package sidekick.enhanced;
  23. //{{{ Imports
  24. import java.awt.Color;
  25. import java.awt.FontMetrics;
  26. import java.awt.Graphics;
  27. import java.awt.event.KeyAdapter;
  28. import java.awt.event.KeyEvent;
  29. import java.awt.event.MouseAdapter;
  30. import java.awt.event.MouseEvent;
  31. import java.awt.event.MouseMotionListener;
  32. import java.util.HashMap;
  33. import java.util.StringTokenizer;
  34. import javax.swing.JPopupMenu;
  35. import javax.swing.JTree;
  36. import javax.swing.ToolTipManager;
  37. import javax.swing.tree.DefaultMutableTreeNode;
  38. import javax.swing.tree.TreeCellRenderer;
  39. import javax.swing.tree.TreeNode;
  40. import javax.swing.tree.TreePath;
  41. import marker.MarkerSetsPlugin;
  42. import org.gjt.sp.jedit.EditPlugin;
  43. import org.gjt.sp.jedit.GUIUtilities;
  44. import org.gjt.sp.jedit.Mode;
  45. import org.gjt.sp.jedit.View;
  46. import org.gjt.sp.jedit.jEdit;
  47. import org.gjt.sp.jedit.EditBus.EBHandler;
  48. import org.gjt.sp.jedit.gui.DockableWindowFactory;
  49. import org.gjt.sp.jedit.gui.KeyEventTranslator;
  50. import org.gjt.sp.jedit.msg.BufferUpdate;
  51. import org.gjt.sp.util.EnhancedTreeCellRenderer;
  52. import sidekick.IAsset;
  53. import sidekick.SideKickPlugin;
  54. import sidekick.SideKickTree;
  55. //}}}
  56. /**
  57. * @author Martin Raspe
  58. * @created Oct 15, 2005
  59. * @modified $Id: SourceTree.java 20420 2011-11-25 08:01:11Z kpouer $
  60. * @version $Revision: 20420 $
  61. * The Structure Browser dockable. Extends the SideKick structure browser,
  62. * adding a popup menu for marker setting and enhanced keyboard handling
  63. * It replaces the SideKickTree dockable if desired.
  64. */
  65. public class SourceTree extends SideKickTree {
  66. //{{{ private vars
  67. private static boolean _hasMarker;
  68. private static boolean _showMarkers = true;
  69. private static Color _markerColor = jEdit.getColorProperty( "view.gutter.markerColor" );
  70. private HashMap _actionShortcuts = new HashMap();
  71. //}}}
  72. public JPopupMenu popup;
  73. public SourceTree( View view, boolean docked ) {
  74. //{{{ SourceTree constructor
  75. super( view, docked );
  76. tree.setCellRenderer( new Renderer() );
  77. tree.addKeyListener( new KeyHandler() );
  78. MouseHandler mh = new MouseHandler();
  79. tree.addMouseListener( mh );
  80. if ( docked )
  81. tree.addMouseMotionListener( mh );
  82. update();
  83. } //}}}
  84. protected void createPopup() {
  85. //{{{ create the tree Popup menu from the "sidekick-tree.{mode}.menu" property
  86. // if not present, use the default menu (see above)
  87. Mode mode = view.getBuffer().getMode();
  88. String modename = (mode == null)
  89. ? ""
  90. : "." + mode.getName();
  91. String menu = "sidekick-tree" + modename + ".menu";
  92. if (jEdit.getProperty(menu) == null)
  93. menu = "sidekick-tree.menu";
  94. popup = GUIUtilities.loadPopupMenu(menu);
  95. } //}}}
  96. protected void update() {
  97. //{{{ create a new popup menu if mode changes
  98. super.update();
  99. createPopup();
  100. } //}}}
  101. private boolean hasMarker(int start, int end) {
  102. //{{{ getMarker method
  103. EditPlugin markerSets = SideKickPlugin.getMarkerSetsPlugin();
  104. if (markerSets != null) {
  105. if (((MarkerSetsPlugin) markerSets).hasMarker(view.getBuffer(), start, end))
  106. return true;
  107. }
  108. return (view.getBuffer().getMarkerInRange(start, end) != null);
  109. } //}}}
  110. public static void toggleMarkersFlag() {
  111. //{{{ method toggleMarkersFlag
  112. _showMarkers = ! _showMarkers;
  113. } //}}}
  114. public static boolean isRegisteredDockable( String name ) {
  115. //{{{ method isRegisteredDockable
  116. // see if the dockable "name" is registered
  117. String[] dockables = DockableWindowFactory.getInstance()
  118. .getRegisteredDockableWindows();
  119. boolean _found = false;
  120. for ( int i = 0; i < dockables.length; i++ ) {
  121. if ( dockables[ i ].equals( name ) ) {
  122. _found = true;
  123. break;
  124. }
  125. }
  126. return _found;
  127. } //}}}
  128. public static boolean isMarkersFlagSet() {
  129. //{{{ method isMarkersFlagSet
  130. // should marked routines be shown in structure tree?
  131. return _showMarkers;
  132. } //}}}
  133. @EBHandler
  134. public void handleBufferUpdate( BufferUpdate upd ) {
  135. //{{{ handleBufferUpdate() method
  136. // react to marker changes immediately
  137. if ( upd.getWhat() == BufferUpdate.MARKERS_CHANGED )
  138. update();
  139. } //}}}
  140. public void handleKey( KeyEvent evt ) {
  141. //{{{ handleKey() method
  142. int _code = evt.getKeyCode();
  143. KeyEventTranslator.Key _key = KeyEventTranslator.translateKeyEvent( evt );
  144. // let the view handle marker actions
  145. // is there an easier way to assign a jEdit shortcut to a tree?
  146. if ( _actionShortcuts.containsKey( _key ) )
  147. view.getInputHandler().handleKey( _key);
  148. else if (( _code == KeyEvent.VK_ESCAPE || _code == KeyEvent.VK_CANCEL ) &&
  149. !evt.isConsumed())
  150. {
  151. view.getTextArea().requestFocus();
  152. }
  153. } //}}}
  154. public void handleMouse( MouseEvent evt ) {
  155. //{{{ handleMouse() method
  156. if ( GUIUtilities.isPopupTrigger( evt ) ) {
  157. GUIUtilities.showPopupMenu( popup, this, evt.getX(), evt.getY() );
  158. view.getTextArea().requestFocus();
  159. }
  160. } //}}}
  161. @Override
  162. protected void propertiesChanged() {
  163. super.propertiesChanged();
  164. Color c = jEdit.getColorProperty("view.gutter.markerColor");
  165. if (! _markerColor.equals(c)) {
  166. _markerColor = c;
  167. repaint();
  168. }
  169. if (jEdit.getBooleanProperty("sidekick.showToolTips"))
  170. ToolTipManager.sharedInstance().registerComponent( tree );
  171. else
  172. ToolTipManager.sharedInstance().unregisterComponent( tree );
  173. }
  174. protected class KeyHandler extends KeyAdapter {
  175. //{{{ KeyHandler class
  176. public void keyPressed( KeyEvent evt ) {
  177. handleKey( evt );
  178. }
  179. } //}}}
  180. protected class MouseHandler extends MouseAdapter implements MouseMotionListener {
  181. //{{{ MouseHandler class
  182. public void mousePressed( MouseEvent evt ) {
  183. handleMouse( evt );
  184. }
  185. public void mouseDragged( MouseEvent evt ) {
  186. // no-op, required for interface
  187. }
  188. public void mouseMoved( MouseEvent evt ) {
  189. TreePath path = tree.getPathForLocation(
  190. evt.getX(), evt.getY() );
  191. if ( path == null )
  192. view.getStatus().setMessage( null );
  193. else {
  194. Object value = ( ( DefaultMutableTreeNode ) path
  195. .getLastPathComponent() ).getUserObject();
  196. if ( value instanceof IAsset ) {
  197. IAsset as = (IAsset)value;
  198. view.getStatus().setMessage(as.getShortString());
  199. setStatus(as.getLongString() == null ? as.getShortString() : as.getLongString());
  200. }
  201. }
  202. }
  203. } //}}}
  204. protected class Renderer extends EnhancedTreeCellRenderer {
  205. //{{{ Renderer class
  206. // based on sidekick/SideKickTree.java
  207. @Override
  208. protected void configureTreeCellRendererComponent(
  209. //{{{ +getTreeCellRendererComponent() : Component
  210. JTree tree, Object value,
  211. boolean sel, boolean expanded, boolean leaf,
  212. int row, boolean hasFocus
  213. ) {
  214. DefaultMutableTreeNode node = ( DefaultMutableTreeNode ) value;
  215. Object nodeValue = node.getUserObject();
  216. _hasMarker = false;
  217. if ( node.getParent() == null ) {
  218. setIcon( org.gjt.sp.jedit.browser.FileCellRenderer.fileIcon );
  219. }
  220. if ( nodeValue instanceof IAsset ) {
  221. IAsset _asset = ( IAsset ) node.getUserObject();
  222. setIcon( _asset.getIcon() );
  223. setText( _asset.getShortString() );
  224. _hasMarker = hasMarker(
  225. _asset.getStart().getOffset(),
  226. _asset.getEnd().getOffset() );
  227. setToolTipText( getToolTipText(node, _asset) );
  228. }
  229. else
  230. setIcon( null );
  231. } //}}}
  232. private void wrap(StringBuffer sb, String indent, String s) {
  233. StringTokenizer st = new StringTokenizer(s, " \t\n", false);
  234. StringBuilder line = new StringBuilder();
  235. while (st.hasMoreTokens())
  236. {
  237. String t = st.nextToken();
  238. if (line.length() + t.length() >= 80)
  239. {
  240. sb.append(line + "<br>" + indent);
  241. line.setLength(0);
  242. }
  243. line.append(t + " ");
  244. }
  245. sb.append(line);
  246. }
  247. private String getToolTipText(DefaultMutableTreeNode node, IAsset asset) {
  248. //{{{ -getToolTipText(DefaultMutableTreeNode, IAsset): String
  249. StringBuffer sb = new StringBuffer("<html><body>");
  250. sb.append(asset.getLongString());
  251. sb.append("<br><br>");
  252. StringBuffer indent = new StringBuffer();
  253. for (TreeNode n: node.getPath()) {
  254. DefaultMutableTreeNode tn = (DefaultMutableTreeNode) n;
  255. Object o = tn.getUserObject();
  256. boolean last = (n == node);
  257. if (last)
  258. sb.append("<b>");
  259. String s;
  260. if (o instanceof IAsset)
  261. s = ((IAsset) o).getShortString();
  262. else
  263. s = o.toString();
  264. wrap(sb, indent.toString(), s);
  265. if (last)
  266. sb.append("</b>");
  267. if (! last) {
  268. sb.append("<br>");
  269. indent.append("&nbsp;&nbsp;");
  270. sb.append(indent.toString());
  271. }
  272. }
  273. sb.append("</body></html>");
  274. return sb.toString();
  275. } //}}}
  276. public void paintComponent( Graphics g ) {
  277. //{{{ +paintComponent(Graphics) : void
  278. // inspired from ProjectViewer plugin
  279. // underlines the asset if it contains a marker
  280. if ( isMarkersFlagSet() && _hasMarker ) {
  281. FontMetrics fm = getFontMetrics( getFont() );
  282. int x, y;
  283. y = getHeight() - 3;
  284. x = ( getIcon() == null )
  285. ? 0
  286. : getIcon().getIconWidth() + getIconTextGap();
  287. g.setColor( _markerColor );
  288. g.fillRect( x, y, fm.stringWidth( getText() ), 3 );
  289. }
  290. // setBackground(_markerColor); // does not work here
  291. super.paintComponent( g );
  292. } //}}}
  293. @Override
  294. protected TreeCellRenderer newInstance() {
  295. return new Renderer();
  296. }
  297. } //}}}
  298. }