PageRenderTime 110ms CodeModel.GetById 49ms app.highlight 56ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre14/org/gjt/sp/jedit/gui/StatusBar.java

#
Java | 842 lines | 588 code | 126 blank | 128 comment | 95 complexity | e66ef813d24bae68ac940641450cdb86 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, 2004 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.font.*;
 32import java.awt.geom.*;
 33import java.awt.*;
 34import java.text.*;
 35import java.util.Calendar;
 36import java.util.Date;
 37import org.gjt.sp.jedit.io.*;
 38import org.gjt.sp.jedit.textarea.*;
 39import org.gjt.sp.jedit.*;
 40import org.gjt.sp.util.*;
 41//}}}
 42
 43/**
 44 * The status bar used to display various information to the user.<p>
 45 *
 46 * Currently, it is used for the following:
 47 * <ul>
 48 * <li>Displaying caret position information
 49 * <li>Displaying {@link InputHandler#readNextChar(String,String)} prompts
 50 * <li>Displaying {@link #setMessage(String)} messages
 51 * <li>Displaying I/O progress
 52 * <li>Displaying various editor settings
 53 * <li>Displaying memory status
 54 * </ul>
 55 *
 56 * @version $Id: StatusBar.java 4998 2004-03-20 06:08:50Z spestov $
 57 * @author Slava Pestov
 58 * @since jEdit 3.2pre2
 59 */
 60public class StatusBar extends JPanel implements WorkThreadProgressListener
 61{
 62	//{{{ StatusBar constructor
 63	public StatusBar(View view)
 64	{
 65		super(new BorderLayout());
 66		setBorder(new CompoundBorder(new EmptyBorder(4,0,0,
 67			(OperatingSystem.isMacOS() ? 18 : 0)),
 68			UIManager.getBorder("TextField.border")));
 69
 70		this.view = view;
 71
 72		panel = new JPanel(new BorderLayout());
 73		box = new Box(BoxLayout.X_AXIS);
 74		panel.add(BorderLayout.EAST,box);
 75		add(BorderLayout.CENTER,panel);
 76
 77		MouseHandler mouseHandler = new MouseHandler();
 78
 79		caretStatus = new ToolTipLabel();
 80		caretStatus.setToolTipText(jEdit.getProperty("view.status.caret-tooltip"));
 81		caretStatus.addMouseListener(mouseHandler);
 82
 83		message = new JLabel(" ");
 84		setMessageComponent(message);
 85
 86		mode = new ToolTipLabel();
 87		mode.setToolTipText(jEdit.getProperty("view.status.mode-tooltip"));
 88		mode.addMouseListener(mouseHandler);
 89
 90		wrap = new ToolTipLabel();
 91		wrap.setHorizontalAlignment(SwingConstants.CENTER);
 92		wrap.setToolTipText(jEdit.getProperty("view.status.wrap-tooltip"));
 93		wrap.addMouseListener(mouseHandler);
 94
 95		multiSelect = new ToolTipLabel();
 96		multiSelect.setHorizontalAlignment(SwingConstants.CENTER);
 97		multiSelect.setToolTipText(jEdit.getProperty("view.status.multi-tooltip"));
 98		multiSelect.addMouseListener(mouseHandler);
 99
100		rectSelect = new ToolTipLabel();
101		rectSelect.setHorizontalAlignment(SwingConstants.CENTER);
102		rectSelect.setToolTipText(jEdit.getProperty("view.status.rect-tooltip"));
103		rectSelect.addMouseListener(mouseHandler);
104
105		overwrite = new ToolTipLabel();
106		overwrite.setHorizontalAlignment(SwingConstants.CENTER);
107		overwrite.setToolTipText(jEdit.getProperty("view.status.overwrite-tooltip"));
108		overwrite.addMouseListener(mouseHandler);
109
110		lineSep = new ToolTipLabel();
111		lineSep.setHorizontalAlignment(SwingConstants.CENTER);
112		lineSep.setToolTipText(jEdit.getProperty("view.status.linesep-tooltip"));
113		lineSep.addMouseListener(mouseHandler);
114	} //}}}
115
116	//{{{ propertiesChanged() method
117	public void propertiesChanged()
118	{
119		Color fg = jEdit.getColorProperty("view.status.foreground");
120		Color bg = jEdit.getColorProperty("view.status.background");
121
122		showCaretStatus = jEdit.getBooleanProperty("view.status.show-caret-status");
123		showEditMode = jEdit.getBooleanProperty("view.status.show-edit-mode");
124		showFoldMode = jEdit.getBooleanProperty("view.status.show-fold-mode");
125		showEncoding = jEdit.getBooleanProperty("view.status.show-encoding");
126		showWrap = jEdit.getBooleanProperty("view.status.show-wrap");
127		showMultiSelect = jEdit.getBooleanProperty("view.status.show-multi-select");
128		showRectSelect = jEdit.getBooleanProperty("view.status.show-rect-select");
129		showOverwrite = jEdit.getBooleanProperty("view.status.show-overwrite");
130		showLineSeperator = jEdit.getBooleanProperty("view.status.show-line-seperator");
131		boolean showMemory = jEdit.getBooleanProperty("view.status.show-memory");
132		boolean showClock = jEdit.getBooleanProperty("view.status.show-clock");
133
134		panel.setBackground(bg);
135		panel.setForeground(fg);
136		caretStatus.setBackground(bg);
137		caretStatus.setForeground(fg);
138		message.setBackground(bg);
139		message.setForeground(fg);
140		mode.setBackground(bg);
141		mode.setForeground(fg);
142		wrap.setBackground(bg);
143		wrap.setForeground(fg);
144		multiSelect.setBackground(bg);
145		multiSelect.setForeground(fg);
146		rectSelect.setBackground(bg);
147		rectSelect.setForeground(fg);
148		overwrite.setBackground(bg);
149		overwrite.setForeground(fg);
150		lineSep.setBackground(bg);
151		lineSep.setForeground(fg);
152
153		// retarded GTK look and feel!
154		Font font = new JLabel().getFont();
155		//UIManager.getFont("Label.font");
156		FontMetrics fm = getFontMetrics(font);
157		Dimension dim = null;
158
159		if (showCaretStatus)
160		{
161			panel.add(BorderLayout.WEST,caretStatus);
162
163			caretStatus.setFont(font);
164
165			dim = new Dimension(fm.stringWidth(caretTestStr),
166				fm.getHeight());
167                        caretStatus.setPreferredSize(dim);
168		}
169		else
170			panel.remove(caretStatus);
171
172		box.removeAll();
173
174		if (showEncoding || showEditMode || showFoldMode)
175			box.add(mode);
176
177		if (showWrap)
178		{
179			dim = new Dimension(Math.max(
180				Math.max(fm.charWidth('-'),fm.charWidth('H')),
181				fm.charWidth('S')) + 1,fm.getHeight());
182			wrap.setPreferredSize(dim);
183			wrap.setMaximumSize(dim);
184			box.add(wrap);
185		}
186
187		if (showMultiSelect)
188		{
189			dim = new Dimension(
190				Math.max(fm.charWidth('-'),fm.charWidth('M')) + 1,
191				fm.getHeight());
192			multiSelect.setPreferredSize(dim);
193			multiSelect.setMaximumSize(dim);
194			box.add(multiSelect);
195		}
196
197		if (showRectSelect)
198		{
199			dim = new Dimension(
200				Math.max(fm.charWidth('-'),fm.charWidth('R')) + 1,
201				fm.getHeight());
202			rectSelect.setPreferredSize(dim);
203			rectSelect.setMaximumSize(dim);
204			box.add(rectSelect);
205		}
206
207		if (showOverwrite)
208		{
209			dim = new Dimension(
210				Math.max(fm.charWidth('-'),fm.charWidth('O')) + 1,
211				fm.getHeight());
212			overwrite.setPreferredSize(dim);
213			overwrite.setMaximumSize(dim);
214			box.add(overwrite);
215		}
216
217		if (showLineSeperator)
218		{
219			dim = new Dimension(Math.max(
220				Math.max(fm.charWidth('U'),
221				fm.charWidth('W')),
222				fm.charWidth('M')) + 1,
223				fm.getHeight());
224			lineSep.setPreferredSize(dim);
225			lineSep.setMaximumSize(dim);
226			box.add(lineSep);
227		}
228
229		if (showMemory)
230			box.add(new MemoryStatus());
231
232		if (showClock)
233			box.add(new Clock());
234
235		updateBufferStatus();
236		updateMiscStatus();
237	} //}}}
238
239	//{{{ addNotify() method
240	public void addNotify()
241	{
242		super.addNotify();
243		VFSManager.getIOThreadPool().addProgressListener(this);
244	} //}}}
245
246	//{{{ removeNotify() method
247	public void removeNotify()
248	{
249		super.removeNotify();
250		VFSManager.getIOThreadPool().removeProgressListener(this);
251	} //}}}
252
253	//{{{ WorkThreadListener implementation
254
255	//{{{ statusUpdate() method
256	public void statusUpdate(final WorkThreadPool threadPool, int threadIndex)
257	{
258		SwingUtilities.invokeLater(new Runnable()
259		{
260			public void run()
261			{
262				// don't obscure existing message
263				if(message != null && !"".equals(message.getText().trim())
264					&& !currentMessageIsIO)
265					return;
266
267				int requestCount = threadPool.getRequestCount();
268				if(requestCount == 0)
269				{
270					setMessageAndClear(jEdit.getProperty(
271						"view.status.io.done"));
272					currentMessageIsIO = true;
273				}
274				else if(requestCount == 1)
275				{
276					setMessage(jEdit.getProperty(
277						"view.status.io-1"));
278					currentMessageIsIO = true;
279				}
280				else
281				{
282					Object[] args = { new Integer(requestCount) };
283					setMessage(jEdit.getProperty(
284						"view.status.io",args));
285					currentMessageIsIO = true;
286				}
287			}
288		});
289	} //}}}
290
291	//{{{ progressUpdate() method
292	public void progressUpdate(WorkThreadPool threadPool, int threadIndex)
293	{
294	} //}}}
295
296	//}}}
297
298	//{{{ setMessageAndClear() method
299	/**
300	 * Show a message for a short period of time.
301	 * @param message The message
302	 * @since jEdit 3.2pre5
303	 */
304	public void setMessageAndClear(String message)
305	{
306		setMessage(message);
307
308		tempTimer = new Timer(0,new ActionListener()
309		{
310			public void actionPerformed(ActionEvent evt)
311			{
312				// so if view is closed in the meantime...
313				if(isShowing())
314					setMessage(null);
315			}
316		});
317
318		tempTimer.setInitialDelay(10000);
319		tempTimer.setRepeats(false);
320		tempTimer.start();
321	} //}}}
322
323	//{{{ setMessage() method
324	/**
325	 * Displays a status message.
326	 */
327	public void setMessage(String message)
328	{
329		if(tempTimer != null)
330		{
331			tempTimer.stop();
332			tempTimer = null;
333		}
334
335		setMessageComponent(this.message);
336
337		if(message == null)
338		{
339			InputHandler inputHandler = view.getInputHandler();
340			/* if(inputHandler.isRepeatEnabled())
341			{
342				int repeatCount = inputHandler.getRepeatCount();
343
344				this.message.setText(jEdit.getProperty("view.status.repeat",
345					new Object[] { repeatCount == 1 ? "" : String.valueOf(repeatCount) }));
346			}
347			else */ if(view.getMacroRecorder() != null)
348				this.message.setText(jEdit.getProperty("view.status.recording"));
349			else
350				this.message.setText(" ");
351		}
352		else
353			this.message.setText(message);
354	} //}}}
355
356	//{{{ setMessageComponent() method
357	public void setMessageComponent(Component comp)
358	{
359		currentMessageIsIO = false;
360
361		if (comp == null || messageComp == comp)
362		{
363			return;
364		}
365
366		messageComp = comp;
367		panel.add(BorderLayout.CENTER, messageComp);
368	} //}}}
369
370	//{{{ updateCaretStatus() method
371	public void updateCaretStatus()
372	{
373		//if(!isShowing())
374		//	return;
375
376		if (showCaretStatus)
377		{
378			Buffer buffer = view.getBuffer();
379
380			if(!buffer.isLoaded() ||
381				/* can happen when switching buffers sometimes */
382				buffer != view.getTextArea().getBuffer())
383			{
384				caretStatus.setText(" ");
385				return;
386			}
387
388			JEditTextArea textArea = view.getTextArea();
389
390			int currLine = textArea.getCaretLine();
391
392			// there must be a better way of fixing this...
393			// the problem is that this method can sometimes
394			// be called as a result of a text area scroll
395			// event, in which case the caret position has
396			// not been updated yet.
397			if(currLine >= buffer.getLineCount())
398				return; // hopefully another caret update will come?
399
400			int start = textArea.getLineStartOffset(currLine);
401			int dot = textArea.getCaretPosition() - start;
402
403			// see above
404			if(dot < 0)
405				return;
406
407			buffer.getText(start,dot,seg);
408			int virtualPosition = MiscUtilities.getVirtualWidth(seg,
409				buffer.getTabSize());
410
411			buf.setLength(0);
412			buf.append(Integer.toString(currLine + 1));
413			buf.append(',');
414			buf.append(Integer.toString(dot + 1));
415
416			if (virtualPosition != dot)
417			{
418				buf.append('-');
419				buf.append(Integer.toString(virtualPosition + 1));
420			}
421
422			buf.append(' ');
423
424			int firstLine = textArea.getFirstLine();
425			int visible = textArea.getVisibleLines();
426			int lineCount = textArea.getDisplayManager().getScrollLineCount();
427
428			if (visible >= lineCount)
429			{
430				buf.append("All");
431			}
432			else if (firstLine == 0)
433			{
434				buf.append("Top");
435			}
436			else if (firstLine + visible >= lineCount)
437			{
438				buf.append("Bot");
439			}
440			else
441			{
442				float percent = (float)firstLine / (float)lineCount
443					* 100.0f;
444				buf.append(Integer.toString((int)percent));
445				buf.append('%');
446			}
447
448			caretStatus.setText(buf.toString());
449		}
450	} //}}}
451
452	//{{{ updateBufferStatus() method
453	public void updateBufferStatus()
454	{
455		//if(!isShowing())
456		//	return;
457
458		Buffer buffer = view.getBuffer();
459
460		if (showWrap)
461		{
462			String wrap = buffer.getStringProperty("wrap");
463			if(wrap.equals("none"))
464				this.wrap.setText("-");
465			else if(wrap.equals("hard"))
466				this.wrap.setText("H");
467			else if(wrap.equals("soft"))
468				this.wrap.setText("S");
469		}
470
471		if (showLineSeperator)
472		{
473			String lineSep = buffer.getStringProperty("lineSeparator");
474			if("\n".equals(lineSep))
475				this.lineSep.setText("U");
476			else if("\r\n".equals(lineSep))
477				this.lineSep.setText("W");
478			else if("\r".equals(lineSep))
479				this.lineSep.setText("M");
480		}
481
482		if (showEditMode || showFoldMode || showEncoding)
483		{
484			/* This doesn't look pretty and mode line should
485			 * probably be split up into seperate
486			 * components/strings
487			 */
488			buf.setLength(0);
489
490			if (buffer.isLoaded())
491			{
492				if (showEditMode)
493					buf.append(buffer.getMode().getName());
494				if (showFoldMode)
495				{
496					if (showEditMode)
497						buf.append(",");
498					buf.append((String)view.getBuffer().getProperty("folding"));
499				}
500				if (showEncoding)
501				{
502					if (showEditMode || showFoldMode)
503						buf.append(",");
504					buf.append(buffer.getStringProperty("encoding"));
505				}
506			}
507
508			mode.setText("(" + buf.toString() + ")");
509		}
510	} //}}}
511
512	//{{{ updateMiscStatus() method
513	public void updateMiscStatus()
514	{
515		//if(!isShowing())
516		//	return;
517
518		JEditTextArea textArea = view.getTextArea();
519
520		if (showMultiSelect)
521			multiSelect.setText(textArea.isMultipleSelectionEnabled()
522				? "M" : "-");
523
524		if (showRectSelect)
525			rectSelect.setText(textArea.isRectangularSelectionEnabled()
526				? "R" : "-");
527
528		if (showOverwrite)
529			overwrite.setText(textArea.isOverwriteEnabled()
530				? "O" : "-");
531	} //}}}
532
533	//{{{ Private members
534	private View view;
535	private JPanel panel;
536	private Box box;
537	private ToolTipLabel caretStatus;
538	private Component messageComp;
539	private JLabel message;
540	private JLabel mode;
541	private JLabel wrap;
542	private JLabel multiSelect;
543	private JLabel rectSelect;
544	private JLabel overwrite;
545	private JLabel lineSep;
546	/* package-private for speed */ StringBuffer buf = new StringBuffer();
547	private Timer tempTimer;
548	private boolean currentMessageIsIO;
549
550	private Segment seg = new Segment();
551
552	private boolean showCaretStatus;
553	private boolean showEditMode;
554	private boolean showFoldMode;
555	private boolean showEncoding;
556	private boolean showWrap;
557	private boolean showMultiSelect;
558	private boolean showRectSelect;
559	private boolean showOverwrite;
560	private boolean showLineSeperator;
561	//}}}
562
563	static final String caretTestStr = "9999,999-999 99%";
564
565	//{{{ MouseHandler class
566	class MouseHandler extends MouseAdapter
567	{
568		public void mouseClicked(MouseEvent evt)
569		{
570			Buffer buffer = view.getBuffer();
571
572			Object source = evt.getSource();
573			if(source == caretStatus)
574			{
575				if(evt.getClickCount() == 2)
576					view.getTextArea().showGoToLineDialog();
577			}
578			else if(source == mode)
579			{
580				if(evt.getClickCount() == 2)
581					new BufferOptions(view,view.getBuffer());
582			}
583			else if(source == wrap)
584				buffer.toggleWordWrap(view);
585			else if(source == multiSelect)
586				view.getTextArea().toggleMultipleSelectionEnabled();
587			else if(source == rectSelect)
588				view.getTextArea().toggleRectangularSelectionEnabled();
589			else if(source == overwrite)
590				view.getTextArea().toggleOverwriteEnabled();
591			else if(source == lineSep)
592				buffer.toggleLineSeparator(view);
593		}
594	} //}}}
595
596	//{{{ ToolTipLabel class
597	class ToolTipLabel extends JLabel
598	{
599		//{{{ getToolTipLocation() method
600		public Point getToolTipLocation(MouseEvent event)
601		{
602			return new Point(event.getX(),-20);
603		} //}}}
604	} //}}}
605
606	//{{{ MemoryStatus class
607	class MemoryStatus extends JComponent implements ActionListener
608	{
609		//{{{ MemoryStatus constructor
610		public MemoryStatus()
611		{
612			// fucking GTK look and feel
613			Font font = new JLabel().getFont();
614			//Font font = UIManager.getFont("Label.font");
615			MemoryStatus.this.setFont(font);
616
617			FontRenderContext frc = new FontRenderContext(
618				null,false,false);
619			Rectangle2D bounds = font.getStringBounds(		
620				memoryTestStr,frc);
621			Dimension dim = new Dimension((int)bounds.getWidth(),
622				(int)bounds.getHeight());
623			setPreferredSize(dim);
624			setMaximumSize(dim);
625			lm = font.getLineMetrics(memoryTestStr,frc);
626
627			setForeground(jEdit.getColorProperty("view.status.foreground"));
628			setBackground(jEdit.getColorProperty("view.status.background"));
629
630			progressForeground = jEdit.getColorProperty(
631				"view.status.memory.foreground");
632			progressBackground = jEdit.getColorProperty(
633				"view.status.memory.background");
634
635			addMouseListener(new MouseHandler());
636		} //}}}
637
638		//{{{ addNotify() method
639		public void addNotify()
640		{
641			super.addNotify();
642			timer = new Timer(2000,this);
643			timer.start();
644			ToolTipManager.sharedInstance().registerComponent(this);
645		} //}}}
646
647		//{{{ removeNotify() method
648		public void removeNotify()
649		{
650			timer.stop();
651			ToolTipManager.sharedInstance().unregisterComponent(this);
652			super.removeNotify();
653		} //}}}
654
655		//{{{ getToolTipText() method
656		public String getToolTipText()
657		{
658			Runtime runtime = Runtime.getRuntime();
659			int freeMemory = (int)(runtime.freeMemory() / 1024);
660			int totalMemory = (int)(runtime.totalMemory() / 1024);
661			int usedMemory = (totalMemory - freeMemory);
662			Integer[] args = { new Integer(usedMemory),
663				new Integer(totalMemory) };
664			return jEdit.getProperty("view.status.memory-tooltip",args);
665		} //}}}
666
667		//{{{ getToolTipLocation() method
668		public Point getToolTipLocation(MouseEvent event)
669		{
670			return new Point(event.getX(),-20);
671		} //}}}
672
673		//{{{ actionPerformed() method
674		public void actionPerformed(ActionEvent evt)
675		{
676			MemoryStatus.this.repaint();
677		} //}}}
678
679		//{{{ paintComponent() method
680		public void paintComponent(Graphics g)
681		{
682			Insets insets = new Insets(0,0,0,0);//MemoryStatus.this.getBorder().getBorderInsets(this);
683
684			Runtime runtime = Runtime.getRuntime();
685			int freeMemory = (int)(runtime.freeMemory() / 1024);
686			int totalMemory = (int)(runtime.totalMemory() / 1024);
687			int usedMemory = (totalMemory - freeMemory);
688
689			int width = MemoryStatus.this.getWidth()
690				- insets.left - insets.right;
691			int height = MemoryStatus.this.getHeight()
692				- insets.top - insets.bottom - 1;
693
694			float fraction = ((float)usedMemory) / totalMemory;
695
696			g.setColor(progressBackground);
697
698			g.fillRect(insets.left,insets.top,
699				(int)(width * fraction),
700				height);
701
702			String str = (usedMemory / 1024) + "/"
703				+ (totalMemory / 1024) + "Mb";
704
705			FontRenderContext frc = new FontRenderContext(null,false,false);
706
707			Rectangle2D bounds = g.getFont().getStringBounds(str,frc);
708		
709			Graphics g2 = g.create();
710			g2.setClip(insets.left,insets.top,
711				(int)(width * fraction),
712				height);
713
714			g2.setColor(progressForeground);
715
716			g2.drawString(str,
717				insets.left + (int)(width - bounds.getWidth()) / 2,
718				(int)(insets.top + lm.getAscent()));
719
720			g2.dispose();
721
722			g2 = g.create();
723
724			g2.setClip(insets.left + (int)(width * fraction),
725				insets.top,MemoryStatus.this.getWidth()
726				- insets.left - (int)(width * fraction),
727				height);
728
729			g2.setColor(MemoryStatus.this.getForeground());
730
731			g2.drawString(str,
732				insets.left + (int)(width - bounds.getWidth()) / 2,
733				(int)(insets.top + lm.getAscent()));
734
735			g2.dispose();
736		} //}}}
737
738		//{{{ Private members
739		private static final String memoryTestStr = "999/999Mb";
740
741		private LineMetrics lm;
742		private Color progressForeground;
743		private Color progressBackground;
744
745		private Timer timer;
746		//}}}
747
748		//{{{ MouseHandler class
749		class MouseHandler extends MouseAdapter
750		{
751			public void mousePressed(MouseEvent evt)
752			{
753				if(evt.getClickCount() == 2)
754				{
755					jEdit.showMemoryDialog(view);
756					repaint();
757				}
758			}
759		} //}}}
760	} //}}}
761
762	//{{{ Clock class
763	class Clock extends JLabel implements ActionListener
764	{
765		//{{{ Clock constructor
766		public Clock()
767		{
768			/* FontRenderContext frc = new FontRenderContext(
769				null,false,false);
770			Rectangle2D bounds = getFont()
771				.getStringBounds(getTime(),frc);
772			Dimension dim = new Dimension((int)bounds.getWidth(),
773				(int)bounds.getHeight());
774			setPreferredSize(dim);
775			setMaximumSize(dim); */
776
777			setForeground(jEdit.getColorProperty("view.status.foreground"));
778			setBackground(jEdit.getColorProperty("view.status.background"));
779		} //}}}
780
781		//{{{ addNotify() method
782		public void addNotify()
783		{
784			super.addNotify();
785			update();
786
787			int millisecondsPerMinute = 1000 * 60;
788
789			timer = new Timer(millisecondsPerMinute,this);
790			timer.setInitialDelay((int)(
791				millisecondsPerMinute
792				- System.currentTimeMillis()
793				% millisecondsPerMinute) + 500);
794			timer.start();
795			ToolTipManager.sharedInstance().registerComponent(this);
796		} //}}}
797
798		//{{{ removeNotify() method
799		public void removeNotify()
800		{
801			timer.stop();
802			ToolTipManager.sharedInstance().unregisterComponent(this);
803			super.removeNotify();
804		} //}}}
805
806		//{{{ getToolTipText() method
807		public String getToolTipText()
808		{
809			return new Date().toString();
810		} //}}}
811
812		//{{{ getToolTipLocation() method
813		public Point getToolTipLocation(MouseEvent event)
814		{
815			return new Point(event.getX(),-20);
816		} //}}}
817
818		//{{{ actionPerformed() method
819		public void actionPerformed(ActionEvent evt)
820		{
821			update();
822		} //}}}
823
824		//{{{ Private members
825		private Timer timer;
826
827		//{{{ getTime() method
828		private String getTime()
829		{
830			return DateFormat.getTimeInstance(
831				DateFormat.SHORT).format(new Date());
832		} //}}}
833
834		//{{{ update() method
835		private void update()
836		{
837			setText(getTime());
838		} //}}}
839
840		//}}}
841	} //}}}
842}