PageRenderTime 66ms CodeModel.GetById 23ms app.highlight 36ms RepoModel.GetById 1ms app.codeStats 0ms

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

#
Java | 583 lines | 418 code | 87 blank | 78 comment | 67 complexity | f2b3e994ba6cb62b4bfd44d2946fce42 MD5 | raw file
  1/*
  2 * StatusBar.java - The status bar displayed at the bottom of views
  3 * :tabSize=8:indentSize=8:noTabs=false:
  4 * :folding=explicit:collapseFolds=1:
  5 *
  6 * Copyright (C) 2001 Slava Pestov
  7 * Portions copyright (C) 2001 mike dillon
  8 *
  9 * This program is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU General Public License
 11 * as published by the Free Software Foundation; either version 2
 12 * of the License, or any later version.
 13 *
 14 * This program is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17 * GNU General Public License for more details.
 18 *
 19 * You should have received a copy of the GNU General Public License
 20 * along with this program; if not, write to the Free Software
 21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 22 */
 23
 24package org.gjt.sp.jedit.gui;
 25
 26//{{{ Imports
 27import javax.swing.border.*;
 28import javax.swing.text.Segment;
 29import javax.swing.*;
 30import java.awt.event.*;
 31import java.awt.*;
 32import org.gjt.sp.jedit.io.*;
 33import org.gjt.sp.jedit.textarea.*;
 34import org.gjt.sp.jedit.*;
 35import org.gjt.sp.util.*;
 36//}}}
 37
 38/**
 39 * The status bar, used for the following:
 40 * <ul>
 41 * <li>Displaying caret position information
 42 * <li>Displaying readNextChar() prompts
 43 * <li>Displaying the status of the overwrite, multi select flags
 44 * <li>I/O progress
 45 * <li>Memory status
 46 * <li>And so on
 47 * </ul>
 48 *
 49 * @version $Id: StatusBar.java 3936 2001-12-21 07:02:14Z spestov $
 50 * @author Slava Pestov
 51 * @since jEdit 3.2pre2
 52 */
 53public class StatusBar extends JPanel implements WorkThreadProgressListener
 54{
 55	//{{{ StatusBar constructor
 56	public StatusBar(View view)
 57	{
 58		super(new BorderLayout(3,3));
 59		setBorder(BorderFactory.createEmptyBorder(3,0,0,0));
 60
 61		this.view = view;
 62
 63		Border border = BorderFactory.createLoweredBevelBorder();
 64
 65		MouseHandler mouseHandler = new MouseHandler();
 66
 67		caretStatus = new VICaretStatus();
 68		caretStatus.setBorder(border);
 69		caretStatus.setToolTipText(jEdit.getProperty("view.status.caret-tooltip"));
 70		caretStatus.addMouseListener(mouseHandler);
 71		add(BorderLayout.WEST,caretStatus);
 72
 73		messagePanel = new JPanel();
 74		messagePanel.setLayout(new BorderLayout(0,0));
 75		messagePanel.setBorder(border);
 76		messagePanel.setPreferredSize(caretStatus.getPreferredSize());
 77		add(BorderLayout.CENTER,messagePanel);
 78
 79		message = new JLabel();
 80		message.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
 81		setMessageComponent(message);
 82
 83		Box box = new Box(BoxLayout.X_AXIS);
 84		mode = new JLabel();
 85		mode.setBorder(border);
 86		mode.setToolTipText(jEdit.getProperty("view.status.mode-tooltip"));
 87		mode.addMouseListener(mouseHandler);
 88		box.add(mode);
 89		box.add(Box.createHorizontalStrut(3));
 90
 91		encoding = new JLabel();
 92		encoding.setBorder(border);
 93		encoding.setToolTipText(jEdit.getProperty("view.status.encoding-tooltip"));
 94		encoding.addMouseListener(mouseHandler);
 95		box.add(encoding);
 96		box.add(Box.createHorizontalStrut(3));
 97
 98		FontMetrics fm = getFontMetrics(UIManager.getFont("Label.font"));
 99
100		foldMode = new JLabel();
101		foldMode.setHorizontalAlignment(SwingConstants.CENTER);
102		foldMode.setBorder(border);
103		foldMode.setToolTipText(jEdit.getProperty("view.status.fold-tooltip"));
104		foldMode.addMouseListener(mouseHandler);
105
106		Dimension dim = foldMode.getPreferredSize();
107		dim.width += Math.max(fm.stringWidth("none"),
108			Math.max(
109			fm.stringWidth("indent"),
110			fm.stringWidth("explicit")));
111		foldMode.setPreferredSize(dim);
112
113		box.add(foldMode);
114		box.add(Box.createHorizontalStrut(3));
115
116		multiSelect = new JLabel();
117		multiSelect.setHorizontalAlignment(SwingConstants.CENTER);
118		multiSelect.setBorder(border);
119		multiSelect.setToolTipText(jEdit.getProperty("view.status.multi-tooltip"));
120		multiSelect.addMouseListener(mouseHandler);
121
122		dim = multiSelect.getPreferredSize();
123		dim.width += Math.max(fm.stringWidth("single"),
124			fm.stringWidth("multi"));
125		multiSelect.setPreferredSize(dim);
126
127		box.add(multiSelect);
128		box.add(Box.createHorizontalStrut(3));
129
130		overwrite = new JLabel();
131		overwrite.setHorizontalAlignment(SwingConstants.CENTER);
132		overwrite.setBorder(border);
133		overwrite.setToolTipText(jEdit.getProperty("view.status.overwrite-tooltip"));
134		overwrite.addMouseListener(mouseHandler);
135
136		dim = overwrite.getPreferredSize();
137		dim.width += Math.max(fm.stringWidth("ovr"),
138			fm.stringWidth("ins"));
139		overwrite.setPreferredSize(dim);
140
141		box.add(overwrite);
142
143		updateBufferStatus();
144		updateMiscStatus();
145
146		box.add(Box.createHorizontalStrut(3));
147		memory = new MemoryStatus();
148		memory.setBorder(border);
149		memory.addMouseListener(mouseHandler);
150		box.add(memory);
151
152		// UI hack because BoxLayout does not give all components the
153		// same height
154		dim = memory.getPreferredSize();
155		dim.width += fm.stringWidth("99Mb/999Mb");
156		dim.height = multiSelect.getPreferredSize().height;
157		memory.setPreferredSize(dim);
158
159		// Leave some room for OS X grow box
160		if(System.getProperty("os.name").indexOf("Mac") != -1)
161			box.add(Box.createHorizontalStrut(18));
162
163		add(BorderLayout.EAST,box);
164	} //}}}
165
166	//{{{ addNotify() method
167	public void addNotify()
168	{
169		super.addNotify();
170		VFSManager.getIOThreadPool().addProgressListener(this);
171	} //}}}
172
173	//{{{ removeNotify() method
174	public void removeNotify()
175	{
176		super.removeNotify();
177		VFSManager.getIOThreadPool().removeProgressListener(this);
178	} //}}}
179
180	//{{{ WorkThreadListener implementation
181
182	//{{{ statusUpdate() method
183	public void statusUpdate(final WorkThreadPool threadPool, int threadIndex)
184	{
185		SwingUtilities.invokeLater(new Runnable()
186		{
187			public void run()
188			{
189				int requestCount = threadPool.getRequestCount();
190				if(requestCount == 0)
191				{
192					setMessageAndClear(jEdit.getProperty(
193						"view.status.io.done"));
194				}
195				else if(requestCount == 1)
196				{
197					setMessage(jEdit.getProperty(
198						"view.status.io-1"));
199				}
200				else
201				{
202					Object[] args = { new Integer(requestCount) };
203					setMessage(jEdit.getProperty(
204						"view.status.io",args));
205				}
206			}
207		});
208	} //}}}
209
210	//{{{ progressUpdate() method
211	public void progressUpdate(WorkThreadPool threadPool, int threadIndex)
212	{
213	} //}}}
214
215	//}}}
216
217	//{{{ setMessageAndClear() method
218	/**
219	 * Show a message for a short period of time.
220	 * @param message The message
221	 * @since jEdit 3.2pre5
222	 */
223	public void setMessageAndClear(String message)
224	{
225		setMessage(message);
226
227		tempTimer = new Timer(0,new ActionListener()
228		{
229			public void actionPerformed(ActionEvent evt)
230			{
231				// so if view is closed in the meantime...
232				if(isShowing())
233					setMessage(null);
234			}
235		});
236
237		tempTimer.setInitialDelay(10000);
238		tempTimer.setRepeats(false);
239		tempTimer.start();
240	} //}}}
241
242	//{{{ setMessage() method
243	public void setMessage(String message)
244	{
245		if(tempTimer != null)
246		{
247			tempTimer.stop();
248			tempTimer = null;
249		}
250
251		setMessageComponent(this.message);
252
253		if(message == null)
254		{
255			InputHandler inputHandler = view.getInputHandler();
256			if(inputHandler.isRepeatEnabled())
257			{
258				int repeatCount = inputHandler.getRepeatCount();
259
260				this.message.setText(jEdit.getProperty("view.status.repeat",
261					new Object[] { repeatCount == 1 ? "" : String.valueOf(repeatCount) }));
262			}
263			else if(view.getMacroRecorder() != null)
264				this.message.setText(jEdit.getProperty("view.status.recording"));
265			else
266				this.message.setText(null);
267		}
268		else
269			this.message.setText(message);
270	} //}}}
271
272	//{{{ setMessageComponent() method
273	public void setMessageComponent(Component comp)
274	{
275		if (comp == null || messageComp == comp)
276		{
277			return;
278		}
279
280		messageComp = comp;
281		messagePanel.add(BorderLayout.CENTER, messageComp);
282	} //}}}
283
284	//{{{ repaintCaretStatus() method
285	public void repaintCaretStatus()
286	{
287		caretStatus.repaint();
288	} //}}}
289
290	//{{{ updateBufferStatus() method
291	public void updateBufferStatus()
292	{
293		Buffer buffer = view.getBuffer();
294		mode.setText(buffer.getMode().getName());
295		encoding.setText(buffer.getStringProperty("encoding"));
296	} //}}}
297
298	//{{{ updateMiscStatus() method
299	public void updateMiscStatus()
300	{
301		JEditTextArea textArea = view.getTextArea();
302
303		multiSelect.setText(textArea.isMultipleSelectionEnabled()
304			? "multi" : "single");
305		overwrite.setText(textArea.isOverwriteEnabled()
306			? "ovr" : "ins");
307		foldMode.setText((String)textArea.getBuffer().getProperty("folding"));
308	} //}}}
309
310	//{{{ Private members
311	private View view;
312	private VICaretStatus caretStatus;
313	private JPanel messagePanel;
314	private Component messageComp;
315	private JLabel message;
316	private JLabel mode;
317	private JLabel encoding;
318	private JLabel foldMode;
319	private JLabel multiSelect;
320	private JLabel overwrite;
321	private MemoryStatus memory;
322	/* package-private for speed */ StringBuffer buf = new StringBuffer();
323	private Timer tempTimer;
324	//}}}
325
326	static final String testStr = "9999,999-999 99%";
327
328	//{{{ MouseHandler class
329	class MouseHandler extends MouseAdapter
330	{
331		//{{{ mouseClicked() method
332		public void mouseClicked(MouseEvent evt)
333		{
334			Object source = evt.getSource();
335			if(source == caretStatus)
336			{
337				if(evt.getClickCount() == 2)
338					view.getTextArea().showGoToLineDialog();
339			}
340			else if(source == mode || source == encoding)
341			{
342				if(evt.getClickCount() == 2)
343					new BufferOptions(view,view.getBuffer());
344			}
345			else if(source == foldMode)
346			{
347				String text = foldMode.getText();
348				if(text.equals("none"))
349					text = "indent";
350				else if(text.equals("indent"))
351					text = "explicit";
352				else if(text.equals("explicit"))
353					text = "none";
354
355				JEditTextArea textArea = view.getTextArea();
356				Buffer buffer = view.getBuffer();
357				buffer.setStringProperty("folding",text);
358				buffer.propertiesChanged();
359
360				int collapseFolds = buffer.getIntegerProperty(
361					"collapseFolds",0);
362				if(collapseFolds != 0)
363				{
364					textArea.getFoldVisibilityManager()
365						.expandFolds(collapseFolds);
366				}
367				else
368				{
369					textArea.getFoldVisibilityManager()
370						.expandAllFolds();
371				}
372			}
373			else if(source == multiSelect)
374				view.getTextArea().toggleMultipleSelectionEnabled();
375			else if(source == overwrite)
376				view.getTextArea().toggleOverwriteEnabled();
377			else if(source == memory)
378			{
379				if(evt.getClickCount() == 2)
380					jEdit.showMemoryDialog(view);
381			}
382		} //}}}
383	} //}}}
384
385	//{{{ VICaretStatus class
386	class VICaretStatus extends JComponent
387	{
388		//{{{ VICaretStatus constructor
389		public VICaretStatus()
390		{
391			VICaretStatus.this.setForeground(UIManager.getColor("Label.foreground"));
392			VICaretStatus.this.setBackground(UIManager.getColor("Label.background"));
393			VICaretStatus.this.setFont(UIManager.getFont("Label.font"));
394
395			Dimension size = new Dimension(
396				VICaretStatus.this.getFontMetrics(
397				VICaretStatus.this.getFont())
398				.stringWidth(testStr),0);
399			VICaretStatus.this.setPreferredSize(size);
400		} //}}}
401
402		//{{{ paintComponent() method
403		public void paintComponent(Graphics g)
404		{
405			Buffer buffer = view.getBuffer();
406
407			if(!buffer.isLoaded())
408				return;
409
410			FontMetrics fm = g.getFontMetrics();
411
412			JEditTextArea textArea = view.getTextArea();
413
414			int currLine = textArea.getCaretLine();
415			int dot = textArea.getCaretPosition()
416				- textArea.getLineStartOffset(currLine);
417			int virtualPosition = getVirtualPosition(dot,buffer,textArea);
418
419			buf.setLength(0);
420			buf.append(Integer.toString(currLine + 1));
421			buf.append(',');
422			buf.append(Integer.toString(dot + 1));
423
424			if (virtualPosition != dot)
425			{
426				buf.append('-');
427				buf.append(Integer.toString(virtualPosition + 1));
428			}
429
430			buf.append(' ');
431
432			int firstLine = textArea.getFirstLine();
433			int visible = textArea.getVisibleLines();
434			int lineCount = textArea.getVirtualLineCount();
435
436			if (visible >= lineCount)
437			{
438				buf.append("All");
439			}
440			else if (firstLine == 0)
441			{
442				buf.append("Top");
443			}
444			else if (firstLine + visible >= lineCount)
445			{
446				buf.append("Bot");
447			}
448			else
449			{
450				float percent = (float)firstLine / (float)lineCount
451					* 100.0f;
452				buf.append(Integer.toString((int)percent));
453				buf.append('%');
454			}
455
456			g.drawString(buf.toString(),
457				VICaretStatus.this.getBorder().getBorderInsets(this).left + 1,
458				(VICaretStatus.this.getHeight() + fm.getAscent()) / 2 - 1);
459		} //}}}
460
461		//{{{ Private members
462		private Segment seg = new Segment();
463
464		//{{{ getVirtualPosition() method
465		private int getVirtualPosition(int dot, Buffer buffer, JEditTextArea textArea)
466		{
467			int line = textArea.getCaretLine();
468
469			textArea.getLineText(line, seg);
470
471			int virtualPosition = 0;
472			int tabSize = buffer.getTabSize();
473
474			for (int i = 0; i < seg.count && i < dot; ++i)
475			{
476				char ch = seg.array[seg.offset + i];
477
478				if (ch == '\t')
479				{
480					virtualPosition += tabSize
481						- (virtualPosition % tabSize);
482				}
483				else
484				{
485					++virtualPosition;
486				}
487			}
488
489			return virtualPosition;
490		} //}}}
491
492		//}}}
493	} //}}}
494
495	//{{{ MemoryStatus class
496	class MemoryStatus extends JComponent implements ActionListener
497	{
498		//{{{ MemoryStatus constructor
499		public MemoryStatus()
500		{
501			MemoryStatus.this.setDoubleBuffered(true);
502			MemoryStatus.this.setForeground(UIManager.getColor("Label.foreground"));
503			MemoryStatus.this.setBackground(UIManager.getColor("Label.background"));
504			MemoryStatus.this.setFont(UIManager.getFont("Label.font"));
505		} //}}}
506
507		//{{{ addNotify() method
508		public void addNotify()
509		{
510			super.addNotify();
511			timer = new Timer(2000,this);
512			timer.start();
513			ToolTipManager.sharedInstance().registerComponent(this);
514		} //}}}
515
516		//{{{ removeNotify() method
517		public void removeNotify()
518		{
519			timer.stop();
520			ToolTipManager.sharedInstance().unregisterComponent(this);
521		} //}}}
522
523		//{{{ getToolTipText() method
524		public String getToolTipText()
525		{
526			Runtime runtime = Runtime.getRuntime();
527			int freeMemory = (int)(runtime.freeMemory() / 1024);
528			int totalMemory = (int)(runtime.totalMemory() / 1024);
529			int usedMemory = (totalMemory - freeMemory);
530			Integer[] args = { new Integer(usedMemory),
531				new Integer(totalMemory) };
532			return jEdit.getProperty("view.status.memory-tooltip",args);
533		} //}}}
534
535		//{{{ actionPerformed() method
536		public void actionPerformed(ActionEvent evt)
537		{
538			MemoryStatus.this.repaint();
539		} //}}}
540
541		//{{{ paintComponent() method
542		public void paintComponent(Graphics g)
543		{
544			Insets insets = MemoryStatus.this.getBorder().getBorderInsets(this);
545
546			Runtime runtime = Runtime.getRuntime();
547			int freeMemory = (int)(runtime.freeMemory() / 1024 / 1024);
548			int totalMemory = (int)(runtime.totalMemory() / 1024 / 1024);
549			int usedMemory = (totalMemory - freeMemory);
550
551			int width = MemoryStatus.this.getWidth()
552				- insets.left - insets.right;
553
554			Color text = MemoryStatus.this.getForeground();
555			Color status = UIManager.getColor("ProgressBar.foreground");
556			if(status.equals(text))
557				g.setXORMode(MemoryStatus.this.getBackground());
558			else
559				g.setColor(status);
560
561			float fraction = ((float)usedMemory) / totalMemory;
562
563			g.fillRect(insets.left,insets.top,
564				(int)(width * fraction),
565				MemoryStatus.this.getHeight()
566				- insets.top - insets.bottom);
567
568			g.setPaintMode();
569
570			g.setColor(text);
571
572			String str = "" + usedMemory + "Mb/"
573				+ totalMemory + "Mb";
574			FontMetrics fm = g.getFontMetrics();
575
576			g.drawString(str,
577				insets.left + (width - fm.stringWidth(str)) / 2,
578				insets.top + fm.getAscent());
579		} //}}}
580
581		private Timer timer;
582	} //}}}
583}