PageRenderTime 182ms CodeModel.GetById 126ms app.highlight 49ms RepoModel.GetById 1ms app.codeStats 1ms

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

#
Java | 1099 lines | 750 code | 142 blank | 207 comment | 115 complexity | 84fbeb9dd1a137ebb3d1c3a8ddb808a6 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 3915 2001-11-24 09:45:13Z 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.remove(entry);
 543			entry.container = null;
 544			entry.win = null;
 545		}
 546		else
 547			entry.container.show(null);
 548	} //}}}
 549
 550	//{{{ toggleDockableWindow() method
 551	/**
 552	 * Toggles the visibility of the specified dockable window.
 553	 * @param name The dockable window name
 554	 */
 555	public void toggleDockableWindow(String name)
 556	{
 557		if(isDockableWindowVisible(name))
 558			removeDockableWindow(name);
 559		else
 560			addDockableWindow(name);
 561	} //}}}
 562
 563	//{{{ getDockableWindow() method
 564	/**
 565	 * @deprecated The DockableWindow interface is deprecated, as is this
 566	 * method. Use <code>getDockable()</code> instead.
 567	 */
 568	public DockableWindow getDockableWindow(String name)
 569	{
 570		if(BeanShell.isScriptRunning())
 571		{
 572			Log.log(Log.WARNING,this,"You are using the"
 573				+ " DockableWindowManager.getDockableWindow() method in");
 574			Log.log(Log.WARNING,this,"your macro.");
 575			Log.log(Log.WARNING,this,"This method is deprecated and will"
 576				+ " be removed in a future jEdit");
 577			Log.log(Log.WARNING,this,"version, because it cannot be used"
 578				+ " with newer plugins.");
 579			Log.log(Log.WARNING,this,"Modify the macro to call"
 580				+ " DockableWindowManager.getDockable() instead.");
 581		}
 582
 583		/* this is broken, so you should switch to getDockable() ASAP.
 584		 * first of all, if the dockable in question returns something
 585		 * other than itself from the getComponent() method, it won't
 586		 * work. it will also fail with dockables using the new API,
 587		 * which don't implement the DockableWindow interface (in
 588		 * which case, this method will return null). */
 589		Component comp = getDockable(name);
 590		if(comp instanceof DockableWindow)
 591			return (DockableWindow)comp;
 592		else
 593			return null;
 594	} //}}}
 595
 596	//{{{ getDockable() method
 597	/**
 598	 * Returns the specified dockable window. Use this method instead of
 599	 * the deprecated <code>getDockableWindow()</code> method.
 600	 * @param name The name of the dockable window
 601	 * @since jEdit 4.0pre1
 602	 */
 603	public JComponent getDockable(String name)
 604	{
 605		Entry entry = (Entry)windows.get(name);
 606		if(entry == null || entry.win == null)
 607			return null;
 608		else
 609			return entry.win;
 610	} //}}}
 611
 612	//{{{ isDockableWindowVisible() method
 613	/**
 614	 * Returns if the specified dockable window is visible.
 615	 * @param name The dockable window name
 616	 */
 617	public boolean isDockableWindowVisible(String name)
 618	{
 619		Entry entry = (Entry)windows.get(name);
 620		if(entry == null || entry.win == null)
 621			return false;
 622		else
 623			return entry.container.isVisible(entry);
 624	} //}}}
 625
 626	//{{{ isDockableWindowDocked() method
 627	/**
 628	 * Returns if the specified dockable window is docked into the
 629	 * view.
 630	 * @param name The dockable's name
 631	 * @since jEdit 4.0pre2
 632	 */
 633	public boolean isDockableWindowDocked(String name)
 634	{
 635		Entry entry = (Entry)windows.get(name);
 636		if(entry == null)
 637			return false;
 638		else
 639			return (entry.position != FLOATING);
 640	} //}}}
 641
 642	//{{{ close() method
 643	/**
 644	 * Called when the view is being closed.
 645	 * @since jEdit 2.6pre3
 646	 */
 647	public void close()
 648	{
 649		top.save();
 650		left.save();
 651		bottom.save();
 652		right.save();
 653
 654		Enumeration enum = windows.elements();
 655		while(enum.hasMoreElements())
 656		{
 657			Entry entry = (Entry)enum.nextElement();
 658			if(entry.win != null)
 659				entry.remove();
 660		}
 661	} //}}}
 662
 663	//{{{ getTopDockingArea() method
 664	public PanelWindowContainer getTopDockingArea()
 665	{
 666		return top;
 667	} //}}}
 668
 669	//{{{ getLeftDockingArea() method
 670	public PanelWindowContainer getLeftDockingArea()
 671	{
 672		return left;
 673	} //}}}
 674
 675	//{{{ getBottomDockingArea() method
 676	public PanelWindowContainer getBottomDockingArea()
 677	{
 678		return bottom;
 679	} //}}}
 680
 681	//{{{ getRightDockingArea() method
 682	public PanelWindowContainer getRightDockingArea()
 683	{
 684		return right;
 685	} //}}}
 686
 687	//{{{ propertiesChanged() method
 688	/**
 689	 * Called by the view when properties change.
 690	 * @since jEdit 2.6pre3
 691	 */
 692	public void propertiesChanged()
 693	{
 694		alternateLayout = jEdit.getBooleanProperty("view.docking.alternateLayout");
 695
 696		Enumeration enum = windows.elements();
 697		while(enum.hasMoreElements())
 698		{
 699			Entry entry = (Entry)enum.nextElement();
 700			String position = entry.position;
 701			String newPosition = jEdit.getProperty(entry.name
 702				+ ".dock-position");
 703			if(newPosition != null /* ??? */
 704				&& !newPosition.equals(position))
 705			{
 706				entry.position = newPosition;
 707				if(entry.container != null)
 708				{
 709					entry.container.remove(entry);
 710					entry.container = null;
 711					entry.win = null;
 712				}
 713
 714				if(newPosition.equals(FLOATING))
 715					/* do nothing */;
 716				else
 717				{
 718					if(newPosition.equals(TOP))
 719						entry.container = top;
 720					else if(newPosition.equals(LEFT))
 721						entry.container = left;
 722					else if(newPosition.equals(BOTTOM))
 723						entry.container = bottom;
 724					else if(newPosition.equals(RIGHT))
 725						entry.container = right;
 726					else
 727						throw new InternalError("Unknown position: " + newPosition);
 728
 729					entry.container.register(entry);
 730				}
 731			}
 732
 733			if(entry.container instanceof FloatingWindowContainer)
 734			{
 735				SwingUtilities.updateComponentTreeUI(((JFrame)entry.container)
 736					.getRootPane());
 737			}
 738		}
 739
 740		revalidate();
 741	} //}}}
 742
 743	//{{{ Private members
 744
 745	//{{{ Instance variables
 746	private View view;
 747	private Hashtable windows;
 748	private boolean alternateLayout;
 749	private PanelWindowContainer left;
 750	private PanelWindowContainer right;
 751	private PanelWindowContainer top;
 752	private PanelWindowContainer bottom;
 753	//}}}
 754
 755	//}}}
 756
 757	//}}}
 758
 759	//{{{ DockableLayout class
 760	class DockableLayout implements LayoutManager2
 761	{
 762		// for backwards compatibility with plugins that fiddle with
 763		// jEdit's UI layout
 764		static final String CENTER = BorderLayout.CENTER;
 765
 766		static final String TOP_BUTTONS = "top-buttons";
 767		static final String LEFT_BUTTONS = "left-buttons";
 768		static final String BOTTOM_BUTTONS = "bottom-buttons";
 769		static final String RIGHT_BUTTONS = "right-buttons";
 770
 771		Component center;
 772		Component top, left, bottom, right;
 773		Component topButtons, leftButtons, bottomButtons, rightButtons;
 774
 775		//{{{ addLayoutComponent() method
 776		public void addLayoutComponent(String name, Component comp)
 777		{
 778			addLayoutComponent(comp,name);
 779		} //}}}
 780
 781		//{{{ addLayoutComponent() method
 782		public void addLayoutComponent(Component comp, Object cons)
 783		{
 784			if(cons == null || CENTER.equals(cons))
 785				center = comp;
 786			else if(TOP.equals(cons))
 787				top = comp;
 788			else if(LEFT.equals(cons))
 789				left = comp;
 790			else if(BOTTOM.equals(cons))
 791				bottom = comp;
 792			else if(RIGHT.equals(cons))
 793				right = comp;
 794			else if(TOP_BUTTONS.equals(cons))
 795				topButtons = comp;
 796			else if(LEFT_BUTTONS.equals(cons))
 797				leftButtons = comp;
 798			else if(BOTTOM_BUTTONS.equals(cons))
 799				bottomButtons = comp;
 800			else if(RIGHT_BUTTONS.equals(cons))
 801				rightButtons = comp;
 802		} //}}}
 803
 804		//{{{ removeLayoutComponent() method
 805		public void removeLayoutComponent(Component comp)
 806		{
 807			if(center == comp)
 808				center = null;
 809			else
 810			{
 811				// none of the others are ever meant to be
 812				// removed. retarded, eh?
 813			}
 814		} //}}}
 815
 816		//{{{ preferredLayoutSize() method
 817		public Dimension preferredLayoutSize(Container parent)
 818		{
 819			Dimension prefSize = new Dimension(0,0);
 820			Dimension _top = top.getPreferredSize();
 821			Dimension _left = left.getPreferredSize();
 822			Dimension _bottom = bottom.getPreferredSize();
 823			Dimension _right = right.getPreferredSize();
 824			Dimension _topButtons = topButtons.getPreferredSize();
 825			Dimension _leftButtons = leftButtons.getPreferredSize();
 826			Dimension _bottomButtons = bottomButtons.getPreferredSize();
 827			Dimension _rightButtons = rightButtons.getPreferredSize();
 828			Dimension _center = (center == null
 829				? new Dimension(0,0)
 830				: center.getPreferredSize());
 831
 832			prefSize.height = _top.height + _bottom.height + _center.height
 833				+ _topButtons.height + _bottomButtons.height;
 834			prefSize.width = _left.width + _right.width + _center.width
 835				+ _leftButtons.width + _rightButtons.width;
 836
 837			return prefSize;
 838		} //}}}
 839
 840		//{{{ minimumLayoutSize() method
 841		public Dimension minimumLayoutSize(Container parent)
 842		{
 843			Dimension minSize = new Dimension(0,0);
 844			Dimension _top = top.getMinimumSize();
 845			Dimension _left = left.getMinimumSize();
 846			Dimension _bottom = bottom.getMinimumSize();
 847			Dimension _right = right.getMinimumSize();
 848			Dimension _topButtons = topButtons.getMinimumSize();
 849			Dimension _leftButtons = leftButtons.getMinimumSize();
 850			Dimension _bottomButtons = bottomButtons.getMinimumSize();
 851			Dimension _rightButtons = rightButtons.getMinimumSize();
 852			Dimension _center = (center == null
 853				? new Dimension(0,0)
 854				: center.getMinimumSize());
 855
 856			minSize.height = _top.height + _bottom.height + _center.height
 857				+ _topButtons.height + _bottomButtons.height;
 858			minSize.width = _left.width + _right.width + _center.width
 859				+ _leftButtons.width + _rightButtons.width;
 860
 861			return minSize;
 862		} //}}}
 863
 864		//{{{ maximumLayoutSize() method
 865		public Dimension maximumLayoutSize(Container parent)
 866		{
 867			return new Dimension(Integer.MAX_VALUE,Integer.MAX_VALUE);
 868		} //}}}
 869
 870		//{{{ layoutContainer() method
 871		public void layoutContainer(Container parent)
 872		{
 873			Dimension size = parent.getSize();
 874
 875			Dimension prefSize = new Dimension(0,0);
 876			Dimension _top = top.getPreferredSize();
 877			Dimension _left = left.getPreferredSize();
 878			Dimension _bottom = bottom.getPreferredSize();
 879			Dimension _right = right.getPreferredSize();
 880			Dimension _topButtons = topButtons.getPreferredSize();
 881			Dimension _leftButtons = leftButtons.getPreferredSize();
 882			Dimension _bottomButtons = bottomButtons.getPreferredSize();
 883			Dimension _rightButtons = rightButtons.getPreferredSize();
 884			Dimension _center = (center == null
 885				? new Dimension(0,0)
 886				: center.getPreferredSize());
 887
 888			int _width = size.width - _leftButtons.width - _rightButtons.width;
 889			int _height = size.height - _topButtons.height - _bottomButtons.height;
 890
 891			if(alternateLayout)
 892			{
 893				topButtons.setBounds(
 894					_leftButtons.width,
 895					0,
 896					_width,
 897					_topButtons.height);
 898
 899				leftButtons.setBounds(
 900					0,
 901					_topButtons.height + _top.height,
 902					_leftButtons.width,
 903					_height - _top.height - _bottom.height);
 904
 905				bottomButtons.setBounds(
 906					_leftButtons.width,
 907					size.height - _bottomButtons.height,
 908					_width,
 909					_bottomButtons.height);
 910
 911				rightButtons.setBounds(
 912					size.width - _rightButtons.width,
 913					_topButtons.height + _top.height,
 914					_rightButtons.width,
 915					_height - _top.height - _bottom.height);
 916
 917				top.setBounds(
 918					_leftButtons.width,
 919					_topButtons.height,
 920					_width,
 921					_top.height);
 922
 923				bottom.setBounds(
 924					_leftButtons.width,
 925					size.height - _bottom.height - _bottomButtons.height,
 926					_width,
 927					_bottom.height);
 928
 929				left.setBounds(
 930					_leftButtons.width,
 931					_topButtons.height + _top.height,
 932					_left.width,
 933					_height - _top.height - _bottom.height);
 934
 935				right.setBounds(
 936					size.width - _right.width - _rightButtons.width,
 937					_topButtons.height + _top.height,
 938					_right.width,
 939					_height - _top.height - _bottom.height);
 940			}
 941			else
 942			{
 943				topButtons.setBounds(
 944					_leftButtons.width + _left.width,
 945					0,
 946					_width - _left.width - _right.width,
 947					_topButtons.height);
 948
 949				leftButtons.setBounds(
 950					0,
 951					_topButtons.height,
 952					_leftButtons.width,
 953					_height);
 954
 955				bottomButtons.setBounds(
 956					_leftButtons.width + _left.width,
 957					size.height - _bottomButtons.height,
 958					_width - _left.width - _right.width,
 959					_bottomButtons.height);
 960
 961				rightButtons.setBounds(
 962					size.width - _rightButtons.width,
 963					_topButtons.height,
 964					_rightButtons.width,
 965					_height);
 966
 967				top.setBounds(
 968					_leftButtons.width + _left.width,
 969					_topButtons.height,
 970					_width - _left.width - _right.width,
 971					_top.height);
 972				bottom.setBounds(
 973					_leftButtons.width + _left.width,
 974					size.height - _bottom.height - _bottomButtons.height,
 975					_width - _left.width - _right.width,
 976					_bottom.height);
 977
 978				left.setBounds(
 979					_leftButtons.width,
 980					_topButtons.height,
 981					_left.width,
 982					_height);
 983
 984				right.setBounds(
 985					size.width - _right.width - _rightButtons.width,
 986					_topButtons.height,
 987					_right.width,
 988					_height);
 989			}
 990
 991			if(center != null)
 992			{
 993				center.setBounds(
 994					_leftButtons.width + _left.width,
 995					_topButtons.height + _top.height,
 996					_width - _left.width - _right.width,
 997					_height - _top.height - _bottom.height);
 998			}
 999		} //}}}
1000
1001		//{{{ getLayoutAlignmentX() method
1002		public float getLayoutAlignmentX(Container target)
1003		{
1004			return 0.5f;
1005		} //}}}
1006
1007		//{{{ getLayoutAlignmentY() method
1008		public float getLayoutAlignmentY(Container target)
1009		{
1010			return 0.5f;
1011		} //}}}
1012
1013		//{{{ invalidateLayout() method
1014		public void invalidateLayout(Container target) {}
1015		//}}}
1016	} //}}}
1017
1018	//{{{ Entry class
1019	class Entry
1020	{
1021		Factory factory;
1022		String name;
1023		String position;
1024		String title;
1025
1026		DockableWindowContainer container;
1027
1028		// only set if open
1029		JComponent win;
1030
1031		//{{{ Entry constructor
1032		Entry(Factory factory)
1033		{
1034			this.factory = factory;
1035			this.name = factory.name;
1036			this.position = jEdit.getProperty(name + ".dock-position",
1037				FLOATING);
1038			title = jEdit.getProperty(name + ".title");
1039
1040			if(position == null)
1041				position = FLOATING;
1042
1043			if(position.equals(FLOATING))
1044				/* do nothing */;
1045			else
1046			{
1047				if(position.equals(TOP))
1048					container = top;
1049				else if(position.equals(LEFT))
1050					container = left;
1051				else if(position.equals(BOTTOM))
1052					container = bottom;
1053				else if(position.equals(RIGHT))
1054					container = right;
1055				else
1056					throw new InternalError("Unknown position: " + position);
1057
1058				container.register(this);
1059			}
1060		} //}}}
1061
1062		//{{{ open() method
1063		void open()
1064		{
1065			win = factory.createDockableWindow(view,position);
1066			if(win == null)
1067			{
1068				// error occurred
1069				return;
1070			}
1071
1072			Log.log(Log.DEBUG,this,"Adding " + name + " with position " + position);
1073
1074			if(position.equals(FLOATING))
1075			{
1076				container = new FloatingWindowContainer(
1077					DockableWindowManager.this);
1078				container.register(this);
1079			}
1080
1081			container.add(this);
1082		} //}}}
1083
1084		//{{{ remove() method
1085		void remove()
1086		{
1087			Log.log(Log.DEBUG,this,"Removing " + name + " from "
1088				+ container);
1089
1090			container.save(this);
1091			container.remove(this);
1092
1093			if(container instanceof FloatingWindowContainer)
1094				container = null;
1095
1096			win = null;
1097		} //}}}
1098	} //}}}
1099}