PageRenderTime 87ms CodeModel.GetById 39ms app.highlight 38ms RepoModel.GetById 1ms app.codeStats 0ms

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

#
Java | 954 lines | 713 code | 114 blank | 127 comment | 113 complexity | f6f7dba1c1c96b57d1af980b8a940396 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, 2004 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
 23package org.gjt.sp.jedit.gui;
 24
 25//{{{ Imports
 26import java.awt.Color;
 27import java.awt.Component;
 28import java.awt.Container;
 29import java.awt.Dimension;
 30import java.awt.Font;
 31import java.awt.Graphics;
 32import java.awt.Graphics2D;
 33import java.awt.Insets;
 34import java.awt.LayoutManager;
 35import java.awt.RenderingHints;
 36import java.awt.Toolkit;
 37import java.awt.event.ActionEvent;
 38import java.awt.event.ActionListener;
 39import java.awt.event.MouseAdapter;
 40import java.awt.event.MouseEvent;
 41import java.awt.font.FontRenderContext;
 42import java.awt.font.GlyphVector;
 43import java.awt.font.LineMetrics;
 44import java.awt.geom.AffineTransform;
 45import java.util.ArrayList;
 46import java.util.Collections;
 47import java.util.Comparator;
 48import java.util.List;
 49
 50import javax.swing.AbstractButton;
 51import javax.swing.ButtonGroup;
 52import javax.swing.Icon;
 53import javax.swing.JButton;
 54import javax.swing.JComponent;
 55import javax.swing.JPanel;
 56import javax.swing.JPopupMenu;
 57import javax.swing.JToggleButton;
 58import javax.swing.UIManager;
 59import javax.swing.border.Border;
 60import javax.swing.border.EmptyBorder;
 61import javax.swing.plaf.metal.MetalLookAndFeel;
 62
 63import org.gjt.sp.jedit.EditBus;
 64import org.gjt.sp.jedit.GUIUtilities;
 65import org.gjt.sp.jedit.OperatingSystem;
 66import org.gjt.sp.jedit.jEdit;
 67import org.gjt.sp.jedit.gui.DockableWindowManager.DockingArea;
 68import org.gjt.sp.jedit.msg.DockableWindowUpdate;
 69import org.gjt.sp.util.StandardUtilities;
 70//}}}
 71
 72/**
 73 * A container for dockable windows. This class should never be used
 74 * directly.
 75 * @author Slava Pestov
 76 * @version $Id: PanelWindowContainer.java 20108 2011-10-18 12:16:38Z evanpw $
 77 * @since jEdit 4.0pre1
 78 */
 79public class PanelWindowContainer implements DockableWindowContainer, DockingArea
 80{
 81	//{{{ PanelWindowContainer constructor
 82	public PanelWindowContainer(DockableWindowManagerImpl wm, String position,
 83		int dimension)
 84	{
 85		this.wm = wm;
 86		this.position = position;
 87
 88		//{{{ Button box setup
 89		buttonPanel = new JPanel(new ButtonLayout());
 90		buttonPanel.setBorder(new EmptyBorder(1,1,1,1));
 91
 92		closeBox = new JButton(GUIUtilities.loadIcon("closebox.gif"));
 93		closeBox.setRequestFocusEnabled(false);
 94		closeBox.setToolTipText(jEdit.getProperty("view.docking.close-tooltip"));
 95		if(OperatingSystem.isMacOSLF())
 96			closeBox.putClientProperty("JButton.buttonType","toolbar");
 97
 98		closeBox.setMargin(new Insets(0,0,0,0));
 99
100		closeBox.addActionListener(new ActionHandler());
101
102		menuBtn = new JButton(GUIUtilities.loadIcon(jEdit.getProperty("dropdown-arrow.icon")));
103		menuBtn.setRequestFocusEnabled(false);
104		menuBtn.setToolTipText(jEdit.getProperty("view.docking.menu-tooltip"));
105		if(OperatingSystem.isMacOSLF())
106			menuBtn.putClientProperty("JButton.buttonType","toolbar");
107
108		menuBtn.setMargin(new Insets(0,0,0,0));
109
110		menuBtn.addMouseListener(new MenuMouseHandler());
111
112		buttonGroup = new ButtonGroup();
113		// JDK 1.4 workaround
114		buttonGroup.add(nullButton = new JToggleButton());
115		//}}}
116
117		dockables = new ArrayList<DockableWindowManagerImpl.Entry>();
118		buttons = new ArrayList<AbstractButton>();
119		dockablePanel = new DockablePanel(this);
120
121		this.dimension = dimension;
122	} //}}}
123
124	//{{{ getDockableWindowManager() method
125	/**
126	 * @since jEdit 4.3pre2
127	 */
128	public DockableWindowManagerImpl getDockableWindowManager()
129	{
130		return wm;
131	} //}}}
132	
133	//{{{ register() method
134	public void register(DockableWindowManagerImpl.Entry entry)
135	{
136		dockables.add(entry);
137
138		//{{{ Create button
139		int rotation;
140		if(position.equals(DockableWindowManagerImpl.TOP)
141			|| position.equals(DockableWindowManagerImpl.BOTTOM))
142			rotation = RotatedTextIcon.NONE;
143		else if(position.equals(DockableWindowManagerImpl.LEFT))
144			rotation = RotatedTextIcon.CCW;
145		else if(position.equals(DockableWindowManagerImpl.RIGHT))
146			rotation = RotatedTextIcon.CW;
147		else
148			throw new InternalError("Invalid position: " + position);
149
150		JToggleButton button = new JToggleButton();
151		button.setMargin(new Insets(1,1,1,1));
152		button.setRequestFocusEnabled(false);
153		button.setIcon(new RotatedTextIcon(rotation,button.getFont(),
154			entry.shortTitle()));
155		button.setActionCommand(entry.factory.name);
156		button.addActionListener(new ActionHandler());
157		button.addMouseListener(new MenuMouseHandler());
158		if(OperatingSystem.isMacOSLF())
159			button.putClientProperty("JButton.buttonType","toolbar");
160		//}}}
161
162		buttonGroup.add(button);
163		buttons.add(button);
164		entry.btn = button;
165
166		wm.revalidate();
167	} //}}}
168
169	//{{{ unregister() method
170	public void unregister(DockableWindowManagerImpl.Entry entry)
171	{
172		if(entry.factory.name.equals(mostRecent))
173			mostRecent = null;
174
175		if(entry.btn != null)
176		{
177			buttonPanel.remove(entry.btn);
178			buttons.remove(entry.btn);
179			entry.btn = null;
180		}
181
182		dockables.remove(entry);
183		if(entry.win != null)
184			dockablePanel.remove(entry.win);
185
186		if(current == entry)
187		{
188			current = null;
189			show(current);
190		}
191		else
192		{
193			wm.revalidate();
194			dockablePanel.repaint();
195			buttonPanel.repaint();
196		}
197	} //}}}
198
199	//{{{ remove() method
200	public void remove(DockableWindowManagerImpl.Entry entry)
201	{
202		if(entry.factory.name.equals(mostRecent))
203			mostRecent = null;
204
205		if(entry.win != null)
206		{
207			dockablePanel.remove(entry.win);
208			entry.win = null;
209		}
210
211		if(current == entry)
212		{
213			current = null;
214			show(current);
215		}
216		else
217		{
218			wm.revalidate();
219			dockablePanel.repaint();
220		}
221	} //}}}
222
223	//{{{ showMostRecent() method
224	public void showMostRecent()
225	{
226		if(dockables.isEmpty())
227		{
228			Toolkit.getDefaultToolkit().beep();
229			return;
230		}
231
232		if(mostRecent == null)
233		{
234			mostRecent = dockables.get(0).factory.name;
235		}
236
237		wm.showDockableWindow(mostRecent);
238	} //}}}
239
240	//{{{ show() method
241	public void show(DockableWindowManagerImpl.Entry entry)
242	{
243		if(current == entry)
244		{
245			if(entry != null)
246			{
247				if(entry.win instanceof DefaultFocusComponent)
248				{
249					((DefaultFocusComponent)entry.win)
250						.focusOnDefaultComponent();
251				}
252				else
253				{
254					entry.win.requestDefaultFocus();
255				}
256			}
257			return;
258		}
259
260		if(entry != null)
261		{
262			if(current == null)
263			{
264				// we didn't have a component previously, so
265				// create a border
266				dockablePanel.setBorder(new DockBorder(position));
267			}
268
269			mostRecent = entry.factory.name;
270			this.current = entry;
271
272			if(entry.win.getParent() != dockablePanel)
273				dockablePanel.add(entry.factory.name,entry.win);
274
275			dockablePanel.showDockable(entry.factory.name);
276
277			entry.btn.setSelected(true);
278
279			if(entry.win instanceof DefaultFocusComponent)
280			{
281				((DefaultFocusComponent)entry.win)
282					.focusOnDefaultComponent();
283			}
284			else
285			{
286				entry.win.requestDefaultFocus();
287			}
288		}
289		else
290		{
291			if (current != null)
292			{
293				
294				Object reason = DockableWindowUpdate.DEACTIVATED;
295				EditBus.send(new DockableWindowUpdate(wm, reason, current.factory.name));
296			}
297			current = null;
298			nullButton.setSelected(true);
299			// removing last component, so remove border
300			dockablePanel.setBorder(null);
301
302			wm.getView().getTextArea().requestFocus();
303		}
304
305		wm.revalidate();
306		dockablePanel.repaint();
307	} //}}}
308
309	//{{{ isVisible() method
310	public boolean isVisible(DockableWindowManagerImpl.Entry entry)
311	{
312		return current == entry;
313	} //}}}
314
315	//{{{ getCurrent() method
316	/**
317	 * Returns the name of the dockable in this container.
318	 * @since jEdit 4.2pre1
319	 */
320	public String getCurrent()
321	{
322		if(current == null)
323			return null;
324		else
325			return current.factory.name;
326	} //}}}
327
328	//{{{ getDimension() method
329	/**
330	 * Returns the width or height (depending on position) of the dockable
331	 * window container.
332	 * @since jEdit 4.2pre1
333	 */
334	public int getDimension()
335	{
336		return dimension;
337	} //}}}
338
339	//{{{ getPosition() method
340	/**
341	 * @since jEdit 4.3pre2
342	 */
343	public String getPosition()
344	{
345		return position;
346	} //}}}
347
348	//{{{ getDockables() method
349	public String[] getDockables()
350	{
351		String[] retVal = new String[dockables.size()];
352		for(int i = 0; i < dockables.size(); i++)
353		{
354			DockableWindowManagerImpl.Entry entry = dockables.get(i);
355			retVal[i] = entry.factory.name;
356		}
357		return retVal;
358	} //}}}
359
360	//{{{ Package-private members
361	static final int SPLITTER_WIDTH = 10;
362	DockablePanel dockablePanel;
363	JPanel buttonPanel;
364
365	//{{{ save() method
366	void save()
367	{
368		jEdit.setIntegerProperty("view.dock." + position + ".dimension",
369			dimension);
370		if(current == null)
371			jEdit.unsetProperty("view.dock." + position + ".last");
372		else
373		{
374			jEdit.setProperty("view.dock." + position + ".last",
375				current.factory.name);
376		}
377	} //}}}
378
379	//{{{ setDimension() method
380	void setDimension(int dimension)
381	{
382		if(dimension > SPLITTER_WIDTH)
383			this.dimension = dimension - SPLITTER_WIDTH;
384	} //}}}
385
386	//{{{ sortDockables() method
387	void sortDockables()
388	{
389		buttonPanel.removeAll();
390		buttonPanel.add(closeBox);
391		buttonPanel.add(menuBtn);
392		Collections.sort(buttons,new DockableWindowCompare());
393		for(int i = 0; i < buttons.size(); i++)
394		{
395			buttonPanel.add(buttons.get(i));
396		}
397	} //}}}
398
399	//{{{ getWrappedDimension() method
400	/**
401	 * Returns the width or height of wrapped rows or columns.
402	 */
403	int getWrappedDimension(int dimension)
404	{
405		return ((ButtonLayout)buttonPanel.getLayout())
406			.getWrappedDimension(buttonPanel,dimension);
407	} //}}}
408
409	//}}}
410
411	//{{{ Private members
412	private final DockableWindowManagerImpl wm;
413	private final String position;
414	private final JButton closeBox;
415	private final JButton menuBtn;
416	private final ButtonGroup buttonGroup;
417	private final JToggleButton nullButton;
418	private int dimension;
419	private final List<DockableWindowManagerImpl.Entry> dockables;
420	private final List<AbstractButton> buttons;
421	private DockableWindowManagerImpl.Entry current;
422	private JPopupMenu popup;
423
424	// remember the most recent dockable
425	private String mostRecent;
426	//}}}
427
428	//{{{ Inner classes
429
430	//{{{ DockableWindowCompare class
431	static class DockableWindowCompare implements Comparator<AbstractButton>
432	{
433		public int compare(AbstractButton o1, AbstractButton o2)
434		{
435			String name1 = o1.getActionCommand();
436			String name2 = o2.getActionCommand();
437			return StandardUtilities.compareStrings(
438				jEdit.getProperty(name1 + ".title",""),
439				jEdit.getProperty(name2 + ".title",""),
440				true);
441		}
442	} //}}}
443
444	//{{{ ActionHandler class
445	class ActionHandler implements ActionListener
446	{
447		public void actionPerformed(ActionEvent evt)
448		{
449			if(popup != null && popup.isVisible())
450				popup.setVisible(false);
451
452			if(evt.getSource() == closeBox)
453				show((DockableWindowManagerImpl.Entry)null);
454			else
455			{
456				if(wm.isDockableWindowVisible(evt.getActionCommand()))
457					show((DockableWindowManagerImpl.Entry)null);
458				else
459					wm.showDockableWindow(evt.getActionCommand());
460			}
461		}
462	} //}}}
463
464	//{{{ MenuMouseHandler class
465	class MenuMouseHandler extends MouseAdapter
466	{
467		public void mousePressed(MouseEvent evt)
468		{
469			if(popup != null && popup.isVisible())
470			{
471				popup.setVisible(false);
472				return;
473			}
474
475			Component comp = (Component)evt.getSource();
476			String dockable;
477			if(comp instanceof JToggleButton)
478				dockable = ((JToggleButton)comp).getActionCommand();
479			else
480				dockable = getCurrent();
481
482			if(comp == menuBtn || GUIUtilities.isPopupTrigger(evt))
483			{
484				if(dockable == null)
485				{
486					popup = wm.createPopupMenu(PanelWindowContainer.this,null,false);
487				}
488				else
489				{
490					popup = wm.createPopupMenu(PanelWindowContainer.this,dockable,false);
491				}
492
493				int x, y;
494				boolean point;
495				if(comp == menuBtn)
496				{
497					x = 0;
498					y = menuBtn.getHeight();
499					point = false;
500				}
501				else
502				{
503					x = evt.getX();
504					y = evt.getY();
505					point = true;
506				}
507				GUIUtilities.showPopupMenu(popup,
508					comp,x,y,point);
509			}
510		}
511	} //}}}
512
513	//{{{ DockBorder class
514	static class DockBorder implements Border
515	{
516		String position;
517		Insets insets;
518		Color color1;
519		Color color2;
520		Color color3;
521
522		//{{{ DockBorder constructor
523		DockBorder(String position)
524		{
525			this.position = position;
526			insets = new Insets(
527				position.equals(DockableWindowManagerImpl.BOTTOM)
528					? SPLITTER_WIDTH : 0,
529				position.equals(DockableWindowManagerImpl.RIGHT)
530					? SPLITTER_WIDTH : 0,
531				position.equals(DockableWindowManagerImpl.TOP)
532					? SPLITTER_WIDTH : 0,
533				position.equals(DockableWindowManagerImpl.LEFT)
534					? SPLITTER_WIDTH : 0);
535		} //}}}
536
537		//{{{ paintBorder() method
538		public void paintBorder(Component c, Graphics g,
539			int x, int y, int width, int height)
540		{
541			updateColors();
542
543			if(color1 == null || color2 == null || color3 == null)
544				return;
545
546			if(position.equals(DockableWindowManagerImpl.BOTTOM))
547				paintHorizBorder(g,x,y,width);
548			else if(position.equals(DockableWindowManagerImpl.RIGHT))
549				paintVertBorder(g,x,y,height);
550			else if(position.equals(DockableWindowManagerImpl.TOP))
551			{
552				paintHorizBorder(g,x,y + height
553					- SPLITTER_WIDTH,width);
554			}
555			else if(position.equals(DockableWindowManagerImpl.LEFT))
556			{
557				paintVertBorder(g,x + width
558					- SPLITTER_WIDTH,y,height);
559			}
560		} //}}}
561
562		//{{{ getBorderInsets() method
563		public Insets getBorderInsets(Component c)
564		{
565			return insets;
566		} //}}}
567
568		//{{{ isBorderOpaque() method
569		public boolean isBorderOpaque()
570		{
571			return false;
572		} //}}}
573
574		//{{{ paintHorizBorder() method
575		private void paintHorizBorder(Graphics g, int x, int y, int width)
576		{
577			g.setColor(color3);
578			g.fillRect(x,y,width,SPLITTER_WIDTH);
579
580			for(int i = 0; i < width / 4 - 1; i++)
581			{
582				g.setColor(color1);
583				g.drawLine(x + (i << 2) + 2,y + 3,
584					x + (i << 2) + 2,y + 3);
585				g.setColor(color2);
586				g.drawLine(x + (i << 2) + 3,y + 4,
587					x + (i << 2) + 3,y + 4);
588				g.setColor(color1);
589				g.drawLine(x + (i << 2) + 4,y + 5,
590					x + (i << 2) + 4,y + 5);
591				g.setColor(color2);
592				g.drawLine(x + (i << 2) + 5,y + 6,
593					x + (i << 2) + 5,y + 6);
594			}
595		} //}}}
596
597		//{{{ paintVertBorder() method
598		private void paintVertBorder(Graphics g, int x, int y, int height)
599		{
600			g.setColor(color3);
601			g.fillRect(x,y,SPLITTER_WIDTH,height);
602
603			for(int i = 0; i < height / 4 - 1; i++)
604			{
605				g.setColor(color1);
606				g.drawLine(x + 3,y + (i << 2) + 2,
607					x + 3,y + (i << 2) + 2);
608				g.setColor(color2);
609				g.drawLine(x + 4,y + (i << 2) + 3,
610					x + 4,y + (i << 2) + 3);
611				g.setColor(color1);
612				g.drawLine(x + 5,y + (i << 2) + 4,
613					x + 5,y + (i << 2) + 4);
614				g.setColor(color2);
615				g.drawLine(x + 6,y + (i << 2) + 5,
616					x + 6,y + (i << 2) + 5);
617			}
618		} //}}}
619
620		//{{{ updateColors() method
621		private void updateColors()
622		{
623			if(UIManager.getLookAndFeel() instanceof MetalLookAndFeel)
624			{
625				color1 = MetalLookAndFeel.getControlHighlight();
626				color2 = MetalLookAndFeel.getControlDarkShadow();
627				color3 = MetalLookAndFeel.getControl();
628			}
629			else
630			{
631				color1 = color2 = color3 = null;
632			}
633		} //}}}
634	} //}}}
635
636	//{{{ RotatedTextIcon class
637	public static class RotatedTextIcon implements Icon
638	{
639		public static final int NONE = 0;
640		public static final int CW = 1;
641		public static final int CCW = 2;
642
643		//{{{ RotatedTextIcon constructor
644		public RotatedTextIcon(int rotate, Font font, String text)
645		{
646			this.rotate = rotate;
647			this.font = font;
648
649			FontRenderContext fontRenderContext
650				= new FontRenderContext(null,true,false);
651			glyphs = font.createGlyphVector(fontRenderContext,text);
652			width = (int)glyphs.getLogicalBounds().getWidth() + 4;
653			//height = (int)glyphs.getLogicalBounds().getHeight();
654
655			LineMetrics lineMetrics = font.getLineMetrics(text,fontRenderContext);
656			ascent = lineMetrics.getAscent();
657			height = (int)lineMetrics.getHeight();
658
659			renderHints = new RenderingHints(
660				RenderingHints.KEY_ANTIALIASING,
661				RenderingHints.VALUE_ANTIALIAS_ON);
662			renderHints.put(RenderingHints.KEY_FRACTIONALMETRICS,
663				RenderingHints.VALUE_FRACTIONALMETRICS_ON);
664			renderHints.put(RenderingHints.KEY_RENDERING,
665				RenderingHints.VALUE_RENDER_QUALITY);
666		} //}}}
667
668		//{{{ getIconWidth() method
669		public int getIconWidth()
670		{
671			return (int)(rotate == RotatedTextIcon.CW
672				|| rotate == RotatedTextIcon.CCW
673				? height : width);
674		} //}}}
675
676		//{{{ getIconHeight() method
677		public int getIconHeight()
678		{
679			return (int)(rotate == RotatedTextIcon.CW
680				|| rotate == RotatedTextIcon.CCW
681				? width : height);
682		} //}}}
683
684		//{{{ paintIcon() method
685		public void paintIcon(Component c, Graphics g, int x, int y)
686		{
687			Graphics2D g2d = (Graphics2D)g;
688			g2d.setFont(font);
689			AffineTransform oldTransform = g2d.getTransform();
690			RenderingHints oldHints = g2d.getRenderingHints();
691
692			g2d.setRenderingHints(renderHints);
693			g2d.setColor(c.getForeground());
694
695			//{{{ No rotation
696			if(rotate == RotatedTextIcon.NONE)
697			{
698				g2d.drawGlyphVector(glyphs,x + 2,y + ascent);
699			} //}}}
700			//{{{ Clockwise rotation
701			else if(rotate == RotatedTextIcon.CW)
702			{
703				AffineTransform trans = new AffineTransform();
704				trans.concatenate(oldTransform);
705				trans.translate(x,y + 2);
706				trans.rotate(Math.PI / 2,
707					height / 2, width / 2);
708				g2d.setTransform(trans);
709				g2d.drawGlyphVector(glyphs,(height - width) / 2,
710					(width - height) / 2
711					+ ascent);
712			} //}}}
713			//{{{ Counterclockwise rotation
714			else if(rotate == RotatedTextIcon.CCW)
715			{
716				AffineTransform trans = new AffineTransform();
717				trans.concatenate(oldTransform);
718				trans.translate(x,y - 2);
719				trans.rotate(Math.PI * 3 / 2,
720					height / 2, width / 2);
721				g2d.setTransform(trans);
722				g2d.drawGlyphVector(glyphs,(height - width) / 2,
723					(width - height) / 2
724					+ ascent);
725			} //}}}
726
727			g2d.setTransform(oldTransform);
728			g2d.setRenderingHints(oldHints);
729		} //}}}
730
731		//{{{ Private members
732		private final int rotate;
733		private final Font font;
734		private final GlyphVector glyphs;
735		private final float width;
736		private final float height;
737		private final float ascent;
738		private final RenderingHints renderHints;
739		//}}}
740	} //}}}
741
742	//{{{ ButtonLayout class
743	class ButtonLayout implements LayoutManager
744	{
745		//{{{ addLayoutComponent() method
746		public void addLayoutComponent(String name, Component comp) {} //}}}
747
748		//{{{ removeLayoutComponent() method
749		public void removeLayoutComponent(Component comp) {} //}}}
750
751		//{{{ getWrappedDimension() method
752		/**
753		 * Returns the width or height of wrapped rows or columns.
754		 */
755		int getWrappedDimension(JComponent parent, int dimension)
756		{
757			Insets insets = parent.getBorder()
758				.getBorderInsets(parent);
759
760			Component[] comp = parent.getComponents();
761			if(comp.length <= 2)
762				return 0;
763
764			Dimension dim = comp[2].getPreferredSize();
765
766			if(position.equals(DockableWindowManagerImpl.TOP)
767				|| position.equals(DockableWindowManagerImpl.BOTTOM))
768			{
769				int width = dimension - insets.right;
770				Dimension returnValue = preferredLayoutSizeLR(insets, comp, dim, width);
771				return returnValue.height;
772			}
773			else
774			{
775				Dimension returnValue = preferredLayoutSizeTB(dimension, insets, comp, dim);
776				return returnValue.width;
777			}
778		} //}}}
779
780		//{{{ preferredLayoutSize() method
781		public Dimension preferredLayoutSize(Container parent)
782		{
783			Insets insets = ((JComponent)parent).getBorder()
784				.getBorderInsets(parent);
785
786			Component[] comp = parent.getComponents();
787			if(comp.length <= 2)
788			{
789				// nothing 'cept close box
790				return new Dimension(0,0);
791			}
792
793			Dimension dim = comp[2].getPreferredSize();
794
795			if(position.equals(DockableWindowManagerImpl.TOP)
796				|| position.equals(DockableWindowManagerImpl.BOTTOM))
797			{
798				int width = parent.getWidth() - insets.right;
799				Dimension returnValue = preferredLayoutSizeLR(insets, comp, dim, width);
800				return returnValue;
801			}
802			else
803			{
804				Dimension returnValue = preferredLayoutSizeTB(parent.getHeight(), insets, comp, dim);
805				return returnValue;
806			}
807		} //}}}
808
809		//{{{ minimumLayoutSize() method
810		public Dimension minimumLayoutSize(Container parent)
811		{
812			return preferredLayoutSize(parent);
813		} //}}}
814
815		//{{{ layoutContainer() method
816		public void layoutContainer(Container parent)
817		{
818			Insets insets = ((JComponent)parent).getBorder()
819				.getBorderInsets(parent);
820
821			Component[] comp = parent.getComponents();
822			if(comp.length <= 2)
823			{
824				for(int i = 0; i < comp.length; i++)
825				{
826					comp[i].setVisible(false);
827				}
828				return;
829			}
830
831			comp[0].setVisible(true);
832			comp[1].setVisible(true);
833
834			Dimension dim = comp[2].getPreferredSize();
835
836			if(position.equals(DockableWindowManagerImpl.TOP)
837				|| position.equals(DockableWindowManagerImpl.BOTTOM))
838			{
839				int width = parent.getWidth() - insets.right;
840				int rowHeight = Math.max(dim.height,closeBox.getPreferredSize().width);
841				int x = (rowHeight << 1) + insets.left;
842				int y = insets.top;
843				closeBox.setBounds(insets.left,insets.top,rowHeight,rowHeight);
844				menuBtn.setBounds(insets.left + rowHeight,insets.top,rowHeight,rowHeight);
845
846				for(int i = 2; i < comp.length; i++)
847				{
848					int btnWidth = comp[i].getPreferredSize().width;
849					if(btnWidth + x > width)
850					{
851						x = insets.left;
852						y += rowHeight;
853					}
854					comp[i].setBounds(x,y,btnWidth,rowHeight);
855					x += btnWidth;
856				}
857
858				/* if(y + rowHeight != parent.getHeight())
859				{
860					parent.setSize(
861						parent.getWidth(),
862						y + rowHeight);
863					((JComponent)parent).revalidate();
864				} */
865			}
866			else
867			{
868				int height = parent.getHeight() - insets.bottom;
869				int colWidth = Math.max(dim.width,closeBox.getPreferredSize().height);
870				int x = insets.left;
871				int y = (colWidth << 1) + insets.top;
872				closeBox.setBounds(insets.left,insets.top,colWidth,colWidth);
873				menuBtn.setBounds(insets.left,insets.top + colWidth,colWidth,colWidth);
874
875				for(int i = 2; i < comp.length; i++)
876				{
877					int btnHeight = comp[i].getPreferredSize().height;
878					if(btnHeight + y > height)
879					{
880						x += colWidth;
881						y = insets.top;
882					}
883					comp[i].setBounds(x,y,colWidth,btnHeight);
884					y += btnHeight;
885				}
886
887				/* if(x + colWidth != parent.getWidth())
888				{
889					parent.setSize(x + colWidth,
890						parent.getHeight());
891					((JComponent)parent).revalidate();
892				} */
893			}
894		} //}}}
895
896		//{{{ preferredLayoutSizeLR() method
897		private Dimension preferredLayoutSizeLR(Insets insets, Component[] comp, Dimension dim, int width)
898		{
899			int rowHeight = Math.max(dim.height,closeBox.getPreferredSize().width);
900			int x = (rowHeight << 1) + insets.left;
901			Dimension returnValue = new Dimension(0,rowHeight
902				+ insets.top + insets.bottom);
903
904			for(int i = 2; i < comp.length; i++)
905			{
906				int btnWidth = comp[i].getPreferredSize().width;
907				if(btnWidth + x > width)
908				{
909					returnValue.height += rowHeight;
910					x = insets.left;
911				}
912
913				x += btnWidth;
914			}
915			return returnValue;
916		} //}}}
917
918		//{{{ preferredLayoutSizeTB() method
919		private Dimension preferredLayoutSizeTB(int dimension, Insets insets, Component[] comp, Dimension dim)
920		{
921			int height = dimension - insets.bottom;
922			int colWidth = Math.max(dim.width,closeBox.getPreferredSize().height);
923			int y = (colWidth << 1) + insets.top;
924			Dimension returnValue = new Dimension(colWidth
925				+ insets.left + insets.right,0);
926
927			for(int i = 2; i < comp.length; i++)
928			{
929				int btnHeight = comp[i].getPreferredSize().height;
930				if(btnHeight + y > height)
931				{
932					returnValue.width += colWidth;
933					y = insets.top;
934				}
935
936				y += btnHeight;
937			}
938			return returnValue;
939		} //}}}
940	} //}}}
941
942	public void show(String name)
943	{
944		DockableWindowManagerImpl.Entry entry = null;
945		if (name != null)
946		{
947			wm.showDockableWindow(name);
948			wm.hideDockableWindow(name);
949		}
950		show(entry);
951	}
952
953	//}}}
954}