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

/jEdit/tags/jedit-4-5-pre1/org/gjt/sp/jedit/gui/DockableWindowManager.java

#
Java | 754 lines | 435 code | 67 blank | 252 comment | 81 complexity | 6a1b3b94746843f931509ad040649cea 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. package org.gjt.sp.jedit.gui;
  2. // {{{ imports
  3. import java.awt.event.KeyAdapter;
  4. import java.awt.event.KeyEvent;
  5. import java.awt.event.KeyListener;
  6. import java.io.File;
  7. import java.io.FilenameFilter;
  8. import java.util.*;
  9. import java.util.Map.Entry;
  10. import javax.swing.JComponent;
  11. import javax.swing.JPanel;
  12. import org.gjt.sp.jedit.EditBus;
  13. import org.gjt.sp.jedit.PluginJAR;
  14. import org.gjt.sp.jedit.View;
  15. import org.gjt.sp.jedit.jEdit;
  16. import org.gjt.sp.jedit.EditBus.EBHandler;
  17. import org.gjt.sp.jedit.View.ViewConfig;
  18. import org.gjt.sp.jedit.gui.KeyEventTranslator.Key;
  19. import org.gjt.sp.jedit.msg.DockableWindowUpdate;
  20. import org.gjt.sp.jedit.msg.PluginUpdate;
  21. import org.gjt.sp.jedit.msg.PropertiesChanged;
  22. import org.gjt.sp.util.Log;
  23. // }}}
  24. @SuppressWarnings("serial")
  25. // {{{ abstract class DockableWindowManager
  26. /**
  27. * <p>Keeps track of all dockable windows for a single View, and provides
  28. * an API for getting/showing/hiding them. </p>
  29. *
  30. * <p>Each {@link org.gjt.sp.jedit.View} has an instance of this class.</p>
  31. *
  32. * <p><b>dockables.xml:</b></p>
  33. *
  34. * <p>Dockable window definitions are read from <code>dockables.xml</code> files
  35. * contained inside plugin JARs. A dockable definition file has the following
  36. * form: </p>
  37. *
  38. * <pre>&lt;?xml version="1.0"?&gt;
  39. *&lt;!DOCTYPE DOCKABLES SYSTEM "dockables.dtd"&gt;
  40. *&lt;DOCKABLES&gt;
  41. * &lt;DOCKABLE NAME="<i>dockableName</i>" MOVABLE="TRUE|FALSE"&gt;
  42. * // Code to create the dockable
  43. * &lt;/DOCKABLE&gt;
  44. *&lt;/DOCKABLES&gt;</pre>
  45. *
  46. * <p>The MOVABLE attribute specifies the behavior when the docking position of
  47. * the dockable window is changed. If MOVABLE is TRUE, the existing instance of
  48. * the dockable window is moved to the new docking position, and if the dockable
  49. * window implements the DockableWindow interface (see {@link DockableWindow}),
  50. * it is also notified about the change in docking position before it is moved.
  51. * If MOVABLE is FALSE, the BeanShell code is invoked to get the instance of
  52. * the dockable window to put in the new docking position. Typically, the
  53. * BeanShell code returns a new instance of the dockable window, and the state
  54. * of the existing instance is not preserved after the change. It is therefore
  55. * recommended to set MOVABLE to TRUE for all dockables in order to make them
  56. * preserve their state when they are moved. For backward compatibility reasons,
  57. * this attribute is set to FALSE by default.</p>
  58. * <p>More than one <code>&lt;DOCKABLE&gt;</code> tag may be present. The code that
  59. * creates the dockable can reference any BeanShell built-in variable
  60. * (see {@link org.gjt.sp.jedit.BeanShell}), along with a variable
  61. * <code>position</code> whose value is one of
  62. * {@link #FLOATING}, {@link #TOP}, {@link #LEFT}, {@link #BOTTOM},
  63. * and {@link #RIGHT}. </p>
  64. *
  65. * <p>The following properties must be defined for each dockable window: </p>
  66. *
  67. * <ul>
  68. * <li><code><i>dockableName</i>.title</code> - the string to show on the dockable
  69. * button. </li>
  70. * <li><code><i>dockableName</i>.label</code> - The string to use for generating
  71. * menu items and action names. </li>
  72. * <li><code><i>dockableName</i>.longtitle</code> - (optional) the string to use
  73. * in the dockable's floating window title (when it is floating).
  74. * If not specified, the <code><i>dockableName</i>.title</code> property is used. </li>
  75. * </ul>
  76. *
  77. * A number of actions are automatically created for each dockable window:
  78. *
  79. * <ul>
  80. * <li><code><i>dockableName</i></code> - opens the dockable window.</li>
  81. * <li><code><i>dockableName</i>-toggle</code> - toggles the dockable window's visibility.</li>
  82. * <li><code><i>dockableName</i>-float</code> - opens the dockable window in a new
  83. * floating window.</li>
  84. * </ul>
  85. *
  86. * Note that only the first action needs a <code>label</code> property, the
  87. * rest have automatically-generated labels.
  88. *
  89. * <p> <b>Implementation details:</b></p>
  90. *
  91. * <p> When an instance of this class is initialized by the {@link org.gjt.sp.jedit.View}
  92. * class, it
  93. * iterates through the list of registered dockable windows (from jEdit itself,
  94. * and any loaded plugins) and
  95. * examines options supplied by the user in the <b>Global
  96. * Options</b> dialog box. Any plugins designated for one of the
  97. * four docking positions are displayed.</p>
  98. *
  99. * <p> To create an instance of a dockable window, the <code>DockableWindowManager</code>
  100. * finds and executes the BeanShell code extracted from the appropriate
  101. * <code>dockables.xml</code> file. This code will typically consist of a call
  102. * to the constructor of the dockable window component. The result of the
  103. * BeanShell expression, typically a newly constructed component, is placed
  104. * in a window managed by this class. </p>
  105. *
  106. * @see org.gjt.sp.jedit.View#getDockableWindowManager()
  107. *
  108. * @author Slava Pestov
  109. * @author John Gellene (API documentation)
  110. * @author Shlomy Reinstein (refactoring into a base and an impl)
  111. * @version $Id: DockableWindowManager.java 20108 2011-10-18 12:16:38Z evanpw $
  112. * @since jEdit 2.6pre3
  113. *
  114. */
  115. public abstract class DockableWindowManager extends JPanel
  116. {
  117. //{{{ Constants
  118. /**
  119. * Floating position.
  120. * @since jEdit 2.6pre3
  121. */
  122. public static final String FLOATING = "floating";
  123. /**
  124. * Top position.
  125. * @since jEdit 2.6pre3
  126. */
  127. public static final String TOP = "top";
  128. /**
  129. * Left position.
  130. * @since jEdit 2.6pre3
  131. */
  132. public static final String LEFT = "left";
  133. /**
  134. * Bottom position.
  135. * @since jEdit 2.6pre3
  136. */
  137. public static final String BOTTOM = "bottom";
  138. /**
  139. * Right position.
  140. * @since jEdit 2.6pre3
  141. */
  142. public static final String RIGHT = "right";
  143. //}}}
  144. // {{{ data members
  145. private final Map<PluginJAR, Set<String>> plugins = new HashMap<PluginJAR, Set<String>>();
  146. private final Map<String, String> positions = new HashMap<String, String>();
  147. protected View view;
  148. protected DockableWindowFactory factory;
  149. protected Map<String, JComponent> windows = new HashMap<String, JComponent>();
  150. // variables for toggling all dock areas
  151. private boolean tBottom, tTop, tLeft, tRight;
  152. private boolean closeToggle = true;
  153. private static final String ALTERNATE_LAYOUT_PROP = "view.docking.alternateLayout";
  154. private boolean alternateLayout;
  155. // }}}
  156. // {{{ DockableWindowManager constructor
  157. public DockableWindowManager(View view, DockableWindowFactory instance,
  158. ViewConfig config)
  159. {
  160. this.view = view;
  161. this.factory = instance;
  162. alternateLayout = jEdit.getBooleanProperty(ALTERNATE_LAYOUT_PROP);
  163. } // }}}
  164. // {{{ Abstract methods
  165. public abstract void setMainPanel(JPanel panel);
  166. public abstract void showDockableWindow(String name);
  167. public abstract void hideDockableWindow(String name);
  168. /** Completely dispose of a dockable - called when a plugin is
  169. unloaded, to remove all references to the its dockables. */
  170. public abstract void disposeDockableWindow(String name);
  171. public abstract JComponent floatDockableWindow(String name);
  172. public abstract boolean isDockableWindowDocked(String name);
  173. public abstract boolean isDockableWindowVisible(String name);
  174. public abstract void closeCurrentArea();
  175. public abstract DockingLayout getDockingLayout(ViewConfig config);
  176. public abstract DockingArea getLeftDockingArea();
  177. public abstract DockingArea getRightDockingArea();
  178. public abstract DockingArea getTopDockingArea();
  179. public abstract DockingArea getBottomDockingArea();
  180. // }}}
  181. // {{{ public methods
  182. // {{{ init()
  183. public void init()
  184. {
  185. EditBus.addToBus(this);
  186. Iterator<DockableWindowFactory.Window> entries = factory.getDockableWindowIterator();
  187. while(entries.hasNext())
  188. {
  189. DockableWindowFactory.Window window = entries.next();
  190. String dockable = window.name;
  191. positions.put(dockable, getDockablePosition(dockable));
  192. addPluginDockable(window.plugin, dockable);
  193. }
  194. } // }}}
  195. // {{{ close()
  196. public void close()
  197. {
  198. EditBus.removeFromBus(this);
  199. } // }}}
  200. // {{{ applyDockingLayout
  201. public void applyDockingLayout(DockingLayout docking)
  202. {
  203. // By default, use the docking positions specified by the jEdit properties
  204. Iterator<Entry<String, String>> iterator = positions.entrySet().iterator();
  205. while (iterator.hasNext())
  206. {
  207. Entry<String, String> entry = iterator.next();
  208. String dockable = entry.getKey();
  209. String position = entry.getValue();
  210. if (! position.equals(FLOATING))
  211. showDockableWindow(dockable);
  212. }
  213. } //}}}
  214. //{{{ addDockableWindow() method
  215. /**
  216. * Opens the specified dockable window. As of jEdit 4.0pre1, has the
  217. * same effect as calling showDockableWindow().
  218. * @param name The dockable window name
  219. * @since jEdit 2.6pre3
  220. */
  221. public void addDockableWindow(String name)
  222. {
  223. showDockableWindow(name);
  224. } //}}}
  225. //{{{ removeDockableWindow() method
  226. /**
  227. * Hides the specified dockable window. As of jEdit 4.2pre1, has the
  228. * same effect as calling hideDockableWindow().
  229. * @param name The dockable window name
  230. * @since jEdit 4.2pre1
  231. */
  232. public void removeDockableWindow(String name)
  233. {
  234. hideDockableWindow(name);
  235. } //}}}
  236. //{{{ toggleDockableWindow() method
  237. /**
  238. * Toggles the visibility of the specified dockable window.
  239. * @param name The dockable window name
  240. */
  241. public void toggleDockableWindow(String name)
  242. {
  243. if(isDockableWindowVisible(name))
  244. removeDockableWindow(name);
  245. else
  246. addDockableWindow(name);
  247. } //}}}
  248. //{{{ getDockableWindow() method
  249. /**
  250. * Returns the specified dockable window.
  251. *
  252. * Note that this method
  253. * will return null if the dockable has not been added yet.
  254. * Make sure you call {@link #addDockableWindow(String)} first.
  255. *
  256. * @param name The name of the dockable window
  257. * @since jEdit 4.1pre2
  258. */
  259. public JComponent getDockableWindow(String name)
  260. {
  261. return getDockable(name);
  262. } //}}}
  263. // {{{ toggleDockAreas()
  264. /**
  265. * Hides all visible dock areas, or shows them again,
  266. * if the last time it was a hide.
  267. * @since jEdit 4.3pre16
  268. *
  269. */
  270. public void toggleDockAreas()
  271. {
  272. if (closeToggle)
  273. {
  274. tTop = getTopDockingArea().getCurrent() != null;
  275. tLeft = getLeftDockingArea().getCurrent() != null;
  276. tRight = getRightDockingArea().getCurrent() != null;
  277. tBottom = getBottomDockingArea().getCurrent() != null;
  278. getBottomDockingArea().show(null);
  279. getTopDockingArea().show(null);
  280. getRightDockingArea().show(null);
  281. getLeftDockingArea().show(null);
  282. }
  283. else
  284. {
  285. if (tBottom) getBottomDockingArea().showMostRecent();
  286. if (tLeft) getLeftDockingArea().showMostRecent();
  287. if (tRight) getRightDockingArea().showMostRecent();
  288. if (tTop) getTopDockingArea().showMostRecent();
  289. }
  290. view.closeAllMenus();
  291. closeToggle = !closeToggle;
  292. view.getTextArea().requestFocus();
  293. } // }}}
  294. // {{{ dockableTitleChanged
  295. public void dockableTitleChanged(String dockable, String newTitle)
  296. {
  297. } // }}}
  298. // {{{ closeListener() method
  299. /**
  300. * The actionEvent "close-docking-area" by default only works on
  301. * dockable windows that have no special keyboard handling.
  302. * If you have dockable widgets with input widgets and/or other fancy
  303. * keyboard handling, those components may not respond to close docking area.
  304. * You can add key listeners to each keyboard-handling component
  305. * in your dockable that usually has keyboard focus.
  306. *
  307. * This function creates and returns a key listener which does exactly that.
  308. * It is also used by FloatingWindowContainer when creating new floating windows.
  309. *
  310. * @param dockableName the name of your dockable
  311. * @return a KeyListener you can add to that plugin's component.
  312. * @since jEdit 4.3pre6
  313. *
  314. */
  315. public KeyListener closeListener(String dockableName)
  316. {
  317. return new KeyHandler(dockableName);
  318. }
  319. // }}}
  320. //{{{ getView() method
  321. /**
  322. * Returns this dockable window manager's view.
  323. * @since jEdit 4.0pre2
  324. */
  325. public View getView()
  326. {
  327. return view;
  328. } //}}}
  329. //{{{ getDockable method
  330. /**
  331. * @since jEdit 4.3pre2
  332. */
  333. public JComponent getDockable(String name)
  334. {
  335. return windows.get(name);
  336. } // }}}
  337. //{{{ getDockableTitle() method
  338. /**
  339. * Returns the title of the specified dockable window.
  340. * @param name The name of the dockable window.
  341. * @since jEdit 4.1pre5
  342. */
  343. public String getDockableTitle(String name)
  344. {
  345. return longTitle(name);
  346. }//}}}
  347. //{{{ setDockableTitle() method
  348. /**
  349. * Changes the .longtitle property of a dockable window, which corresponds to the
  350. * title shown when it is floating (not docked). Fires a change event that makes sure
  351. * all floating dockables change their title.
  352. *
  353. * @param dockable the name of the dockable, as specified in the dockables.xml
  354. * @param title the new .longtitle you want to see above it.
  355. * @since 4.3pre5
  356. *
  357. */
  358. public void setDockableTitle(String dockable, String title)
  359. {
  360. String propName = getLongTitlePropertyName(dockable);
  361. String oldTitle = jEdit.getProperty(propName);
  362. jEdit.setProperty(propName, title);
  363. firePropertyChange(propName, oldTitle, title);
  364. dockableTitleChanged(dockable, title);
  365. }
  366. // }}}
  367. //{{{ getRegisteredDockableWindows() method
  368. public static String[] getRegisteredDockableWindows()
  369. {
  370. return DockableWindowFactory.getInstance()
  371. .getRegisteredDockableWindows();
  372. } //}}}
  373. //{{{ getDockableWindowPluginClassName() method
  374. public static String getDockableWindowPluginName(String name)
  375. {
  376. String pluginClass =
  377. DockableWindowFactory.getInstance().getDockableWindowPluginClass(name);
  378. if (pluginClass == null)
  379. return null;
  380. return jEdit.getProperty("plugin." + pluginClass + ".name");
  381. } //}}}
  382. // {{{ setDockingLayout method
  383. public void setDockingLayout(DockingLayout docking)
  384. {
  385. applyDockingLayout(docking);
  386. applyAlternateLayout(alternateLayout);
  387. } // }}}
  388. // {{{ addPluginDockable
  389. private void addPluginDockable(PluginJAR plugin, String name)
  390. {
  391. Set<String> dockables = plugins.get(plugin);
  392. if (dockables == null)
  393. {
  394. dockables = new HashSet<String>();
  395. plugins.put(plugin, dockables);
  396. }
  397. dockables.add(name);
  398. }
  399. // }}}
  400. // {{{ handleDockableWindowUpdate() method
  401. @EBHandler
  402. public void handleDockableWindowUpdate(DockableWindowUpdate msg)
  403. {
  404. if(msg.getWhat() == DockableWindowUpdate.PROPERTIES_CHANGED)
  405. propertiesChanged();
  406. } // }}}
  407. // {{{ handlePropertiesChanged() method
  408. @EBHandler
  409. public void handlePropertiesChanged(PropertiesChanged msg)
  410. {
  411. propertiesChanged();
  412. } // }}}
  413. // {{{ handlePluginUpdate() method
  414. @EBHandler
  415. public void handlePluginUpdate(PluginUpdate pmsg)
  416. {
  417. if (pmsg.getWhat() == PluginUpdate.LOADED)
  418. {
  419. Iterator<DockableWindowFactory.Window> iter = factory.getDockableWindowIterator();
  420. while (iter.hasNext())
  421. {
  422. DockableWindowFactory.Window w = iter.next();
  423. if (w.plugin == pmsg.getPluginJAR())
  424. {
  425. String position = getDockablePosition(w.name);
  426. positions.put(w.name, position);
  427. addPluginDockable(w.plugin, w.name);
  428. dockableLoaded(w.name, position);
  429. }
  430. }
  431. propertiesChanged();
  432. }
  433. else if(pmsg.isExiting())
  434. {
  435. // we don't care
  436. }
  437. else if(pmsg.getWhat() == PluginUpdate.DEACTIVATED ||
  438. pmsg.getWhat() == PluginUpdate.UNLOADED)
  439. {
  440. Set<String> dockables = plugins.remove(pmsg.getPluginJAR());
  441. if (dockables != null)
  442. {
  443. for (String dockable: dockables)
  444. {
  445. disposeDockableWindow(dockable);
  446. windows.remove(dockable);
  447. }
  448. }
  449. }
  450. } // }}}
  451. // {{{ longTitle() method
  452. public String longTitle(String name)
  453. {
  454. String title = jEdit.getProperty(getLongTitlePropertyName(name));
  455. if (title == null)
  456. return shortTitle(name);
  457. return title;
  458. } // }}}
  459. // {{{ shortTitle() method
  460. public String shortTitle(String name)
  461. {
  462. String title = jEdit.getProperty(name + ".title");
  463. if(title == null)
  464. return "NO TITLE PROPERTY: " + name;
  465. return title;
  466. } // }}}
  467. // }}}
  468. // {{{ protected methods
  469. // {{{ applyAlternateLayout
  470. protected void applyAlternateLayout(boolean alternateLayout)
  471. {
  472. } //}}}
  473. // {{{
  474. protected void dockableLoaded(String dockableName, String position)
  475. {
  476. }
  477. // }}}
  478. // {{{
  479. protected void dockingPositionChanged(String dockableName,
  480. String oldPosition, String newPosition)
  481. {
  482. } //}}}
  483. // {{{ getAlternateLayoutProp()
  484. protected boolean getAlternateLayoutProp()
  485. {
  486. return alternateLayout;
  487. } // }}}
  488. // {{{ propertiesChanged
  489. protected void propertiesChanged()
  490. {
  491. if(view.isPlainView())
  492. return;
  493. boolean newAlternateLayout = jEdit.getBooleanProperty(ALTERNATE_LAYOUT_PROP);
  494. if (newAlternateLayout != alternateLayout)
  495. {
  496. alternateLayout = newAlternateLayout;
  497. applyAlternateLayout(newAlternateLayout);
  498. }
  499. String[] dockables = factory.getRegisteredDockableWindows();
  500. for(int i = 0; i < dockables.length; i++)
  501. {
  502. String dockable = dockables[i];
  503. String oldPosition = positions.get(dockable);
  504. String newPosition = getDockablePosition(dockable);
  505. if (oldPosition == null || !newPosition.equals(oldPosition))
  506. {
  507. positions.put(dockable, newPosition);
  508. dockingPositionChanged(dockable, oldPosition, newPosition);
  509. }
  510. }
  511. } // }}}
  512. // {{{ createDockable()
  513. protected JComponent createDockable(String name)
  514. {
  515. DockableWindowFactory.Window wf = factory.getDockableWindowFactory(name);
  516. if (wf == null)
  517. {
  518. Log.log(Log.ERROR,this,"Unknown dockable window: " + name);
  519. return null;
  520. }
  521. String position = getDockablePosition(name);
  522. JComponent window = wf.createDockableWindow(view, position);
  523. if (window != null)
  524. windows.put(name, window);
  525. return window;
  526. } // }}}
  527. // {{{ getDockablePosition()
  528. protected String getDockablePosition(String name)
  529. {
  530. return jEdit.getProperty(name + ".dock-position", FLOATING);
  531. } // }}}
  532. // {{{ focusDockable
  533. protected void focusDockable(String name)
  534. {
  535. JComponent c = getDockable(name);
  536. if (c == null)
  537. return;
  538. if (c instanceof DefaultFocusComponent)
  539. ((DefaultFocusComponent)c).focusOnDefaultComponent();
  540. else
  541. c.requestFocus();
  542. } // }}}
  543. // {{{ getLongTitlePropertyName()
  544. protected String getLongTitlePropertyName(String dockableName)
  545. {
  546. return dockableName + ".longtitle";
  547. } //}}}
  548. // }}}
  549. // {{{ Inner classes
  550. // {{{ DockingArea interface
  551. public interface DockingArea
  552. {
  553. void showMostRecent();
  554. String getCurrent();
  555. void show(String name);
  556. String [] getDockables();
  557. }
  558. // }}}
  559. //{{{ KeyHandler class
  560. /**
  561. * This keyhandler responds to only two key events - those corresponding to
  562. * the close-docking-area action event.
  563. *
  564. * @author ezust
  565. */
  566. class KeyHandler extends KeyAdapter
  567. {
  568. static final String action = "close-docking-area";
  569. private List<Key> b1;
  570. private List<Key> b2;
  571. private final String name;
  572. private int match1;
  573. private int match2;
  574. KeyHandler(String dockableName)
  575. {
  576. String shortcut1=jEdit.getProperty(action + ".shortcut");
  577. String shortcut2=jEdit.getProperty(action + ".shortcut2");
  578. if (shortcut1 != null)
  579. b1 = parseShortcut(shortcut1);
  580. if (shortcut2 != null)
  581. b2 = parseShortcut(shortcut2);
  582. name = dockableName;
  583. match1 = match2 = 0;
  584. }
  585. @Override
  586. public void keyTyped(KeyEvent e)
  587. {
  588. if (b1 != null)
  589. match1 = match(e, b1, match1);
  590. if (b2 != null)
  591. match2 = match(e, b2, match2);
  592. if ((match1 > 0 && match1 == b1.size()) ||
  593. (match2 > 0 && match2 == b2.size()))
  594. {
  595. hideDockableWindow(name);
  596. match1 = match2 = 0;
  597. }
  598. }
  599. private int match(KeyEvent e, List<Key> shortcut, int index)
  600. {
  601. char c = e.getKeyChar();
  602. if (shortcut != null && c == shortcut.get(index).key)
  603. return index + 1;
  604. return 0;
  605. }
  606. private List<Key> parseShortcut(String shortcut)
  607. {
  608. String [] parts = shortcut.split("\\s+");
  609. List<Key> keys = new ArrayList<Key>(parts.length);
  610. for (String part: parts)
  611. {
  612. if (part.length() > 0)
  613. keys.add(KeyEventTranslator.parseKey(part));
  614. }
  615. return keys;
  616. }
  617. } //}}}
  618. // {{{ DockingLayout class
  619. /**
  620. * Objects of DockingLayout class describe which dockables are docked where,
  621. * which ones are floating, and their sizes/positions for saving/loading perspectives.
  622. */
  623. public abstract static class DockingLayout
  624. {
  625. public static final int NO_VIEW_INDEX = -1;
  626. public abstract boolean loadLayout(String baseName, int viewIndex);
  627. public abstract boolean saveLayout(String baseName, int viewIndex);
  628. public abstract String getName();
  629. public void setPlainView(boolean plain)
  630. {
  631. }
  632. public String [] getSavedLayouts()
  633. {
  634. String layoutDir = getLayoutDirectory();
  635. if (layoutDir == null)
  636. return null;
  637. File dir = new File(layoutDir);
  638. File[] files = dir.listFiles(new FilenameFilter()
  639. {
  640. public boolean accept(File dir, String name)
  641. {
  642. return name.endsWith(".xml");
  643. }
  644. });
  645. String[] layouts = new String[files.length];
  646. for (int i = 0; i < files.length; i++)
  647. layouts[i] = fileToLayout(files[i].getName());
  648. return layouts;
  649. }
  650. private static String fileToLayout(String filename)
  651. {
  652. return filename.replaceFirst(".xml", "");
  653. }
  654. private static String layoutToFile(String baseName, int viewIndex)
  655. {
  656. StringBuilder name = new StringBuilder(baseName);
  657. if (viewIndex != NO_VIEW_INDEX)
  658. name.append("-view").append(viewIndex);
  659. name.append(".xml");
  660. return name.toString();
  661. }
  662. public String getLayoutFilename(String baseName, int viewIndex)
  663. {
  664. String dir = getLayoutDirectory();
  665. if (dir == null)
  666. return null;
  667. return dir + File.separator + layoutToFile(baseName, viewIndex);
  668. }
  669. private String getLayoutDirectory()
  670. {
  671. String name = getName();
  672. if (name == null)
  673. return null;
  674. String dir = jEdit.getSettingsDirectory();
  675. if (dir == null)
  676. return null;
  677. dir = dir + File.separator + name;
  678. File d = new File(dir);
  679. if (!d.exists())
  680. d.mkdir();
  681. return dir;
  682. }
  683. } // }}}
  684. //}}}
  685. } // }}}