Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/gjt/sp/jedit/gui/StatusBar.java


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