1 19 20 package org.netbeans.editor; 21 22 import java.awt.*; 23 import java.awt.event.ActionEvent ; 24 import java.beans.PropertyChangeListener ; 25 import java.beans.PropertyChangeEvent ; 26 import java.util.List ; 27 import java.util.Iterator ; 28 import javax.swing.text.*; 29 import javax.swing.event.DocumentListener ; 30 import javax.swing.event.DocumentEvent ; 31 import javax.swing.plaf.TextUI ; 32 import javax.swing.JComponent ; 33 import javax.swing.JEditorPane ; 34 import javax.swing.SwingUtilities ; 35 import javax.swing.Action ; 36 import javax.swing.UIManager ; 37 import javax.swing.plaf.basic.BasicTextUI ; 38 import org.netbeans.editor.view.spi.LockView; 39 40 46 47 public class BaseTextUI extends BasicTextUI 48 implements PropertyChangeListener , DocumentListener , SettingsChangeListener { 49 50 51 private EditorUI editorUI; 52 53 private boolean foldingEnabled; 54 55 private boolean needsRefresh = false; 56 57 58 int componentID = -1; 59 60 private AbstractDocument lastDocument; 61 62 63 private static final GetFocusedComponentAction gfcAction 64 = new GetFocusedComponentAction(); 65 66 public BaseTextUI() { 67 } 68 69 protected String getPropertyPrefix() { 70 return "EditorPane"; } 72 73 public static JTextComponent getFocusedComponent() { 74 return gfcAction.getFocusedComponent2(); 75 } 76 77 protected boolean isRootViewReplaceNecessary() { 78 boolean replaceNecessary = false; 79 80 Document doc = getComponent().getDocument(); 81 if (doc != lastDocument) { 82 replaceNecessary = true; 83 } 84 85 return replaceNecessary; 86 } 87 88 protected void rootViewReplaceNotify() { 89 lastDocument = (AbstractDocument)getComponent().getDocument(); 91 } 92 93 94 protected void modelChanged() { 95 JTextComponent component = getComponent(); 96 Document doc = component.getDocument(); 98 99 if (doc != null && !(doc instanceof AbstractDocument)) { 100 return; } 103 AbstractDocument adoc = (AbstractDocument)doc; 104 105 131 132 if (doc != null) { 133 ViewFactory f = getRootView(component).getViewFactory(); 134 BaseKit kit = (BaseKit)getEditorKit(component); 135 136 component.removeAll(); 137 138 if (isRootViewReplaceNecessary()) { 139 rootViewReplaceNotify(); 140 Element elem = doc.getDefaultRootElement(); 141 View v = f.create(elem); 142 setView(v); 143 } 144 145 component.revalidate(); 146 147 Settings.KitAndValue[] kv = Settings.getValueHierarchy(kit.getClass(), 149 SettingsNames.DOC_INSTALL_ACTION_NAME_LIST); 150 for (int i = kv.length - 1; i >= 0; i--) { 151 List actList = (List )kv[i].value; 152 actList = kit.translateActionNameList(actList); if (actList != null) { 154 for (Iterator iter = actList.iterator(); iter.hasNext();) { 155 Action a = (Action )iter.next(); 156 a.actionPerformed(new ActionEvent (component, 157 ActionEvent.ACTION_PERFORMED, "")); } 159 } 160 } 161 } 162 } 163 164 165 170 protected void installKeyboardActions() { 171 String mapName = getPropertyPrefix() + ".actionMap"; UIManager.getLookAndFeelDefaults().put(mapName, null); 176 UIManager.getDefaults().put(mapName, null); super.installKeyboardActions(); 178 } 179 180 181 public void installUI(JComponent c) { 182 super.installUI(c); 183 184 if (!(c instanceof JTextComponent)) { 185 return; 186 } 187 188 JTextComponent component = getComponent(); 189 190 Object value = Settings.getValue(Utilities.getKitClass(component), SettingsNames.MARGIN); 192 Insets margin = (value instanceof Insets) ? (Insets)value : null; 193 component.setMargin(margin); 194 195 getEditorUI().installUI(component); 196 Boolean foldingEnabledBoolean = (Boolean )Settings.getValue(Utilities.getKitClass(component), SettingsNames.CODE_FOLDING_ENABLE); 197 foldingEnabled = foldingEnabledBoolean.booleanValue(); 198 component.putClientProperty(SettingsNames.CODE_FOLDING_ENABLE, foldingEnabledBoolean); 199 200 Settings.addSettingsChangeListener(this); 201 202 if (component.getClientProperty(UIWatcher.class) == null) { 205 UIWatcher uiWatcher = new UIWatcher(this.getClass()); 206 component.addPropertyChangeListener(uiWatcher); 207 component.putClientProperty(UIWatcher.class, uiWatcher); 208 } 209 210 BaseKit kit = (BaseKit)getEditorKit(component); 211 ViewFactory vf = kit.getViewFactory(); 212 Caret caret = kit.createCaret(); 214 component.setCaretColor(Color.black); component.setCaret(caret); 216 217 int br = SettingsUtil.getInteger(Utilities.getKitClass(component), SettingsNames.CARET_BLINK_RATE, 219 SettingsDefaults.defaultCaretBlinkRate.intValue()); 220 caret.setBlinkRate(br); 221 222 228 229 SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_FOCUSED, null); 230 231 Registry.addComponent(component); 232 Registry.activate(component); 233 component.setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); 234 } 235 236 237 public void uninstallUI(JComponent c) { 238 super.uninstallUI(c); 239 240 Settings.removeSettingsChangeListener(this); 241 243 if (c instanceof JTextComponent){ 244 JTextComponent comp = (JTextComponent)c; 245 BaseDocument doc = Utilities.getDocument(comp); 246 if (doc != null) { 247 doc.removeDocumentListener(this); 248 } 249 250 comp.setKeymap(null); 251 comp.setCaret(null); 252 253 getEditorUI().uninstallUI(comp); 254 Registry.removeComponent(comp); 255 } 256 257 editorUI = null; 260 } 261 262 public int getYFromPos(int pos) throws BadLocationException { 263 Rectangle ret = modelToView(getComponent(), pos); 264 return (ret == null) ? 0 : ret.y; 265 272 } 273 274 public int getPosFromY(int y) throws BadLocationException { 275 return viewToModel(getComponent(), 0, y); 276 } 277 278 public int getBaseX(int y) { 279 return getEditorUI().getTextMargin().left; 280 } 281 282 public int viewToModel(JTextComponent c, int x, int y) { 283 return viewToModel(c, new Point(x, y)); 284 } 285 286 287 290 public int getNextVisualPositionFrom(JTextComponent t, int pos, 291 Position.Bias b, int direction, Position.Bias[] biasRet) 292 throws BadLocationException{ 293 if (biasRet == null) { 294 biasRet = new Position.Bias[1]; 295 biasRet[0] = Position.Bias.Forward; 296 } 297 return super.getNextVisualPositionFrom(t, pos, b, direction, biasRet); 298 } 299 300 301 302 306 public EditorKit getEditorKit(JTextComponent c) { 307 JEditorPane pane = (JEditorPane )getComponent(); 308 return (pane==null) ? null : pane.getEditorKit(); 309 } 310 311 312 313 public EditorUI getEditorUI() { 314 if (editorUI == null) { 315 JTextComponent c = getComponent(); 316 BaseKit kit = (BaseKit)getEditorKit(c); 317 editorUI = kit.createEditorUI(); 318 editorUI.initLineHeight(c); 319 } 320 return editorUI; 321 } 322 323 327 public void propertyChange(PropertyChangeEvent evt) { 328 String propName = evt.getPropertyName(); 329 if ("document".equals(propName)) { BaseDocument oldDoc = (evt.getOldValue() instanceof BaseDocument) 331 ? (BaseDocument)evt.getOldValue() : null; 332 333 if (oldDoc != null) { 334 oldDoc.removeDocumentListener(this); 335 } 336 337 BaseDocument newDoc = (evt.getNewValue() instanceof BaseDocument) 338 ? (BaseDocument)evt.getNewValue() : null; 339 340 if (newDoc != null) { 341 newDoc.addDocumentListener(this); 342 Registry.activate(newDoc); } 344 } else if ("ancestor".equals(propName)) { JTextComponent comp = (JTextComponent)evt.getSource(); 346 if (comp.isDisplayable() && editorUI != null && editorUI.hasExtComponent()) { 347 if (!Boolean.TRUE.equals(comp.getClientProperty("ancestorOverride"))) { comp.putClientProperty("ancestorOverride", Boolean.TRUE); } 353 } 354 } 355 } 356 357 358 public void insertUpdate(DocumentEvent evt) { 359 try { 360 BaseDocumentEvent bevt = (BaseDocumentEvent)evt; 361 EditorUI editorUI = getEditorUI(); 362 int y = getYFromPos(evt.getOffset()); 363 int lineHeight = editorUI.getLineHeight(); 364 int syntaxY = getYFromPos(bevt.getSyntaxUpdateOffset()); 365 if (bevt.getSyntaxUpdateOffset() == evt.getDocument().getLength()) { 367 syntaxY += lineHeight; 368 } 369 if (getComponent().isShowing()) { 370 editorUI.repaint(y, Math.max(lineHeight, syntaxY - y)); 371 } 372 } catch (BadLocationException ex) { 373 Utilities.annotateLoggable(ex); 374 } 375 } 376 377 378 public void removeUpdate(DocumentEvent evt) { 379 try { 380 BaseDocumentEvent bevt = (BaseDocumentEvent)evt; 381 EditorUI editorUI = getEditorUI(); 382 int y = getYFromPos(evt.getOffset()); 383 int lineHeight = editorUI.getLineHeight(); 384 int syntaxY = getYFromPos(bevt.getSyntaxUpdateOffset()); 385 if (bevt.getSyntaxUpdateOffset() == evt.getDocument().getLength()) { 387 syntaxY += lineHeight; 388 } 389 if (getComponent().isShowing()) { 390 editorUI.repaint(y, Math.max(lineHeight, syntaxY - y)); 391 } 392 393 } catch (BadLocationException ex) { 394 Utilities.annotateLoggable(ex); 395 } 396 } 397 398 402 public void changedUpdate(DocumentEvent evt) { 403 if (evt instanceof BaseDocumentEvent) { 404 BaseDocumentEvent bdevt = (BaseDocumentEvent)evt; 405 BaseDocument doc = (BaseDocument)bdevt.getDocument(); 406 String layerName = bdevt.getDrawLayerName(); 407 if (layerName != null) { 408 getEditorUI().addLayer(doc.findLayer(layerName), 409 bdevt.getDrawLayerVisibility()); 410 }else{ try { 412 JTextComponent comp = getComponent(); 413 if (comp!=null && comp.isShowing()) { 414 getEditorUI().repaintBlock(evt.getOffset(), evt.getOffset() + evt.getLength()); 415 } 416 } catch (BadLocationException ex) { 417 Utilities.annotateLoggable(ex); 418 } 419 } 420 } 421 } 422 423 424 425 430 public View create(Element elem) { 431 String kind = elem.getName(); 432 443 444 if (kind != null) { 445 if (kind.equals(AbstractDocument.ContentElementName)) { 446 return new LabelView(elem); 447 } else if (kind.equals(AbstractDocument.ParagraphElementName)) { 448 return new DrawEngineLineView(elem); } else if (kind.equals(AbstractDocument.SectionElementName)) { 451 return new LockView(new DrawEngineDocView(elem)); } else if (kind.equals(StyleConstants.ComponentElementName)) { 456 return new ComponentView(elem); 457 } else if (kind.equals(StyleConstants.IconElementName)) { 458 return new IconView(elem); 459 } 460 } 461 462 return new DrawEngineLineView(elem); 464 } 465 466 472 public View create(Element elem, int p0, int p1) { 473 return null; 474 } 475 476 477 public void preferenceChanged(boolean width, boolean height) { 478 modelChanged(); 479 } 480 481 public void invalidateStartY() { 482 } 484 485 public void settingsChange(SettingsChangeEvent evt) { 486 JTextComponent component = getComponent(); 487 if (component == null) return; 488 489 if (evt == null || Utilities.getKitClass(component) != evt.getKitClass()) return; 490 491 if (SettingsNames.CODE_FOLDING_ENABLE.equals(evt.getSettingName())){ 492 Boolean foldingEnabledBoolean =(Boolean )Settings.getValue(evt.getKitClass(), SettingsNames.CODE_FOLDING_ENABLE); 493 foldingEnabled = foldingEnabledBoolean.booleanValue(); 494 component.putClientProperty(SettingsNames.CODE_FOLDING_ENABLE, foldingEnabledBoolean); 495 needsRefresh = true; 496 Utilities.runInEventDispatchThread(new Runnable () { 497 public void run() { 498 refresh(); 499 } 500 }); 501 } 502 } 503 504 boolean isFoldingEnabled() { 505 return foldingEnabled; 506 } 507 508 protected void refresh(){ 509 if (getComponent().isShowing() && needsRefresh){ 510 modelChanged(); 511 needsRefresh = false; 512 } 513 } 514 515 private static class GetFocusedComponentAction extends TextAction { 516 517 private GetFocusedComponentAction() { 518 super("get-focused-component"); } 520 521 public void actionPerformed(ActionEvent evt) { 522 } 523 524 JTextComponent getFocusedComponent2() { 525 return super.getFocusedComponent(); 526 } 527 528 } 529 530 class EditorUIBoxView extends BoxView{ 531 public EditorUIBoxView(Element elem, int axis){ 532 super(elem, axis); 533 } 534 535 private DrawEngine.PreinitializedDrawEngine getPreinitializedDrawEngine(Graphics g){ 536 DrawEngine.PreinitializedDrawEngine drawEngine = null; 537 538 Rectangle clip = g.getClipBounds(); 539 if (clip.height <= 0 || clip.width < 0) { 540 return null; 541 } 542 543 int clipY = clip.y; 544 int clipHeight = clip.height; 545 int paintY = Math.max(clipY, 0); 547 BaseDocument doc = (BaseDocument)getEditorUI().getDocument(); 548 try { 549 int startPos = getPosFromY(paintY); 550 int pos = getPosFromY(clipY + clipHeight - 1); 551 int endPos = Utilities.getRowEnd(doc, pos); 552 553 int startOffset = startPos; 554 int endOffset = endPos; 555 int y = getYFromPos(startOffset); 556 557 if (endOffset > startOffset){ 558 drawEngine = DrawEngine.getDrawEngine().getDrawEngine( 559 this, 560 new DrawGraphics.GraphicsDG(g), 561 getEditorUI(), 562 startOffset, 563 endOffset, 564 getBaseX(y), 565 y, 566 Integer.MAX_VALUE 567 ); 568 } 569 }catch(BadLocationException ble){ 570 ble.printStackTrace(); 571 } 572 return drawEngine; 573 } 574 575 public void paint(Graphics g, Shape allocation) { 576 super.paint(g, allocation); 577 DrawEngine.PreinitializedDrawEngine pde = null; 578 JTextComponent component = getComponent(); 579 580 try{ 581 pde = getPreinitializedDrawEngine(g); 582 583 if (component!=null){ 585 component.putClientProperty(DrawEngine.PreinitializedDrawEngine.class, pde); } 587 588 getEditorUI().paint(g); 589 590 }finally{ 591 if (pde!=null) pde.release(); 593 if (component!=null){ 594 component.putClientProperty(DrawEngine.PreinitializedDrawEngine.class, null); 595 } 596 } 597 } 598 } 599 600 static void uninstallUIWatcher(JTextComponent c) { 601 UIWatcher uiWatcher = (UIWatcher)c.getClientProperty(UIWatcher.class); 602 if (uiWatcher != null) { 603 c.removePropertyChangeListener(uiWatcher); 604 c.putClientProperty(UIWatcher.class, null); 605 } 606 } 607 608 611 static class UIWatcher implements PropertyChangeListener { 612 613 private Class uiClass; 614 615 UIWatcher(Class uiClass) { 616 this.uiClass = uiClass; 617 } 618 619 public void propertyChange(PropertyChangeEvent evt) { 620 Object newValue = evt.getNewValue(); 621 if ("UI".equals(evt.getPropertyName()) 622 && (newValue != null) && !(newValue instanceof BaseTextUI) 623 ) { 624 JTextComponent c = (JTextComponent)evt.getSource(); 625 EditorKit kit = ((TextUI )newValue).getEditorKit(c); 626 if (kit instanceof BaseKit) { 627 try { 629 c.setUI((BaseTextUI)uiClass.newInstance()); 630 } catch (InstantiationException e) { 631 } catch (IllegalAccessException e) { 632 } 633 } 634 } 635 } 636 637 } 638 639 } 640 | Popular Tags |