PageRenderTime 94ms CodeModel.GetById 44ms app.highlight 44ms RepoModel.GetById 1ms app.codeStats 0ms

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

#
Java | 1111 lines | 760 code | 144 blank | 207 comment | 117 complexity | 903f0519d201faf93cbab3e8e99d7eb5 MD5 | raw file
   1/*
   2 * DockableWindowManager.java - manages dockable windows
   3 * :tabSize=8:indentSize=8:noTabs=false:
   4 * :folding=explicit:collapseFolds=1:
   5 *
   6 * Copyright (C) 2000, 2001 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 bsh.EvalError;
  27import com.microstar.xml.*;
  28import org.gjt.sp.jedit.browser.VFSBrowser;
  29import org.gjt.sp.jedit.msg.CreateDockableWindow;
  30import org.gjt.sp.jedit.search.HyperSearchResults;
  31import org.gjt.sp.jedit.*;
  32import org.gjt.sp.util.Log;
  33import javax.swing.*;
  34import java.awt.event.*;
  35import java.awt.*;
  36import java.io.*;
  37import java.util.*;
  38//}}}
  39
  40/**
  41 * Manages dockable windows.
  42 * @author Slava Pestov
  43 * @version $Id: DockableWindowManager.java 4012 2002-02-05 06:28:10Z spestov $
  44 * @since jEdit 2.6pre3
  45 */
  46public class DockableWindowManager extends JPanel
  47{
  48	//{{{ Static part of class
  49
  50	//{{{ Constants
  51	/**
  52	 * Floating position.
  53	 * @since jEdit 2.6pre3
  54	 */
  55	public static final String FLOATING = "floating";
  56
  57	/**
  58	 * Top position.
  59	 * @since jEdit 2.6pre3
  60	 */
  61	public static final String TOP = "top";
  62
  63	/**
  64	 * Left position.
  65	 * @since jEdit 2.6pre3
  66	 */
  67	public static final String LEFT = "left";
  68
  69	/**
  70	 * Bottom position.
  71	 * @since jEdit 2.6pre3
  72	 */
  73	public static final String BOTTOM = "bottom";
  74
  75	/**
  76	 * Right position.
  77	 * @since jEdit 2.6pre3
  78	 */
  79	public static final String RIGHT = "right";
  80	//}}}
  81
  82	//{{{ loadDockableWindows() method
  83	/**
  84	 * Plugins shouldn't need to call this method.
  85	 * @since jEdit 4.0pre1
  86	 */
  87	public static boolean loadDockableWindows(String path, Reader in, ActionSet actionSet)
  88	{
  89		try
  90		{
  91			Log.log(Log.DEBUG,jEdit.class,"Loading dockables from " + path);
  92
  93			DockableListHandler dh = new DockableListHandler(path,actionSet);
  94			XmlParser parser = new XmlParser();
  95			parser.setHandler(dh);
  96			parser.parse(null, null, in);
  97			return true;
  98		}
  99		catch(XmlException xe)
 100		{
 101			int line = xe.getLine();
 102			String message = xe.getMessage();
 103			Log.log(Log.ERROR,jEdit.class,path + ":" + line
 104				+ ": " + message);
 105		}
 106		catch(Exception e)
 107		{
 108			Log.log(Log.ERROR,jEdit.class,e);
 109		}
 110
 111		return false;
 112	} //}}}
 113
 114	//{{{ registerDockableWindow() method
 115	public static void registerDockableWindow(String name, String code,
 116		boolean actions, ActionSet actionSet)
 117	{
 118		dockableWindowFactories.addElement(new Factory(name,code,
 119			actions,actionSet));
 120	} //}}}
 121
 122	//{{{ getRegisteredDockableWindows() method
 123	public static String[] getRegisteredDockableWindows()
 124	{
 125		String[] retVal = new String[dockableWindowFactories.size()];
 126		for(int i = 0; i < dockableWindowFactories.size(); i++)
 127		{
 128			retVal[i] = ((Factory)dockableWindowFactories.elementAt(i)).name;
 129		}
 130		return retVal;
 131	} //}}}
 132
 133	//{{{ DockableListHandler class
 134	static class DockableListHandler extends HandlerBase
 135	{
 136		//{{{ DockableListHandler constructor
 137		DockableListHandler(String path, ActionSet actionSet)
 138		{
 139			this.path = path;
 140			this.actionSet = actionSet;
 141			stateStack = new Stack();
 142			actions = true;
 143		} //}}}
 144
 145		//{{{ resolveEntity() method
 146		public Object resolveEntity(String publicId, String systemId)
 147		{
 148			if("dockables.dtd".equals(systemId))
 149			{
 150				try
 151				{
 152					return new BufferedReader(new InputStreamReader(
 153						getClass().getResourceAsStream
 154						("/org/gjt/sp/jedit/dockables.dtd")));
 155				}
 156				catch(Exception e)
 157				{
 158					Log.log(Log.ERROR,this,"Error while opening"
 159						+ " dockables.dtd:");
 160					Log.log(Log.ERROR,this,e);
 161				}
 162			}
 163
 164			return null;
 165		} //}}}
 166
 167		//{{{ attribute() method
 168		public void attribute(String aname, String value, boolean isSpecified)
 169		{
 170			aname = (aname == null) ? null : aname.intern();
 171			value = (value == null) ? null : value.intern();
 172
 173			if(aname == "NAME")
 174				dockableName = value;
 175			else if(aname == "NO_ACTIONS")
 176				actions = (value == "FALSE");
 177		} //}}}
 178
 179		//{{{ doctypeDecl() method
 180		public void doctypeDecl(String name, String publicId,
 181			String systemId) throws Exception
 182		{
 183			if("DOCKABLES".equals(name))
 184				return;
 185
 186			Log.log(Log.ERROR,this,path + ": DOCTYPE must be DOCKABLES");
 187		} //}}}
 188
 189		//{{{ charData() method
 190		public void charData(char[] c, int off, int len)
 191		{
 192			String tag = peekElement();
 193			String text = new String(c, off, len);
 194
 195			if (tag == "DOCKABLE")
 196			{
 197				code = text;
 198			}
 199		} //}}}
 200
 201		//{{{ startElement() method
 202		public void startElement(String tag)
 203		{
 204			tag = pushElement(tag);
 205		} //}}}
 206
 207		//{{{ endElement() method
 208		public void endElement(String name)
 209		{
 210			if(name == null)
 211				return;
 212
 213			String tag = peekElement();
 214
 215			if(name.equals(tag))
 216			{
 217				if(tag == "DOCKABLE")
 218				{
 219					registerDockableWindow(dockableName,
 220						code,actions,actionSet);
 221					// make default be true for the next
 222					// action
 223					actions = true;
 224				}
 225
 226				popElement();
 227			}
 228			else
 229			{
 230				// can't happen
 231				throw new InternalError();
 232			}
 233		} //}}}
 234
 235		//{{{ startDocument() method
 236		public void startDocument()
 237		{
 238			try
 239			{
 240				pushElement(null);
 241			}
 242			catch (Exception e)
 243			{
 244				e.printStackTrace();
 245			}
 246		} //}}}
 247
 248		//{{{ Private members
 249
 250		//{{{ Instance variables
 251		private String path;
 252		private ActionSet actionSet;
 253
 254		private String dockableName;
 255		private String code;
 256		private boolean actions;
 257
 258		private Stack stateStack;
 259		//}}}
 260
 261		//{{{ pushElement() method
 262		private String pushElement(String name)
 263		{
 264			name = (name == null) ? null : name.intern();
 265
 266			stateStack.push(name);
 267
 268			return name;
 269		} //}}}
 270
 271		//{{{ peekElement() method
 272		private String peekElement()
 273		{
 274			return (String) stateStack.peek();
 275		} //}}}
 276
 277		//{{{ popElement() method
 278		private String popElement()
 279		{
 280			return (String) stateStack.pop();
 281		} //}}}
 282
 283		//}}}
 284	} //}}}
 285
 286	//{{{ Factory class
 287	static class Factory
 288	{
 289		String name;
 290		String code;
 291
 292		//{{{ Factory constructor
 293		Factory(String name, String code, boolean actions, ActionSet actionSet)
 294		{
 295			this.name = name;
 296			this.code = code;
 297			if(actions)
 298			{
 299				actionSet.addAction(new OpenAction());
 300				actionSet.addAction(new ToggleAction());
 301			}
 302		} //}}}
 303
 304		//{{{ createDockableWindow() method
 305		JComponent createDockableWindow(View view, String position)
 306		{
 307			// BACKWARDS COMPATIBILITY with jEdit 2.6-3.2 docking APIs
 308			if(code == null)
 309			{
 310				CreateDockableWindow msg = new CreateDockableWindow(view,name,
 311					position);
 312				EditBus.send(msg);
 313
 314				DockableWindow win = msg.getDockableWindow();
 315				if(win == null)
 316				{
 317					Log.log(Log.ERROR,this,"Unknown dockable window: " + name);
 318					return null;
 319				}
 320				return (JComponent)win.getComponent();
 321			}
 322			// END BACKWARDS COMPATIBILITY
 323			else
 324			{
 325				try
 326				{
 327					BeanShell.getNameSpace().setVariable(
 328						"position",position);
 329				}
 330				catch(EvalError e)
 331				{
 332					Log.log(Log.ERROR,this,e);
 333				}
 334				JComponent win = (JComponent)
 335					BeanShell.eval(view,
 336					code,false);
 337				return win;
 338			}
 339		} //}}}
 340
 341		//{{{ OpenAction class
 342		class OpenAction extends EditAction
 343		{
 344			//{{{ OpenAction constructor
 345			OpenAction()
 346			{
 347				super(name);
 348			} //}}}
 349
 350			//{{{ invoke() method
 351			public void invoke(View view)
 352			{
 353				view.getDockableWindowManager()
 354					.showDockableWindow(name);
 355			} //}}}
 356
 357			//{{{ getCode() method
 358			public String getCode()
 359			{
 360				return "view.getDockableWindowManager()"
 361					+ ".showDockableWindow(\"" + name + "\");";
 362			} //}}}
 363		} //}}}
 364
 365		//{{{ ToggleAction class
 366		class ToggleAction extends EditAction
 367		{
 368			//{{{ ToggleAction constructor
 369			ToggleAction()
 370			{
 371				super(name + "-toggle");
 372			} //}}}
 373
 374			//{{{ invoke() method
 375			public void invoke(View view)
 376			{
 377				view.getDockableWindowManager()
 378					.toggleDockableWindow(name);
 379			} //}}}
 380
 381			//{{{ isToggle() method
 382			public boolean isToggle()
 383			{
 384				return true;
 385			} //}}}
 386
 387			//{{{ isSelected() method
 388			public boolean isSelected(View view)
 389			{
 390				return view.getDockableWindowManager()
 391					.isDockableWindowVisible(name);
 392			} //}}}
 393
 394			//{{{ getCode() method
 395			public String getCode()
 396			{
 397				return "view.getDockableWindowManager()"
 398					+ ".toggleDockableWindow(\"" + name + "\");";
 399			} //}}}
 400		} //}}}
 401	} //}}}
 402
 403	private static Vector dockableWindowFactories;
 404
 405	//{{{ Static initializer
 406	static
 407	{
 408		dockableWindowFactories = new Vector();
 409	} //}}}
 410
 411	//}}}
 412
 413	//{{{ Instance part of class
 414
 415	//{{{ DockableWindowManager constructor
 416	/**
 417	 * Creates a new dockable window manager.
 418	 * @param view The view
 419	 * @since jEdit 2.6pre3
 420	 */
 421	public DockableWindowManager(View view)
 422	{
 423		setLayout(new DockableLayout());
 424		this.view = view;
 425		windows = new Hashtable();
 426
 427		top = new PanelWindowContainer(this,TOP);
 428		left = new PanelWindowContainer(this,LEFT);
 429		bottom = new PanelWindowContainer(this,BOTTOM);
 430		right = new PanelWindowContainer(this,RIGHT);
 431
 432		add(DockableLayout.TOP_BUTTONS,top.getButtonBox());
 433		add(DockableLayout.LEFT_BUTTONS,left.getButtonBox());
 434		add(DockableLayout.BOTTOM_BUTTONS,bottom.getButtonBox());
 435		add(DockableLayout.RIGHT_BUTTONS,right.getButtonBox());
 436
 437		add(TOP,top.getDockablePanel());
 438		add(LEFT,left.getDockablePanel());
 439		add(BOTTOM,bottom.getDockablePanel());
 440		add(RIGHT,right.getDockablePanel());
 441	} //}}}
 442
 443	//{{{ init() method
 444	/**
 445	 * Initialises dockable window manager.
 446	 * @since jEdit 2.6pre3
 447	 */
 448	public void init()
 449	{
 450		for(int i = 0; i < dockableWindowFactories.size(); i++)
 451		{
 452			Factory factory = (Factory)
 453				dockableWindowFactories.elementAt(i);
 454			Entry entry = new Entry(factory);
 455			windows.put(factory.name,entry);
 456		}
 457
 458		String lastTop = jEdit.getProperty("view.dock.top.last");
 459		if(lastTop != null)
 460			showDockableWindow(lastTop);
 461
 462		String lastLeft = jEdit.getProperty("view.dock.left.last");
 463		if(lastLeft != null)
 464			showDockableWindow(lastLeft);
 465
 466		String lastBottom = jEdit.getProperty("view.dock.bottom.last");
 467		if(lastBottom != null)
 468			showDockableWindow(lastBottom);
 469
 470		String lastRight = jEdit.getProperty("view.dock.right.last");
 471		if(lastRight != null)
 472			showDockableWindow(lastRight);
 473	} //}}}
 474
 475	//{{{ getView() method
 476	/**
 477	 * Returns this dockable window manager's view.
 478	 * @since jEdit 4.0pre2
 479	 */
 480	public View getView()
 481	{
 482		return view;
 483	} //}}}
 484
 485	//{{{ showDockableWindow() method
 486	/**
 487	 * Opens the specified dockable window.
 488	 * @param name The dockable window name
 489	 * @since jEdit 2.6pre3
 490	 */
 491	public void showDockableWindow(String name)
 492	{
 493		Entry entry = (Entry)windows.get(name);
 494		if(entry == null)
 495		{
 496			Log.log(Log.ERROR,this,"Unknown dockable window: " + name);
 497			return;
 498		}
 499
 500		if(entry.win == null)
 501			entry.open();
 502
 503		if(entry.win != null)
 504			entry.container.show(entry);
 505		else
 506			/* an error occurred */;
 507	} //}}}
 508
 509	//{{{ addDockableWindow() method
 510	/**
 511	 * Opens the specified dockable window. As of version 4.0pre1, has the same
 512	 * effect as calling showDockableWindow().
 513	 * @param name The dockable window name
 514	 * @since jEdit 2.6pre3
 515	 */
 516	public void addDockableWindow(String name)
 517	{
 518		showDockableWindow(name);
 519	} //}}}
 520
 521	//{{{ removeDockableWindow() method
 522	/**
 523	 * Removes the specified dockable window.
 524	 * @param name The dockable window name
 525	 * @since jEdit 2.6pre3
 526	 */
 527	public void removeDockableWindow(String name)
 528	{
 529		Entry entry = (Entry)windows.get(name);
 530		if(entry == null)
 531		{
 532			Log.log(Log.ERROR,this,"This DockableWindowManager"
 533				+ " does not have a window named " + name);
 534			return;
 535		}
 536
 537		if(entry.win == null)
 538			return;
 539
 540		if(entry.container instanceof FloatingWindowContainer)
 541		{
 542			entry.container.save(entry);
 543			entry.container.remove(entry);
 544			entry.container = null;
 545			entry.win = null;
 546		}
 547		else
 548			entry.container.show(null);
 549	} //}}}
 550
 551	//{{{ toggleDockableWindow() method
 552	/**
 553	 * Toggles the visibility of the specified dockable window.
 554	 * @param name The dockable window name
 555	 */
 556	public void toggleDockableWindow(String name)
 557	{
 558		if(isDockableWindowVisible(name))
 559			removeDockableWindow(name);
 560		else
 561			addDockableWindow(name);
 562	} //}}}
 563
 564	//{{{ getDockableWindow() method
 565	/**
 566	 * @deprecated The DockableWindow interface is deprecated, as is this
 567	 * method. Use <code>getDockable()</code> instead.
 568	 */
 569	public DockableWindow getDockableWindow(String name)
 570	{
 571		if(BeanShell.isScriptRunning())
 572		{
 573			Log.log(Log.WARNING,this,"You are using the"
 574				+ " DockableWindowManager.getDockableWindow() method in");
 575			Log.log(Log.WARNING,this,"your macro.");
 576			Log.log(Log.WARNING,this,"This method is deprecated and will"
 577				+ " be removed in a future jEdit");
 578			Log.log(Log.WARNING,this,"version, because it cannot be used"
 579				+ " with newer plugins.");
 580			Log.log(Log.WARNING,this,"Modify the macro to call"
 581				+ " DockableWindowManager.getDockable() instead.");
 582		}
 583
 584		/* this is broken, so you should switch to getDockable() ASAP.
 585		 * first of all, if the dockable in question returns something
 586		 * other than itself from the getComponent() method, it won't
 587		 * work. it will also fail with dockables using the new API,
 588		 * which don't implement the DockableWindow interface (in
 589		 * which case, this method will return null). */
 590		Component comp = getDockable(name);
 591		if(comp instanceof DockableWindow)
 592			return (DockableWindow)comp;
 593		else
 594			return null;
 595	} //}}}
 596
 597	//{{{ getDockable() method
 598	/**
 599	 * Returns the specified dockable window. Use this method instead of
 600	 * the deprecated <code>getDockableWindow()</code> method.
 601	 * @param name The name of the dockable window
 602	 * @since jEdit 4.0pre1
 603	 */
 604	public JComponent getDockable(String name)
 605	{
 606		Entry entry = (Entry)windows.get(name);
 607		if(entry == null || entry.win == null)
 608			return null;
 609		else
 610			return entry.win;
 611	} //}}}
 612
 613	//{{{ isDockableWindowVisible() method
 614	/**
 615	 * Returns if the specified dockable window is visible.
 616	 * @param name The dockable window name
 617	 */
 618	public boolean isDockableWindowVisible(String name)
 619	{
 620		Entry entry = (Entry)windows.get(name);
 621		if(entry == null || entry.win == null)
 622			return false;
 623		else
 624			return entry.container.isVisible(entry);
 625	} //}}}
 626
 627	//{{{ isDockableWindowDocked() method
 628	/**
 629	 * Returns if the specified dockable window is docked into the
 630	 * view.
 631	 * @param name The dockable's name
 632	 * @since jEdit 4.0pre2
 633	 */
 634	public boolean isDockableWindowDocked(String name)
 635	{
 636		Entry entry = (Entry)windows.get(name);
 637		if(entry == null)
 638			return false;
 639		else
 640			return (entry.position != FLOATING);
 641	} //}}}
 642
 643	//{{{ close() method
 644	/**
 645	 * Called when the view is being closed.
 646	 * @since jEdit 2.6pre3
 647	 */
 648	public void close()
 649	{
 650		top.save();
 651		left.save();
 652		bottom.save();
 653		right.save();
 654
 655		Enumeration enum = windows.elements();
 656		while(enum.hasMoreElements())
 657		{
 658			Entry entry = (Entry)enum.nextElement();
 659			if(entry.win != null)
 660				entry.remove();
 661		}
 662	} //}}}
 663
 664	//{{{ getTopDockingArea() method
 665	public PanelWindowContainer getTopDockingArea()
 666	{
 667		return top;
 668	} //}}}
 669
 670	//{{{ getLeftDockingArea() method
 671	public PanelWindowContainer getLeftDockingArea()
 672	{
 673		return left;
 674	} //}}}
 675
 676	//{{{ getBottomDockingArea() method
 677	public PanelWindowContainer getBottomDockingArea()
 678	{
 679		return bottom;
 680	} //}}}
 681
 682	//{{{ getRightDockingArea() method
 683	public PanelWindowContainer getRightDockingArea()
 684	{
 685		return right;
 686	} //}}}
 687
 688	//{{{ propertiesChanged() method
 689	/**
 690	 * Called by the view when properties change.
 691	 * @since jEdit 2.6pre3
 692	 */
 693	public void propertiesChanged()
 694	{
 695		alternateLayout = jEdit.getBooleanProperty("view.docking.alternateLayout");
 696
 697		Enumeration enum = windows.elements();
 698		while(enum.hasMoreElements())
 699		{
 700			Entry entry = (Entry)enum.nextElement();
 701			String position = entry.position;
 702			String newPosition = jEdit.getProperty(entry.name
 703				+ ".dock-position");
 704			if(newPosition != null /* ??? */
 705				&& !newPosition.equals(position))
 706			{
 707				entry.position = newPosition;
 708				if(entry.container != null)
 709				{
 710					entry.container.remove(entry);
 711					entry.container = null;
 712					entry.win = null;
 713				}
 714
 715				if(newPosition.equals(FLOATING))
 716					/* do nothing */;
 717				else
 718				{
 719					if(newPosition.equals(TOP))
 720						entry.container = top;
 721					else if(newPosition.equals(LEFT))
 722						entry.container = left;
 723					else if(newPosition.equals(BOTTOM))
 724						entry.container = bottom;
 725					else if(newPosition.equals(RIGHT))
 726						entry.container = right;
 727					else
 728						throw new InternalError("Unknown position: " + newPosition);
 729
 730					entry.container.register(entry);
 731				}
 732			}
 733
 734			if(entry.container instanceof FloatingWindowContainer)
 735			{
 736				SwingUtilities.updateComponentTreeUI(((JFrame)entry.container)
 737					.getRootPane());
 738			}
 739		}
 740
 741		revalidate();
 742	} //}}}
 743
 744	//{{{ Private members
 745
 746	//{{{ Instance variables
 747	private View view;
 748	private Hashtable windows;
 749	private boolean alternateLayout;
 750	private PanelWindowContainer left;
 751	private PanelWindowContainer right;
 752	private PanelWindowContainer top;
 753	private PanelWindowContainer bottom;
 754	//}}}
 755
 756	//}}}
 757
 758	//}}}
 759
 760	//{{{ DockableLayout class
 761	class DockableLayout implements LayoutManager2
 762	{
 763		// for backwards compatibility with plugins that fiddle with
 764		// jEdit's UI layout
 765		static final String CENTER = BorderLayout.CENTER;
 766
 767		static final String TOP_BUTTONS = "top-buttons";
 768		static final String LEFT_BUTTONS = "left-buttons";
 769		static final String BOTTOM_BUTTONS = "bottom-buttons";
 770		static final String RIGHT_BUTTONS = "right-buttons";
 771
 772		Component center;
 773		Component top, left, bottom, right;
 774		Component topButtons, leftButtons, bottomButtons, rightButtons;
 775
 776		//{{{ addLayoutComponent() method
 777		public void addLayoutComponent(String name, Component comp)
 778		{
 779			addLayoutComponent(comp,name);
 780		} //}}}
 781
 782		//{{{ addLayoutComponent() method
 783		public void addLayoutComponent(Component comp, Object cons)
 784		{
 785			if(cons == null || CENTER.equals(cons))
 786				center = comp;
 787			else if(TOP.equals(cons))
 788				top = comp;
 789			else if(LEFT.equals(cons))
 790				left = comp;
 791			else if(BOTTOM.equals(cons))
 792				bottom = comp;
 793			else if(RIGHT.equals(cons))
 794				right = comp;
 795			else if(TOP_BUTTONS.equals(cons))
 796				topButtons = comp;
 797			else if(LEFT_BUTTONS.equals(cons))
 798				leftButtons = comp;
 799			else if(BOTTOM_BUTTONS.equals(cons))
 800				bottomButtons = comp;
 801			else if(RIGHT_BUTTONS.equals(cons))
 802				rightButtons = comp;
 803		} //}}}
 804
 805		//{{{ removeLayoutComponent() method
 806		public void removeLayoutComponent(Component comp)
 807		{
 808			if(center == comp)
 809				center = null;
 810			else
 811			{
 812				// none of the others are ever meant to be
 813				// removed. retarded, eh?
 814			}
 815		} //}}}
 816
 817		//{{{ preferredLayoutSize() method
 818		public Dimension preferredLayoutSize(Container parent)
 819		{
 820			Dimension prefSize = new Dimension(0,0);
 821			Dimension _top = top.getPreferredSize();
 822			Dimension _left = left.getPreferredSize();
 823			Dimension _bottom = bottom.getPreferredSize();
 824			Dimension _right = right.getPreferredSize();
 825			Dimension _topButtons = topButtons.getPreferredSize();
 826			Dimension _leftButtons = leftButtons.getPreferredSize();
 827			Dimension _bottomButtons = bottomButtons.getPreferredSize();
 828			Dimension _rightButtons = rightButtons.getPreferredSize();
 829			Dimension _center = (center == null
 830				? new Dimension(0,0)
 831				: center.getPreferredSize());
 832
 833			prefSize.height = _top.height + _bottom.height + _center.height
 834				+ _topButtons.height + _bottomButtons.height;
 835			prefSize.width = _left.width + _right.width + _center.width
 836				+ _leftButtons.width + _rightButtons.width;
 837
 838			return prefSize;
 839		} //}}}
 840
 841		//{{{ minimumLayoutSize() method
 842		public Dimension minimumLayoutSize(Container parent)
 843		{
 844			Dimension minSize = new Dimension(0,0);
 845			Dimension _top = top.getMinimumSize();
 846			Dimension _left = left.getMinimumSize();
 847			Dimension _bottom = bottom.getMinimumSize();
 848			Dimension _right = right.getMinimumSize();
 849			Dimension _topButtons = topButtons.getMinimumSize();
 850			Dimension _leftButtons = leftButtons.getMinimumSize();
 851			Dimension _bottomButtons = bottomButtons.getMinimumSize();
 852			Dimension _rightButtons = rightButtons.getMinimumSize();
 853			Dimension _center = (center == null
 854				? new Dimension(0,0)
 855				: center.getMinimumSize());
 856
 857			minSize.height = _top.height + _bottom.height + _center.height
 858				+ _topButtons.height + _bottomButtons.height;
 859			minSize.width = _left.width + _right.width + _center.width
 860				+ _leftButtons.width + _rightButtons.width;
 861
 862			return minSize;
 863		} //}}}
 864
 865		//{{{ maximumLayoutSize() method
 866		public Dimension maximumLayoutSize(Container parent)
 867		{
 868			return new Dimension(Integer.MAX_VALUE,Integer.MAX_VALUE);
 869		} //}}}
 870
 871		//{{{ layoutContainer() method
 872		public void layoutContainer(Container parent)
 873		{
 874			Dimension size = parent.getSize();
 875
 876			Dimension _topButtons = topButtons.getPreferredSize();
 877			Dimension _leftButtons = leftButtons.getPreferredSize();
 878			Dimension _bottomButtons = bottomButtons.getPreferredSize();
 879			Dimension _rightButtons = rightButtons.getPreferredSize();
 880			Dimension _center = (center == null
 881				? new Dimension(0,0)
 882				: center.getPreferredSize());
 883
 884			int _width = size.width - _leftButtons.width - _rightButtons.width;
 885			int _height = size.height - _topButtons.height - _bottomButtons.height;
 886
 887			Dimension _top = top.getPreferredSize();
 888			Dimension _left = left.getPreferredSize();
 889			Dimension _bottom = bottom.getPreferredSize();
 890			Dimension _right = right.getPreferredSize();
 891
 892			int topHeight = Math.min(Math.max(0,_height - _bottom.height),_top.height);
 893			int leftWidth = Math.min(Math.max(0,_width - _right.width),_left.width);
 894			int bottomHeight = Math.min(Math.max(0,_height - topHeight),_bottom.height);
 895			int rightWidth = Math.min(Math.max(0,_width - leftWidth),_right.width);
 896
 897			if(alternateLayout)
 898			{
 899				topButtons.setBounds(
 900					_leftButtons.width,
 901					0,
 902					_width,
 903					_topButtons.height);
 904
 905				leftButtons.setBounds(
 906					0,
 907					_topButtons.height + _top.height,
 908					_leftButtons.width,
 909					_height - _top.height - _bottom.height);
 910
 911				bottomButtons.setBounds(
 912					_leftButtons.width,
 913					size.height - _bottomButtons.height,
 914					_width,
 915					_bottomButtons.height);
 916
 917				rightButtons.setBounds(
 918					size.width - _rightButtons.width,
 919					_topButtons.height + _top.height,
 920					_rightButtons.width,
 921					_height - _top.height - _bottom.height);
 922
 923				top.setBounds(
 924					_leftButtons.width,
 925					_topButtons.height,
 926					_width,
 927					topHeight);
 928
 929				bottom.setBounds(
 930					_leftButtons.width,
 931					size.height - bottomHeight - _bottomButtons.height,
 932					_width,
 933					bottomHeight);
 934
 935				left.setBounds(
 936					_leftButtons.width,
 937					_topButtons.height + topHeight,
 938					leftWidth,
 939					_height - topHeight - bottomHeight);
 940
 941				right.setBounds(
 942					size.width - rightWidth - _rightButtons.width,
 943					_topButtons.height + topHeight,
 944					rightWidth,
 945					_height - topHeight - bottomHeight);
 946			}
 947			else
 948			{
 949				topButtons.setBounds(
 950					_leftButtons.width + leftWidth,
 951					0,
 952					_width - leftWidth - rightWidth,
 953					_topButtons.height);
 954
 955				leftButtons.setBounds(
 956					0,
 957					_topButtons.height,
 958					_leftButtons.width,
 959					_height);
 960
 961				bottomButtons.setBounds(
 962					_leftButtons.width + leftWidth,
 963					size.height - _bottomButtons.height,
 964					_width - leftWidth - rightWidth,
 965					_bottomButtons.height);
 966
 967				rightButtons.setBounds(
 968					size.width - _rightButtons.width,
 969					_topButtons.height,
 970					_rightButtons.width,
 971					_height);
 972
 973				top.setBounds(
 974					_leftButtons.width + leftWidth,
 975					_topButtons.height,
 976					_width - leftWidth - rightWidth,
 977					topHeight);
 978				bottom.setBounds(
 979					_leftButtons.width + leftWidth,
 980					size.height - bottomHeight - _bottomButtons.height,
 981					_width - leftWidth - rightWidth,
 982					bottomHeight);
 983
 984				left.setBounds(
 985					_leftButtons.width,
 986					_topButtons.height,
 987					leftWidth,
 988					_height);
 989
 990				right.setBounds(
 991					size.width - rightWidth - _rightButtons.width,
 992					_topButtons.height,
 993					rightWidth,
 994					_height);
 995			}
 996
 997			if(center != null)
 998			{
 999				center.setBounds(
1000					_leftButtons.width + _left.width,
1001					_topButtons.height + _top.height,
1002					_width - _left.width - _right.width,
1003					_height - _top.height - _bottom.height);
1004			}
1005		} //}}}
1006
1007		//{{{ getLayoutAlignmentX() method
1008		public float getLayoutAlignmentX(Container target)
1009		{
1010			return 0.5f;
1011		} //}}}
1012
1013		//{{{ getLayoutAlignmentY() method
1014		public float getLayoutAlignmentY(Container target)
1015		{
1016			return 0.5f;
1017		} //}}}
1018
1019		//{{{ invalidateLayout() method
1020		public void invalidateLayout(Container target) {}
1021		//}}}
1022	} //}}}
1023
1024	//{{{ Entry class
1025	class Entry
1026	{
1027		Factory factory;
1028		String name;
1029		String position;
1030		String title;
1031
1032		DockableWindowContainer container;
1033
1034		// only set if open
1035		JComponent win;
1036
1037		//{{{ Entry constructor
1038		Entry(Factory factory)
1039		{
1040			this.factory = factory;
1041			this.name = factory.name;
1042			this.position = jEdit.getProperty(name + ".dock-position",
1043				FLOATING);
1044			title = jEdit.getProperty(name + ".title");
1045			if(title == null)
1046			{
1047				Log.log(Log.WARNING,this,name + ".title property"
1048					+ " not defined");
1049				title = name;
1050			}
1051
1052			if(position == null)
1053				position = FLOATING;
1054
1055			if(position.equals(FLOATING))
1056				/* do nothing */;
1057			else
1058			{
1059				if(position.equals(TOP))
1060					container = top;
1061				else if(position.equals(LEFT))
1062					container = left;
1063				else if(position.equals(BOTTOM))
1064					container = bottom;
1065				else if(position.equals(RIGHT))
1066					container = right;
1067				else
1068					throw new InternalError("Unknown position: " + position);
1069
1070				container.register(this);
1071			}
1072		} //}}}
1073
1074		//{{{ open() method
1075		void open()
1076		{
1077			win = factory.createDockableWindow(view,position);
1078			if(win == null)
1079			{
1080				// error occurred
1081				return;
1082			}
1083
1084			Log.log(Log.DEBUG,this,"Adding " + name + " with position " + position);
1085
1086			if(position.equals(FLOATING))
1087			{
1088				container = new FloatingWindowContainer(
1089					DockableWindowManager.this);
1090				container.register(this);
1091			}
1092
1093			container.add(this);
1094		} //}}}
1095
1096		//{{{ remove() method
1097		void remove()
1098		{
1099			Log.log(Log.DEBUG,this,"Removing " + name + " from "
1100				+ container);
1101
1102			container.save(this);
1103			container.remove(this);
1104
1105			if(container instanceof FloatingWindowContainer)
1106				container = null;
1107
1108			win = null;
1109		} //}}}
1110	} //}}}
1111}