/plugins/SideKick/tags/release-0-3-2/sidekick/SideKickActions.java

# · Java · 347 lines · 254 code · 44 blank · 49 comment · 77 complexity · ed78ffaaa045205322fadd6ce78ca156 MD5 · raw file

  1. /*
  2. * SideKickActions.java
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2003 Slava Pestov
  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;
  23. //{{{ Import statements
  24. import javax.swing.tree.*;
  25. import javax.swing.SwingUtilities;
  26. import javax.swing.Timer;
  27. import java.awt.event.*;
  28. import org.gjt.sp.jedit.textarea.*;
  29. import org.gjt.sp.jedit.*;
  30. //}}}
  31. public class SideKickActions
  32. {
  33. //{{{ keyComplete() method
  34. public static void keyComplete(View view)
  35. {
  36. if(timer != null)
  37. timer.stop();
  38. if(!completeInstant)
  39. return;
  40. complete(view,COMPLETE_INSTANT_KEY);
  41. } //}}}
  42. //{{{ keyCompleteWithDelay() method
  43. public static void keyCompleteWithDelay(final View view)
  44. {
  45. if(!completeDelay)
  46. return;
  47. if(timer != null)
  48. timer.stop();
  49. final JEditTextArea textArea = view.getTextArea();
  50. caretWhenCompleteKeyPressed = textArea.getCaretPosition();
  51. if(timer == null)
  52. {
  53. timer = new Timer(0,new ActionListener()
  54. {
  55. public void actionPerformed(ActionEvent evt)
  56. {
  57. if(caretWhenCompleteKeyPressed == textArea.getCaretPosition())
  58. complete(view,COMPLETE_DELAY_KEY);
  59. }
  60. });
  61. timer.setInitialDelay(delay);
  62. timer.setRepeats(false);
  63. }
  64. timer.start();
  65. } //}}}
  66. //{{{ complete() method
  67. public static final int COMPLETE_COMMAND = 0;
  68. public static final int COMPLETE_DELAY_KEY = 1;
  69. public static final int COMPLETE_INSTANT_KEY = 2;
  70. public static void complete(View view, int mode)
  71. {
  72. EditPane editPane = view.getEditPane();
  73. Buffer buffer = editPane.getBuffer();
  74. JEditTextArea textArea = editPane.getTextArea();
  75. SideKickParser parser = SideKickPlugin
  76. .getParserForBuffer(buffer);
  77. SideKickParsedData data = SideKickParsedData
  78. .getParsedData(view);
  79. SideKickCompletion complete = null;
  80. if(buffer.isEditable()
  81. && data != null && parser != null
  82. && parser.supportsCompletion())
  83. {
  84. complete = parser.complete(editPane,
  85. textArea.getCaretPosition());
  86. }
  87. if(complete == null || complete.size() == 0)
  88. {
  89. if(mode == COMPLETE_INSTANT_KEY
  90. || mode == COMPLETE_DELAY_KEY)
  91. {
  92. // don't bother user with beep if eg
  93. // they press < in XML mode
  94. return;
  95. }
  96. else
  97. {
  98. view.getToolkit().beep();
  99. return;
  100. }
  101. }
  102. else if(complete.size() == 1)
  103. {
  104. // if user invokes complete explicitly, insert the
  105. // completion immediately.
  106. //
  107. // if the user eg enters </ in XML mode, there will
  108. // only be one completion and / is an instant complete
  109. // key, so we insert it
  110. if(mode == COMPLETE_COMMAND
  111. || mode == COMPLETE_INSTANT_KEY)
  112. {
  113. complete.insert(0);
  114. return;
  115. }
  116. }
  117. // show the popup if
  118. // - complete has one element and user invoked with delay key
  119. // - or complete has multiple elements
  120. // and popup is not already shown because of explicit invocation
  121. // of the complete action during the trigger delay
  122. if(popup != null)
  123. return;
  124. popup = new SideKickCompletionPopup(view,parser,
  125. textArea.getCaretPosition(), complete)
  126. {
  127. /** forget reference to this popup when it is disposed */
  128. public void dispose()
  129. {
  130. super.dispose();
  131. popup = null;
  132. }
  133. };
  134. } //}}}
  135. //{{{ selectAsset() method
  136. public static void selectAsset(View view)
  137. {
  138. SideKickParsedData data = SideKickParsedData.getParsedData(view);
  139. if(data == null)
  140. {
  141. view.getToolkit().beep();
  142. return;
  143. }
  144. JEditTextArea textArea = view.getTextArea();
  145. Asset asset = data.getAssetAtPosition(
  146. textArea.getCaretPosition());
  147. if(asset == null || asset.end == null)
  148. {
  149. view.getToolkit().beep();
  150. return;
  151. }
  152. textArea.setCaretPosition(asset.end.getOffset());
  153. textArea.addToSelection(
  154. new Selection.Range(
  155. asset.start.getOffset(),
  156. asset.end.getOffset()));
  157. } //}}}
  158. //{{{ narrowToAsset() method
  159. public static void narrowToAsset(View view)
  160. {
  161. SideKickParsedData data = SideKickParsedData.getParsedData(view);
  162. if(data == null)
  163. {
  164. view.getToolkit().beep();
  165. return;
  166. }
  167. JEditTextArea textArea = view.getTextArea();
  168. TreePath path = data.getTreePathForPosition(textArea.getCaretPosition());
  169. if(path == null)
  170. {
  171. view.getToolkit().beep();
  172. return;
  173. }
  174. Asset asset = (Asset)((DefaultMutableTreeNode)path
  175. .getLastPathComponent()).getUserObject();
  176. if(asset == null || asset.end == null)
  177. {
  178. view.getToolkit().beep();
  179. return;
  180. }
  181. textArea.getDisplayManager().narrow(
  182. textArea.getLineOfOffset(asset.start.getOffset()),
  183. textArea.getLineOfOffset(asset.end.getOffset()));
  184. } //}}}
  185. //{{{ goToPrevAsset() method
  186. public static void goToPrevAsset(View view)
  187. {
  188. SideKickParsedData data = SideKickParsedData.getParsedData(view);
  189. if(data == null)
  190. {
  191. view.getToolkit().beep();
  192. return;
  193. }
  194. JEditTextArea textArea = view.getTextArea();
  195. int caret = textArea.getCaretPosition();
  196. TreePath path = data.getTreePathForPosition(caret);
  197. if(path == null)
  198. {
  199. view.getToolkit().beep();
  200. return;
  201. }
  202. DefaultMutableTreeNode node = (DefaultMutableTreeNode)
  203. path.getLastPathComponent();
  204. // see if caret is at the end of a child of the current asset
  205. for(int i = 0; i < node.getChildCount(); i++)
  206. {
  207. Asset asset = (Asset)((DefaultMutableTreeNode)node.getChildAt(i))
  208. .getUserObject();
  209. if(asset.end != null && caret == asset.end.getOffset())
  210. {
  211. textArea.setCaretPosition(asset.start.getOffset());
  212. return;
  213. }
  214. }
  215. Asset asset = ((Asset)node.getUserObject());
  216. if(caret == asset.start.getOffset())
  217. {
  218. DefaultMutableTreeNode parent = (DefaultMutableTreeNode)
  219. node.getParent();
  220. for(int i = 0; i < parent.getChildCount(); i++)
  221. {
  222. if(node == parent.getChildAt(i))
  223. {
  224. if(i == 0)
  225. {
  226. if(parent.getUserObject() instanceof Asset)
  227. {
  228. textArea.setCaretPosition(
  229. ((Asset)parent.getUserObject())
  230. .start.getOffset());
  231. }
  232. }
  233. else
  234. {
  235. Asset prevAsset = (Asset)((DefaultMutableTreeNode)
  236. parent.getChildAt(i - 1)).getUserObject();
  237. if(prevAsset.end != null)
  238. textArea.setCaretPosition(prevAsset.end.getOffset());
  239. }
  240. return;
  241. }
  242. }
  243. }
  244. else
  245. textArea.setCaretPosition(asset.start.getOffset());
  246. } //}}}
  247. //{{{ goToNextAsset() method
  248. public static void goToNextAsset(View view)
  249. {
  250. SideKickParsedData data = SideKickParsedData.getParsedData(view);
  251. if(data == null)
  252. {
  253. view.getToolkit().beep();
  254. return;
  255. }
  256. JEditTextArea textArea = view.getTextArea();
  257. int caret = textArea.getCaretPosition();
  258. TreePath path = data.getTreePathForPosition(caret);
  259. if(path == null)
  260. {
  261. view.getToolkit().beep();
  262. return;
  263. }
  264. DefaultMutableTreeNode node = (DefaultMutableTreeNode)
  265. path.getLastPathComponent();
  266. // see if caret is at the end of a child of the current asset
  267. for(int i = 0; i < node.getChildCount(); i++)
  268. {
  269. Asset asset = (Asset)((DefaultMutableTreeNode)node.getChildAt(i))
  270. .getUserObject();
  271. if(caret == asset.end.getOffset())
  272. {
  273. if(i != node.getChildCount() - 1)
  274. {
  275. Asset nextAsset = (Asset)((DefaultMutableTreeNode)
  276. node.getChildAt(i + 1)).getUserObject();
  277. textArea.setCaretPosition(nextAsset.start.getOffset());
  278. return;
  279. }
  280. else
  281. break;
  282. }
  283. }
  284. textArea.setCaretPosition(((Asset)node.getUserObject()).end.getOffset());
  285. } //}}}
  286. //{{{ propertiesChanged() method
  287. public static void propertiesChanged()
  288. {
  289. completeDelay = jEdit.getBooleanProperty("sidekick.complete-delay.toggle");
  290. completeInstant = jEdit.getBooleanProperty("sidekick.complete-instant.toggle");
  291. delay = jEdit.getIntegerProperty("sidekick.complete-delay",500);
  292. if(timer != null)
  293. timer.setInitialDelay(delay);
  294. } //}}}
  295. //{{{ Private members
  296. private static boolean completeDelay;
  297. private static boolean completeInstant;
  298. private static int delay;
  299. private static int caretWhenCompleteKeyPressed;
  300. private static Timer timer;
  301. private static SideKickCompletionPopup popup;
  302. //}}}
  303. }