PageRenderTime 66ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/org/gjt/sp/jedit/gui/DockableWindowManager.java

#
Java | 1001 lines | 620 code | 102 blank | 279 comment | 115 complexity | 019d0dfb602ed8d32d349095a530f2f9 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. * DockableWindowManager.java - manages dockable windows
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2000, 2005 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 org.gjt.sp.jedit.gui;
  23. //{{{ Imports
  24. import bsh.*;
  25. import javax.swing.*;
  26. import java.awt.event.*;
  27. import java.awt.*;
  28. import java.io.*;
  29. import java.net.URL;
  30. import java.util.*;
  31. import org.gjt.sp.jedit.msg.*;
  32. import org.gjt.sp.jedit.*;
  33. import org.gjt.sp.util.Log;
  34. //}}}
  35. /**
  36. * The <code>DockableWindowManager</code> keeps track of dockable windows.
  37. * Each {@link org.gjt.sp.jedit.View} has an instance of this class.<p>
  38. *
  39. * <b>dockables.xml:</b><p>
  40. *
  41. * Dockable window definitions are read from <code>dockables.xml</code> files
  42. * contained inside plugin JARs. A dockable definition file has the following
  43. * form:
  44. *
  45. * <pre>&lt;?xml version="1.0"?&gt;
  46. *&lt;!DOCTYPE DOCKABLES SYSTEM "dockables.dtd"&gt;
  47. *&lt;DOCKABLES&gt;
  48. * &lt;DOCKABLE NAME="name"&gt;
  49. * // Code to create the dockable
  50. * &lt;/DOCKABLE&gt;
  51. *&lt;/DOCKABLES&gt;</pre>
  52. *
  53. * More than one <code>&lt;DOCKABLE&gt;<code> tag may be present. The code that
  54. * creates the dockable can reference any BeanShell built-in variable
  55. * (see {@link org.gjt.sp.jedit.BeanShell}), along with a variable
  56. * <code>position</code> whose value is one of
  57. * {@link #FLOATING}, {@link #TOP}, {@link #LEFT}, {@link #BOTTOM},
  58. * and {@link #RIGHT}.<p>
  59. *
  60. * The following properties must be defined for each dockable window:
  61. *
  62. * <ul>
  63. * <li><code><i>name</i>.title</code> - the string to show in the title bar
  64. * of the dockable.</li>
  65. * <li><code><i>name</i>.label</code> - the dockable's menu item label.</li>
  66. * </ul>
  67. *
  68. * A number of actions are automatically created for each dockable window:
  69. *
  70. * <ul>
  71. * <li><code><i>name</i></code> - opens the dockable window.</li>
  72. * <li><code><i>name</i>-toggle</code> - toggles the dockable window's visibility.</li>
  73. * <li><code><i>name</i>-float</code> - opens the dockable window in a new
  74. * floating window.</li>
  75. * </ul>
  76. *
  77. * Note that only the first action needs a <code>label</code> property, the
  78. * rest have automatically-generated labels.
  79. *
  80. * <b>Implementation details:</b><p>
  81. *
  82. * When an instance of this class is initialized by the {@link org.gjt.sp.jedit.View}
  83. * class, it
  84. * iterates through the list of registered dockable windows (from jEdit itself,
  85. * and any loaded plugins) and
  86. * examines options supplied by the user in the <b>Global
  87. * Options</b> dialog box. Any plugins designated for one of the
  88. * four docking positions are displayed.<p>
  89. *
  90. * To create an instance of a dockable window, the <code>DockableWindowManager</code>
  91. * finds and executes the BeanShell code extracted from the appropriate
  92. * <code>dockables.xml</code> file. This code will typically consist of a call
  93. * to the constructor of the dockable window component. The result of the
  94. * BeanShell expression, typically a newly constructed component, is placed
  95. * in a window managed by this class.
  96. *
  97. * @see org.gjt.sp.jedit.View#getDockableWindowManager()
  98. *
  99. * @author Slava Pestov
  100. * @author John Gellene (API documentation)
  101. * @version $Id: DockableWindowManager.java 5519 2006-07-03 17:38:56Z ezust $
  102. * @since jEdit 2.6pre3
  103. */
  104. public class DockableWindowManager extends JPanel implements EBComponent
  105. {
  106. //{{{ Constants
  107. /**
  108. * Floating position.
  109. * @since jEdit 2.6pre3
  110. */
  111. public static final String FLOATING = "floating";
  112. /**
  113. * Top position.
  114. * @since jEdit 2.6pre3
  115. */
  116. public static final String TOP = "top";
  117. /**
  118. * Left position.
  119. * @since jEdit 2.6pre3
  120. */
  121. public static final String LEFT = "left";
  122. /**
  123. * Bottom position.
  124. * @since jEdit 2.6pre3
  125. */
  126. public static final String BOTTOM = "bottom";
  127. /**
  128. * Right position.
  129. * @since jEdit 2.6pre3
  130. */
  131. public static final String RIGHT = "right";
  132. //}}}
  133. //{{{ getRegisteredDockableWindows() method
  134. /**
  135. * @since jEdit 4.3pre2
  136. */
  137. public static String[] getRegisteredDockableWindows()
  138. {
  139. return DockableWindowFactory.getInstance()
  140. .getRegisteredDockableWindows();
  141. } //}}}
  142. //{{{ DockableWindowManager constructor
  143. /**
  144. * Creates a new dockable window manager.
  145. * @param view The view
  146. * @param factory A {@link DockableWindowFactory}, usually
  147. * <code>DockableWindowFactory.getInstance()</code>.
  148. * @param config A docking configuration
  149. * @since jEdit 2.6pre3
  150. */
  151. public DockableWindowManager(View view, DockableWindowFactory factory,
  152. View.ViewConfig config)
  153. {
  154. setLayout(new DockableLayout());
  155. this.view = view;
  156. this.factory = factory;
  157. windows = new Hashtable();
  158. clones = new ArrayList();
  159. top = new PanelWindowContainer(this,TOP,config.topPos);
  160. left = new PanelWindowContainer(this,LEFT,config.leftPos);
  161. bottom = new PanelWindowContainer(this,BOTTOM,config.bottomPos);
  162. right = new PanelWindowContainer(this,RIGHT,config.rightPos);
  163. add(DockableLayout.TOP_BUTTONS,top.buttonPanel);
  164. add(DockableLayout.LEFT_BUTTONS,left.buttonPanel);
  165. add(DockableLayout.BOTTOM_BUTTONS,bottom.buttonPanel);
  166. add(DockableLayout.RIGHT_BUTTONS,right.buttonPanel);
  167. add(TOP,top.dockablePanel);
  168. add(LEFT,left.dockablePanel);
  169. add(BOTTOM,bottom.dockablePanel);
  170. add(RIGHT,right.dockablePanel);
  171. } //}}}
  172. //{{{ init() method
  173. /**
  174. * Initialises dockable window manager. Do not call this method directly.
  175. */
  176. public void init()
  177. {
  178. EditBus.addToBus(this);
  179. Iterator entries = factory.getDockableWindowIterator();
  180. while(entries.hasNext())
  181. addEntry((DockableWindowFactory.Window)entries.next());
  182. propertiesChanged();
  183. } //}}}
  184. //{{{ getView() method
  185. /**
  186. * Returns this dockable window manager's view.
  187. * @since jEdit 4.0pre2
  188. */
  189. public View getView()
  190. {
  191. return view;
  192. } //}}}
  193. //{{{ floatDockableWindow() method
  194. /**
  195. * Opens a new instance of the specified dockable window in a floating
  196. * container.
  197. * @param name The dockable window name
  198. * @return The new dockable window instance
  199. * @since jEdit 4.1pre2
  200. */
  201. public JComponent floatDockableWindow(String name)
  202. {
  203. Entry entry = (Entry)windows.get(name);
  204. if(entry == null)
  205. {
  206. Log.log(Log.ERROR,this,"Unknown dockable window: " + name);
  207. return null;
  208. }
  209. // create a copy of this dockable window and float it
  210. Entry newEntry = new Entry(entry.factory,FLOATING);
  211. newEntry.win = newEntry.factory.createDockableWindow(view,FLOATING);
  212. if(newEntry.win != null)
  213. {
  214. newEntry.container = new FloatingWindowContainer(this,true);
  215. newEntry.container.register(newEntry);
  216. newEntry.container.show(newEntry);
  217. }
  218. clones.add(newEntry);
  219. return newEntry.win;
  220. } //}}}
  221. //{{{ showDockableWindow() method
  222. /**
  223. * Opens the specified dockable window.
  224. * @param name The dockable window name
  225. * @since jEdit 2.6pre3
  226. */
  227. public void showDockableWindow(String name)
  228. {
  229. Entry entry = (Entry)windows.get(name);
  230. if(entry == null)
  231. {
  232. Log.log(Log.ERROR,this,"Unknown dockable window: " + name);
  233. return;
  234. }
  235. if(entry.win == null)
  236. {
  237. entry.win = entry.factory.createDockableWindow(
  238. view,entry.position);
  239. }
  240. if(entry.win != null)
  241. {
  242. if(entry.position.equals(FLOATING)
  243. && entry.container == null)
  244. {
  245. entry.container = new FloatingWindowContainer(
  246. this,view.isPlainView());
  247. entry.container.register(entry);
  248. }
  249. entry.container.show(entry);
  250. Object reason = DockableWindowUpdate.ACTIVATED;
  251. EditBus.send(new DockableWindowUpdate(this, reason, name));
  252. }
  253. else
  254. /* an error occurred */;
  255. } //}}}
  256. //{{{ addDockableWindow() method
  257. /**
  258. * Opens the specified dockable window. As of jEdit 4.0pre1, has the
  259. * same effect as calling showDockableWindow().
  260. * @param name The dockable window name
  261. * @since jEdit 2.6pre3
  262. */
  263. public void addDockableWindow(String name)
  264. {
  265. showDockableWindow(name);
  266. } //}}}
  267. //{{{ hideDockableWindow() method
  268. /**
  269. * Hides the specified dockable window.
  270. * @param name The dockable window name
  271. * @since jEdit 2.6pre3
  272. */
  273. public void hideDockableWindow(String name)
  274. {
  275. Entry entry = (Entry)windows.get(name);
  276. if(entry == null)
  277. {
  278. Log.log(Log.ERROR,this,"Unknown dockable window: " + name);
  279. return;
  280. }
  281. if(entry.win == null)
  282. return;
  283. Object reason = DockableWindowUpdate.DEACTIVATED;
  284. EditBus.send(new DockableWindowUpdate(this, reason, name));
  285. entry.container.show(null);
  286. } //}}}
  287. //{{{ removeDockableWindow() method
  288. /**
  289. * Hides the specified dockable window. As of jEdit 4.2pre1, has the
  290. * same effect as calling hideDockableWindow().
  291. * @param name The dockable window name
  292. * @since jEdit 4.2pre1
  293. */
  294. public void removeDockableWindow(String name)
  295. {
  296. hideDockableWindow(name);
  297. } //}}}
  298. //{{{ toggleDockableWindow() method
  299. /**
  300. * Toggles the visibility of the specified dockable window.
  301. * @param name The dockable window name
  302. */
  303. public void toggleDockableWindow(String name)
  304. {
  305. if(isDockableWindowVisible(name))
  306. removeDockableWindow(name);
  307. else
  308. addDockableWindow(name);
  309. } //}}}
  310. //{{{ getDockableWindow() method
  311. /**
  312. * Returns the specified dockable window.
  313. *
  314. * Note that this method
  315. * will return null if the dockable has not been added yet.
  316. * Make sure you call {@link #addDockableWindow(String)} first.
  317. *
  318. * @param name The name of the dockable window
  319. * @since jEdit 4.1pre2
  320. */
  321. public JComponent getDockableWindow(String name)
  322. {
  323. return getDockable(name);
  324. } //}}}
  325. //{{{ getDockable() method
  326. /**
  327. * Returns the specified dockable window.
  328. *
  329. * Note that this method
  330. * will return null if the dockable has not been added yet.
  331. * Make sure you call {@link #addDockableWindow(String)} first.
  332. *
  333. * For historical reasons, this
  334. * does the same thing as {@link #getDockableWindow(String)}.
  335. *
  336. * @param name The name of the dockable window
  337. * @since jEdit 4.0pre1
  338. */
  339. public JComponent getDockable(String name)
  340. {
  341. Entry entry = (Entry)windows.get(name);
  342. if(entry == null || entry.win == null)
  343. return null;
  344. else
  345. return entry.win;
  346. } //}}}
  347. //{{{ getDockableTitle() method
  348. /**
  349. * Returns the title of the specified dockable window.
  350. * @param name The name of the dockable window.
  351. * @since jEdit 4.1pre5
  352. */
  353. public String getDockableTitle(String name)
  354. {
  355. String title = jEdit.getProperty(name + ".title");
  356. if(title == null)
  357. return "NO TITLE PROPERTY: " + name;
  358. else
  359. return title;
  360. } //}}}
  361. /**
  362. * Changes the title string of a floating dockable.
  363. *
  364. * @param dockableName the name of the dockable, as specified in the dockables.xml
  365. * @param newTitle the new title you want to see above it. This is prefixed by the
  366. * Dockable's label.
  367. * @since 4.3pre5
  368. *
  369. */
  370. public void setDockableTitle(String dockableName, String newTitle) {
  371. String propName = dockableName + ".title";
  372. Entry entry = (Entry)windows.get(dockableName);
  373. String dockLabel = entry.label();
  374. newTitle = dockLabel + ": " + newTitle;
  375. String oldTitle = jEdit.getProperty(propName);
  376. jEdit.setProperty(propName, newTitle);
  377. firePropertyChange(propName, oldTitle, newTitle);
  378. }
  379. //{{{ isDockableWindowVisible() method
  380. /**
  381. * Returns if the specified dockable window is visible.
  382. * @param name The dockable window name
  383. */
  384. public boolean isDockableWindowVisible(String name)
  385. {
  386. Entry entry = (Entry)windows.get(name);
  387. if(entry == null || entry.win == null)
  388. return false;
  389. else
  390. return entry.container.isVisible(entry);
  391. } //}}}
  392. //{{{ isDockableWindowDocked() method
  393. /**
  394. * Returns if the specified dockable window is docked into the
  395. * view.
  396. * @param name The dockable's name
  397. * @since jEdit 4.0pre2
  398. */
  399. public boolean isDockableWindowDocked(String name)
  400. {
  401. Entry entry = (Entry)windows.get(name);
  402. if(entry == null)
  403. return false;
  404. else
  405. return !entry.position.equals(FLOATING);
  406. } //}}}
  407. //{{{ closeCurrentArea() method
  408. /**
  409. * Closes the currently focused docking area.
  410. * @since jEdit 4.1pre3
  411. */
  412. public void closeCurrentArea()
  413. {
  414. // I don't know of any other way to fix this, since invoking this
  415. // command from a menu results in the focus owner being the menu
  416. // until the menu goes away.
  417. SwingUtilities.invokeLater(new Runnable()
  418. {
  419. public void run()
  420. {
  421. Component comp = view.getFocusOwner();
  422. while(comp != null)
  423. {
  424. //System.err.println(comp.getClass());
  425. if(comp instanceof DockablePanel)
  426. {
  427. PanelWindowContainer container =
  428. ((DockablePanel)comp)
  429. .getWindowContainer();
  430. container.show(null);
  431. return;
  432. }
  433. comp = comp.getParent();
  434. }
  435. getToolkit().beep();
  436. }
  437. });
  438. } //}}}
  439. //{{{ close() method
  440. /**
  441. * Called when the view is being closed.
  442. * @since jEdit 2.6pre3
  443. */
  444. public void close()
  445. {
  446. EditBus.removeFromBus(this);
  447. Iterator iter = windows.values().iterator();
  448. while(iter.hasNext())
  449. {
  450. Entry entry = (Entry)iter.next();
  451. if(entry.win != null)
  452. {
  453. entry.container.unregister(entry);
  454. }
  455. }
  456. iter = clones.iterator();
  457. while(iter.hasNext())
  458. {
  459. Entry entry = (Entry)iter.next();
  460. if(entry.win != null)
  461. {
  462. entry.container.unregister(entry);
  463. }
  464. }
  465. } //}}}
  466. //{{{ getTopDockingArea() method
  467. public PanelWindowContainer getTopDockingArea()
  468. {
  469. return top;
  470. } //}}}
  471. //{{{ getLeftDockingArea() method
  472. public PanelWindowContainer getLeftDockingArea()
  473. {
  474. return left;
  475. } //}}}
  476. //{{{ getBottomDockingArea() method
  477. public PanelWindowContainer getBottomDockingArea()
  478. {
  479. return bottom;
  480. } //}}}
  481. //{{{ getRightDockingArea() method
  482. public PanelWindowContainer getRightDockingArea()
  483. {
  484. return right;
  485. } //}}}
  486. //{{{ createPopupMenu() method
  487. public JPopupMenu createPopupMenu(
  488. final DockableWindowContainer container,
  489. final String dockable,
  490. final boolean clone)
  491. {
  492. JPopupMenu popup = new JPopupMenu();
  493. if(dockable == null && container instanceof PanelWindowContainer)
  494. {
  495. ActionListener listener = new ActionListener()
  496. {
  497. public void actionPerformed(ActionEvent evt)
  498. {
  499. showDockableWindow(evt.getActionCommand());
  500. }
  501. };
  502. String[] dockables = ((PanelWindowContainer)
  503. container).getDockables();
  504. for(int i = 0; i < dockables.length; i++)
  505. {
  506. String name = dockables[i];
  507. JMenuItem item = new JMenuItem(getDockableTitle(name));
  508. item.setActionCommand(name);
  509. item.addActionListener(listener);
  510. popup.add(item);
  511. }
  512. }
  513. else
  514. {
  515. JMenuItem caption = new JMenuItem(getDockableTitle(dockable));
  516. caption.setEnabled(false);
  517. popup.add(caption);
  518. popup.addSeparator();
  519. String currentPos = jEdit.getProperty(dockable + ".dock-position",FLOATING);
  520. if(!clone)
  521. {
  522. String[] positions = { FLOATING, TOP, LEFT, BOTTOM, RIGHT };
  523. for(int i = 0; i < positions.length; i++)
  524. {
  525. final String pos = positions[i];
  526. if(pos.equals(currentPos))
  527. continue;
  528. JMenuItem moveMenuItem = new JMenuItem(jEdit.getProperty("view.docking.menu-"
  529. + pos));
  530. moveMenuItem.addActionListener(new ActionListener()
  531. {
  532. public void actionPerformed(ActionEvent evt)
  533. {
  534. jEdit.setProperty(dockable + ".dock-position",pos);
  535. EditBus.send(new DockableWindowUpdate(
  536. DockableWindowManager.this,
  537. DockableWindowUpdate.PROPERTIES_CHANGED,
  538. null
  539. ));
  540. showDockableWindow(dockable);
  541. }
  542. });
  543. popup.add(moveMenuItem);
  544. }
  545. popup.addSeparator();
  546. }
  547. JMenuItem cloneMenuItem = new JMenuItem(jEdit.getProperty("view.docking.menu-clone"));
  548. cloneMenuItem.addActionListener(new ActionListener()
  549. {
  550. public void actionPerformed(ActionEvent evt)
  551. {
  552. floatDockableWindow(dockable);
  553. }
  554. });
  555. popup.add(cloneMenuItem);
  556. popup.addSeparator();
  557. JMenuItem closeMenuItem = new JMenuItem(jEdit.getProperty("view.docking.menu-close"));
  558. closeMenuItem.addActionListener(new ActionListener()
  559. {
  560. public void actionPerformed(ActionEvent evt)
  561. {
  562. if(clone)
  563. ((FloatingWindowContainer)container).dispose();
  564. else
  565. removeDockableWindow(dockable);
  566. }
  567. });
  568. popup.add(closeMenuItem);
  569. if(!(clone || currentPos.equals(FLOATING)))
  570. {
  571. JMenuItem undockMenuItem = new JMenuItem(jEdit.getProperty("view.docking.menu-undock"));
  572. undockMenuItem.addActionListener(new ActionListener()
  573. {
  574. public void actionPerformed(ActionEvent evt)
  575. {
  576. jEdit.setProperty(dockable + ".dock-position",FLOATING);
  577. EditBus.send(new DockableWindowUpdate(
  578. DockableWindowManager.this,
  579. DockableWindowUpdate.PROPERTIES_CHANGED,
  580. null
  581. ));
  582. }
  583. });
  584. popup.add(undockMenuItem);
  585. }
  586. }
  587. return popup;
  588. } //}}}
  589. //{{{ paintChildren() method
  590. public void paintChildren(Graphics g)
  591. {
  592. super.paintChildren(g);
  593. if(resizeRect != null)
  594. {
  595. g.setColor(Color.darkGray);
  596. g.fillRect(resizeRect.x,resizeRect.y,
  597. resizeRect.width,resizeRect.height);
  598. }
  599. } //}}}
  600. //{{{ handleMessage() method
  601. public void handleMessage(EBMessage msg)
  602. {
  603. if(msg instanceof DockableWindowUpdate)
  604. {
  605. if(((DockableWindowUpdate)msg).getWhat()
  606. == DockableWindowUpdate.PROPERTIES_CHANGED)
  607. propertiesChanged();
  608. }
  609. else if(msg instanceof PropertiesChanged)
  610. propertiesChanged();
  611. else if(msg instanceof PluginUpdate)
  612. {
  613. PluginUpdate pmsg = (PluginUpdate)msg;
  614. if(pmsg.getWhat() == PluginUpdate.LOADED)
  615. {
  616. Iterator iter = factory.getDockableWindowIterator();
  617. while(iter.hasNext())
  618. {
  619. DockableWindowFactory.Window w = (DockableWindowFactory.Window)iter.next();
  620. if(w.plugin == pmsg.getPluginJAR())
  621. addEntry(w);
  622. }
  623. propertiesChanged();
  624. }
  625. else if(pmsg.isExiting())
  626. {
  627. // we don't care
  628. }
  629. else if(pmsg.getWhat() == PluginUpdate.DEACTIVATED)
  630. {
  631. Iterator iter = getAllPluginEntries(
  632. pmsg.getPluginJAR(),false);
  633. while(iter.hasNext())
  634. {
  635. Entry entry = (Entry)iter.next();
  636. if(entry.container != null)
  637. entry.container.remove(entry);
  638. }
  639. }
  640. else if(pmsg.getWhat() == PluginUpdate.UNLOADED)
  641. {
  642. Iterator iter = getAllPluginEntries(
  643. pmsg.getPluginJAR(),true);
  644. while(iter.hasNext())
  645. {
  646. Entry entry = (Entry)iter.next();
  647. if(entry.container != null)
  648. {
  649. entry.container.unregister(entry);
  650. entry.win = null;
  651. entry.container = null;
  652. }
  653. }
  654. }
  655. }
  656. } //}}}
  657. //{{{ Package-private members
  658. int resizePos;
  659. Rectangle resizeRect;
  660. //{{{ setResizePos() method
  661. void setResizePos(int resizePos, PanelWindowContainer resizing)
  662. {
  663. this.resizePos = resizePos;
  664. if(resizePos < 0)
  665. resizePos = 0;
  666. Rectangle newResizeRect = new Rectangle(0,0,
  667. PanelWindowContainer.SPLITTER_WIDTH - 2,
  668. PanelWindowContainer.SPLITTER_WIDTH - 2);
  669. if(resizing == top)
  670. {
  671. resizePos = Math.min(resizePos,getHeight()
  672. - top.buttonPanel.getHeight()
  673. - bottom.dockablePanel.getHeight()
  674. - bottom.buttonPanel.getHeight()
  675. - PanelWindowContainer.SPLITTER_WIDTH);
  676. newResizeRect.x = top.dockablePanel.getX() + 1;
  677. newResizeRect.y = resizePos + top.buttonPanel.getHeight() + 1;
  678. newResizeRect.width = top.dockablePanel.getWidth() - 2;
  679. }
  680. else if(resizing == left)
  681. {
  682. resizePos = Math.min(resizePos,getWidth()
  683. - left.buttonPanel.getWidth()
  684. - right.dockablePanel.getWidth()
  685. - right.buttonPanel.getWidth()
  686. - PanelWindowContainer.SPLITTER_WIDTH);
  687. newResizeRect.x = resizePos + left.buttonPanel.getWidth() + 1;
  688. newResizeRect.y = left.dockablePanel.getY() + 1;
  689. newResizeRect.height = left.dockablePanel.getHeight() - 2;
  690. }
  691. else if(resizing == bottom)
  692. {
  693. resizePos = Math.min(resizePos,getHeight()
  694. - bottom.buttonPanel.getHeight()
  695. - top.dockablePanel.getHeight()
  696. - top.buttonPanel.getHeight()
  697. - PanelWindowContainer.SPLITTER_WIDTH);
  698. newResizeRect.x = bottom.dockablePanel.getX() + 1;
  699. newResizeRect.y = getHeight() - bottom.buttonPanel.getHeight() - resizePos
  700. - PanelWindowContainer.SPLITTER_WIDTH + 2;
  701. newResizeRect.width = bottom.dockablePanel.getWidth() - 2;
  702. }
  703. else if(resizing == right)
  704. {
  705. resizePos = Math.min(resizePos,getWidth()
  706. - right.buttonPanel.getWidth()
  707. - left.dockablePanel.getWidth()
  708. - left.buttonPanel.getWidth()
  709. - PanelWindowContainer.SPLITTER_WIDTH);
  710. newResizeRect.x = getWidth() - right.buttonPanel.getWidth() - resizePos
  711. - PanelWindowContainer.SPLITTER_WIDTH + 1;
  712. newResizeRect.y = right.dockablePanel.getY() + 1;
  713. newResizeRect.height = right.dockablePanel.getHeight() - 2;
  714. }
  715. Rectangle toRepaint;
  716. if(resizeRect == null)
  717. toRepaint = newResizeRect;
  718. else
  719. toRepaint = resizeRect.union(newResizeRect);
  720. resizeRect = newResizeRect;
  721. repaint(toRepaint);
  722. } //}}}
  723. //{{{ finishResizing() method
  724. void finishResizing()
  725. {
  726. resizeRect = null;
  727. repaint();
  728. } //}}}
  729. //}}}
  730. //{{{ Private members
  731. private View view;
  732. private DockableWindowFactory factory;
  733. private Hashtable windows;
  734. private PanelWindowContainer left;
  735. private PanelWindowContainer right;
  736. private PanelWindowContainer top;
  737. private PanelWindowContainer bottom;
  738. private ArrayList clones;
  739. //{{{ propertiesChanged() method
  740. private void propertiesChanged()
  741. {
  742. if(view.isPlainView())
  743. return;
  744. ((DockableLayout)getLayout()).setAlternateLayout(
  745. jEdit.getBooleanProperty("view.docking.alternateLayout"));
  746. String[] windowList = factory.getRegisteredDockableWindows();
  747. for(int i = 0; i < windowList.length; i++)
  748. {
  749. String dockable = windowList[i];
  750. Entry entry = (Entry)windows.get(dockable);
  751. String newPosition = jEdit.getProperty(dockable
  752. + ".dock-position",FLOATING);
  753. if(newPosition.equals(entry.position))
  754. {
  755. continue;
  756. }
  757. entry.position = newPosition;
  758. if(entry.container != null)
  759. {
  760. entry.container.unregister(entry);
  761. entry.container = null;
  762. entry.win = null;
  763. }
  764. if(newPosition.equals(FLOATING)) {
  765. }
  766. else
  767. {
  768. if(newPosition.equals(TOP))
  769. entry.container = top;
  770. else if(newPosition.equals(LEFT))
  771. entry.container = left;
  772. else if(newPosition.equals(BOTTOM))
  773. entry.container = bottom;
  774. else if(newPosition.equals(RIGHT))
  775. entry.container = right;
  776. else
  777. {
  778. Log.log(Log.WARNING,this,
  779. "Unknown position: "
  780. + newPosition);
  781. continue;
  782. }
  783. entry.container.register(entry);
  784. }
  785. }
  786. top.sortDockables();
  787. left.sortDockables();
  788. bottom.sortDockables();
  789. right.sortDockables();
  790. revalidate();
  791. repaint();
  792. } //}}}
  793. //{{{ addEntry() method
  794. private void addEntry(DockableWindowFactory.Window factory)
  795. {
  796. Entry e;
  797. if(view.isPlainView())
  798. {
  799. // don't show menu items to dock into a plain view
  800. e = new Entry(factory,FLOATING);
  801. }
  802. else
  803. {
  804. e = new Entry(factory);
  805. if(e.position.equals(FLOATING))
  806. /* nothing to do */;
  807. else if(e.position.equals(TOP))
  808. e.container = top;
  809. else if(e.position.equals(LEFT))
  810. e.container = left;
  811. else if(e.position.equals(BOTTOM))
  812. e.container = bottom;
  813. else if(e.position.equals(RIGHT))
  814. e.container = right;
  815. else
  816. {
  817. Log.log(Log.WARNING,this,
  818. "Unknown position: "
  819. + e.position);
  820. }
  821. if(e.container != null)
  822. e.container.register(e);
  823. }
  824. windows.put(factory.name,e);
  825. } //}}}
  826. //{{{ getAllPluginEntries() method
  827. /**
  828. * If remove is false, only remove from clones list, otherwise remove
  829. * from both entries and clones.
  830. */
  831. private Iterator getAllPluginEntries(PluginJAR plugin, boolean remove)
  832. {
  833. java.util.List returnValue = new LinkedList();
  834. Iterator iter = windows.values().iterator();
  835. while(iter.hasNext())
  836. {
  837. Entry entry = (Entry)iter.next();
  838. if(entry.factory.plugin == plugin)
  839. {
  840. returnValue.add(entry);
  841. if(remove)
  842. iter.remove();
  843. }
  844. }
  845. iter = clones.iterator();
  846. while(iter.hasNext())
  847. {
  848. Entry entry = (Entry)iter.next();
  849. if(entry.factory.plugin == plugin)
  850. {
  851. returnValue.add(entry);
  852. iter.remove();
  853. }
  854. }
  855. return returnValue.iterator();
  856. } //}}}
  857. //}}}
  858. //{{{ Entry class
  859. class Entry
  860. {
  861. DockableWindowFactory.Window factory;
  862. // String title;
  863. String position;
  864. DockableWindowContainer container;
  865. // only set if open
  866. JComponent win;
  867. // only for docked
  868. AbstractButton btn;
  869. //{{{ Entry constructor
  870. Entry(DockableWindowFactory.Window factory)
  871. {
  872. this(factory,jEdit.getProperty(factory.name
  873. + ".dock-position",FLOATING));
  874. } //}}}
  875. /**
  876. * @return The title for the floating dockable window
  877. */
  878. public String title() {
  879. return getDockableTitle(factory.name);
  880. }
  881. /**
  882. * @return A label appropriate for the title on the dock buttons.
  883. */
  884. public String label() {
  885. String retval = jEdit.getProperty(factory.name + ".label");
  886. retval = retval.replaceAll("\\$", "");
  887. return retval;
  888. }
  889. //{{{ Entry constructor
  890. Entry(DockableWindowFactory.Window factory, String position)
  891. {
  892. this.factory = factory;
  893. this.position = position;
  894. // get the title here, not in the factory constructor,
  895. // since the factory might be created before a plugin's
  896. // props are loaded
  897. } //}}}
  898. } //}}}
  899. }