KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > editor > StatusBar


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.editor;
21
22 import java.awt.Color JavaDoc;
23 import java.awt.Dimension JavaDoc;
24 import java.awt.Font JavaDoc;
25 import java.awt.Insets JavaDoc;
26 import java.awt.GridBagLayout JavaDoc;
27 import java.awt.GridBagConstraints JavaDoc;
28 import java.awt.FontMetrics JavaDoc;
29 import java.awt.event.ActionListener JavaDoc;
30 import java.awt.event.ActionEvent JavaDoc;
31 import java.awt.event.MouseAdapter JavaDoc;
32 import java.awt.event.MouseEvent JavaDoc;
33 import java.beans.PropertyChangeEvent JavaDoc;
34 import java.beans.PropertyChangeListener JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.ArrayList JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.ResourceBundle JavaDoc;
39 import javax.swing.Action JavaDoc;
40 import javax.swing.JPanel JavaDoc;
41 import javax.swing.JLabel JavaDoc;
42 import javax.swing.Timer JavaDoc;
43 import javax.swing.BorderFactory JavaDoc;
44 import javax.swing.JComponent JavaDoc;
45 import javax.swing.SwingConstants JavaDoc;
46 import javax.swing.SwingUtilities JavaDoc;
47 import javax.swing.border.Border JavaDoc;
48 import javax.swing.event.ChangeListener JavaDoc;
49 import javax.swing.event.ChangeEvent JavaDoc;
50 import javax.swing.text.JTextComponent JavaDoc;
51 import javax.swing.text.Caret JavaDoc;
52 import javax.swing.text.Document JavaDoc;
53 import javax.swing.event.DocumentEvent JavaDoc;
54 import javax.swing.event.DocumentListener JavaDoc;
55 import javax.swing.UIManager JavaDoc;
56 import org.openide.util.NbBundle;
57
58 /**
59 * Status bar support
60 *
61 * @author Miloslav Metelka
62 * @version 1.00
63 */

