1 19 20 package org.netbeans.editor; 21 22 import java.awt.Graphics ; 23 import java.awt.Shape ; 24 import java.awt.event.ActionEvent ; 25 import java.awt.event.ActionListener ; 26 import java.beans.PropertyChangeListener ; 27 import java.util.ArrayList ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import javax.swing.Timer ; 31 import javax.swing.plaf.TextUI ; 32 import javax.swing.text.AbstractDocument ; 33 import javax.swing.text.Element ; 34 import javax.swing.text.JTextComponent ; 35 import javax.swing.text.View ; 36 import javax.swing.text.ViewFactory ; 37 import org.netbeans.api.editor.fold.Fold; 38 import org.netbeans.api.editor.fold.FoldHierarchy; 39 import org.netbeans.api.editor.fold.FoldUtilities; 40 import org.netbeans.api.editor.fold.FoldHierarchyEvent; 41 import org.netbeans.api.editor.fold.FoldHierarchyListener; 42 import org.netbeans.lib.editor.view.GapDocumentView; 43 import org.netbeans.editor.view.spi.LockView; 44 45 50 class DrawEngineDocView extends GapDocumentView 51 implements FoldHierarchyListener, PropertyChangeListener { 52 53 private static final boolean debugRebuild 54 = Boolean.getBoolean("netbeans.debug.editor.view.rebuild"); 56 private FoldHierarchy foldHierarchy; 57 58 private EditorUI editorUI; 59 60 private Iterator collapsedFoldIterator; 61 private Fold collapsedFold; 62 private int collapsedFoldStartOffset; 63 private int collapsedFoldEndOffset; 64 65 private boolean collapsedFoldsInPresentViews; 66 67 private boolean estimatedSpanResetInitiated; 68 69 DrawEngineDocView(Element elem) { 70 super(elem); 71 72 setEstimatedSpan(true); 73 } 74 75 public void setParent(View parent) { 76 if (parent != null) { JTextComponent component = (JTextComponent )parent.getContainer(); 78 foldHierarchy = FoldHierarchy.get(component); 79 foldHierarchy.addFoldHierarchyListener(this); 80 TextUI tui = component.getUI(); 81 if (tui instanceof BaseTextUI){ 82 editorUI = ((BaseTextUI)tui).getEditorUI(); 83 if (editorUI!=null){ 84 editorUI.addPropertyChangeListener(this); 85 } 86 } 87 } 88 89 super.setParent(parent); 90 91 if (parent == null) { 92 foldHierarchy.removeFoldHierarchyListener(this); 93 foldHierarchy = null; 94 if (editorUI!=null){ 95 editorUI.removePropertyChangeListener(this); 96 editorUI = null; 97 } 98 } 99 } 100 101 protected void attachListeners(){ 102 if (foldHierarchy != null) { 103 } 104 } 105 106 private FoldHierarchy getFoldHierarchy() { 107 return foldHierarchy; 108 } 109 110 protected boolean useCustomReloadChildren() { 111 return true; 112 } 113 114 122 protected Fold nextCollapsedFold() { 123 while (true) { 124 Fold fold = collapsedFoldIterator.hasNext() ? (Fold)collapsedFoldIterator.next() : null; 125 126 if (fold != null) { 128 collapsedFoldStartOffset = fold.getStartOffset(); 129 collapsedFoldEndOffset = fold.getEndOffset(); 130 136 if (collapsedFoldStartOffset == collapsedFoldEndOffset) { 137 if (debugRebuild) { 138 System.err.println( 139 "GapBoxView.nextCollapsedFold(): ignored empty fold " + fold 141 ); 142 } 143 continue; } 145 146 if (collapsedFoldEndOffset > getDocument().getLength()) { 147 155 fold = null; 156 } 157 } 158 159 if (fold != null) { 160 collapsedFoldsInPresentViews = true; 161 } 162 163 return fold; 164 } 165 } 166 167 170 protected void initCustomReloadChildren(FoldHierarchy hierarchy, 171 int startOffset, int endOffset) { 172 collapsedFoldIterator = FoldUtilities.collapsedFoldIterator(hierarchy, startOffset, endOffset); 173 collapsedFold = nextCollapsedFold(); 174 } 175 176 179 protected void finishCustomReloadChildren(FoldHierarchy hierarchy) { 180 collapsedFoldIterator = null; 181 collapsedFold = null; 182 } 183 184 protected void customReloadChildren(int index, int removeLength, int startOffset, int endOffset) { 185 if (index == 0 && removeLength == getViewCount()) { 187 collapsedFoldsInPresentViews = false; } 189 190 FoldHierarchy hierarchy = getFoldHierarchy(); 191 if (hierarchy != null) { 193 hierarchy.lock(); 194 try { 195 initCustomReloadChildren(hierarchy, startOffset, endOffset); 196 197 super.customReloadChildren(index, removeLength, startOffset, endOffset); 198 199 finishCustomReloadChildren(hierarchy); 200 201 } finally { 202 hierarchy.unlock(); 203 } 204 } 205 } 206 207 protected View createCustomView(ViewFactory f, 208 int startOffset, int maxEndOffset, int elementIndex) { 209 if (elementIndex == -1) { 210 throw new IllegalStateException ("Need underlying line element structure"); } 212 213 View view = null; 214 215 Element elem = getElement(); 216 Element lineElem = elem.getElement(elementIndex); 217 boolean createCollapsed = (collapsedFold != null); 218 219 if (createCollapsed) { int lineElemEndOffset = lineElem.getEndOffset(); 221 createCollapsed = (collapsedFoldStartOffset < lineElemEndOffset); 222 if (createCollapsed) { Element firstLineElem = lineElem; 224 List foldAndEndLineElemList = new ArrayList (); 225 226 while (true) { 227 int collapsedFoldEndOffset = collapsedFold.getEndOffset(); 228 while (collapsedFoldEndOffset > lineElemEndOffset) { 230 elementIndex++; 231 lineElem = elem.getElement(elementIndex); 232 lineElemEndOffset = lineElem.getEndOffset(); 233 } 234 235 foldAndEndLineElemList.add(collapsedFold); 236 foldAndEndLineElemList.add(lineElem); 237 238 collapsedFold = nextCollapsedFold(); 239 240 if (collapsedFold == null || collapsedFoldStartOffset >= lineElemEndOffset) { 242 break; 243 } 244 } 245 246 view = new FoldMultiLineView(firstLineElem, foldAndEndLineElemList); 248 } 249 } 250 251 if (!createCollapsed) { 252 view = f.create(lineElem); 253 } 254 255 return view; 256 } 257 258 public void foldHierarchyChanged(FoldHierarchyEvent evt) { 259 LockView lockView = LockView.get(this); 260 lockView.lock(); 261 try { 262 layoutLock(); 263 try { 264 FoldHierarchy hierarchy = (FoldHierarchy)evt.getSource(); 265 if (hierarchy.getComponent().getDocument() != lockView.getDocument()) { 266 return; 270 } 271 272 boolean rebuildViews = true; 273 int affectedStartOffset = evt.getAffectedStartOffset(); 274 int affectedEndOffset = evt.getAffectedEndOffset(); 275 276 if (!collapsedFoldsInPresentViews) { if (FoldUtilities.findCollapsedFold(hierarchy, 281 affectedStartOffset, affectedEndOffset) == null 282 ) { rebuildViews = false; 284 } 285 } 286 287 if (rebuildViews) { 288 291 int docLength = getDocument().getLength(); 292 int rebuildStartOffset = Math.min(affectedStartOffset, docLength); 293 int rebuildEndOffset = Math.min(affectedEndOffset, docLength); 294 offsetRebuild(rebuildStartOffset, rebuildEndOffset); 295 } 296 } finally { 297 updateLayout(); 298 layoutUnlock(); 299 } 300 } finally { 301 lockView.unlock(); 302 } 303 } 304 305 public void paint(Graphics g, Shape allocation) { 306 java.awt.Component c = getContainer(); 307 if (c instanceof javax.swing.text.JTextComponent ){ 308 TextUI textUI = ((javax.swing.text.JTextComponent )c).getUI(); 309 if (textUI instanceof BaseTextUI){ 310 ((BaseTextUI) textUI).getEditorUI().paint(g); 311 } 312 } 313 314 super.paint(g, allocation); 315 } 316 317 public void setSize(float width, float height) { 318 super.setSize(width, height); 319 320 350 } 351 352 protected boolean isChildrenResizeDisabled() { 353 return true; 354 } 355 356 public void propertyChange(java.beans.PropertyChangeEvent evt) { 357 JTextComponent component = (JTextComponent )getContainer(); 358 if (component==null || evt==null || 359 !EditorUI.LINE_HEIGHT_CHANGED_PROP.equals(evt.getPropertyName())) return; 360 361 AbstractDocument doc = (AbstractDocument )getDocument(); 362 if (doc!=null) { 363 doc.readLock(); 364 try{ 365 LockView lockView = LockView.get(this); 366 lockView.lock(); 367 try { 368 rebuild(0, getViewCount()); 369 } finally { 370 lockView.unlock(); 371 } 372 } finally { 373 doc.readUnlock(); 374 } 375 component.revalidate(); 376 } 377 } 378 379 } 380 | Popular Tags |