1 19 20 package org.netbeans.editor; 21 22 import java.awt.Color ; 23 import java.awt.Dimension ; 24 import java.awt.Font ; 25 import java.awt.Insets ; 26 import java.awt.GridBagLayout ; 27 import java.awt.GridBagConstraints ; 28 import java.awt.FontMetrics ; 29 import java.awt.event.ActionListener ; 30 import java.awt.event.ActionEvent ; 31 import java.awt.event.MouseAdapter ; 32 import java.awt.event.MouseEvent ; 33 import java.beans.PropertyChangeEvent ; 34 import java.beans.PropertyChangeListener ; 35 import java.util.List ; 36 import java.util.ArrayList ; 37 import java.util.Iterator ; 38 import java.util.ResourceBundle ; 39 import javax.swing.Action ; 40 import javax.swing.JPanel ; 41 import javax.swing.JLabel ; 42 import javax.swing.Timer ; 43 import javax.swing.BorderFactory ; 44 import javax.swing.JComponent ; 45 import javax.swing.SwingConstants ; 46 import javax.swing.SwingUtilities ; 47 import javax.swing.border.Border ; 48 import javax.swing.event.ChangeListener ; 49 import javax.swing.event.ChangeEvent ; 50 import javax.swing.text.JTextComponent ; 51 import javax.swing.text.Caret ; 52 import javax.swing.text.Document ; 53 import javax.swing.event.DocumentEvent ; 54 import javax.swing.event.DocumentListener ; 55 import javax.swing.UIManager ; 56 import org.openide.util.NbBundle; 57 58 64 65 public class StatusBar implements PropertyChangeListener , SettingsChangeListener, DocumentListener { 66 67 public static final String CELL_MAIN = "main"; 69 public static final String CELL_POSITION = "position"; 71 public static final String CELL_TYPING_MODE = "typing-mode"; 73 public static final String INSERT_LOCALE = "status-bar-insert"; 75 public static final String OVERWRITE_LOCALE = "status-bar-overwrite"; 77 private static final String [] POS_MAX_STRINGS = new String [] { "99999:999" }; 79 private static final Insets NULL_INSETS = new Insets (0, 0, 0, 0); 80 81 static final Border CELL_BORDER = 82 BorderFactory.createCompoundBorder( 83 BorderFactory.createCompoundBorder( 84 BorderFactory.createMatteBorder(1,0,0,0,UIManager.getDefaults().getColor("control")), BorderFactory.createCompoundBorder( 86 BorderFactory.createMatteBorder(0,0,1,1,UIManager.getDefaults().getColor("controlHighlight")), BorderFactory.createLineBorder(UIManager.getDefaults().getColor("controlDkShadow")) ) 89 ), 90 BorderFactory.createEmptyBorder(0, 2, 0, 2) 91 ); 92 93 protected EditorUI editorUI; 94 95 96 private JPanel panel; 97 98 private boolean visible; 99 100 private Coloring coloring; 101 102 private Coloring boldColoring; 103 104 private List cellList = new ArrayList (); 105 106 private Caret caret; 107 108 private CaretListener caretL; 109 110 private int caretDelay; 111 112 private boolean overwriteModeDisplayed; 113 114 private String insText; 115 116 private String ovrText; 117 118 private String caretPositionLocaleString; 119 private String insertModeLocaleString; 120 private String 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 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"); insertModeLocaleString = bundle.getString("status-bar-insert-mode"); overwriteModeLocaleString = bundle.getString("status-bar-overwrite-mode"); 136 Settings.addSettingsChangeListener(this); 137 138 synchronized (editorUI.getComponentLock()) { 139 JTextComponent component = editorUI.getComponent(); 141 if (component != null) { 142 propertyChange(new PropertyChangeEvent (editorUI, 143 EditorUI.COMPONENT_PROPERTY, null, component)); 144 } 145 146 editorUI.addPropertyChangeListener(this); 147 } 148 } 149 150 public void settingsChange(SettingsChangeEvent evt) { 151 Class kitClass = Utilities.getKitClass(editorUI.getComponent()); 152 String settingName = (evt != null) ? evt.getSettingName() : null; 153 if (kitClass != null) { 154 coloring = editorUI.getColoring(SettingsNames.STATUS_BAR_COLORING); 157 boldColoring = editorUI.getColoring(SettingsNames.STATUS_BAR_BOLD_COLORING); 158 159 SwingUtilities.invokeLater(new Runnable (){ 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 evt) { 185 Utilities.runInEventDispatchThread(new Runnable () { 186 public void run() { 187 setText(CELL_MAIN, ""); 189 } 190 }); 191 } 192 193 public void insertUpdate(DocumentEvent evt) { 194 if (evt.getType() == DocumentEvent.EventType.REMOVE) { documentUndo(evt); 196 } 197 } 198 199 public void removeUpdate(DocumentEvent evt) { 200 if (evt.getType() == DocumentEvent.EventType.INSERT) { documentUndo(evt); 202 } 203 } 204 205 public void changedUpdate(DocumentEvent evt) { 206 } 207 208 209 protected JPanel createPanel() { 210 return new JPanel (new GridBagLayout ()); 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) { refreshPanel(); 224 } 225 if (SwingUtilities.isEventDispatchThread()) { 227 getPanel().setVisible(visible); 228 } else { 229 SwingUtilities.invokeLater( 230 new Runnable () { 231 public void run() { 232 getPanel().setVisible(visible); 233 } 234 } 235 ); 236 } 237 } 238 } 239 } 240 241 public final JPanel getPanel() { 242 if (panel == null) { 243 panel = createPanel(); 244 initPanel(); 245 } 246 return panel; 247 } 248 249 protected void initPanel() { 250 JLabel cell = addCell(CELL_POSITION, POS_MAX_STRINGS); 251 cell.setHorizontalAlignment(SwingConstants.CENTER); 252 cell.addMouseListener(new MouseAdapter () { 253 public void mouseClicked(MouseEvent e) { 254 if (e.getClickCount() == 2) { 255 Action a = Utilities.getKit(editorUI.getComponent()).getActionByName(org.netbeans.editor.ext.ExtKit.gotoAction); 256 if (a != null) 257 a.actionPerformed(new ActionEvent (editorUI.getComponent(), 0, null)); 258 } 259 } 260 }); 261 addCell(CELL_TYPING_MODE, new String [] { 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 evt) { 269 String propName = evt.getPropertyName(); 270 271 if (EditorUI.COMPONENT_PROPERTY.equals(propName)) { 272 JTextComponent component = (JTextComponent )evt.getNewValue(); 273 if (component != null) { component.addPropertyChangeListener(this); 275 276 caret = component.getCaret(); 277 if (caret != null) { 278 caret.addChangeListener(caretL); 279 } 280 281 Document doc = component.getDocument(); 282 if (doc != null) { 283 doc.addDocumentListener(this); 284 } 285 286 settingsChange(null); 287 refreshPanel(); 288 289 } else { component = (JTextComponent )evt.getOldValue(); 291 292 component.removePropertyChangeListener(this); 293 294 caret = component.getCaret(); 295 if (caret != null) { 296 caret.removeChangeListener(caretL); 297 } 298 299 Document doc = component.getDocument(); 300 if (doc != null) { 301 doc.removeDocumentListener(this); 302 } 303 } 304 305 } else if ("caret".equals(propName)) { if (caret != null) { 307 caret.removeChangeListener(caretL); 308 } 309 310 caret = (Caret )evt.getNewValue(); 311 if (caret != null) { 312 caret.addChangeListener(caretL); 313 } 314 } else if ("document".equals(propName)) { Document old = (Document )evt.getOldValue(); 316 Document cur = (Document )evt.getNewValue(); 317 if (old != null) { 318 old.removeDocumentListener(this); 319 } 320 if (cur != null) { 321 cur.addDocumentListener(this); 322 } 323 } 324 325 if (EditorUI.OVERWRITE_MODE_PROPERTY.equals(propName)) { 327 caretL.actionPerformed(null); 329 } else { caretL.stateChanged(null); 331 } 332 } 333 334 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 addCell(String name, String [] widestStrings) { 352 return addCell(-1, name, widestStrings); 353 } 354 355 public JLabel addCell(int i, String name, String [] widestStrings) { 356 Cell c = new Cell(name, widestStrings); 357 addCellImpl(i, c); 358 return c; 359 } 360 361 public void addCustomCell(int i, JLabel c) { 362 addCellImpl(i, c); 363 } 364 365 private void addCellImpl(int i, JLabel c) { 366 synchronized (cellList) { 367 ArrayList newCellList = new ArrayList (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 385 private void updateCellBorders(int addedIndex) { 386 int cellCount = getCellCount(); 387 Border innerBorder = (Border )UIManager.get("Nb.Editor.Status.innerBorder"); Border leftBorder = (Border )UIManager.get("Nb.Editor.Status.leftBorder"); Border rightBorder = (Border )UIManager.get("Nb.Editor.Status.rightBorder"); Border onlyOneBorder = (Border )UIManager.get("Nb.Editor.Status.onlyOneBorder"); if ((innerBorder == null) || (leftBorder == null) || (rightBorder == null) 392 || onlyOneBorder == null) { 393 return; 395 } 396 if (cellCount == 1) { 397 ((JLabel )cellList.get(0)).setBorder(onlyOneBorder); 399 return; 400 } 401 if (addedIndex == 0) { 402 ((JLabel )cellList.get(0)).setBorder(leftBorder); 404 JLabel second = (JLabel )cellList.get(1); 405 second.setBorder(cellCount == 2 ? rightBorder : innerBorder); 406 } else if (addedIndex == cellCount - 1) { 407 ((JLabel )cellList.get(cellCount - 1)).setBorder(rightBorder); 409 JLabel previous = (JLabel )cellList.get(cellCount - 2); 410 previous.setBorder(cellCount == 2 ? leftBorder : innerBorder); 411 } else { 412 ((JLabel )cellList.get(addedIndex)).setBorder(innerBorder); 414 } 415 } 416 417 public JLabel getCellByName(String name) { 418 Iterator i = cellList.iterator(); 419 while (i.hasNext()) { 420 JLabel c = (JLabel )i.next(); 421 if (name.equals(c.getName())) { 422 return c; 423 } 424 } 425 return null; 426 } 427 428 public String getText(String cellName) { 429 JLabel cell = getCellByName(cellName); 430 return (cell != null) ? cell.getText() : null; 431 } 432 433 public void setText(String cellName, String text) { 434 setText(cellName, text, null); 435 } 436 437 public void setBoldText(String cellName, String text) { 438 setText(cellName, text, boldColoring); 439 } 440 441 public void setText(String cellName, String text, 442 Coloring extraColoring) { 443 JLabel 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); } 460 461 if (c != null && cell instanceof Cell) { 462 applyColoring((Cell) cell, c); 463 } 464 } 465 } 466 467 470 private void refreshPanel() { 471 if (isVisible()) { Iterator it = cellList.iterator(); 474 while (it.hasNext()) { 475 JLabel c = (JLabel )it.next(); 476 if (c instanceof Cell && coloring != null) { 477 applyColoring((Cell) c, coloring); 478 } 479 } 480 481 GridBagConstraints gc = new GridBagConstraints (); 483 gc.gridx = GridBagConstraints.RELATIVE; 484 gc.gridwidth = 1; 485 gc.gridheight = 1; 486 487 it = cellList.iterator(); 488 while (it.hasNext()) { 489 JLabel c = (JLabel )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 , ActionListener { 505 506 Timer timer; 507 508 CaretListener(int delay) { 509 timer = new Timer (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 evt) { 518 timer.restart(); 519 } 520 521 public void actionPerformed(ActionEvent evt) { 522 Caret c = caret; 523 JTextComponent 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 s = Utilities.debugPosition(doc, pos); 531 setText(CELL_POSITION, s); 532 } 533 } 534 535 Boolean b = (Boolean )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 { 547 548 Dimension maxDimension; 549 550 String [] widestStrings; 551 552 private final Color defaultBackground; 553 554 private final Color defaultForeground; 555 556 static final long serialVersionUID =-2554600362177165648L; 557 558 Cell(String name, String [] 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 f = getFont(); 569 if (maxDimension == null) { 570 maxDimension = new Dimension (); 571 } 572 if (f != null) { 573 Border b = getBorder(); 574 Insets ins = (b != null) ? b.getBorderInsets(this) : NULL_INSETS; 575 FontMetrics 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 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 getPreferredSize() { 592 if (maxDimension == null) { 593 maxDimension = new Dimension (); 594 } 595 return new Dimension (maxDimension); 596 } 597 598 public Dimension getMinimumSize(){ 599 if (maxDimension == null) { 600 maxDimension = new Dimension (); 601 } 602 return new Dimension (maxDimension); 603 } 604 605 public void setFont(Font f) { 606 super.setFont(f); 607 updateSize(); 608 } 609 610 613 public Color getDefaultForeground () { 614 Color color = (Color ) UIManager.get("Label.foreground"); 615 return color != null ? color : defaultForeground; 616 } 617 618 621 public Color getDefaultBackground () { 622 Color color = (Color ) 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 createSideBar(JTextComponent target) { 631 return Utilities.getEditorUI(target).getStatusBar().getPanel(); 632 } 633 634 635 } 636 } 637 | Popular Tags |