PageRenderTime 348ms CodeModel.GetById 251ms app.highlight 43ms RepoModel.GetById 38ms app.codeStats 1ms

/jEdit/tags/jedit-4-2-pre4/org/gjt/sp/jedit/View.java

#
Java | 1670 lines | 990 code | 216 blank | 464 comment | 203 complexity | 0b0155a9a9f3cf590e1bd42ace047363 MD5 | raw file
   1/*
   2 * View.java - jEdit view
   3 * :tabSize=8:indentSize=8:noTabs=false:
   4 * :folding=explicit:collapseFolds=1:
   5 *
   6 * Copyright (C) 1998, 2003 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;
  24
  25//{{{ Imports
  26import javax.swing.event.*;
  27import javax.swing.text.*;
  28import javax.swing.*;
  29import java.awt.*;
  30import java.awt.event.*;
  31import java.io.IOException;
  32import java.net.Socket;
  33import java.util.*;
  34import org.gjt.sp.jedit.msg.*;
  35import org.gjt.sp.jedit.gui.*;
  36import org.gjt.sp.jedit.search.*;
  37import org.gjt.sp.jedit.textarea.*;
  38import org.gjt.sp.util.Log;
  39//}}}
  40
  41/**
  42 * A <code>View</code> is jEdit's top-level frame window.<p>
  43 *
  44 * In a BeanShell script, you can obtain the current view instance from the
  45 * <code>view</code> variable.<p>
  46 *
  47 * The largest component it contains is an {@link EditPane} that in turn
  48 * contains a {@link org.gjt.sp.jedit.textarea.JEditTextArea} that displays a
  49 * {@link Buffer}.
  50 * A view can have more than one edit pane in a split window configuration.
  51 * A view also contains a menu bar, an optional toolbar and other window
  52 * decorations, as well as docked windows.<p>
  53 *
  54 * The <b>View</b> class performs two important operations
  55 * dealing with plugins: creating plugin menu items, and managing dockable
  56 * windows.
  57 *
  58 * <ul>
  59 * <li>When a view is being created, its initialization routine
  60 * iterates through the collection of loaded plugins and constructs the
  61 * <b>Plugins</b> menu using the properties as specified in the
  62 * {@link EditPlugin} class.</li>
  63 * <li>The view also creates and initializes a
  64 * {@link org.gjt.sp.jedit.gui.DockableWindowManager}
  65 * object.  This object is
  66 * responsible for creating, closing and managing dockable windows.</li>
  67 * </ul>
  68 *
  69 * This class does not have a public constructor.
  70 * Views can be opened and closed using methods in the <code>jEdit</code>
  71 * class.
  72 *
  73 * @see org.gjt.sp.jedit.jEdit#newView(View)
  74 * @see org.gjt.sp.jedit.jEdit#newView(View,Buffer)
  75 * @see org.gjt.sp.jedit.jEdit#newView(View,Buffer,boolean)
  76 * @see org.gjt.sp.jedit.jEdit#closeView(View)
  77 *
  78 * @author Slava Pestov
  79 * @author John Gellene (API documentation)
  80 * @version $Id: View.java 4841 2003-07-28 21:08:04Z spestov $
  81 */
  82public class View extends JFrame implements EBComponent
  83{
  84	//{{{ User interface
  85
  86	//{{{ ToolBar-related constants
  87
  88	//{{{ Groups
  89	/**
  90	 * The group of tool bars above the DockableWindowManager
  91	 * @see #addToolBar(int,int,java.awt.Component)
  92	 * @since jEdit 4.0pre7
  93	 */
  94	public static final int TOP_GROUP = 0;
  95
  96	/**
  97	 * The group of tool bars below the DockableWindowManager
  98	 * @see #addToolBar(int,int,java.awt.Component)
  99	 * @since jEdit 4.0pre7
 100	 */
 101	public static final int BOTTOM_GROUP = 1;
 102	public static final int DEFAULT_GROUP = TOP_GROUP;
 103	//}}}
 104
 105	//{{{ Layers
 106
 107	// Common layers
 108	/**
 109	 * The highest possible layer.
 110	 * @see #addToolBar(int,int,java.awt.Component)
 111	 * @since jEdit 4.0pre7
 112	 */
 113	public static final int TOP_LAYER = Integer.MAX_VALUE;
 114
 115	/**
 116	 * The default layer for tool bars with no preference.
 117	 * @see #addToolBar(int,int,java.awt.Component)
 118	 * @since jEdit 4.0pre7
 119	 */
 120	public static final int DEFAULT_LAYER = 0;
 121
 122	/**
 123	 * The lowest possible layer.
 124	 * @see #addToolBar(int,int,java.awt.Component)
 125	 * @since jEdit 4.0pre7
 126	 */
 127	public static final int BOTTOM_LAYER = Integer.MIN_VALUE;
 128
 129	// Layers for top group
 130	/**
 131	 * Above system tool bar layer.
 132	 * @see #addToolBar(int,int,java.awt.Component)
 133	 * @since jEdit 4.0pre7
 134	 */
 135	public static final int ABOVE_SYSTEM_BAR_LAYER = 150;
 136
 137	/**
 138	 * System tool bar layer.
 139	 * jEdit uses this for the main tool bar.
 140	 * @see #addToolBar(int,int,java.awt.Component)
 141	 * @since jEdit 4.0pre7
 142	 */
 143	public static final int SYSTEM_BAR_LAYER = 100;
 144
 145	/**
 146	 * Below system tool bar layer.
 147	 * @see #addToolBar(int,int,java.awt.Component)
 148	 * @since jEdit 4.0pre7
 149	 */
 150	public static final int BELOW_SYSTEM_BAR_LAYER = 75;
 151
 152	/**
 153	 * Search bar layer.
 154	 * @see #addToolBar(int,int,java.awt.Component)
 155	 * @since jEdit 4.0pre7
 156	 */
 157	public static final int SEARCH_BAR_LAYER = 75;
 158
 159	/**
 160	 * Below search bar layer.
 161	 * @see #addToolBar(int,int,java.awt.Component)
 162	 * @since jEdit 4.0pre7
 163	 */
 164	public static final int BELOW_SEARCH_BAR_LAYER = 50;
 165
 166	// Layers for bottom group
 167	/**
 168	 * @deprecated Status bar no longer added as a tool bar.
 169	 */
 170	public static final int ABOVE_ACTION_BAR_LAYER = -50;
 171
 172	/**
 173	 * Action bar layer.
 174	 * @see #addToolBar(int,int,java.awt.Component)
 175	 * @since jEdit 4.2pre1
 176	 */
 177	public static final int ACTION_BAR_LAYER = -75;
 178
 179	/**
 180	 * Status bar layer.
 181	 * @see #addToolBar(int,int,java.awt.Component)
 182	 * @since jEdit 4.2pre1
 183	 */
 184	public static final int STATUS_BAR_LAYER = -100;
 185
 186	/**
 187	 * Status bar layer.
 188	 * @see #addToolBar(int,int,java.awt.Component)
 189	 * @since jEdit 4.2pre1
 190	 */
 191	public static final int BELOW_STATUS_BAR_LAYER = -150;
 192	//}}}
 193
 194	//}}}
 195
 196	//{{{ getDockableWindowManager() method
 197	/**
 198	 * Returns the dockable window manager associated with this view.
 199	 * @since jEdit 2.6pre3
 200	 */
 201	public DockableWindowManager getDockableWindowManager()
 202	{
 203		return dockableWindowManager;
 204	} //}}}
 205
 206	//{{{ getToolBar() method
 207	/**
 208	 * Returns the view's tool bar.
 209	 * @since jEdit 4.2pre1
 210	 */
 211	public Box getToolBar()
 212	{
 213		return toolBar;
 214	} //}}}
 215
 216	//{{{ addToolBar() method
 217	/**
 218	 * Adds a tool bar to this view.
 219	 * @param toolBar The tool bar
 220	 */
 221	public void addToolBar(Component toolBar)
 222	{
 223		addToolBar(DEFAULT_GROUP, DEFAULT_LAYER, toolBar);
 224	} //}}}
 225
 226	//{{{ addToolBar() method
 227	/**
 228	 * Adds a tool bar to this view.
 229	 * @param group The tool bar group to add to
 230	 * @param toolBar The tool bar
 231	 * @see org.gjt.sp.jedit.gui.ToolBarManager
 232	 * @since jEdit 4.0pre7
 233	 */
 234	public void addToolBar(int group, Component toolBar)
 235	{
 236		addToolBar(group, DEFAULT_LAYER, toolBar);
 237	} //}}}
 238
 239	//{{{ addToolBar() method
 240	/**
 241	 * Adds a tool bar to this view.
 242	 * @param group The tool bar group to add to
 243	 * @param layer The layer of the group to add to
 244	 * @param toolBar The tool bar
 245	 * @see org.gjt.sp.jedit.gui.ToolBarManager
 246	 * @since jEdit 4.0pre7
 247	 */
 248	public void addToolBar(int group, int layer, Component toolBar)
 249	{
 250		toolBarManager.addToolBar(group, layer, toolBar);
 251		getRootPane().revalidate();
 252	} //}}}
 253
 254	//{{{ removeToolBar() method
 255	/**
 256	 * Removes a tool bar from this view.
 257	 * @param toolBar The tool bar
 258	 */
 259	public void removeToolBar(Component toolBar)
 260	{
 261		toolBarManager.removeToolBar(toolBar);
 262		getRootPane().revalidate();
 263	} //}}}
 264
 265	//{{{ showWaitCursor() method
 266	/**
 267	 * Shows the wait cursor. This method and
 268	 * {@link #hideWaitCursor()} are implemented using a reference
 269	 * count of requests for wait cursors, so that nested calls work
 270	 * correctly; however, you should be careful to use these methods in
 271	 * tandem.<p>
 272	 *
 273	 * To ensure that {@link #hideWaitCursor()} is always called
 274	 * after a {@link #showWaitCursor()}, use a
 275	 * <code>try</code>/<code>finally</code> block, like this:
 276	 * <pre>try
 277	 *{
 278	 *    view.showWaitCursor();
 279	 *    // ...
 280	 *}
 281	 *finally
 282	 *{
 283	 *    view.hideWaitCursor();
 284	 *}</pre>
 285	 */
 286	public synchronized void showWaitCursor()
 287	{
 288		if(waitCount++ == 0)
 289		{
 290			Cursor cursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
 291			setCursor(cursor);
 292			EditPane[] editPanes = getEditPanes();
 293			for(int i = 0; i < editPanes.length; i++)
 294			{
 295				EditPane editPane = editPanes[i];
 296				editPane.getTextArea().getPainter()
 297					.setCursor(cursor);
 298			}
 299		}
 300	} //}}}
 301
 302	//{{{ hideWaitCursor() method
 303	/**
 304	 * Hides the wait cursor.
 305	 */
 306	public synchronized void hideWaitCursor()
 307	{
 308		if(waitCount > 0)
 309			waitCount--;
 310
 311		if(waitCount == 0)
 312		{
 313			// still needed even though glass pane
 314			// has a wait cursor
 315			Cursor cursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
 316			setCursor(cursor);
 317			cursor = Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR);
 318			EditPane[] editPanes = getEditPanes();
 319			for(int i = 0; i < editPanes.length; i++)
 320			{
 321				EditPane editPane = editPanes[i];
 322				editPane.getTextArea().getPainter()
 323					.setCursor(cursor);
 324			}
 325		}
 326	} //}}}
 327
 328	//{{{ getSearchBar() method
 329	/**
 330	 * Returns the search bar.
 331	 * @since jEdit 2.4pre4
 332	 */
 333	public final SearchBar getSearchBar()
 334	{
 335		return searchBar;
 336	} //}}}
 337
 338	//{{{ getActionBar() method
 339	/**
 340	 * Returns the action bar.
 341	 * @since jEdit 4.2pre3
 342	 */
 343	public final ActionBar getActionBar()
 344	{
 345		return actionBar;
 346	} //}}}
 347
 348	//{{{ getStatus() method
 349	/**
 350	 * Returns the status bar. The
 351	 * {@link org.gjt.sp.jedit.gui.StatusBar#setMessage(String)} and
 352	 * {@link org.gjt.sp.jedit.gui.StatusBar#setMessageAndClear(String)} methods can
 353	 * be called on the return value of this method to display status
 354	 * information to the user.
 355	 * @since jEdit 3.2pre2
 356	 */
 357	public StatusBar getStatus()
 358	{
 359		return status;
 360	} //}}}
 361
 362	//}}}
 363
 364	//{{{ Input handling
 365
 366	//{{{ getKeyEventInterceptor() method
 367	/**
 368	 * Returns the listener that will handle all key events in this
 369	 * view, if any.
 370	 */
 371	public KeyListener getKeyEventInterceptor()
 372	{
 373		return keyEventInterceptor;
 374	} //}}}
 375
 376	//{{{ setKeyEventInterceptor() method
 377	/**
 378	 * Sets the listener that will handle all key events in this
 379	 * view. For example, the complete word command uses this so
 380	 * that all key events are passed to the word list popup while
 381	 * it is visible.
 382	 * @param comp The component
 383	 */
 384	public void setKeyEventInterceptor(KeyListener listener)
 385	{
 386		this.keyEventInterceptor = listener;
 387	} //}}}
 388
 389	//{{{ getInputHandler() method
 390	/**
 391	 * Returns the input handler.
 392	 */
 393	public InputHandler getInputHandler()
 394	{
 395		return inputHandler;
 396	} //}}}
 397
 398	//{{{ setInputHandler() method
 399	/**
 400	 * Sets the input handler.
 401	 * @param inputHandler The new input handler
 402	 */
 403	public void setInputHandler(InputHandler inputHandler)
 404	{
 405		this.inputHandler = inputHandler;
 406	} //}}}
 407
 408	//{{{ getMacroRecorder() method
 409	/**
 410	 * Returns the macro recorder.
 411	 */
 412	public Macros.Recorder getMacroRecorder()
 413	{
 414		return recorder;
 415	} //}}}
 416
 417	//{{{ setMacroRecorder() method
 418	/**
 419	 * Sets the macro recorder.
 420	 * @param recorder The macro recorder
 421	 */
 422	public void setMacroRecorder(Macros.Recorder recorder)
 423	{
 424		this.recorder = recorder;
 425	} //}}}
 426
 427	//{{{ processKeyEvent() method
 428	/**
 429	 * Forwards key events directly to the input handler.
 430	 * This is slightly faster than using a KeyListener
 431	 * because some Swing overhead is avoided.
 432	 */
 433	public void processKeyEvent(KeyEvent evt)
 434	{
 435		processKeyEvent(evt,false);
 436	} //}}}
 437
 438	//{{{ processKeyEvent() method
 439	/**
 440	 * Forwards key events directly to the input handler.
 441	 * This is slightly faster than using a KeyListener
 442	 * because some Swing overhead is avoided.
 443	 */
 444	public void processKeyEvent(KeyEvent evt, boolean calledFromTextArea)
 445	{
 446		if(Debug.DUMP_KEY_EVENTS && calledFromTextArea)
 447			Log.log(Log.DEBUG,this,"Key event: " + evt);
 448
 449		if(getTextArea().hasFocus() && !calledFromTextArea)
 450			return;
 451
 452		evt = _preprocessKeyEvent(evt);
 453		if(evt == null)
 454			return;
 455
 456		switch(evt.getID())
 457		{
 458		case KeyEvent.KEY_TYPED:
 459			boolean focusOnTextArea = false;
 460			// if the user pressed eg C+e n n in the
 461			// search bar we want focus to go back there
 462			// after the prefix is done
 463			if(prefixFocusOwner != null)
 464			{
 465				if(prefixFocusOwner.isShowing())
 466				{
 467					prefixFocusOwner.requestFocus();
 468					focusOnTextArea = true;
 469				}
 470			}
 471
 472			if(keyEventInterceptor != null)
 473				keyEventInterceptor.keyTyped(evt);
 474			else if(inputHandler.isPrefixActive()
 475				|| getTextArea().hasFocus())
 476			{
 477				inputHandler.keyTyped(evt);
 478			}
 479
 480			// we might have been closed as a result of
 481			// the above
 482			if(isClosed())
 483				return;
 484
 485			// this is a weird hack.
 486			// we don't want C+e a to insert 'a' in the
 487			// search bar if the search bar has focus...
 488			if(inputHandler.isPrefixActive())
 489			{
 490				if(getFocusOwner() instanceof JTextComponent)
 491				{
 492					prefixFocusOwner = getFocusOwner();
 493					getTextArea().requestFocus();
 494				}
 495				else if(focusOnTextArea)
 496				{
 497					getTextArea().requestFocus();
 498				}
 499				else
 500				{
 501					prefixFocusOwner = null;
 502				}
 503			}
 504			else
 505			{
 506				prefixFocusOwner = null;
 507			}
 508
 509			break;
 510		case KeyEvent.KEY_PRESSED:
 511			if(keyEventInterceptor != null)
 512				keyEventInterceptor.keyPressed(evt);
 513			else
 514			{
 515				/* boolean */ focusOnTextArea = false;
 516				if(prefixFocusOwner != null)
 517				{
 518					if(prefixFocusOwner.isShowing())
 519					{
 520						prefixFocusOwner.requestFocus();
 521						focusOnTextArea = true;
 522					}
 523					prefixFocusOwner = null;
 524				}
 525
 526				inputHandler.keyPressed(evt);
 527
 528				// we might have been closed as a result of
 529				// the above
 530				if(isClosed())
 531					return;
 532
 533				// this is a weird hack.
 534				// we don't want C+e a to insert 'a' in the
 535				// search bar if the search bar has focus...
 536				if(inputHandler.isPrefixActive())
 537				{
 538					if(getFocusOwner() instanceof JTextComponent)
 539					{
 540						prefixFocusOwner = getFocusOwner();
 541						getTextArea().requestFocus();
 542					}
 543					else if(focusOnTextArea)
 544					{
 545						getTextArea().requestFocus();
 546					}
 547					else
 548					{
 549						prefixFocusOwner = null;
 550					}
 551				}
 552				else
 553				{
 554					prefixFocusOwner = null;
 555				}
 556			}
 557			break;
 558		case KeyEvent.KEY_RELEASED:
 559			if(keyEventInterceptor != null)
 560				keyEventInterceptor.keyReleased(evt);
 561			else
 562				inputHandler.keyReleased(evt);
 563			break;
 564		}
 565
 566		if(!evt.isConsumed())
 567			super.processKeyEvent(evt);
 568	} //}}}
 569
 570	//}}}
 571
 572	//{{{ Buffers, edit panes, split panes
 573
 574	//{{{ splitHorizontally() method
 575	/**
 576	 * Splits the view horizontally.
 577	 * @since jEdit 4.1pre2
 578	 */
 579	public EditPane splitHorizontally()
 580	{
 581		return split(JSplitPane.VERTICAL_SPLIT);
 582	} //}}}
 583
 584	//{{{ splitVertically() method
 585	/**
 586	 * Splits the view vertically.
 587	 * @since jEdit 4.1pre2
 588	 */
 589	public EditPane splitVertically()
 590	{
 591		return split(JSplitPane.HORIZONTAL_SPLIT);
 592	} //}}}
 593
 594	//{{{ split() method
 595	/**
 596	 * Splits the view.
 597	 * @since jEdit 4.1pre2
 598	 */
 599	public EditPane split(int orientation)
 600	{
 601		editPane.saveCaretInfo();
 602		EditPane oldEditPane = editPane;
 603		setEditPane(createEditPane(oldEditPane.getBuffer()));
 604		editPane.loadCaretInfo();
 605
 606		JComponent oldParent = (JComponent)oldEditPane.getParent();
 607
 608		final JSplitPane newSplitPane = new JSplitPane(orientation);
 609		newSplitPane.setOneTouchExpandable(true);
 610		newSplitPane.setBorder(null);
 611		newSplitPane.setMinimumSize(new Dimension(0,0));
 612
 613		int parentSize = (orientation == JSplitPane.VERTICAL_SPLIT
 614			? oldEditPane.getHeight() : oldEditPane.getWidth());
 615		final int dividerPosition = (int)((double)(parentSize
 616			- newSplitPane.getDividerSize()) * 0.5);
 617		newSplitPane.setDividerLocation(dividerPosition);
 618
 619		if(oldParent instanceof JSplitPane)
 620		{
 621			JSplitPane oldSplitPane = (JSplitPane)oldParent;
 622			int dividerPos = oldSplitPane.getDividerLocation();
 623
 624			Component left = oldSplitPane.getLeftComponent();
 625
 626			if(left == oldEditPane)
 627				oldSplitPane.setLeftComponent(newSplitPane);
 628			else
 629				oldSplitPane.setRightComponent(newSplitPane);
 630
 631			newSplitPane.setLeftComponent(oldEditPane);
 632			newSplitPane.setRightComponent(editPane);
 633
 634			oldSplitPane.setDividerLocation(dividerPos);
 635		}
 636		else
 637		{
 638			this.splitPane = newSplitPane;
 639
 640			newSplitPane.setLeftComponent(oldEditPane);
 641			newSplitPane.setRightComponent(editPane);
 642
 643			oldParent.add(newSplitPane,0);
 644			oldParent.revalidate();
 645		}
 646
 647		SwingUtilities.invokeLater(new Runnable()
 648		{
 649			public void run()
 650			{
 651				newSplitPane.setDividerLocation(dividerPosition);
 652			}
 653		});
 654
 655		editPane.focusOnTextArea();
 656
 657		return editPane;
 658	} //}}}
 659
 660	//{{{ unsplit() method
 661	/**
 662	 * Unsplits the view.
 663	 * @since jEdit 2.3pre2
 664	 */
 665	public void unsplit()
 666	{
 667		if(splitPane != null)
 668		{
 669			EditPane[] editPanes = getEditPanes();
 670			for(int i = 0; i < editPanes.length; i++)
 671			{
 672				EditPane _editPane = editPanes[i];
 673				if(editPane != _editPane)
 674					_editPane.close();
 675			}
 676
 677			JComponent parent = (JComponent)splitPane.getParent();
 678
 679			parent.remove(splitPane);
 680			parent.add(editPane,0);
 681			parent.revalidate();
 682
 683			splitPane = null;
 684			updateTitle();
 685
 686			editPane.focusOnTextArea();
 687		}
 688		else
 689			getToolkit().beep();
 690	} //}}}
 691
 692	//{{{ unsplitCurrent() method
 693	/**
 694	 * Removes the current split.
 695	 * @since jEdit 2.3pre2
 696	 */
 697	public void unsplitCurrent()
 698	{
 699		if(splitPane != null)
 700		{
 701			// find first split pane parenting current edit pane
 702			Component comp = editPane;
 703			while(!(comp instanceof JSplitPane))
 704			{
 705				comp = comp.getParent();
 706			}
 707
 708			// get rid of any edit pane that is a child
 709			// of the current edit pane's parent splitter
 710			EditPane[] editPanes = getEditPanes();
 711			for(int i = 0; i < editPanes.length; i++)
 712			{
 713				EditPane _editPane = editPanes[i];
 714				if(GUIUtilities.isAncestorOf(comp,_editPane)
 715					&& _editPane != editPane)
 716					_editPane.close();
 717			}
 718
 719			JComponent parent = (JComponent)comp.getParent();
 720
 721			if(parent instanceof JSplitPane)
 722			{
 723				JSplitPane parentSplit = (JSplitPane)parent;
 724				int pos = parentSplit.getDividerLocation();
 725				if(parentSplit.getLeftComponent() == comp)
 726					parentSplit.setLeftComponent(editPane);
 727				else
 728					parentSplit.setRightComponent(editPane);
 729				parentSplit.setDividerLocation(pos);
 730			}
 731			else
 732			{
 733				parent.remove(comp);
 734				parent.add(editPane,0);
 735				splitPane = null;
 736			}
 737
 738			parent.revalidate();
 739
 740			updateTitle();
 741
 742			editPane.focusOnTextArea();
 743		}
 744		else
 745			getToolkit().beep();
 746	} //}}}
 747
 748	//{{{ nextTextArea() method
 749	/**
 750	 * Moves keyboard focus to the next text area.
 751	 * @since jEdit 2.7pre4
 752	 */
 753	public void nextTextArea()
 754	{
 755		EditPane[] editPanes = getEditPanes();
 756		for(int i = 0; i < editPanes.length; i++)
 757		{
 758			if(editPane == editPanes[i])
 759			{
 760				if(i == editPanes.length - 1)
 761					editPanes[0].focusOnTextArea();
 762				else
 763					editPanes[i+1].focusOnTextArea();
 764				break;
 765			}
 766		}
 767	} //}}}
 768
 769	//{{{ prevTextArea() method
 770	/**
 771	 * Moves keyboard focus to the previous text area.
 772	 * @since jEdit 2.7pre4
 773	 */
 774	public void prevTextArea()
 775	{
 776		EditPane[] editPanes = getEditPanes();
 777		for(int i = 0; i < editPanes.length; i++)
 778		{
 779			if(editPane == editPanes[i])
 780			{
 781				if(i == 0)
 782					editPanes[editPanes.length - 1].focusOnTextArea();
 783				else
 784					editPanes[i-1].focusOnTextArea();
 785				break;
 786			}
 787		}
 788	} //}}}
 789
 790	//{{{ getSplitPane() method
 791	/**
 792	 * Returns the top-level split pane, if any.
 793	 * @since jEdit 2.3pre2
 794	 */
 795	public JSplitPane getSplitPane()
 796	{
 797		return splitPane;
 798	} //}}}
 799
 800	//{{{ getBuffer() method
 801	/**
 802	 * Returns the current edit pane's buffer.
 803	 */
 804	public Buffer getBuffer()
 805	{
 806		if(editPane == null)
 807			return null;
 808		else
 809			return editPane.getBuffer();
 810	} //}}}
 811
 812	//{{{ setBuffer() method
 813	/**
 814	 * Sets the current edit pane's buffer.
 815	 */
 816	public void setBuffer(Buffer buffer)
 817	{
 818		editPane.setBuffer(buffer);
 819	} //}}}
 820
 821	//{{{ goToBuffer() method
 822	/**
 823	 * If this buffer is open in one of the view's edit panes, sets focus
 824	 * to that edit pane. Otherwise, opens the buffer in the currently
 825	 * active edit pane.
 826	 * @param buffer The buffer
 827	 * @since jEdit 4.2pre1
 828	 */
 829	public EditPane goToBuffer(Buffer buffer)
 830	{
 831		if(editPane.getBuffer() == buffer)
 832		{
 833			editPane.focusOnTextArea();
 834			return editPane;
 835		}
 836
 837		EditPane[] editPanes = getEditPanes();
 838		for(int i = 0; i < editPanes.length; i++)
 839		{
 840			EditPane ep = editPanes[i];
 841			if(ep.getBuffer() == buffer)
 842			{
 843				setEditPane(ep);
 844				ep.focusOnTextArea();
 845				return ep;
 846			}
 847		}
 848		setBuffer(buffer);
 849		return editPane;
 850	} //}}}
 851
 852	//{{{ getTextArea() method
 853	/**
 854	 * Returns the current edit pane's text area.
 855	 */
 856	public JEditTextArea getTextArea()
 857	{
 858		if(editPane == null)
 859			return null;
 860		else
 861			return editPane.getTextArea();
 862	} //}}}
 863
 864	//{{{ getEditPane() method
 865	/**
 866	 * Returns the current edit pane.
 867	 * @since jEdit 2.5pre2
 868	 */
 869	public EditPane getEditPane()
 870	{
 871		return editPane;
 872	} //}}}
 873
 874	//{{{ getEditPanes() method
 875	/**
 876	 * Returns all edit panes.
 877	 * @since jEdit 2.5pre2
 878	 */
 879	public EditPane[] getEditPanes()
 880	{
 881		if(splitPane == null)
 882		{
 883			EditPane[] ep = { editPane };
 884			return ep;
 885		}
 886		else
 887		{
 888			Vector vec = new Vector();
 889			getEditPanes(vec,splitPane);
 890			EditPane[] ep = new EditPane[vec.size()];
 891			vec.copyInto(ep);
 892			return ep;
 893		}
 894	} //}}}
 895
 896	//{{{ getViewConfig() method
 897	/**
 898	 * @since jEdit 4.2pre1
 899	 */
 900	public ViewConfig getViewConfig()
 901	{
 902		StringBuffer splitConfig = new StringBuffer();
 903		if(splitPane != null)
 904			getSplitConfig(splitPane,splitConfig);
 905		else
 906		{
 907			splitConfig.append(getBuffer().getIndex());
 908			splitConfig.append(" buffer");
 909		}
 910
 911		ViewConfig config = new ViewConfig();
 912		config.plainView = isPlainView();
 913		config.splitConfig = splitConfig.toString();
 914		config.x = getX();
 915		config.y = getY();
 916		config.width = getWidth();
 917		config.height = getHeight();
 918		config.extState = GUIUtilities.getExtendedState(this);
 919
 920		config.top = dockableWindowManager.getTopDockingArea().getCurrent();
 921		config.left = dockableWindowManager.getLeftDockingArea().getCurrent();
 922		config.bottom = dockableWindowManager.getBottomDockingArea().getCurrent();
 923		config.right = dockableWindowManager.getRightDockingArea().getCurrent();
 924
 925		config.topPos = dockableWindowManager.getTopDockingArea().getDimension();
 926		config.leftPos = dockableWindowManager.getLeftDockingArea().getDimension();
 927		config.bottomPos = dockableWindowManager.getBottomDockingArea().getDimension();
 928		config.rightPos = dockableWindowManager.getRightDockingArea().getDimension();
 929
 930		return config;
 931	} //}}}
 932
 933	//}}}
 934
 935	//{{{ quickIncrementalSearch() method
 936	/**
 937	 * Quick search.
 938	 * @since jEdit 4.0pre3
 939	 */
 940	public void quickIncrementalSearch(boolean word)
 941	{
 942		if(searchBar == null)
 943			searchBar = new SearchBar(this,true);
 944		if(searchBar.getParent() == null)
 945			addToolBar(TOP_GROUP,SEARCH_BAR_LAYER,searchBar);
 946
 947		searchBar.setHyperSearch(false);
 948
 949		JEditTextArea textArea = getTextArea();
 950
 951		if(word)
 952		{
 953			String text = textArea.getSelectedText();
 954			if(text == null)
 955			{
 956				textArea.selectWord();
 957				text = textArea.getSelectedText();
 958			}
 959			else if(text.indexOf('\n') != -1)
 960				text = null;
 961
 962			searchBar.getField().setText(text);
 963		}
 964
 965		searchBar.getField().requestFocus();
 966		searchBar.getField().selectAll();
 967	} //}}}
 968
 969	//{{{ quickHyperSearch() method
 970	/**
 971	 * Quick HyperSearch.
 972	 * @since jEdit 4.0pre3
 973	 */
 974	public void quickHyperSearch(boolean word)
 975	{
 976		JEditTextArea textArea = getTextArea();
 977
 978		if(word)
 979		{
 980			String text = textArea.getSelectedText();
 981			if(text == null)
 982			{
 983				textArea.selectWord();
 984				text = textArea.getSelectedText();
 985			}
 986
 987			if(text != null && text.indexOf('\n') == -1)
 988			{
 989				HistoryModel.getModel("find").addItem(text);
 990				SearchAndReplace.setSearchString(text);
 991				SearchAndReplace.setSearchFileSet(new CurrentBufferSet());
 992				SearchAndReplace.hyperSearch(this);
 993
 994				return;
 995			}
 996		}
 997
 998		if(searchBar == null)
 999			searchBar = new SearchBar(this,true);
1000		if(searchBar.getParent() == null)
1001			addToolBar(TOP_GROUP,SEARCH_BAR_LAYER,searchBar);
1002
1003		searchBar.setHyperSearch(true);
1004		searchBar.getField().setText(null);
1005		searchBar.getField().requestFocus();
1006		searchBar.getField().selectAll();
1007	} //}}}
1008
1009	//{{{ actionBar() method
1010	/**
1011	 * Shows the action bar if needed, and sends keyboard focus there.
1012	 * @since jEdit 4.2pre1
1013	 */
1014	public void actionBar()
1015	{
1016		if(actionBar == null)
1017			actionBar = new ActionBar(this,true);
1018		if(actionBar.getParent() == null)
1019			addToolBar(BOTTOM_GROUP,ACTION_BAR_LAYER,actionBar);
1020
1021		actionBar.goToActionBar();
1022	} //}}}
1023
1024	//{{{ isClosed() method
1025	/**
1026	 * Returns true if this view has been closed with
1027	 * {@link jEdit#closeView(View)}.
1028	 */
1029	public boolean isClosed()
1030	{
1031		return closed;
1032	} //}}}
1033
1034	//{{{ isPlainView() method
1035	/**
1036	 * Returns true if this is an auxilliary view with no dockable windows.
1037	 * @since jEdit 4.1pre2
1038	 */
1039	public boolean isPlainView()
1040	{
1041		return plainView;
1042	} //}}}
1043
1044	//{{{ getNext() method
1045	/**
1046	 * Returns the next view in the list.
1047	 */
1048	public View getNext()
1049	{
1050		return next;
1051	} //}}}
1052
1053	//{{{ getPrev() method
1054	/**
1055	 * Returns the previous view in the list.
1056	 */
1057	public View getPrev()
1058	{
1059		return prev;
1060	} //}}}
1061
1062	//{{{ handleMessage() method
1063	public void handleMessage(EBMessage msg)
1064	{
1065		if(msg instanceof PropertiesChanged)
1066			propertiesChanged();
1067		else if(msg instanceof SearchSettingsChanged)
1068		{
1069			if(searchBar != null)
1070				searchBar.update();
1071		}
1072		else if(msg instanceof BufferUpdate)
1073			handleBufferUpdate((BufferUpdate)msg);
1074		else if(msg instanceof EditPaneUpdate)
1075			handleEditPaneUpdate((EditPaneUpdate)msg);
1076		else if(msg instanceof PluginUpdate)
1077		{
1078			if(actionBar != null)
1079				actionBar.actionListChanged();
1080		}
1081	} //}}}
1082
1083	//{{{ getMinimumSize() method
1084	public Dimension getMinimumSize()
1085	{
1086		return new Dimension(0,0);
1087	} //}}}
1088
1089	//{{{ setWaitSocket() method
1090	/**
1091	 * This socket is closed when the buffer is closed.
1092	 */
1093	public void setWaitSocket(Socket waitSocket)
1094	{
1095		this.waitSocket = waitSocket;
1096	} //}}}
1097
1098	//{{{ toString() method
1099	public String toString()
1100	{
1101		return getClass().getName() + "["
1102			+ (jEdit.getActiveView() == this
1103			? "active" : "inactive")
1104			+ "]";
1105	} //}}}
1106
1107	//{{{ Package-private members
1108	View prev;
1109	View next;
1110
1111	//{{{ View constructor
1112	View(Buffer buffer, ViewConfig config)
1113	{
1114		this.plainView = config.plainView;
1115
1116		enableEvents(AWTEvent.KEY_EVENT_MASK);
1117
1118		setIconImage(GUIUtilities.getEditorIcon());
1119
1120		dockableWindowManager = new DockableWindowManager(this,config);
1121
1122		topToolBars = new JPanel(new VariableGridLayout(
1123			VariableGridLayout.FIXED_NUM_COLUMNS,
1124			1));
1125		bottomToolBars = new JPanel(new VariableGridLayout(
1126			VariableGridLayout.FIXED_NUM_COLUMNS,
1127			1));
1128		/* bottomToolBars.setLayout(new BoxLayout(bottomToolBars,
1129			BoxLayout.X_AXIS)); */
1130
1131		toolBarManager = new ToolBarManager(topToolBars, bottomToolBars);
1132
1133		status = new StatusBar(this);
1134
1135		inputHandler = new DefaultInputHandler(this,(DefaultInputHandler)
1136			jEdit.getInputHandler());
1137
1138		Component comp = restoreSplitConfig(buffer,config.splitConfig);
1139		dockableWindowManager.add(comp,0);
1140
1141		getContentPane().add(BorderLayout.CENTER,dockableWindowManager);
1142
1143		dockableWindowManager.init();
1144
1145		// tool bar and status bar gets added in propertiesChanged()
1146		// depending in the 'tool bar alternate layout' setting.
1147		propertiesChanged();
1148
1149		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
1150		addWindowListener(new WindowHandler());
1151
1152		EditBus.addToBus(this);
1153
1154		SearchDialog.preloadSearchDialog(this);
1155	} //}}}
1156
1157	//{{{ close() method
1158	void close()
1159	{
1160		GUIUtilities.saveGeometry(this,plainView ? "plain-view" : "view");
1161		closed = true;
1162
1163		// save dockable window geometry, and close 'em
1164		dockableWindowManager.close();
1165
1166		EditBus.removeFromBus(this);
1167		dispose();
1168
1169		EditPane[] editPanes = getEditPanes();
1170		for(int i = 0; i < editPanes.length; i++)
1171			editPanes[i].close();
1172
1173		// null some variables so that retaining references
1174		// to closed views won't hurt as much.
1175		toolBarManager = null;
1176		toolBar = null;
1177		searchBar = null;
1178		splitPane = null;
1179		inputHandler = null;
1180		recorder = null;
1181
1182		getContentPane().removeAll();
1183
1184		// notify clients with -wait
1185		if(waitSocket != null)
1186		{
1187			try
1188			{
1189				waitSocket.getOutputStream().write('\0');
1190				waitSocket.getOutputStream().flush();
1191				waitSocket.getInputStream().close();
1192				waitSocket.getOutputStream().close();
1193				waitSocket.close();
1194			}
1195			catch(IOException io)
1196			{
1197				//Log.log(Log.ERROR,this,io);
1198			}
1199		}
1200	} //}}}
1201
1202	//{{{ updateTitle() method
1203	/**
1204	 * Updates the title bar.
1205	 */
1206	void updateTitle()
1207	{
1208		Vector buffers = new Vector();
1209		EditPane[] editPanes = getEditPanes();
1210		for(int i = 0; i < editPanes.length; i++)
1211		{
1212			Buffer buffer = editPanes[i].getBuffer();
1213			if(buffers.indexOf(buffer) == -1)
1214				buffers.addElement(buffer);
1215		}
1216
1217		StringBuffer title = new StringBuffer(jEdit.getProperty("view.title"));
1218		for(int i = 0; i < buffers.size(); i++)
1219		{
1220			if(i != 0)
1221				title.append(", ");
1222
1223			Buffer buffer = (Buffer)buffers.elementAt(i);
1224			title.append((showFullPath && !buffer.isNewFile())
1225				? buffer.getPath() : buffer.getName());
1226			if(buffer.isDirty())
1227				title.append(jEdit.getProperty("view.title.dirty"));
1228		}
1229		setTitle(title.toString());
1230	} //}}}
1231
1232	//}}}
1233
1234	//{{{ Private members
1235
1236	//{{{ Instance variables
1237	private boolean closed;
1238
1239	private DockableWindowManager dockableWindowManager;
1240
1241	private JPanel topToolBars;
1242	private JPanel bottomToolBars;
1243	private ToolBarManager toolBarManager;
1244
1245	private Box toolBar;
1246	private SearchBar searchBar;
1247	private ActionBar actionBar;
1248
1249	private EditPane editPane;
1250	private JSplitPane splitPane;
1251
1252	private StatusBar status;
1253
1254	private KeyListener keyEventInterceptor;
1255	private InputHandler inputHandler;
1256	private Macros.Recorder recorder;
1257	private Component prefixFocusOwner;
1258
1259	private int waitCount;
1260
1261	private boolean showFullPath;
1262
1263	private boolean plainView;
1264
1265	private Socket waitSocket;
1266	//}}}
1267
1268	//{{{ getEditPanes() method
1269	private void getEditPanes(Vector vec, Component comp)
1270	{
1271		if(comp instanceof EditPane)
1272			vec.addElement(comp);
1273		else if(comp instanceof JSplitPane)
1274		{
1275			JSplitPane split = (JSplitPane)comp;
1276			getEditPanes(vec,split.getLeftComponent());
1277			getEditPanes(vec,split.getRightComponent());
1278		}
1279	} //}}}
1280
1281	//{{{ getSplitConfig() method
1282	/*
1283	 * The split config is recorded in a simple RPN "language".
1284	 */
1285	private void getSplitConfig(JSplitPane splitPane,
1286		StringBuffer splitConfig)
1287	{
1288		Component right = splitPane.getRightComponent();
1289		if(right instanceof JSplitPane)
1290			getSplitConfig((JSplitPane)right,splitConfig);
1291		else
1292		{
1293			splitConfig.append(((EditPane)right).getBuffer().getIndex());
1294			splitConfig.append(" buffer");
1295		}
1296
1297		splitConfig.append(' ');
1298
1299		Component left = splitPane.getLeftComponent();
1300		if(left instanceof JSplitPane)
1301			getSplitConfig((JSplitPane)left,splitConfig);
1302		else
1303		{
1304			splitConfig.append(((EditPane)left).getBuffer().getIndex());
1305			splitConfig.append(" buffer");
1306		}
1307
1308		splitConfig.append(' ');
1309		splitConfig.append(splitPane.getDividerLocation());
1310		splitConfig.append(' ');
1311		splitConfig.append(splitPane.getOrientation()
1312			== JSplitPane.VERTICAL_SPLIT ? "vertical" : "horizontal");
1313	} //}}}
1314
1315	//{{{ restoreSplitConfig() method
1316	private Component restoreSplitConfig(Buffer buffer, String splitConfig)
1317	{
1318		if(buffer != null)
1319			return (editPane = createEditPane(buffer));
1320		else if(splitConfig == null)
1321			return (editPane = createEditPane(jEdit.getFirstBuffer()));
1322
1323		Buffer[] buffers = jEdit.getBuffers();
1324
1325		Stack stack = new Stack();
1326
1327		StringTokenizer st = new StringTokenizer(splitConfig);
1328
1329		while(st.hasMoreTokens())
1330		{
1331			String token = st.nextToken();
1332			if(token.equals("vertical") || token.equals("horizontal"))
1333			{
1334				int orientation = (token.equals("vertical")
1335					? JSplitPane.VERTICAL_SPLIT
1336					: JSplitPane.HORIZONTAL_SPLIT);
1337				int divider = Integer.parseInt((String)stack.pop());
1338				stack.push(splitPane = new JSplitPane(
1339					orientation,
1340					(Component)stack.pop(),
1341					(Component)stack.pop()));
1342				splitPane.setOneTouchExpandable(true);
1343				splitPane.setBorder(null);
1344				splitPane.setMinimumSize(new Dimension(0,0));
1345				splitPane.setDividerLocation(divider);
1346			}
1347			else if(token.equals("buffer"))
1348			{
1349				int index = Integer.parseInt((String)stack.pop());
1350				if(index < buffers.length && index >= 0)
1351					buffer = buffers[index];
1352				if(buffer == null)
1353					buffer = jEdit.getFirstBuffer();
1354
1355				stack.push(editPane = createEditPane(buffer));
1356			}
1357			else
1358			{
1359				stack.push(token);
1360			}
1361		}
1362
1363		updateGutterBorders();
1364
1365		return (Component)stack.peek();
1366	} //}}}
1367
1368	//{{{ propertiesChanged() method
1369	/**
1370	 * Reloads various settings from the properties.
1371	 */
1372	private void propertiesChanged()
1373	{
1374		setJMenuBar(GUIUtilities.loadMenuBar("view.mbar"));
1375
1376		loadToolBars();
1377
1378		showFullPath = jEdit.getBooleanProperty("view.showFullPath");
1379		updateTitle();
1380
1381		status.propertiesChanged();
1382
1383		removeToolBar(status);
1384		getContentPane().remove(status);
1385
1386		if(jEdit.getBooleanProperty("view.toolbar.alternateLayout"))
1387		{
1388			getContentPane().add(BorderLayout.NORTH,topToolBars);
1389			getContentPane().add(BorderLayout.SOUTH,bottomToolBars);
1390			if(!plainView && jEdit.getBooleanProperty("view.status.visible"))
1391				addToolBar(BOTTOM_GROUP,STATUS_BAR_LAYER,status);
1392		}
1393		else
1394		{
1395			dockableWindowManager.add(topToolBars,
1396				DockableWindowManager.DockableLayout
1397				.TOP_TOOLBARS,0);
1398			dockableWindowManager.add(bottomToolBars,
1399				DockableWindowManager.DockableLayout
1400				.BOTTOM_TOOLBARS,0);
1401			if(!plainView && jEdit.getBooleanProperty("view.status.visible"))
1402				getContentPane().add(BorderLayout.SOUTH,status);
1403		}
1404
1405		getRootPane().revalidate();
1406
1407		//SwingUtilities.updateComponentTreeUI(getRootPane());
1408	} //}}}
1409
1410	//{{{ loadToolBars() method
1411	private void loadToolBars()
1412	{
1413		if(jEdit.getBooleanProperty("view.showToolbar") && !plainView)
1414		{
1415			if(toolBar != null)
1416				toolBarManager.removeToolBar(toolBar);
1417
1418			toolBar = GUIUtilities.loadToolBar("view.toolbar");
1419
1420			addToolBar(TOP_GROUP, SYSTEM_BAR_LAYER, toolBar);
1421		}
1422		else if(toolBar != null)
1423		{
1424			removeToolBar(toolBar);
1425			toolBar = null;
1426		}
1427
1428		if(searchBar != null)
1429			removeToolBar(searchBar);
1430
1431		if(jEdit.getBooleanProperty("view.showSearchbar") && !plainView)
1432		{
1433			if(searchBar == null)
1434				searchBar = new SearchBar(this,false);
1435			searchBar.propertiesChanged();
1436			addToolBar(TOP_GROUP,SEARCH_BAR_LAYER,searchBar);
1437		}
1438	} //}}}
1439
1440	//{{{ createEditPane() method
1441	private EditPane createEditPane(Buffer buffer)
1442	{
1443		EditPane editPane = new EditPane(this,buffer);
1444		JEditTextArea textArea = editPane.getTextArea();
1445		textArea.addFocusListener(new FocusHandler());
1446		textArea.addCaretListener(new CaretHandler());
1447		textArea.addScrollListener(new ScrollHandler());
1448		EditBus.send(new EditPaneUpdate(editPane,EditPaneUpdate.CREATED));
1449		return editPane;
1450	} //}}}
1451
1452	//{{{ setEditPane() method
1453	private void setEditPane(EditPane editPane)
1454	{
1455		this.editPane = editPane;
1456		status.updateCaretStatus();
1457		status.updateBufferStatus();
1458		status.updateMiscStatus();
1459
1460		// repaint the gutter so that the border color
1461		// reflects the focus state
1462		updateGutterBorders();
1463
1464		EditBus.send(new ViewUpdate(this,ViewUpdate.EDIT_PANE_CHANGED));
1465	} //}}}
1466
1467	//{{{ handleBufferUpdate() method
1468	private void handleBufferUpdate(BufferUpdate msg)
1469	{
1470		Buffer buffer = msg.getBuffer();
1471		if(msg.getWhat() == BufferUpdate.DIRTY_CHANGED
1472			|| msg.getWhat() == BufferUpdate.LOADED)
1473		{
1474			EditPane[] editPanes = getEditPanes();
1475			for(int i = 0; i < editPanes.length; i++)
1476			{
1477				if(editPanes[i].getBuffer() == buffer)
1478				{
1479					updateTitle();
1480					break;
1481				}
1482			}
1483		}
1484	} //}}}
1485
1486	//{{{ handleEditPaneUpdate() method
1487	private void handleEditPaneUpdate(EditPaneUpdate msg)
1488	{
1489		EditPane editPane = msg.getEditPane();
1490		if(editPane.getView() == this
1491			&& msg.getWhat() == EditPaneUpdate.BUFFER_CHANGED
1492			&& editPane.getBuffer().isLoaded())
1493		{
1494			status.updateCaretStatus();
1495			status.updateBufferStatus();
1496			status.updateMiscStatus();
1497		}
1498	} //}}}
1499
1500	//{{{ updateGutterBorders() method
1501	/**
1502	 * Updates the borders of all gutters in this view to reflect the
1503	 * currently focused text area.
1504	 * @since jEdit 2.6final
1505	 */
1506	private void updateGutterBorders()
1507	{
1508		EditPane[] editPanes = getEditPanes();
1509		for(int i = 0; i < editPanes.length; i++)
1510			editPanes[i].getTextArea().getGutter().updateBorder();
1511	} //}}}
1512
1513	//{{{ _preprocessKeyEvent() method
1514	private KeyEvent _preprocessKeyEvent(KeyEvent evt)
1515	{
1516		if(isClosed())
1517			return null;
1518
1519		if(getFocusOwner() instanceof JComponent)
1520		{
1521			JComponent comp = (JComponent)getFocusOwner();
1522			InputMap map = comp.getInputMap();
1523			ActionMap am = comp.getActionMap();
1524
1525			if(map != null && am != null && comp.isEnabled())
1526			{
1527				Object binding = map.get(KeyStroke.getKeyStrokeForEvent(evt));
1528				if(binding != null && am.get(binding) != null)
1529				{
1530					return null;
1531				}
1532			}
1533		}
1534
1535		if(getFocusOwner() instanceof JTextComponent)
1536		{
1537			// fix for the bug where key events in JTextComponents
1538			// inside views are also handled by the input handler
1539			if(evt.getID() == KeyEvent.KEY_PRESSED)
1540			{
1541				switch(evt.getKeyCode())
1542				{
1543				case KeyEvent.VK_ENTER:
1544				case KeyEvent.VK_TAB:
1545				case KeyEvent.VK_BACK_SPACE:
1546				case KeyEvent.VK_SPACE:
1547					return null;
1548				}
1549			}
1550		}
1551
1552		if(evt.isConsumed())
1553			return null;
1554
1555		return KeyEventWorkaround.processKeyEvent(evt);
1556	} //}}}
1557
1558	//}}}
1559
1560	//{{{ Inner classes
1561
1562	//{{{ CaretHandler class
1563	class CaretHandler implements CaretListener
1564	{
1565		public void caretUpdate(CaretEvent evt)
1566		{
1567			if(evt.getSource() == getTextArea())
1568				status.updateCaretStatus();
1569		}
1570	} //}}}
1571
1572	//{{{ FocusHandler class
1573	class FocusHandler extends FocusAdapter
1574	{
1575		public void focusGained(FocusEvent evt)
1576		{
1577			// walk up hierarchy, looking for an EditPane
1578			Component comp = (Component)evt.getSource();
1579			while(!(comp instanceof EditPane))
1580			{
1581				if(comp == null)
1582					return;
1583
1584				comp = comp.getParent();
1585			}
1586
1587			if(comp != editPane)
1588				setEditPane((EditPane)comp);
1589			else
1590				updateGutterBorders();
1591		}
1592	} //}}}
1593
1594	//{{{ ScrollHandler class
1595	class ScrollHandler implements ScrollListener
1596	{
1597		public void scrolledVertically(JEditTextArea textArea)
1598		{
1599			if(getTextArea() == textArea)
1600				status.updateCaretStatus();
1601		}
1602
1603		public void scrolledHorizontally(JEditTextArea textArea) {}
1604	} //}}}
1605
1606	//{{{ WindowHandler class
1607	class WindowHandler extends WindowAdapter
1608	{
1609		public void windowActivated(WindowEvent evt)
1610		{
1611			jEdit.setActiveView(View.this);
1612
1613			// People have reported hangs with JDK 1.4; might be
1614			// caused by modal dialogs being displayed from
1615			// windowActivated()
1616			SwingUtilities.invokeLater(new Runnable()
1617			{
1618				public void run()
1619				{
1620					jEdit.checkBufferStatus(View.this);
1621				}
1622			});
1623		}
1624
1625		public void windowClosing(WindowEvent evt)
1626		{
1627			jEdit.closeView(View.this);
1628		}
1629	} //}}}
1630
1631	//{{{ ViewConfig class
1632	public static class ViewConfig
1633	{
1634		public boolean plainView;
1635		public String splitConfig;
1636		public int x, y, width, height, extState;
1637
1638		// dockables
1639		public String top, left, bottom, right;
1640		public int topPos, leftPos, bottomPos, rightPos;
1641
1642		public ViewConfig()
1643		{
1644		}
1645
1646		public ViewConfig(boolean plainView)
1647		{
1648			this.plainView = plainView;
1649			String prefix = (plainView ? "plain-view" : "view");
1650			x = jEdit.getIntegerProperty(prefix + ".x",0);
1651			y = jEdit.getIntegerProperty(prefix + ".y",0);
1652			width = jEdit.getIntegerProperty(prefix + ".width",0);
1653			height = jEdit.getIntegerProperty(prefix + ".height",0);
1654		}
1655
1656		public ViewConfig(boolean plainView, String splitConfig,
1657			int x, int y, int width, int height, int extState)
1658		{
1659			this.plainView = plainView;
1660			this.splitConfig = splitConfig;
1661			this.x = x;
1662			this.y = y;
1663			this.width = width;
1664			this.height = height;
1665			this.extState = extState;
1666		}
1667	} //}}}
1668
1669	//}}}
1670}