PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/bundles/plugins-trunk/SideKick/sidekick/SideKickPlugin.java

#
Java | 434 lines | 302 code | 47 blank | 85 comment | 63 complexity | 943cc9d3791be5cb2b8302d3e04b1b6d 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. * SideKickPlugin.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. //{{{ Imports
  24. import org.gjt.sp.jedit.*;
  25. import org.gjt.sp.jedit.EditBus.EBHandler;
  26. import org.gjt.sp.jedit.msg.BufferUpdate;
  27. import org.gjt.sp.jedit.msg.EditPaneUpdate;
  28. import org.gjt.sp.jedit.msg.PluginUpdate;
  29. import org.gjt.sp.jedit.msg.PropertiesChanged;
  30. import org.gjt.sp.jedit.msg.ViewUpdate;
  31. import org.gjt.sp.jedit.textarea.JEditTextArea;
  32. import java.util.HashMap;
  33. import java.util.HashSet;
  34. import java.util.Iterator;
  35. import java.util.Map;
  36. import java.util.Set;
  37. import java.util.concurrent.Executor;
  38. import java.util.concurrent.Executors;
  39. import javax.swing.SwingWorker;
  40. //}}}
  41. /**
  42. * SideKick plugin core class
  43. * Manages a mapping of View to SideKick instances, creating/destroying
  44. * SideKick objects whenever Views are created/destroyed.
  45. *
  46. * @version $Id: SideKickPlugin.java 20353 2011-11-16 08:04:45Z kpouer $
  47. */
  48. public class SideKickPlugin extends EditPlugin
  49. {
  50. private static final String MARKER_SETS_PLUGIN = "marker.MarkerSetsPlugin";
  51. private static final String SHOW_TOOL_BAR = "sidekick.showToolBar";
  52. /** The name of the dockable */
  53. public static final String NAME = "sidekick-tree";
  54. //{{{ Some constants
  55. public static final String PARSER_MODE_PROPERTY = "sidekick.parser-mode";
  56. public static final String PARSER_PROPERTY = "sidekick.parser";
  57. public static final String PARSED_DATA_PROPERTY = "sidekick.parsed-data";
  58. public static final String PARSE_COUNT = "sidekick.parse-count";
  59. //}}}
  60. public static final String NONE="None";
  61. public static final String DEFAULT = "default parser";
  62. //{{{ Private members
  63. private static final String MACRO_PATH = "/macros";
  64. private static Map<View, SideKick> sidekicks;
  65. private static Map<String, SideKickParser> parsers;
  66. private static Executor executor;
  67. private static Set<Buffer> parsedBufferSet;
  68. private static Map<View, SideKickToolBar> toolBars;
  69. private static boolean toolBarsEnabled;
  70. private static Map<View, SwingWorker<SideKickParsedData, Object>> workers;
  71. private static EditPlugin markerSetsPlugin;
  72. //{{{ start() method
  73. public void start()
  74. {
  75. BeanShell.getNameSpace().addCommandPath(MACRO_PATH, getClass());
  76. markerSetsPlugin = jEdit.getPlugin(MARKER_SETS_PLUGIN, false);
  77. sidekicks = new HashMap<View, SideKick>();
  78. parsers = new HashMap<String, SideKickParser>();
  79. workers = new HashMap<View, SwingWorker<SideKickParsedData, Object>>();
  80. parsedBufferSet = new HashSet<Buffer>();
  81. toolBars = new HashMap<View, SideKickToolBar>();
  82. toolBarsEnabled = jEdit.getBooleanProperty(SHOW_TOOL_BAR);
  83. View view = jEdit.getFirstView();
  84. while(view != null)
  85. {
  86. initView(view);
  87. EditPane[] panes = view.getEditPanes();
  88. for(int i = 0; i < panes.length; i++)
  89. initTextArea(panes[i].getTextArea());
  90. view = view.getNext();
  91. }
  92. jEdit.addActionSet(SideKickMenuProvider.getParserSwitchers());
  93. SideKickActions.propertiesChanged();
  94. EditBus.addToBus(this);
  95. } //}}}
  96. //{{{ stop() method
  97. public void stop()
  98. {
  99. EditBus.removeFromBus(this);
  100. jEdit.removeActionSet(SideKickMenuProvider.getParserSwitchers());
  101. View view = jEdit.getFirstView();
  102. while(view != null)
  103. {
  104. uninitView(view);
  105. SideKickParsedData.setParsedData(view,null);
  106. EditPane[] panes = view.getEditPanes();
  107. for(int i = 0; i < panes.length; i++)
  108. uninitTextArea(panes[i].getTextArea());
  109. view = view.getNext();
  110. }
  111. Buffer buffer = jEdit.getFirstBuffer();
  112. while(buffer != null)
  113. {
  114. buffer.setProperty(PARSED_DATA_PROPERTY,null);
  115. buffer = buffer.getNext();
  116. }
  117. sidekicks = null;
  118. parsers = null;
  119. parsedBufferSet = null;
  120. toolBars = null;
  121. workers = null;
  122. } //}}}
  123. //{{{ handleViewUpdate() method
  124. @EBHandler
  125. public void handleViewUpdate(ViewUpdate vu)
  126. {
  127. View view = vu.getView();
  128. if(vu.getWhat() == ViewUpdate.CREATED)
  129. initView(view);
  130. else if(vu.getWhat() == ViewUpdate.CLOSED)
  131. uninitView(view);
  132. } //}}}
  133. //{{{ handleEditPaneUpdate() method
  134. @EBHandler
  135. public void handleEditPaneUpdate(EditPaneUpdate epu)
  136. {
  137. EditPane editPane = epu.getEditPane();
  138. if(epu.getWhat() == EditPaneUpdate.CREATED)
  139. initTextArea(editPane.getTextArea());
  140. else if(epu.getWhat() == EditPaneUpdate.DESTROYED)
  141. uninitTextArea(editPane.getTextArea());
  142. } //}}}
  143. //{{{ handleBufferUpdate() method
  144. @EBHandler
  145. public void handleBufferUpdate(BufferUpdate bu)
  146. {
  147. if(bu.getWhat() == BufferUpdate.CLOSED)
  148. finishParsingBuffer(bu.getBuffer());
  149. } //}}}
  150. //{{{ handlePropertiesChanged() method
  151. @EBHandler
  152. public void handlePropertiesChanged(PropertiesChanged msg)
  153. {
  154. SideKickActions.propertiesChanged();
  155. boolean showToolBar = jEdit.getBooleanProperty(SHOW_TOOL_BAR);
  156. if (showToolBar != toolBarsEnabled)
  157. {
  158. toolBarsEnabled = showToolBar;
  159. for (View v: jEdit.getViews())
  160. {
  161. if (toolBarsEnabled)
  162. attachToolBar(v);
  163. else
  164. detachToolBar(v);
  165. }
  166. }
  167. } //}}}
  168. // {{{ handlePluginUpdate() method
  169. @EBHandler
  170. public void handlePluginUpdate(PluginUpdate msg)
  171. {
  172. EditPlugin plugin = msg.getPluginJAR().getPlugin();
  173. if (plugin == null)
  174. return;
  175. if (plugin.getClassName().equals(MARKER_SETS_PLUGIN))
  176. {
  177. if (msg.getWhat() == PluginUpdate.ACTIVATED)
  178. markerSetsPlugin = plugin;
  179. else if (msg.getWhat() == PluginUpdate.DEACTIVATED)
  180. markerSetsPlugin = null;
  181. }
  182. } //}}}
  183. // {{{ getMarkerSetsPlugin() method
  184. public static EditPlugin getMarkerSetsPlugin()
  185. {
  186. return markerSetsPlugin;
  187. } //}}}
  188. /**
  189. * Returns the parser for the given mode.
  190. *
  191. * @param m the mode (it must not be null)
  192. * @return the parser associated to this mode (or null if there is no parser)
  193. */
  194. public static SideKickParser getParserForMode(Mode m) {
  195. String modeStr = m.getName();
  196. String propName = "mode." + modeStr + '.' + SideKickPlugin.PARSER_PROPERTY;
  197. String parserName = jEdit.getProperty(propName);
  198. if (parserName == null)
  199. return null;
  200. SideKickParser parser = (SideKickParser) ServiceManager.getService(
  201. SideKickParser.SERVICE, parserName);
  202. return parser;
  203. }
  204. //{{{ getParser() method
  205. /**
  206. * @param name - the name of the parser, as defined in services.xml
  207. */
  208. public static SideKickParser getParser(String name)
  209. {
  210. SideKickParser parser = (SideKickParser)ServiceManager
  211. .getService(SideKickParser.SERVICE,name);
  212. if(parser != null)
  213. return parser;
  214. else
  215. return parsers.get(name);
  216. } //}}}
  217. //{{{ getParserForView() method
  218. public static SideKickParser getParserForView(View view)
  219. {
  220. SideKick sidekick = sidekicks.get(view);
  221. if(sidekick == null)
  222. return null;
  223. else
  224. return sidekick.getParser();
  225. } //}}}
  226. /**
  227. *
  228. * @param buffer
  229. * @param parserName the new parser we want to use
  230. * @since Sidekick 0.6
  231. */
  232. public static void setParserForBuffer(Buffer buffer, String parserName)
  233. {
  234. if (parserName.equals(NONE) ) {
  235. buffer.setStringProperty(PARSER_PROPERTY, parserName);
  236. return;
  237. }
  238. if (parserName.equals(DEFAULT)) {
  239. buffer.unsetProperty(PARSER_PROPERTY);
  240. return;
  241. }
  242. SideKickParser newParser = getParser(parserName);
  243. if (newParser != null) {
  244. buffer.setStringProperty(PARSER_PROPERTY, parserName);
  245. }
  246. else throw new RuntimeException("Unknown parser: " + parserName);
  247. }
  248. //{{{ getParserForBuffer() method
  249. public static SideKickParser getParserForBuffer(Buffer buffer)
  250. {
  251. String parserName = buffer.getStringProperty(PARSER_PROPERTY);
  252. Mode mode = buffer.getMode();
  253. String modeName = (mode != null) ? mode.getName() : "";
  254. buffer.setStringProperty(PARSER_MODE_PROPERTY, modeName);
  255. if(parserName == null || parserName.equals(DEFAULT) || parserName.length() == 0) {
  256. if (mode != null)
  257. return getParserForMode(mode);
  258. else return null;
  259. }
  260. if (parserName.equals(NONE)) {
  261. return null;
  262. }
  263. return getParser(parserName);
  264. } //}}}
  265. //{{{ parse() method
  266. /**
  267. * Immediately begins parsing the current buffer in a background thread.
  268. * @param view The view
  269. * @param showParsingMessage Clear the tree and show a status message
  270. * there?
  271. */
  272. public static void parse(View view, boolean showParsingMessage)
  273. {
  274. SideKick sidekick = sidekicks.get(view);
  275. if (sidekick == null) return;
  276. // Had to remove this
  277. sidekick.setParser(view.getBuffer());
  278. sidekick.parse(showParsingMessage);
  279. } //}}}
  280. public static void execute(Runnable runnable)
  281. {
  282. if (executor == null)
  283. {
  284. executor = Executors.newSingleThreadExecutor();
  285. }
  286. executor.execute(runnable);
  287. }
  288. public static void execute(View view, SwingWorker<SideKickParsedData, Object> worker)
  289. {
  290. // QUESTION: there should be only one worker per view. Is it possible
  291. // there could be more than one?
  292. // ANSWER: No.
  293. workers.put(view, worker);
  294. worker.execute();
  295. }
  296. public static void cleanup(View view)
  297. {
  298. workers.remove(view);
  299. }
  300. //{{{ isParsingBuffer()
  301. public static boolean isParsingBuffer(Buffer buffer)
  302. {
  303. return parsedBufferSet.contains(buffer);
  304. } //}}}
  305. //{{{ Package-private members
  306. //{{{ startParsingBuffer()
  307. static void startParsingBuffer(Buffer buffer)
  308. {
  309. parsedBufferSet.add(buffer);
  310. } //}}}
  311. //{{{ finishParsingBuffer()
  312. static void finishParsingBuffer(Buffer buffer)
  313. {
  314. parsedBufferSet.remove(buffer);
  315. } //}}}
  316. //}}}
  317. //{{{ attachToolBar() method
  318. private static void attachToolBar(View view)
  319. {
  320. SideKickToolBar toolBar = new SideKickToolBar(view);
  321. view.addToolBar(toolBar);
  322. toolBars.put(view, toolBar);
  323. } //}}}
  324. //{{{ detachToolBar() method
  325. private static void detachToolBar(View view)
  326. {
  327. SideKickToolBar toolBar = toolBars.remove(view);
  328. if (toolBar != null)
  329. {
  330. view.removeToolBar(toolBar);
  331. toolBar.dispose();
  332. }
  333. } //}}}
  334. //{{{ initView() method
  335. private static void initView(View view)
  336. {
  337. SideKick sideKick = new SideKick(view);
  338. sidekicks.put(view, sideKick);
  339. sideKick.parse(true);
  340. if (toolBarsEnabled)
  341. attachToolBar(view);
  342. } //}}}
  343. // {{{ getSideKick() method
  344. static SideKick getSideKick(View v) {
  345. return sidekicks.get(v);
  346. }
  347. // }}}
  348. //{{{ uninitView() method
  349. private static void uninitView(View view)
  350. {
  351. SideKick sidekick = sidekicks.get(view);
  352. sidekick.dispose();
  353. sidekicks.remove(view);
  354. stop(view);
  355. workers.remove(view);
  356. detachToolBar(view);
  357. } //}}}
  358. //{{{ initTextArea() method
  359. private static void initTextArea(JEditTextArea textArea)
  360. {
  361. SideKickBindings b = new SideKickBindings();
  362. textArea.putClientProperty(SideKickBindings.class,b);
  363. textArea.addKeyListener(b);
  364. } //}}}
  365. //{{{ uninitTextArea() method
  366. private static void uninitTextArea(JEditTextArea textArea)
  367. {
  368. SideKickBindings b = (SideKickBindings)
  369. textArea.getClientProperty(
  370. SideKickBindings.class);
  371. textArea.putClientProperty(SideKickBindings.class,null);
  372. textArea.removeKeyListener(b);
  373. SideKickTree.CaretHandler caretHandler = (SideKickTree.CaretHandler) textArea.getClientProperty(SideKickTree.CaretHandler.class);
  374. if (caretHandler != null)
  375. {
  376. textArea.putClientProperty(SideKickTree.CaretHandler.class, null);
  377. textArea.removeCaretListener(caretHandler);
  378. }
  379. } //}}}
  380. public static void stop(View view) {
  381. SwingWorker<SideKickParsedData, Object> worker = workers.get(view);
  382. if (worker != null && !worker.isCancelled() && !worker.isDone()) {
  383. worker.cancel(true);
  384. }
  385. }
  386. //}}}
  387. }