64
65 public class StatusBar implements PropertyChangeListener JavaDoc, SettingsChangeListener, DocumentListener JavaDoc {
66
67     public static final String JavaDoc CELL_MAIN = "main"; // NOI18N
68

69     public static final String JavaDoc CELL_POSITION = "position"; // NOI18N
70

71     public static final String JavaDoc CELL_TYPING_MODE = "typing-mode"; // NOI18N
72

73     public static final String JavaDoc INSERT_LOCALE = "status-bar-insert"; // NOI18N
74

75     public static final String JavaDoc OVERWRITE_LOCALE = "status-bar-overwrite"; // NOI18N
76

77     private static final String JavaDoc[] POS_MAX_STRINGS = new String JavaDoc[] { "99999:999" }; // NOI18N
78

79     private static final Insets JavaDoc NULL_INSETS = new Insets JavaDoc(0, 0, 0, 0);
80
81     static final Border JavaDoc CELL_BORDER =
82     BorderFactory.createCompoundBorder(
83         BorderFactory.createCompoundBorder(
84             BorderFactory.createMatteBorder(1,0,0,0,UIManager.getDefaults().getColor("control")), // NOI18N
85
BorderFactory.createCompoundBorder(
86                 BorderFactory.createMatteBorder(0,0,1,1,UIManager.getDefaults().getColor("controlHighlight")), // NOI18N
87
BorderFactory.createLineBorder(UIManager.getDefaults().getColor("controlDkShadow")) // NOI18N
88
)
89         ),
90         BorderFactory.createEmptyBorder(0, 2, 0, 2)
91     );
92
93     protected EditorUI editorUI;
94
95     /** The status bar panel into which the cells are added. */
96     private JPanel JavaDoc panel;
97
98     private boolean visible;
99
100     private Coloring coloring;
101
102     private Coloring boldColoring;
103
104     private List JavaDoc cellList = new ArrayList JavaDoc();
105
106     private Caret JavaDoc caret;
107
108     private CaretListener caretL;
109
110     private int caretDelay;
111
112     private boolean overwriteModeDisplayed;
113
114     private String JavaDoc insText;
115
116     private String JavaDoc ovrText;
117     
118     private String JavaDoc caretPositionLocaleString;
119     private String JavaDoc insertModeLocaleString;
120     private String JavaDoc overwriteModeLocaleString;
121
122     static final long serialVersionUID =-6266183959929157349L;
123
124     public StatusBar(EditorUI editorUI) {
125         this.editorUI = editorUI;
126
127         caretDelay = 10;
128         caretL = new CaretListener(caretDelay);
129         ResourceBundle JavaDoc bundle = NbBundle.getBundle(BaseKit.class);
130         insText = bundle.getString(INSERT_LOCALE);
131         ovrText = bundle.getString(OVERWRITE_LOCALE);
132         caretPositionLocaleString = bundle.getString("status-bar-caret-position"); //NOI18N
133
insertModeLocaleString = bundle.getString("status-bar-insert-mode"); //NOI18N
134
overwriteModeLocaleString = bundle.getString("status-bar-overwrite-mode"); //NOI18N
135

136         Settings.addSettingsChangeListener(this);
137
138         synchronized (editorUI.getComponentLock()) {
139             // if component already installed in EditorUI simulate installation
140
JTextComponent JavaDoc component = editorUI.getComponent();
141             if (component != null) {
142                 propertyChange(new PropertyChangeEvent JavaDoc(editorUI,
143                                                        EditorUI.COMPONENT_PROPERTY, null, component));
144             }
145
146             editorUI.addPropertyChangeListener(this);
147         }
148     }
149
150     public void settingsChange(SettingsChangeEvent evt) {
151         Class JavaDoc kitClass = Utilities.getKitClass(editorUI.getComponent());
152         String JavaDoc settingName = (evt != null) ? evt.getSettingName() : null;
153         if (kitClass != null) {
154             // #86272: Colorings not based on default editor coloring anymore,
155
// to provide native LF
156
coloring = editorUI.getColoring(SettingsNames.STATUS_BAR_COLORING);
157             boldColoring = editorUI.getColoring(SettingsNames.STATUS_BAR_BOLD_COLORING);
158
159             // #50073
160
SwingUtilities.invokeLater(new Runnable JavaDoc(){
161                 public void run(){
162                     refreshPanel();
163                 }
164             });
165             
166
167             if (settingName == null || SettingsNames.STATUS_BAR_CARET_DELAY.equals(settingName)) {
168                 caretDelay = SettingsUtil.getInteger(kitClass, SettingsNames.STATUS_BAR_CARET_DELAY,
169                                                      SettingsDefaults.defaultStatusBarCaretDelay);
170                 if (caretL != null) {
171                     caretL.setDelay(caretDelay);
172                 }
173             }
174
175             if (settingName == null || SettingsNames.STATUS_BAR_VISIBLE.equals(settingName)) {
176                 boolean wantVisible = SettingsUtil.getBoolean(kitClass,
177                                       SettingsNames.STATUS_BAR_VISIBLE, SettingsDefaults.defaultStatusBarVisible);
178                 setVisible(wantVisible);
179             }
180
181         }
182     }
183     
184     private void documentUndo(DocumentEvent JavaDoc evt) {
185         Utilities.runInEventDispatchThread(new Runnable JavaDoc() {
186             public void run() {
187                 // Clear the main cell
188
setText(CELL_MAIN, "");
189             }
190         });
191     }
192
193     public void insertUpdate(DocumentEvent JavaDoc evt) {
194         if (evt.getType() == DocumentEvent.EventType.REMOVE) { // undo
195
documentUndo(evt);
196         }
197     }
198
199     public void removeUpdate(DocumentEvent JavaDoc evt) {
200         if (evt.getType() == DocumentEvent.EventType.INSERT) { // undo
201
documentUndo(evt);
202         }
203     }
204
205     public void changedUpdate(DocumentEvent JavaDoc evt) {
206     }
207
208
209     protected JPanel JavaDoc createPanel() {
210         return new JPanel JavaDoc(new GridBagLayout JavaDoc());
211     }
212
213     public boolean isVisible() {
214         return visible;
215     }
216
217     public void setVisible(boolean v) {
218         if (v != visible) {
219             visible = v;
220
221             if (panel != null || visible) {
222                 if (visible) { // need to refresh first
223
refreshPanel();
224                 }
225                 // fix for issue 13842
226
if (SwingUtilities.isEventDispatchThread()) {
227                     getPanel().setVisible(visible);
228                 } else {
229                     SwingUtilities.invokeLater(
230                         new Runnable JavaDoc() {
231                             public void run() {
232                                 getPanel().setVisible(visible);
233                             }
234                         }
235                     );
236                 }
237             }
238         }
239     }
240
241     public final JPanel JavaDoc getPanel() {
242         if (panel == null) {
243             panel = createPanel();
244             initPanel();
245         }
246         return panel;
247     }
248
249     protected void initPanel() {
250         JLabel JavaDoc cell = addCell(CELL_POSITION, POS_MAX_STRINGS);
251         cell.setHorizontalAlignment(SwingConstants.CENTER);
252         cell.addMouseListener(new MouseAdapter JavaDoc() {
253             public void mouseClicked(MouseEvent JavaDoc e) {
254                 if (e.getClickCount() == 2) {
255                     Action JavaDoc a = Utilities.getKit(editorUI.getComponent()).getActionByName(org.netbeans.editor.ext.ExtKit.gotoAction);
256                     if (a != null)
257                         a.actionPerformed(new ActionEvent JavaDoc(editorUI.getComponent(), 0, null));
258                 }
259             }
260         });
261         addCell(CELL_TYPING_MODE, new String JavaDoc[] { insText, ovrText }).setHorizontalAlignment(
262             SwingConstants.CENTER);
263         setText(CELL_TYPING_MODE, insText);
264         addCell(CELL_MAIN, null);
265         
266     }
267
268     public void propertyChange(PropertyChangeEvent JavaDoc evt) {
269         String JavaDoc propName = evt.getPropertyName();
270
271         if (EditorUI.COMPONENT_PROPERTY.equals(propName)) {
272             JTextComponent JavaDoc component = (JTextComponent JavaDoc)evt.getNewValue();
273             if (component != null) { // just installed
274
component.addPropertyChangeListener(this);
275
276                 caret = component.getCaret();
277                 if (caret != null) {
278                     caret.addChangeListener(caretL);
279                 }
280                 
281                 Document JavaDoc doc = component.getDocument();
282                 if (doc != null) {
283                     doc.addDocumentListener(this);
284                 }
285
286                 settingsChange(null);
287                 refreshPanel();
288
289             } else { // just deinstalled
290
component = (JTextComponent JavaDoc)evt.getOldValue();
291
292                 component.removePropertyChangeListener(this);
293
294                 caret = component.getCaret();
295                 if (caret != null) {
296                     caret.removeChangeListener(caretL);
297                 }
298
299                 Document JavaDoc doc = component.getDocument();
300                 if (doc != null) {
301                     doc.removeDocumentListener(this);
302                 }
303             }
304
305         } else if ("caret".equals(propName)) { // NOI18N
306
if (caret != null) {
307                 caret.removeChangeListener(caretL);
308             }
309
310             caret = (Caret JavaDoc)evt.getNewValue();
311             if (caret != null) {
312                 caret.addChangeListener(caretL);
313             }
314         } else if ("document".equals(propName)) { // NOI18N
315
Document JavaDoc old = (Document JavaDoc)evt.getOldValue();
316             Document JavaDoc cur = (Document JavaDoc)evt.getNewValue();
317             if (old != null) {
318                 old.removeDocumentListener(this);
319             }
320             if (cur != null) {
321                 cur.addDocumentListener(this);
322             }
323         }
324
325         // Refresh the panel after each property-change
326
if (EditorUI.OVERWRITE_MODE_PROPERTY.equals(propName)) {
327             caretL.actionPerformed(null); // refresh immediately
328

329         } else { // not overwrite mode change
330
caretL.stateChanged(null);
331         }
332     }
333
334     /** #86272: Applies given coloring on cell in special way, stick with default
335      * LF color for status bar cells when foreColor or backColor of Coloring is null
336      */

337     private void applyColoring(Cell cell, Coloring coloring) {
338         coloring.apply(cell);
339         if (coloring.getForeColor() == null) {
340             cell.setForeground(cell.getDefaultForeground());
341         }
342         if (coloring.getBackColor() == null) {
343             cell.setBackground(cell.getDefaultBackground());
344         }
345     }
346
347     public int getCellCount() {
348         return cellList.size();
349     }
350
351     public JLabel JavaDoc addCell(String JavaDoc name, String JavaDoc[] widestStrings) {
352         return addCell(-1, name, widestStrings);
353     }
354
355     public JLabel JavaDoc addCell(int i, String JavaDoc name, String JavaDoc[] widestStrings) {
356         Cell c = new Cell(name, widestStrings);
357         addCellImpl(i, c);
358         return c;
359     }
360
361     public void addCustomCell(int i, JLabel JavaDoc c) {
362         addCellImpl(i, c);
363     }
364
365     private void addCellImpl(int i, JLabel JavaDoc c) {
366         synchronized (cellList) {
367             ArrayList JavaDoc newCellList = new ArrayList JavaDoc(cellList);
368             int cnt = newCellList.size();
369             if (i < 0 || i > cnt) {
370                 i = cnt;
371             }
372             newCellList.add(i, c);
373
374             cellList = newCellList;
375             
376             updateCellBorders(i);
377         }
378
379         refreshPanel();
380     }
381
382     /** Manages cell borders so that left, right and inner cells have properly
383      * assigned borders for various LFs. Borders are special, installed by
384      * core into UIManager maps. */

385     private void updateCellBorders(int addedIndex) {
386         int cellCount = getCellCount();
387         Border JavaDoc innerBorder = (Border JavaDoc)UIManager.get("Nb.Editor.Status.innerBorder"); //NOI18N
388
Border JavaDoc leftBorder = (Border JavaDoc)UIManager.get("Nb.Editor.Status.leftBorder"); //NOI18N
389
Border JavaDoc rightBorder = (Border JavaDoc)UIManager.get("Nb.Editor.Status.rightBorder"); //NOI18N
390
Border JavaDoc onlyOneBorder = (Border JavaDoc)UIManager.get("Nb.Editor.Status.onlyOneBorder"); //NOI18N
391
if ((innerBorder == null) || (leftBorder == null) || (rightBorder == null)
392             || onlyOneBorder == null) {
393             // don't modify borders at all if some is not available
394
return;
395         }
396         if (cellCount == 1) {
397             // only one cell
398
((JLabel JavaDoc)cellList.get(0)).setBorder(onlyOneBorder);
399             return;
400         }
401         if (addedIndex == 0) {
402             // added as first, updates second
403
((JLabel JavaDoc)cellList.get(0)).setBorder(leftBorder);
404             JLabel JavaDoc second = (JLabel JavaDoc)cellList.get(1);
405             second.setBorder(cellCount == 2 ? rightBorder : innerBorder);
406         } else if (addedIndex == cellCount - 1) {
407             // added as last, updates previous
408
((JLabel JavaDoc)cellList.get(cellCount - 1)).setBorder(rightBorder);
409             JLabel JavaDoc previous = (JLabel JavaDoc)cellList.get(cellCount - 2);
410             previous.setBorder(cellCount == 2 ? leftBorder : innerBorder);
411         } else {
412             // cell added inside
413
((JLabel JavaDoc)cellList.get(addedIndex)).setBorder(innerBorder);
414         }
415     }
416
417     public JLabel JavaDoc getCellByName(String JavaDoc name) {
418         Iterator JavaDoc i = cellList.iterator();
419         while (i.hasNext()) {
420             JLabel JavaDoc c = (JLabel JavaDoc)i.next();
421             if (name.equals(c.getName())) {
422                 return c;
423             }
424         }
425         return null;
426     }
427
428     public String JavaDoc getText(String JavaDoc cellName) {
429         JLabel JavaDoc cell = getCellByName(cellName);
430         return (cell != null) ? cell.getText() : null;
431     }
432
433     public void setText(String JavaDoc cellName, String JavaDoc text) {
434         setText(cellName, text, null);
435     }
436
437     public void setBoldText(String JavaDoc cellName, String JavaDoc text) {
438         setText(cellName, text, boldColoring);
439     }
440
441     public void setText(String JavaDoc cellName, String JavaDoc text,
442                         Coloring extraColoring) {
443         JLabel JavaDoc cell = getCellByName(cellName);
444         if (cell != null) {
445             Coloring c = coloring;
446             if (c != null && extraColoring != null) {
447                 c = extraColoring.apply(c);
448             } else if (c == null) {
449                 c = extraColoring;
450             }
451             cell.setText(text);
452             
453             if (CELL_POSITION.equals(cellName)){
454                 cell.setToolTipText(caretPositionLocaleString);
455             }else if (CELL_TYPING_MODE.equals(cellName)){
456                 cell.setToolTipText(insText.equals(text)? insertModeLocaleString : overwriteModeLocaleString);
457             }else{
458                 cell.setToolTipText("".equals(text) ? null : text); //NOI18N
459
}
460             
461             if (c != null && cell instanceof Cell) {
462                 applyColoring((Cell) cell, c);
463             }
464         }
465     }
466
467     /* Refresh the whole panel by removing all the components
468     * and adding only those that appear in the cell-list.
469     */

470     private void refreshPanel() {
471         if (isVisible()) { // refresh only if visible
472
// Apply coloring to all cells
473
Iterator JavaDoc it = cellList.iterator();
474             while (it.hasNext()) {
475                 JLabel JavaDoc c = (JLabel JavaDoc)it.next();
476                 if (c instanceof Cell && coloring != null) {
477                     applyColoring((Cell) c, coloring);
478                 }
479             }
480
481             // Layout cells
482
GridBagConstraints JavaDoc gc = new GridBagConstraints JavaDoc();
483             gc.gridx = GridBagConstraints.RELATIVE;
484             gc.gridwidth = 1;
485             gc.gridheight = 1;
486
487             it = cellList.iterator();
488             while (it.hasNext()) {
489                 JLabel JavaDoc c = (JLabel JavaDoc)it.next();
490                 boolean main = CELL_MAIN.equals(c.getName());
491                 if (main) {
492                     gc.fill = GridBagConstraints.HORIZONTAL;
493                     gc.weightx = 1.0;
494                 }
495                 getPanel().add(c, gc);
496                 if (main) {
497                     gc.fill = GridBagConstraints.NONE;
498                     gc.weightx = 0;
499                 }
500             }
501         }
502     }
503
504     class CaretListener implements ChangeListener JavaDoc, ActionListener JavaDoc {
505
506         Timer JavaDoc timer;
507
508         CaretListener(int delay) {
509             timer = new Timer JavaDoc(delay, new WeakTimerListener(this));
510             timer.setRepeats(false);
511         }
512
513         void setDelay(int delay) {
514             timer.setInitialDelay(delay);
515         }
516
517         public void stateChanged(ChangeEvent JavaDoc evt) {
518             timer.restart();
519         }
520
521         public void actionPerformed(ActionEvent JavaDoc evt) {
522             Caret JavaDoc c = caret;
523             JTextComponent JavaDoc component = editorUI.getComponent();
524
525             if (component != null) {
526                 if (c != null) {
527                     BaseDocument doc = Utilities.getDocument(editorUI.getComponent());
528                     if (doc != null && doc.getDefaultRootElement().getElementCount()>0) {
529                         int pos = c.getDot();
530                         String JavaDoc s = Utilities.debugPosition(doc, pos);
531                         setText(CELL_POSITION, s);
532                     }
533                 }
534
535                 Boolean JavaDoc b = (Boolean JavaDoc)editorUI.getProperty(EditorUI.OVERWRITE_MODE_PROPERTY);
536                 boolean om = (b != null && b.booleanValue());
537                 if (om != overwriteModeDisplayed) {
538                     overwriteModeDisplayed = om;
539                     setText(CELL_TYPING_MODE, overwriteModeDisplayed ? ovrText : insText);
540                 }
541             }
542         }
543
544     }
545
546     static class Cell extends JLabel JavaDoc {
547
548         Dimension JavaDoc maxDimension;
549
550         String JavaDoc[] widestStrings;
551         
552         private final Color JavaDoc defaultBackground;
553         
554         private final Color JavaDoc defaultForeground;
555
556         static final long serialVersionUID =-2554600362177165648L;
557
558         Cell(String JavaDoc name, String JavaDoc[] widestStrings) {
559             setName(name);
560             setBorder(CELL_BORDER);
561             setOpaque(true);
562             this.widestStrings = widestStrings;
563             this.defaultBackground = getBackground();
564             this.defaultForeground = getForeground();
565         }
566         
567         private void updateSize() {
568             Font JavaDoc f = getFont();
569             if (maxDimension == null) {
570                 maxDimension = new Dimension JavaDoc();
571             }
572             if (f != null) {
573                 Border JavaDoc b = getBorder();
574                 Insets JavaDoc ins = (b != null) ? b.getBorderInsets(this) : NULL_INSETS;
575                 FontMetrics JavaDoc fm = getFontMetrics(f);
576                 int mw = fm.stringWidth(this.getText());
577                 maxDimension.height = fm.getHeight() + ins.top + ins.bottom;
578                 if (widestStrings != null) {
579                     for (int i = 0; i < widestStrings.length; i++) {
580                         String JavaDoc widestString = widestStrings[i];
581                         if (widestString == null){
582                             continue;
583                         }
584                         mw = Math.max(mw, fm.stringWidth(widestString));
585                     }
586                 }
587                 maxDimension.width = mw + ins.left + ins.right;
588             }
589         }
590
591         public Dimension JavaDoc getPreferredSize() {
592             if (maxDimension == null) {
593                 maxDimension = new Dimension JavaDoc();
594             }
595             return new Dimension JavaDoc(maxDimension);
596         }
597         
598         public Dimension JavaDoc getMinimumSize(){
599             if (maxDimension == null) {
600                 maxDimension = new Dimension JavaDoc();
601             }
602             return new Dimension JavaDoc(maxDimension);
603         }
604
605         public void setFont(Font JavaDoc f) {
606             super.setFont(f);
607             updateSize();
608         }
609
610         /** Returns default foreground color of the cell, for current LF and theme.
611          * @return Default foreground color
612          */

613         public Color JavaDoc getDefaultForeground () {
614             Color JavaDoc color = (Color JavaDoc) UIManager.get("Label.foreground");
615             return color != null ? color : defaultForeground;
616         }
617         
618         /** Returns default background color of the cell, for current LF and theme.
619          * @return Default background color
620          */

621         public Color JavaDoc getDefaultBackground () {
622             Color JavaDoc color = (Color JavaDoc) UIManager.get("Label.background");
623             return color != null ? color : defaultBackground;
624         }
625
626     }
627
628     public static final class StatusBarFactory implements SideBarFactory {
629         
630         public JComponent JavaDoc createSideBar(JTextComponent JavaDoc target) {
631             return Utilities.getEditorUI(target).getStatusBar().getPanel();
632         }
633         
634         
635     }
636 }
637
Popular Tags