PageRenderTime 71ms CodeModel.GetById 47ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 1ms

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

#
Java | 578 lines | 384 code | 67 blank | 127 comment | 118 complexity | 942f7b118e208f17a7f519c9b5256af5 MD5 | raw file
  1/*
  2 * EditPane.java - Text area and buffer switcher
  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;
 24
 25//{{{ Imports
 26import javax.swing.event.*;
 27import javax.swing.*;
 28import java.awt.*;
 29import org.gjt.sp.jedit.gui.*;
 30import org.gjt.sp.jedit.io.VFSManager;
 31import org.gjt.sp.jedit.msg.*;
 32import org.gjt.sp.jedit.syntax.*;
 33import org.gjt.sp.jedit.textarea.*;
 34import org.gjt.sp.util.Log;
 35//}}}
 36
 37/**
 38 * A panel containing a text area. Each edit pane can edit one buffer at
 39 * a time.
 40 * @author Slava Pestov
 41 * @version $Id: EditPane.java 4012 2002-02-05 06:28:10Z spestov $
 42 */
 43public class EditPane extends JPanel implements EBComponent
 44{
 45	//{{{ getView() method
 46	/**
 47	 * Returns the view containing this edit pane.
 48	 * @since jEdit 2.5pre2
 49	 */
 50	public View getView()
 51	{
 52		return view;
 53	} //}}}
 54
 55	//{{{ getBuffer() method
 56	/**
 57	 * Returns the current buffer.
 58	 * @since jEdit 2.5pre2
 59	 */
 60	public Buffer getBuffer()
 61	{
 62		return buffer;
 63	} //}}}
 64
 65	//{{{ setBuffer() method
 66	/**
 67	 * Sets the current buffer.
 68	 * @param buffer The buffer to edit.
 69	 * @since jEdit 2.5pre2
 70	 */
 71	public void setBuffer(final Buffer buffer)
 72	{
 73		if(this.buffer == buffer)
 74			return;
 75
 76		if(buffer.insideCompoundEdit())
 77			buffer.endCompoundEdit();
 78
 79		recentBuffer = this.buffer;
 80		if(recentBuffer != null)
 81			saveCaretInfo();
 82		this.buffer = buffer;
 83
 84		textArea.setBuffer(buffer);
 85
 86		if(!init)
 87		{
 88			view.updateTitle();
 89
 90			if(bufferSwitcher != null)
 91			{
 92				if(bufferSwitcher.getSelectedItem() != buffer)
 93					bufferSwitcher.setSelectedItem(buffer);
 94			}
 95
 96			EditBus.send(new EditPaneUpdate(this,EditPaneUpdate
 97				.BUFFER_CHANGED));
 98		}
 99
100		SwingUtilities.invokeLater(new Runnable()
101		{
102			public void run()
103			{
104				// only do this if we are the current edit pane
105				if(view.getEditPane() == EditPane.this
106					&& (bufferSwitcher == null
107					|| !bufferSwitcher.isPopupVisible()))
108				{
109					focusOnTextArea();
110				}
111			}
112		});
113
114		// Only do this after all I/O requests are complete
115		Runnable runnable = new Runnable()
116		{
117			public void run()
118			{
119				loadCaretInfo();
120				buffer.checkModTime(view);
121			}
122		};
123
124		if(buffer.isPerformingIO())
125			VFSManager.runInAWTThread(runnable);
126		else
127			runnable.run();
128	} //}}}
129
130	//{{{ prevBuffer() method
131	/**
132	 * Selects the previous buffer.
133	 * @since jEdit 2.7pre2
134	 */
135	public void prevBuffer()
136	{
137		Buffer buffer = this.buffer.getPrev();
138		if(buffer == null)
139			setBuffer(jEdit.getLastBuffer());
140		else
141			setBuffer(buffer);
142	} //}}}
143
144	//{{{ nextBuffer() method
145	/**
146	 * Selects the next buffer.
147	 * @since jEdit 2.7pre2
148	 */
149	public void nextBuffer()
150	{
151		Buffer buffer = this.buffer.getNext();
152		if(buffer == null)
153			setBuffer(jEdit.getFirstBuffer());
154		else
155			setBuffer(buffer);
156	} //}}}
157
158	//{{{ recentBuffer() method
159	/**
160	 * Selects the most recently edited buffer.
161	 * @since jEdit 2.7pre2
162	 */
163	public void recentBuffer()
164	{
165		if(recentBuffer != null)
166			setBuffer(recentBuffer);
167		else
168			getToolkit().beep();
169	} //}}}
170
171	//{{{ focusOnTextArea() method
172	/**
173	 * Sets the focus onto the text area.
174	 * @since jEdit 2.5pre2
175	 */
176	public void focusOnTextArea()
177	{
178		textArea.grabFocus();
179		// trying to work around buggy focus handling in some
180		// Java versions
181//		if(!textArea.hasFocus())
182//		{
183//			textArea.processFocusEvent(new FocusEvent(textArea,
184//				FocusEvent.FOCUS_GAINED));
185//		}
186	} //}}}
187
188	//{{{ getTextArea() method
189	/**
190	 * Returns the view's text area.
191	 * @since jEdit 2.5pre2
192	 */
193	public JEditTextArea getTextArea()
194	{
195		return textArea;
196	} //}}}
197
198	//{{{ saveCaretInfo() method
199	/**
200	 * Saves the caret information to the current buffer.
201	 * @since jEdit 2.5pre2
202	 */
203	public void saveCaretInfo()
204	{
205		buffer.setIntegerProperty(Buffer.CARET,
206			textArea.getCaretPosition());
207
208		/*Selection[] selection = textArea.getSelection();
209		if(selection != null)
210			buffer.setProperty(Buffer.SELECTION,selection);*/
211
212		buffer.setIntegerProperty(Buffer.SCROLL_VERT,
213			textArea.getFirstPhysicalLine());
214		buffer.setIntegerProperty(Buffer.SCROLL_HORIZ,
215			textArea.getHorizontalOffset());
216	} //}}}
217
218	//{{{ loadCaretInfo() method
219	/**
220	 * Loads the caret information from the current buffer.
221	 * @since jEdit 2.5pre2
222	 */
223	public void loadCaretInfo()
224	{
225		Integer caret = (Integer)buffer.getProperty(Buffer.CARET);
226		//Selection[] selection = (Selection[])buffer.getProperty(Buffer.SELECTION);
227
228		Integer firstLine = (Integer)buffer.getProperty(Buffer.SCROLL_VERT);
229		Integer horizontalOffset = (Integer)buffer.getProperty(Buffer.SCROLL_HORIZ);
230
231		if(caret != null)
232		{
233			textArea.setCaretPosition(Math.min(caret.intValue(),
234				buffer.getLength()));
235		}
236
237		/*if(selection != null)
238			textArea.setSelection(selection);*/
239
240		if(firstLine != null)
241			textArea.setFirstLine(textArea.physicalToVirtual(firstLine.intValue()));
242
243		if(horizontalOffset != null)
244			textArea.setHorizontalOffset(horizontalOffset.intValue());
245
246		/* Silly bug workaround #8694. If you look at the above code,
247		 * note that we restore the saved caret position first, then
248		 * scroll to the saved location. However, the caret changing
249		 * can itself result in scrolling to a different location than
250		 * what was saved; and since moveCaretPosition() calls
251		 * updateBracketHighlight(), the bracket highlight's out of
252		 * bounds calculation will rely on a different set of physical
253		 * first/last lines than what we will end up with eventually.
254		 * Instead of confusing the user with status messages that
255		 * appear at random when switching buffers, we simply hide the
256		 * message altogether. */
257		view.getStatus().setMessage(null);
258	} //}}}
259
260	//{{{ handleMessage() method
261	public void handleMessage(EBMessage msg)
262	{
263		if(msg instanceof PropertiesChanged)
264		{
265			propertiesChanged();
266			loadBufferSwitcher();
267		}
268		else if(msg instanceof BufferUpdate)
269			handleBufferUpdate((BufferUpdate)msg);
270	} //}}}
271
272	//{{{ getMinimumSize() method
273	/**
274	 * Returns 0,0 for split pane compatibility.
275	 */
276	public final Dimension getMinimumSize()
277	{
278		return new Dimension(0,0);
279	} //}}}
280
281	//{{{ Package-private members
282
283	//{{{ EditPane constructor
284	EditPane(View view, Buffer buffer)
285	{
286		super(new BorderLayout());
287
288		init = true;
289
290		this.view = view;
291
292		EditBus.addToBus(this);
293
294		textArea = new JEditTextArea(view);
295
296		add(BorderLayout.CENTER,textArea);
297
298		propertiesChanged();
299
300		if(buffer == null)
301			setBuffer(jEdit.getFirstBuffer());
302		else
303			setBuffer(buffer);
304
305		loadBufferSwitcher();
306
307		init = false;
308	} //}}}
309
310	//{{{ close() method
311	void close()
312	{
313		saveCaretInfo();
314		EditBus.send(new EditPaneUpdate(this,EditPaneUpdate.DESTROYED));
315		EditBus.removeFromBus(this);
316	} //}}}
317
318	//}}}
319
320	//{{{ Private members
321
322	//{{{ Instance variables
323	private boolean init;
324	private View view;
325	private Buffer buffer;
326	private Buffer recentBuffer;
327	private BufferSwitcher bufferSwitcher;
328	private JEditTextArea textArea;
329	//}}}
330
331	//{{{ propertiesChanged() method
332	private void propertiesChanged()
333	{
334		TextAreaPainter painter = textArea.getPainter();
335
336		painter.setFont(UIManager.getFont("TextArea.font"));
337		painter.setBracketHighlightEnabled(jEdit.getBooleanProperty(
338			"view.bracketHighlight"));
339		painter.setBracketHighlightColor(
340			jEdit.getColorProperty("view.bracketHighlightColor"));
341		painter.setEOLMarkersPainted(jEdit.getBooleanProperty(
342			"view.eolMarkers"));
343		painter.setEOLMarkerColor(
344			jEdit.getColorProperty("view.eolMarkerColor"));
345		painter.setWrapGuidePainted(jEdit.getBooleanProperty(
346			"view.wrapGuide"));
347		painter.setWrapGuideColor(
348			jEdit.getColorProperty("view.wrapGuideColor"));
349		painter.setCaretColor(
350			jEdit.getColorProperty("view.caretColor"));
351		painter.setSelectionColor(
352			jEdit.getColorProperty("view.selectionColor"));
353		painter.setBackground(
354			jEdit.getColorProperty("view.bgColor"));
355		painter.setForeground(
356			jEdit.getColorProperty("view.fgColor"));
357		painter.setBlockCaretEnabled(jEdit.getBooleanProperty(
358			"view.blockCaret"));
359		painter.setFoldedLineColor(
360			jEdit.getColorProperty("view.foldedLineColor"));
361		painter.setLineHighlightEnabled(jEdit.getBooleanProperty(
362			"view.lineHighlight"));
363		painter.setLineHighlightColor(
364			jEdit.getColorProperty("view.lineHighlightColor"));
365		painter.setAntiAliasEnabled(jEdit.getBooleanProperty(
366			"view.antiAlias"));
367		painter.setFractionalFontMetricsEnabled(jEdit.getBooleanProperty(
368			"view.fracFontMetrics"));
369		painter.setStyles(GUIUtilities.loadStyles(
370			jEdit.getProperty("view.font"),
371			jEdit.getIntegerProperty("view.fontsize",12)));
372
373		Gutter gutter = textArea.getGutter();
374		gutter.setExpanded(jEdit.getBooleanProperty(
375			"view.gutter.lineNumbers"));
376		int interval = jEdit.getIntegerProperty(
377			"view.gutter.highlightInterval",5);
378		gutter.setHighlightInterval(interval);
379		gutter.setCurrentLineHighlightEnabled(jEdit.getBooleanProperty(
380			"view.gutter.highlightCurrentLine"));
381		gutter.setBracketHighlightEnabled(jEdit.getBooleanProperty(
382			"view.gutter.bracketHighlight"));
383		gutter.setBracketHighlightColor(
384			jEdit.getColorProperty("view.gutter.bracketHighlightColor"));
385		gutter.setBackground(
386			jEdit.getColorProperty("view.gutter.bgColor"));
387		gutter.setForeground(
388			jEdit.getColorProperty("view.gutter.fgColor"));
389		gutter.setHighlightedForeground(
390			jEdit.getColorProperty("view.gutter.highlightColor"));
391		gutter.setFoldColor(
392			jEdit.getColorProperty("view.gutter.foldColor"));
393		gutter.setMarkerHighlightColor(
394			jEdit.getColorProperty("view.gutter.markerColor"));
395		gutter.setMarkerHighlightEnabled(jEdit.getBooleanProperty(
396			"view.gutter.markerHighlight"));
397		gutter.setCurrentLineForeground(
398			jEdit.getColorProperty("view.gutter.currentLineColor"));
399		String alignment = jEdit.getProperty(
400			"view.gutter.numberAlignment");
401		if ("right".equals(alignment))
402		{
403			gutter.setLineNumberAlignment(Gutter.RIGHT);
404		}
405		else if ("center".equals(alignment))
406		{
407			gutter.setLineNumberAlignment(Gutter.CENTER);
408		}
409		else // left == default case
410		{
411			gutter.setLineNumberAlignment(Gutter.LEFT);
412		}
413
414		gutter.setFont(jEdit.getFontProperty("view.gutter.font"));
415
416		int width = jEdit.getIntegerProperty(
417			"view.gutter.borderWidth",3);
418		gutter.setBorder(width,
419			jEdit.getColorProperty("view.gutter.focusBorderColor"),
420			jEdit.getColorProperty("view.gutter.noFocusBorderColor"),
421			textArea.getPainter().getBackground());
422
423		textArea.setCaretBlinkEnabled(jEdit.getBooleanProperty(
424			"view.caretBlink"));
425
426		textArea.setElectricScroll(jEdit.getIntegerProperty(
427			"view.electricBorders",0));
428
429		// Set up the right-click popup menu
430		textArea.setRightClickPopup(GUIUtilities
431			.loadPopupMenu("view.context"));
432
433		textArea.setMiddleMousePasteEnabled(jEdit.getBooleanProperty(
434			"view.middleMousePaste"));
435
436		textArea.propertiesChanged();
437	} //}}}
438
439	//{{{ loadBufferSwitcher() method
440	private void loadBufferSwitcher()
441	{
442		if(jEdit.getBooleanProperty("view.showBufferSwitcher"))
443		{
444			if(bufferSwitcher == null)
445			{
446				bufferSwitcher = new BufferSwitcher(this);
447				add(BorderLayout.NORTH,bufferSwitcher);
448				bufferSwitcher.updateBufferList();
449				revalidate();
450			}
451		}
452		else if(bufferSwitcher != null)
453		{
454			remove(bufferSwitcher);
455			revalidate();
456			bufferSwitcher = null;
457		}
458	} //}}}
459
460	//{{{ handleBufferUpdate() method
461	private void handleBufferUpdate(BufferUpdate msg)
462	{
463		Buffer _buffer = msg.getBuffer();
464		if(msg.getWhat() == BufferUpdate.CREATED)
465		{
466			if(bufferSwitcher != null)
467				bufferSwitcher.updateBufferList();
468
469			/* When closing the last buffer, the BufferUpdate.CLOSED
470			 * handler doesn't call setBuffer(), because null buffers
471			 * are not supported. Instead, it waits for the subsequent
472			 * 'Untitled' file creation. */
473			if(buffer.isClosed())
474				setBuffer(jEdit.getFirstBuffer());
475		}
476		else if(msg.getWhat() == BufferUpdate.CLOSED)
477		{
478			if(bufferSwitcher != null)
479				bufferSwitcher.updateBufferList();
480
481			if(_buffer == buffer)
482			{
483				Buffer newBuffer = (recentBuffer != null ?
484					recentBuffer : _buffer.getPrev());
485				if(newBuffer != null && !newBuffer.isClosed())
486					setBuffer(newBuffer);
487				else if(jEdit.getBufferCount() != 0)
488					setBuffer(jEdit.getFirstBuffer());
489
490				recentBuffer = null;
491			}
492			else if(_buffer == recentBuffer)
493				recentBuffer = null;
494		}
495		else if(msg.getWhat() == BufferUpdate.LOAD_STARTED)
496		{
497			if(_buffer == buffer)
498			{
499				textArea.setCaretPosition(0);
500				textArea.getPainter().repaint();
501			}
502		}
503		else if(msg.getWhat() == BufferUpdate.DIRTY_CHANGED)
504		{
505			if(_buffer == buffer)
506			{
507				if(bufferSwitcher != null)
508				{
509					if(buffer.isDirty())
510						bufferSwitcher.repaint();
511					else
512						bufferSwitcher.updateBufferList();
513				}
514			}
515		}
516		else if(msg.getWhat() == BufferUpdate.LOADED)
517		{
518			if(_buffer == buffer)
519			{
520				textArea.repaint();
521				textArea.updateScrollBars();
522				if(bufferSwitcher != null)
523					bufferSwitcher.updateBufferList();
524
525				if(view.getEditPane() == this)
526				{
527					StatusBar status = view.getStatus();
528					status.repaintCaretStatus();
529					status.updateBufferStatus();
530					status.updateMiscStatus();
531				}
532
533				loadCaretInfo();
534			}
535
536		}
537		else if(msg.getWhat() == BufferUpdate.MARKERS_CHANGED)
538		{
539			if(_buffer == buffer)
540				textArea.getGutter().repaint();
541		}
542		else if(msg.getWhat() == BufferUpdate.MODE_CHANGED)
543		{
544			if(_buffer == buffer)
545			{
546				textArea.propertiesChanged();
547
548				if(view.getEditPane() == this)
549					view.getStatus().updateBufferStatus();
550			}
551		}
552		else if(msg.getWhat() == BufferUpdate.ENCODING_CHANGED)
553		{
554			if(_buffer == buffer)
555			{
556				if(view.getEditPane() == this)
557					view.getStatus().updateBufferStatus();
558			}
559		}
560		else if(msg.getWhat() == BufferUpdate.FOLD_HANDLER_CHANGED)
561		{
562			if(_buffer == buffer)
563			{
564				textArea.repaint();
565
566				if(view.getEditPane() == this)
567					view.getStatus().updateMiscStatus();
568			}
569		}
570		else if(msg.getWhat() == BufferUpdate.SAVED)
571		{
572			if(_buffer == buffer)
573				textArea.propertiesChanged();
574		}
575	} //}}}
576
577	//}}}
578}