/jEdit/tags/jedit-4-1-pre5/org/gjt/sp/jedit/gui/PanelWindowContainer.java

# · Java · 945 lines · 717 code · 115 blank · 113 comment · 120 complexity · 6ada05e020d4107e94ccc4a2b5817867 MD5 · raw file

  1. /*
  2. * PanelWindowContainer.java - holds dockable windows
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2000, 2001, 2002 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 javax.swing.border.*;
  25. import javax.swing.plaf.metal.*;
  26. import javax.swing.*;
  27. import java.awt.event.*;
  28. import java.awt.font.*;
  29. import java.awt.geom.AffineTransform;
  30. import java.awt.image.*;
  31. import java.awt.*;
  32. import java.util.Vector;
  33. import org.gjt.sp.jedit.*;
  34. //}}}
  35. /**
  36. * A container for dockable windows. This class should never be used
  37. * directly.
  38. * @author Slava Pestov
  39. * @version $Id: PanelWindowContainer.java 4342 2002-09-20 19:53:23Z spestov $
  40. * @since jEdit 4.0pre1
  41. */
  42. public class PanelWindowContainer implements DockableWindowContainer
  43. {
  44. //{{{ PanelWindowContainer constructor
  45. public PanelWindowContainer(DockableWindowManager wm, String position)
  46. {
  47. this.wm = wm;
  48. this.position = position;
  49. //{{{ Button box setup
  50. buttons = new JPanel(new ButtonLayout());
  51. buttons.setBorder(new EmptyBorder(1,1,1,1));
  52. // the close box must be the same size as the other buttons to look good.
  53. // there are two ways to achieve this:
  54. // a) write a custom layout manager
  55. // b) when the first button is added, give the close box the proper size
  56. // I'm lazy so I chose "b". See register() for details.
  57. closeBox = new JButton(GUIUtilities.loadIcon("closebox.gif"));
  58. closeBox.setRequestFocusEnabled(false);
  59. closeBox.setToolTipText(jEdit.getProperty("view.docking.close-tooltip"));
  60. if(OperatingSystem.isMacOSLF())
  61. closeBox.putClientProperty("JButton.buttonType","toolbar");
  62. // makes it look a bit better
  63. int left;
  64. if(position.equals(DockableWindowManager.RIGHT)
  65. || position.equals(DockableWindowManager.LEFT))
  66. left = 1;
  67. else
  68. left = 0;
  69. closeBox.setMargin(new Insets(0,left,0,0));
  70. buttons.add(closeBox);
  71. closeBox.addActionListener(new ActionHandler());
  72. closeBox.addMouseListener(new MouseHandler());
  73. popupButton = new JButton(GUIUtilities.loadIcon("ToolbarMenu.gif"));
  74. popupButton.setRequestFocusEnabled(false);
  75. popupButton.setToolTipText(jEdit.getProperty("view.docking.menu-tooltip"));
  76. if(OperatingSystem.isMacOSLF())
  77. popupButton.putClientProperty("JButton.buttonType","toolbar");
  78. buttons.add(popupButton);
  79. popupButton.addMouseListener(new MouseHandler());
  80. buttonGroup = new ButtonGroup();
  81. // JDK 1.4 workaround
  82. buttonGroup.add(nullButton = new JToggleButton());
  83. //}}}
  84. dockables = new Vector();
  85. dockablePanel = new DockablePanel();
  86. dimension = jEdit.getIntegerProperty(
  87. "view.dock." + position + ".dimension",0);
  88. buttons.addMouseListener(new MouseHandler());
  89. } //}}}
  90. //{{{ register() method
  91. public void register(final DockableWindowManager.Entry entry)
  92. {
  93. dockables.addElement(entry);
  94. //{{{ Create button
  95. int rotation;
  96. if(position.equals(DockableWindowManager.TOP)
  97. || position.equals(DockableWindowManager.BOTTOM))
  98. rotation = RotatedTextIcon.NONE;
  99. else if(position.equals(DockableWindowManager.LEFT))
  100. rotation = RotatedTextIcon.CCW;
  101. else if(position.equals(DockableWindowManager.RIGHT))
  102. rotation = RotatedTextIcon.CW;
  103. else
  104. throw new InternalError("Invalid position: " + position);
  105. JToggleButton button = new JToggleButton();
  106. button.setMargin(new Insets(0,0,0,0));
  107. button.setRequestFocusEnabled(false);
  108. button.setIcon(new RotatedTextIcon(rotation,button.getFont(),
  109. entry.title));
  110. button.setActionCommand(entry.factory.name);
  111. button.addActionListener(new ActionHandler());
  112. //}}}
  113. buttonGroup.add(button);
  114. buttons.add(button);
  115. button.addMouseListener(new MouseHandler());
  116. wm.revalidate();
  117. } //}}}
  118. //{{{ add() method
  119. public void add(DockableWindowManager.Entry entry)
  120. {
  121. dockablePanel.add(entry.factory.name,entry.win);
  122. } //}}}
  123. //{{{ remove() method
  124. public void remove(DockableWindowManager.Entry entry)
  125. {
  126. if(entry.factory.name.equals(mostRecent))
  127. mostRecent = null;
  128. int index = dockables.indexOf(entry);
  129. buttons.remove(index + 2);
  130. dockables.removeElement(entry);
  131. if(entry.win != null)
  132. dockablePanel.remove(entry.win);
  133. if(current == entry)
  134. {
  135. current = null;
  136. show(null);
  137. }
  138. else
  139. wm.revalidate();
  140. } //}}}
  141. //{{{ save() method
  142. public void save(DockableWindowManager.Entry entry) {}
  143. //}}}
  144. //{{{ showMostRecent() method
  145. public void showMostRecent()
  146. {
  147. if(dockables.size() == 0)
  148. {
  149. Toolkit.getDefaultToolkit().beep();
  150. return;
  151. }
  152. if(mostRecent == null)
  153. {
  154. mostRecent = ((DockableWindowManager.Entry)
  155. dockables.get(0)).factory.name;
  156. }
  157. wm.showDockableWindow(mostRecent);
  158. } //}}}
  159. //{{{ show() method
  160. public void show(final DockableWindowManager.Entry entry)
  161. {
  162. if(current == entry)
  163. {
  164. if(entry != null)
  165. {
  166. entry.win.requestFocus();
  167. entry.win.requestDefaultFocus();
  168. }
  169. return;
  170. }
  171. if(current == null)
  172. {
  173. // we didn't have a component previously, so create a border
  174. dockablePanel.setBorder(new DockBorder(position));
  175. }
  176. if(entry != null)
  177. {
  178. mostRecent = entry.factory.name;
  179. this.current = entry;
  180. dockablePanel.showDockable(entry.factory.name);
  181. int index = dockables.indexOf(entry);
  182. ((JToggleButton)buttons.getComponent(index + 2)).setSelected(true);
  183. SwingUtilities.invokeLater(new Runnable()
  184. {
  185. public void run()
  186. {
  187. entry.win.requestFocus();
  188. entry.win.requestDefaultFocus();
  189. }
  190. });
  191. }
  192. else
  193. {
  194. current = null;
  195. nullButton.setSelected(true);
  196. // removing last component, so remove border
  197. dockablePanel.setBorder(null);
  198. wm.getView().getTextArea().requestFocus();
  199. }
  200. wm.revalidate();
  201. dockablePanel.repaint();
  202. } //}}}
  203. //{{{ isVisible() method
  204. public boolean isVisible(DockableWindowManager.Entry entry)
  205. {
  206. return current == entry;
  207. } //}}}
  208. //{{{ getCurrent() method
  209. public DockableWindowManager.Entry getCurrent()
  210. {
  211. return current;
  212. } //}}}
  213. //{{{ getDockables() method
  214. public String[] getDockables()
  215. {
  216. String[] retVal = new String[dockables.size()];
  217. for(int i = 0; i < dockables.size(); i++)
  218. {
  219. DockableWindowManager.Entry entry =
  220. (DockableWindowManager.Entry) dockables.elementAt(i);
  221. retVal[i] = entry.factory.name;
  222. }
  223. return retVal;
  224. } //}}}
  225. //{{{ Package-private members
  226. static final int SPLITTER_WIDTH = 10;
  227. DockablePanel dockablePanel;
  228. //{{{ save() method
  229. void save()
  230. {
  231. jEdit.setIntegerProperty("view.dock." + position + ".dimension",
  232. dimension);
  233. if(current == null)
  234. jEdit.unsetProperty("view.dock." + position + ".last");
  235. else
  236. {
  237. jEdit.setProperty("view.dock." + position + ".last",
  238. current.factory.name);
  239. }
  240. } //}}}
  241. //{{{ getButtonBox() method
  242. JPanel getButtonBox()
  243. {
  244. return buttons;
  245. } //}}}
  246. //{{{ getDockablePanel() method
  247. DockablePanel getDockablePanel()
  248. {
  249. return dockablePanel;
  250. } //}}}
  251. //{{{ setDimension() method
  252. void setDimension(int dimension)
  253. {
  254. if(dimension != 0)
  255. this.dimension = dimension - SPLITTER_WIDTH - 3;
  256. } //}}}
  257. //}}}
  258. //{{{ Private members
  259. private DockableWindowManager wm;
  260. private String position;
  261. private JPanel buttons;
  262. private JButton closeBox;
  263. private JButton popupButton;
  264. private ButtonGroup buttonGroup;
  265. private JToggleButton nullButton;
  266. private int dimension;
  267. private Vector dockables;
  268. private DockableWindowManager.Entry current;
  269. // remember the most recent dockable
  270. private String mostRecent;
  271. //}}}
  272. //{{{ Inner classes
  273. //{{{ ActionHandler class
  274. class ActionHandler implements ActionListener
  275. {
  276. public void actionPerformed(ActionEvent evt)
  277. {
  278. if(evt.getSource() == closeBox)
  279. show(null);
  280. else
  281. {
  282. if(wm.isDockableWindowVisible(evt.getActionCommand()))
  283. show(null);
  284. else
  285. wm.showDockableWindow(evt.getActionCommand());
  286. }
  287. }
  288. } //}}}
  289. //{{{ MouseHandler class
  290. class MouseHandler extends MouseAdapter
  291. {
  292. JPopupMenu popup;
  293. public void mousePressed(MouseEvent evt)
  294. {
  295. if(evt.getSource() == popupButton
  296. || GUIUtilities.isPopupTrigger(evt))
  297. {
  298. if(popup != null && popup.isVisible())
  299. popup.setVisible(false);
  300. else
  301. {
  302. popup = createPopupMenu();
  303. GUIUtilities.showPopupMenu(popup,
  304. (Component)evt.getSource(),
  305. evt.getX(),evt.getY());
  306. }
  307. }
  308. }
  309. private JPopupMenu createPopupMenu()
  310. {
  311. JPopupMenu popup = new JPopupMenu();
  312. JMenu floatMenu = new JMenu(jEdit.getProperty("view.docking.menu-float"));
  313. String[] dockables = getDockables();
  314. for(int i = 0; i < dockables.length; i++)
  315. {
  316. final String entry = dockables[i];
  317. JMenuItem selectMenuItem = new JMenuItem(wm.getDockableTitle(entry));
  318. selectMenuItem.addActionListener(new ActionListener()
  319. {
  320. public void actionPerformed(ActionEvent evt)
  321. {
  322. wm.showDockableWindow(entry);
  323. }
  324. });
  325. JMenuItem floatMenuItem = new JMenuItem(wm.getDockableTitle(entry));
  326. floatMenuItem.addActionListener(new ActionListener()
  327. {
  328. public void actionPerformed(ActionEvent evt)
  329. {
  330. wm.floatDockableWindow(entry);
  331. }
  332. });
  333. popup.add(selectMenuItem);
  334. floatMenu.add(floatMenuItem);
  335. }
  336. popup.addSeparator();
  337. popup.add(floatMenu);
  338. return popup;
  339. }
  340. } //}}}
  341. //{{{ DockBorder class
  342. static class DockBorder implements Border
  343. {
  344. String position;
  345. Insets insets;
  346. Color color1;
  347. Color color2;
  348. Color color3;
  349. //{{{ DockBorder constructor
  350. DockBorder(String position)
  351. {
  352. this.position = position;
  353. insets = new Insets(
  354. position.equals(DockableWindowManager.BOTTOM)
  355. ? SPLITTER_WIDTH : 0,
  356. position.equals(DockableWindowManager.RIGHT)
  357. ? SPLITTER_WIDTH : 0,
  358. position.equals(DockableWindowManager.TOP)
  359. ? SPLITTER_WIDTH : 0,
  360. position.equals(DockableWindowManager.LEFT)
  361. ? SPLITTER_WIDTH : 0);
  362. } //}}}
  363. //{{{ paintBorder() method
  364. public void paintBorder(Component c, Graphics g,
  365. int x, int y, int width, int height)
  366. {
  367. updateColors();
  368. if(color1 == null || color2 == null || color3 == null)
  369. return;
  370. if(position.equals(DockableWindowManager.BOTTOM))
  371. paintHorizBorder(g,x,y,width);
  372. else if(position.equals(DockableWindowManager.RIGHT))
  373. paintVertBorder(g,x,y,height);
  374. else if(position.equals(DockableWindowManager.TOP))
  375. {
  376. paintHorizBorder(g,x,y + height
  377. - SPLITTER_WIDTH,width);
  378. }
  379. else if(position.equals(DockableWindowManager.LEFT))
  380. {
  381. paintVertBorder(g,x + width
  382. - SPLITTER_WIDTH,y,height);
  383. }
  384. } //}}}
  385. //{{{ getBorderInsets() method
  386. public Insets getBorderInsets(Component c)
  387. {
  388. return insets;
  389. } //}}}
  390. //{{{ isBorderOpaque() method
  391. public boolean isBorderOpaque()
  392. {
  393. return false;
  394. } //}}}
  395. //{{{ paintHorizBorder() method
  396. private void paintHorizBorder(Graphics g, int x, int y, int width)
  397. {
  398. g.setColor(color3);
  399. g.fillRect(x,y,width,SPLITTER_WIDTH);
  400. for(int i = 0; i < width / 4 - 1; i++)
  401. {
  402. g.setColor(color1);
  403. g.drawLine(x + i * 4 + 2,y + 3,
  404. x + i * 4 + 2,y + 3);
  405. g.setColor(color2);
  406. g.drawLine(x + i * 4 + 3,y + 4,
  407. x + i * 4 + 3,y + 4);
  408. g.setColor(color1);
  409. g.drawLine(x + i * 4 + 4,y + 5,
  410. x + i * 4 + 4,y + 5);
  411. g.setColor(color2);
  412. g.drawLine(x + i * 4 + 5,y + 6,
  413. x + i * 4 + 5,y + 6);
  414. }
  415. } //}}}
  416. //{{{ paintVertBorder() method
  417. private void paintVertBorder(Graphics g, int x, int y, int height)
  418. {
  419. g.setColor(color3);
  420. g.fillRect(x,y,SPLITTER_WIDTH,height);
  421. for(int i = 0; i < height / 4 - 1; i++)
  422. {
  423. g.setColor(color1);
  424. g.drawLine(x + 3,y + i * 4 + 2,
  425. x + 3,y + i * 4 + 2);
  426. g.setColor(color2);
  427. g.drawLine(x + 4,y + i * 4 + 3,
  428. x + 4,y + i * 4 + 3);
  429. g.setColor(color1);
  430. g.drawLine(x + 5,y + i * 4 + 4,
  431. x + 5,y + i * 4 + 4);
  432. g.setColor(color2);
  433. g.drawLine(x + 6,y + i * 4 + 5,
  434. x + 6,y + i * 4 + 5);
  435. }
  436. } //}}}
  437. //{{{ updateColors() method
  438. private void updateColors()
  439. {
  440. if(UIManager.getLookAndFeel() instanceof MetalLookAndFeel)
  441. {
  442. color1 = MetalLookAndFeel.getControlHighlight();
  443. color2 = MetalLookAndFeel.getControlDarkShadow();
  444. color3 = MetalLookAndFeel.getControl();
  445. }
  446. else
  447. {
  448. color1 = color2 = color3 = null;
  449. }
  450. } //}}}
  451. } //}}}
  452. //{{{ RotatedTextIcon class
  453. public static class RotatedTextIcon implements Icon
  454. {
  455. public static final int NONE = 0;
  456. public static final int CW = 1;
  457. public static final int CCW = 2;
  458. //{{{ RotatedTextIcon constructor
  459. public RotatedTextIcon(int rotate, Font font, String text)
  460. {
  461. this.rotate = rotate;
  462. this.font = font;
  463. FontRenderContext fontRenderContext
  464. = new FontRenderContext(null,true,true);
  465. this.text = text;
  466. glyphs = font.createGlyphVector(fontRenderContext,text);
  467. width = (int)glyphs.getLogicalBounds().getWidth() + 4;
  468. //height = (int)glyphs.getLogicalBounds().getHeight();
  469. LineMetrics lineMetrics = font.getLineMetrics(text,fontRenderContext);
  470. ascent = lineMetrics.getAscent();
  471. height = (int)lineMetrics.getHeight();
  472. renderHints = new RenderingHints(
  473. RenderingHints.KEY_ANTIALIASING,
  474. RenderingHints.VALUE_ANTIALIAS_ON);
  475. renderHints.put(RenderingHints.KEY_FRACTIONALMETRICS,
  476. RenderingHints.VALUE_FRACTIONALMETRICS_ON);
  477. renderHints.put(RenderingHints.KEY_RENDERING,
  478. RenderingHints.VALUE_RENDER_QUALITY);
  479. } //}}}
  480. //{{{ getIconWidth() method
  481. public int getIconWidth()
  482. {
  483. return (int)(rotate == RotatedTextIcon.CW
  484. || rotate == RotatedTextIcon.CCW
  485. ? height : width);
  486. } //}}}
  487. //{{{ getIconHeight() method
  488. public int getIconHeight()
  489. {
  490. return (int)(rotate == RotatedTextIcon.CW
  491. || rotate == RotatedTextIcon.CCW
  492. ? width : height);
  493. } //}}}
  494. //{{{ paintIcon() method
  495. public void paintIcon(Component c, Graphics g, int x, int y)
  496. {
  497. Graphics2D g2d = (Graphics2D)g;
  498. g2d.setFont(font);
  499. AffineTransform oldTransform = g2d.getTransform();
  500. RenderingHints oldHints = g2d.getRenderingHints();
  501. g2d.setRenderingHints(renderHints);
  502. g2d.setColor(c.getForeground());
  503. //{{{ No rotation
  504. if(rotate == RotatedTextIcon.NONE)
  505. {
  506. g2d.drawGlyphVector(glyphs,x + 2,y + ascent);
  507. } //}}}
  508. //{{{ Clockwise rotation
  509. else if(rotate == RotatedTextIcon.CW)
  510. {
  511. AffineTransform trans = new AffineTransform();
  512. trans.concatenate(oldTransform);
  513. trans.translate(x,y + 2);
  514. trans.rotate(Math.PI / 2,
  515. height / 2, width / 2);
  516. g2d.setTransform(trans);
  517. g2d.drawGlyphVector(glyphs,(height - width) / 2,
  518. (width - height) / 2
  519. + ascent);
  520. } //}}}
  521. //{{{ Counterclockwise rotation
  522. else if(rotate == RotatedTextIcon.CCW)
  523. {
  524. AffineTransform trans = new AffineTransform();
  525. trans.concatenate(oldTransform);
  526. trans.translate(x,y - 2);
  527. trans.rotate(Math.PI * 3 / 2,
  528. height / 2, width / 2);
  529. g2d.setTransform(trans);
  530. g2d.drawGlyphVector(glyphs,(height - width) / 2,
  531. (width - height) / 2
  532. + ascent);
  533. } //}}}
  534. g2d.setTransform(oldTransform);
  535. g2d.setRenderingHints(oldHints);
  536. } //}}}
  537. //{{{ Private members
  538. private int rotate;
  539. private Font font;
  540. private String text;
  541. private GlyphVector glyphs;
  542. private float width;
  543. private float height;
  544. private float ascent;
  545. private RenderingHints renderHints;
  546. //}}}
  547. } //}}}
  548. //{{{ ButtonLayout class
  549. class ButtonLayout implements LayoutManager
  550. {
  551. //{{{ addLayoutComponent() method
  552. public void addLayoutComponent(String name, Component comp) {} //}}}
  553. //{{{ removeLayoutComponent() method
  554. public void removeLayoutComponent(Component comp) {} //}}}
  555. //{{{ preferredLayoutSize() method
  556. public Dimension preferredLayoutSize(Container parent)
  557. {
  558. Insets insets = ((JComponent)parent).getBorder()
  559. .getBorderInsets((JComponent)parent);
  560. Component[] comp = parent.getComponents();
  561. if(comp.length == 2)
  562. {
  563. // nothing 'cept close box and popup button
  564. return new Dimension(0,0);
  565. }
  566. else
  567. {
  568. if(position.equals(DockableWindowManager.TOP)
  569. || position.equals(DockableWindowManager.BOTTOM))
  570. {
  571. return new Dimension(0,
  572. comp[2].getPreferredSize().height
  573. + insets.top
  574. + insets.bottom);
  575. }
  576. else
  577. {
  578. return new Dimension(
  579. comp[2].getPreferredSize().width
  580. + insets.left + insets.right,0);
  581. }
  582. }
  583. } //}}}
  584. //{{{ minimumLayoutSize() method
  585. public Dimension minimumLayoutSize(Container parent)
  586. {
  587. return preferredLayoutSize(parent);
  588. } //}}}
  589. //{{{ layoutContainer() method
  590. public void layoutContainer(Container parent)
  591. {
  592. Insets insets = ((JComponent)parent).getBorder()
  593. .getBorderInsets((JComponent)parent);
  594. Component[] comp = parent.getComponents();
  595. if(comp.length != 2)
  596. {
  597. boolean closeBoxSizeSet = false;
  598. boolean noMore = false;
  599. popupButton.setVisible(false);
  600. Dimension parentSize = parent.getSize();
  601. int pos = (position.equals(DockableWindowManager.TOP)
  602. || position.equals(DockableWindowManager.BOTTOM)
  603. ) ? 0 : insets.left;
  604. for(int i = 2; i < comp.length; i++)
  605. {
  606. Dimension size = comp[i].getPreferredSize();
  607. if(position.equals(DockableWindowManager.TOP)
  608. || position.equals(DockableWindowManager.BOTTOM))
  609. {
  610. if(!closeBoxSizeSet)
  611. {
  612. closeBox.setBounds(pos,
  613. insets.top,
  614. size.height,size.height);
  615. pos += size.height;
  616. closeBoxSizeSet = true;
  617. }
  618. if(noMore || pos + size.width > parentSize.width
  619. - (i == comp.length - 1
  620. ? 0 : closeBox.getWidth()))
  621. {
  622. popupButton.setBounds(
  623. parentSize.width - size.height
  624. - insets.right,
  625. insets.top,size.height,
  626. size.height);
  627. popupButton.setVisible(true);
  628. comp[i].setVisible(false);
  629. noMore = true;
  630. }
  631. else
  632. {
  633. comp[i].setBounds(pos,insets.top,
  634. size.width,size.height);
  635. comp[i].setVisible(true);
  636. pos += size.width;
  637. }
  638. }
  639. else
  640. {
  641. if(!closeBoxSizeSet)
  642. {
  643. closeBox.setBounds(insets.left,
  644. insets.top,size.width,size.width);
  645. pos += size.width;
  646. closeBoxSizeSet = true;
  647. }
  648. if(noMore || pos + size.height > parentSize.height
  649. - (i == comp.length - 1
  650. ? 0 : closeBox.getHeight()))
  651. {
  652. popupButton.setBounds(
  653. insets.top,
  654. parentSize.height - size.width,
  655. size.width,size.width);
  656. popupButton.setVisible(true);
  657. comp[i].setVisible(false);
  658. noMore = true;
  659. }
  660. else
  661. {
  662. comp[i].setBounds(insets.left,
  663. pos,size.width,size.height);
  664. comp[i].setVisible(true);
  665. pos += size.height;
  666. }
  667. }
  668. }
  669. }
  670. } //}}}
  671. } //}}}
  672. //{{{ DockablePanel class
  673. class DockablePanel extends JPanel
  674. {
  675. //{{{ DockablePanel constructor
  676. DockablePanel()
  677. {
  678. super(new CardLayout());
  679. ResizeMouseHandler resizeMouseHandler = new ResizeMouseHandler();
  680. addMouseListener(resizeMouseHandler);
  681. addMouseMotionListener(resizeMouseHandler);
  682. } //}}}
  683. //{{{ getWindowContainer() method
  684. PanelWindowContainer getWindowContainer()
  685. {
  686. return PanelWindowContainer.this;
  687. } //}}}
  688. //{{{ showDockable() method
  689. void showDockable(String name)
  690. {
  691. ((CardLayout)getLayout()).show(this,name);
  692. } //}}}
  693. //{{{ getMinimumSize() method
  694. public Dimension getMinimumSize()
  695. {
  696. return new Dimension(0,0);
  697. } //}}}
  698. //{{{ getPreferredSize() method
  699. public Dimension getPreferredSize()
  700. {
  701. if(current == null)
  702. return new Dimension(0,0);
  703. else
  704. {
  705. if(dimension <= 0)
  706. {
  707. int width = super.getPreferredSize().width;
  708. dimension = width - SPLITTER_WIDTH - 3;
  709. }
  710. if(position.equals(DockableWindowManager.TOP)
  711. || position.equals(DockableWindowManager.BOTTOM))
  712. {
  713. return new Dimension(0,
  714. dimension + SPLITTER_WIDTH + 3);
  715. }
  716. else
  717. {
  718. return new Dimension(dimension + SPLITTER_WIDTH + 3,
  719. 0);
  720. }
  721. }
  722. } //}}}
  723. //{{{ ResizeMouseHandler class
  724. class ResizeMouseHandler extends MouseAdapter implements MouseMotionListener
  725. {
  726. boolean canDrag;
  727. int dragStartDimension;
  728. Point dragStart;
  729. //{{{ mousePressed() method
  730. public void mousePressed(MouseEvent evt)
  731. {
  732. dragStartDimension = dimension;
  733. dragStart = evt.getPoint();
  734. } //}}}
  735. //{{{ mouseMoved() method
  736. public void mouseMoved(MouseEvent evt)
  737. {
  738. Border border = getBorder();
  739. if(border == null)
  740. {
  741. // collapsed
  742. return;
  743. }
  744. Insets insets = border.getBorderInsets(DockablePanel.this);
  745. int cursor = Cursor.DEFAULT_CURSOR;
  746. canDrag = false;
  747. //{{{ Top...
  748. if(position.equals(DockableWindowManager.TOP))
  749. {
  750. if(evt.getY() >= getHeight() - insets.bottom)
  751. {
  752. cursor = Cursor.N_RESIZE_CURSOR;
  753. canDrag = true;
  754. }
  755. } //}}}
  756. //{{{ Left...
  757. else if(position.equals(DockableWindowManager.LEFT))
  758. {
  759. if(evt.getX() >= getWidth() - insets.right)
  760. {
  761. cursor = Cursor.W_RESIZE_CURSOR;
  762. canDrag = true;
  763. }
  764. } //}}}
  765. //{{{ Bottom...
  766. else if(position.equals(DockableWindowManager.BOTTOM))
  767. {
  768. if(evt.getY() <= insets.top)
  769. {
  770. cursor = Cursor.S_RESIZE_CURSOR;
  771. canDrag = true;
  772. }
  773. } //}}}
  774. //{{{ Right...
  775. else if(position.equals(DockableWindowManager.RIGHT))
  776. {
  777. if(evt.getX() <= insets.left)
  778. {
  779. cursor = Cursor.E_RESIZE_CURSOR;
  780. canDrag = true;
  781. }
  782. } //}}}
  783. setCursor(Cursor.getPredefinedCursor(cursor));
  784. } //}}}
  785. //{{{ mouseDragged() method
  786. public void mouseDragged(MouseEvent evt)
  787. {
  788. if(!canDrag)
  789. return;
  790. if(dragStart == null) // can't happen?
  791. return;
  792. //{{{ Top...
  793. if(position.equals(DockableWindowManager.TOP))
  794. {
  795. dimension = evt.getY()
  796. + dragStartDimension
  797. - dragStart.y;
  798. } //}}}
  799. //{{{ Left...
  800. else if(position.equals(DockableWindowManager.LEFT))
  801. {
  802. dimension = evt.getX()
  803. + dragStartDimension
  804. - dragStart.x;
  805. } //}}}
  806. //{{{ Bottom...
  807. else if(position.equals(DockableWindowManager.BOTTOM))
  808. {
  809. dimension += (dragStart.y - evt.getY());
  810. } //}}}
  811. //{{{ Right...
  812. else if(position.equals(DockableWindowManager.RIGHT))
  813. {
  814. dimension += (dragStart.x - evt.getX());
  815. } //}}}
  816. if(dimension <= 0)
  817. dimension = dragStartDimension;
  818. wm.invalidate();
  819. wm.validate();
  820. } //}}}
  821. //{{{ mouseExited() method
  822. public void mouseExited(MouseEvent evt)
  823. {
  824. setCursor(Cursor.getPredefinedCursor(
  825. Cursor.DEFAULT_CURSOR));
  826. } //}}}
  827. } //}}}
  828. } //}}}
  829. //}}}
  830. }