KickJava   Java API By Example, From Geeks To Geeks.

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


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.Insets JavaDoc;
23 import java.awt.Color JavaDoc;
24 import java.awt.Font JavaDoc;
25 import java.awt.font.FontRenderContext JavaDoc;
26 import java.awt.Graphics JavaDoc;
27 import java.awt.Shape JavaDoc;
28 import java.awt.Rectangle JavaDoc;
29 import javax.swing.text.Element JavaDoc;
30 import javax.swing.text.View JavaDoc;
31 import javax.swing.text.ViewFactory JavaDoc;
32 import javax.swing.text.Position JavaDoc;
33 import javax.swing.text.BadLocationException JavaDoc;
34 import javax.swing.text.JTextComponent JavaDoc;
35 import javax.swing.text.Document JavaDoc;
36 import javax.swing.SwingUtilities JavaDoc;
37 import javax.swing.event.DocumentEvent JavaDoc;
38
39 /**
40 * Leaf view implementation. This corresponds and requires leaf element
41 * to be element for this view.
42 *
43 * The view has the following structure:
44 * +---------------------------------------------------------+
45 * | insets.top area | A
46 * | | | insets.top
47 * | | V
48 * | +--------------------------------------------------+
49 * | | | A
50 * | | | |
51 * | i | | |
52 * | n | | |
53 * | s | | |
54 * | e | | |
55 * | t | | |
56 * | s | | |
57 * | . | | |
58 * | l | | |
59 * | e | Main area of this view | | mainHeight
60 * | f | | |
61 * | t | | |
62 * | | | |
63 * | a | | |
64 * | r | | |
65 * | e | | |
66 * | a | | |
67 * | | | |
68 * | | | |
69 * | | | |
70 * | | | |
71 * | | | V
72 * | +--------------------------------------------------+
73 * | insets.bottom area | A
74 * | | | insets.bottom
75 * | | V
76 * +---------------------------------------------------------+
77 *
78 * @author Miloslav Metelka
79 * @version 1.00
80 */

81
82 public class LeafView extends BaseView {
83
84     /** Height of the area this view manages excluding areas
85     * managed by its children and excluding insets.
86     */

87     protected int mainHeight;
88
89     /** Draw graphics for converting position to coords */
90     ModelToViewDG modelToViewDG = new ModelToViewDG();
91
92     /** Draw graphics for converting coords to position */
93     ViewToModelDG viewToModelDG = new ViewToModelDG();
94
95     /** Construct new base view */
96     public LeafView(Element JavaDoc elem) {
97         super(elem);
98     }
99
100     public void setParent(View JavaDoc parent) {
101         super.setParent(parent);
102         
103         if (getParent() != null) {
104             updateMainHeight();
105         }
106     }
107     
108     /** Returns binary composition of paint areas */
109     protected int getPaintAreas(Graphics JavaDoc g, int clipY, int clipHeight) {
110         // invalid or empty height
111
if (clipHeight <= 0) {
112             return 0;
113         }
114
115         int clipEndY = clipY + clipHeight;
116         int startY = getStartY();
117         if (insets != null) { // valid insets
118
int mainAreaY = startY + insets.top;
119             if (clipEndY <= mainAreaY) {
120                 return INSETS_TOP;
121             }
122             int bottomInsetsY = mainAreaY + mainHeight;
123             if (clipEndY <= bottomInsetsY) {
124                 if (clipY <= mainAreaY) {
125                     return INSETS_TOP + MAIN_AREA;
126                 } else {
127                     return MAIN_AREA;
128                 }
129             }
130             if (clipY <= mainAreaY) {
131                 return INSETS_TOP + MAIN_AREA + INSETS_BOTTOM;
132             } else if (clipY <= bottomInsetsY) {
133                 return MAIN_AREA + INSETS_BOTTOM;
134             } else if (clipY <= bottomInsetsY + insets.bottom) {
135                 return INSETS_BOTTOM;
136             } else {
137                 return 0;
138             }
139         } else { // no insets
140
if (clipEndY <= startY || clipY >= startY + getHeight()) {
141                 return 0;
142             } else {
143                 return MAIN_AREA;
144             }
145         }
146     }
147
148     /** Paint either top insets, main area, or bottom insets depending on paintAreas variable */
149     protected void paintAreas(Graphics JavaDoc g, int clipY, int clipHeight, int paintAreas) {
150         if ((paintAreas & MAIN_AREA) == MAIN_AREA) {
151             EditorUI editorUI = getEditorUI();
152             int paintY = Math.max(clipY, 0); // relative start of area to paint
153
int startPos = getPosFromY(paintY);
154             if (clipHeight > 0) { // needs to be painted
155
BaseDocument doc = (BaseDocument)getDocument();
156                 try {
157                     int pos = getPosFromY(clipY + clipHeight - 1);
158                     int endPos = Utilities.getRowEnd(doc, pos);
159                     int baseY = getYFromPos(startPos);
160                     DrawEngine.getDrawEngine().draw(new DrawGraphics.GraphicsDG(g),
161                         editorUI, startPos, endPos,
162                         getBaseX(baseY), baseY, Integer.MAX_VALUE
163                     );
164                 } catch (BadLocationException JavaDoc e) {
165                     e.printStackTrace();
166                 }
167             }
168         }
169     }
170
171     /** Get total height of this view */
172     public int getHeight() {
173         if (insets != null) {
174             return insets.top + mainHeight + insets.bottom;
175         } else {
176             return mainHeight;
177         }
178     }
179
180     /** Compute and update main area height */
181     public void updateMainHeight() {
182         LeafElement elem = (LeafElement)getElement(); // need leaf element
183
try {
184             int lineDiff = (elem.getEndMark().getLine() - elem.getStartMark().getLine()
185                             + 1);
186             mainHeight = lineDiff * getEditorUI().getLineHeight();
187         } catch (InvalidMarkException e) {
188             Utilities.annotateLoggable(e);
189             mainHeight = 0;
190         }
191     }
192
193     /** Get begin of line position from y-coord.
194     * If the position is before main area begining
195     * it returns start position. If it's beyond the end of view it returns
196     * end position.
197     * @param y y-coord to inspect
198     * always returns startOffset for y < start of main area
199     * @param eol means to return end of specified line instead of begining
200     * @return position in the document
201     */

202     protected int getPosFromY(int y) {
203         // relative distance from begining of main area
204
int relY = y - getStartY() - ((insets != null) ? insets.top : 0);
205         if (relY < 0) { // before the view
206
return getStartOffset();
207         }
208         if (relY >= mainHeight) { // beyond the view
209
return getEndOffset();
210         }
211
212         int line = 0;
213         // get the begining line of the element
214
try {
215             line = ((BaseElement)getElement()).getStartMark().getLine();
216         } catch (InvalidMarkException e) {
217             Utilities.annotateLoggable(e);
218         }
219         // advance the line by by relative distance
220
line += relY / getEditorUI().getLineHeight();
221
222         int startOffset = getStartOffset();
223         int pos;
224         pos = Utilities.getRowStartFromLineOffset(((BaseDocument)getDocument()), line);
225         if (pos == -1) {
226             pos = startOffset;
227         }
228         return Math.max(pos, startOffset);
229     }
230
231     public int getBaseX(int y) {
232         return getEditorUI().getTextMargin().left + ((insets != null) ? insets.left : 0);
233     }
234
235     /** Returns the number of child views in this view. */
236     public final int getViewCount() {
237         return 0;
238     }
239
240     /** Gets the n-th child view. */
241     public final View JavaDoc getView(int n) {
242         return null;
243     }
244
245     /** !!! osetrit konec view -> jump na dalsi v branchview */
246     public int getNextVisualPositionFrom(int pos, Position.Bias JavaDoc b, Shape JavaDoc a,
247                                          int direction, Position.Bias JavaDoc[] biasRet)
248     throws BadLocationException JavaDoc {
249         if (biasRet != null) {
250             biasRet[0] = Position.Bias.Forward;
251         }
252         switch (direction) {
253         case NORTH:
254             {
255                 try {
256                     BaseDocument doc = (BaseDocument)getDocument();
257                     int visCol = doc.getVisColFromPos(pos);
258                     pos = doc.getOffsetFromVisCol(visCol, Utilities.getRowStart(doc, pos, -1));
259                 } catch (BadLocationException JavaDoc e) {
260                     // leave the original position
261
}
262                 return pos;
263             }
264         case SOUTH:
265             {
266                 try {
267                     BaseDocument doc = (BaseDocument)getDocument();
268                     int visCol = doc.getVisColFromPos(pos);
269                     pos = doc.getOffsetFromVisCol(visCol, Utilities.getRowStart(doc, pos, 1));
270                 } catch (BadLocationException JavaDoc e) {
271                     // leave the original position
272
}
273                 return pos;
274             }
275         case WEST:
276             return (pos == -1) ? getStartOffset() : (pos - 1);
277         case EAST:
278             return (pos == -1) ? getEndOffset() : (pos + 1);
279         default:
280             throw new IllegalArgumentException JavaDoc("Bad direction: " + direction); // NOI18N
281
}
282     }
283
284     /** Get y coordinate from position.
285     * The position can lay anywhere inside this view.
286     */

287     protected int getYFromPos(int pos) throws BadLocationException JavaDoc {
288         int relLine = 0;
289         try {
290             relLine = Utilities.getLineOffset(((BaseDocument)getDocument()), pos)
291                       - ((BaseElement)getElement()).getStartMark().getLine();
292         } catch (InvalidMarkException e) {
293             Utilities.annotateLoggable(e);
294         }
295         return getStartY() + ((insets != null) ? insets.top : 0)
296                + relLine * getEditorUI().getLineHeight();
297     }
298
299     public Shape JavaDoc modelToView(int pos, Shape JavaDoc a, Position.Bias JavaDoc b) throws BadLocationException JavaDoc {
300         EditorUI editorUI = getEditorUI();
301         Rectangle JavaDoc ret = new Rectangle JavaDoc();
302         BaseDocument doc = (BaseDocument)getDocument();
303         if (pos < 0 || pos > doc.getLength()) {
304             throw new BadLocationException JavaDoc("Invalid offset", pos); // NOI18N
305
}
306
307         ret.y = getYFromPos(pos);
308
309         try {
310             synchronized (modelToViewDG) {
311                 modelToViewDG.r = ret; // set the current rectangle
312

313                 Element JavaDoc lineElement = doc.getParagraphElement(pos);
314                 int bolPos = lineElement.getStartOffset();
315                 int eolPos = lineElement.getEndOffset() - 1;
316                 DrawEngine.getDrawEngine().draw(modelToViewDG, editorUI,
317                     bolPos, eolPos,
318                     getBaseX(ret.y), ret.y, pos
319                 );
320                 modelToViewDG.r = null;
321             }
322         } catch (BadLocationException JavaDoc e) {
323             Utilities.annotateLoggable(e);
324         }
325
326         return ret;
327     }
328
329     public Shape JavaDoc modelToView(int p0, Position.Bias JavaDoc b0, int p1, Position.Bias JavaDoc b1,
330                              Shape JavaDoc a) throws BadLocationException JavaDoc {
331         Rectangle JavaDoc r0 = (Rectangle JavaDoc)modelToView(p0, a, b0);
332         Rectangle JavaDoc r1 = (Rectangle JavaDoc)modelToView(p1, a, b1);
333         if (r0.y != r1.y) {
334             // If it spans lines, force it to be the width of the view.
335
r0.x = getComponent().getX();
336             r0.width = getComponent().getWidth();
337         }
338         r0.add(r1);
339         return r0;
340     }
341
342     public void modelToViewDG(int pos, DrawGraphics dg)
343     throws BadLocationException JavaDoc {
344         EditorUI editorUI = getEditorUI();
345         BaseDocument doc = (BaseDocument)getDocument();
346         if (pos < 0 || pos > doc.getLength()) {
347             throw new BadLocationException JavaDoc("Invalid offset", pos); // NOI18N
348
}
349
350         int y = getYFromPos(pos);
351         Element JavaDoc lineElement = doc.getParagraphElement(pos);
352         DrawEngine.getDrawEngine().draw(dg, editorUI, lineElement.getStartOffset(),
353             lineElement.getEndOffset() - 1, getBaseX(y), y, pos);
354     }
355
356     /** Get position from location on screen.
357     * @param x the X coordinate >= 0
358     * @param y the Y coordinate >= 0
359     * @param a the allocated region to render into
360     * @return the location within the model that best represents the
361     * given point in the view >= 0
362     */

363     public int viewToModel(float x, float y, Shape JavaDoc a, Position.Bias JavaDoc[] biasReturn) {
364         int intX = (int)x;
365         int intY = (int)y;
366         if (biasReturn != null) {
367             biasReturn[0] = Position.Bias.Forward;
368         }
369         int begMainY = getStartY() + ((insets != null) ? insets.top : 0);
370         if (intY < begMainY) { // top insets or before this view
371
return -1; // getStartOffset();
372
} else if (intY > begMainY + mainHeight) { // bottom insets or beyond
373
return getEndOffset();
374         } else { // inside the view
375
int pos = getPosFromY(intY); // first get BOL of target line
376
EditorUI editorUI = getEditorUI();
377             try {
378                 int eolPos = Utilities.getRowEnd((BaseDocument)getDocument(), pos);
379                 synchronized (viewToModelDG) {
380                     viewToModelDG.setTargetX(intX);
381                     viewToModelDG.setEOLOffset(eolPos);
382                     DrawEngine.getDrawEngine().draw(viewToModelDG, editorUI, pos, eolPos,
383                                                     getBaseX(intY), 0, -1);
384                     pos = viewToModelDG.getOffset();
385                 }
386             } catch (BadLocationException JavaDoc e) {
387                 // return begining of line in this case
388
}
389             return pos;
390         }
391     }
392
393     /** Gives notification that something was inserted into the document
394     * in a location that this view is responsible for.
395     *
396     * @param e the change information from the associated document
397     * @param a the current allocation of the view
398     * @param f the factory to use to rebuild if the view has children
399     */

400     public void insertUpdate(DocumentEvent JavaDoc evt, Shape JavaDoc a, ViewFactory JavaDoc f) {
401         try {
402             BaseDocumentEvent bevt = (BaseDocumentEvent)evt;
403             EditorUI editorUI = getEditorUI();
404             int y = getYFromPos(evt.getOffset());
405             int lineHeight = editorUI.getLineHeight();
406             if (bevt.getLFCount() > 0) { // one or more lines inserted
407
int addHeight = bevt.getLFCount() * lineHeight;
408                 mainHeight += addHeight;
409                 editorUI.repaint(y);
410
411             } else { // inserting on one line
412

413                 int syntaxY = getYFromPos(bevt.getSyntaxUpdateOffset());
414                 // !!! patch for case when DocMarksOp.eolMark is at the end of document
415
if (bevt.getSyntaxUpdateOffset() == evt.getDocument().getLength()) {
416                     syntaxY += lineHeight;
417                 }
418
419                 if (getComponent().isShowing()) {
420                     editorUI.repaint(y, Math.max(lineHeight, syntaxY - y));
421                 }
422             }
423
424         } catch (BadLocationException JavaDoc ex) {
425             Utilities.annotateLoggable(ex);
426         }
427     }
428
429     /** Gives notification from the document that attributes were removed
430     * in a location that this view is responsible for.
431     *
432     * @param e the change information from the associated document
433     * @param a the current allocation of the view
434     * @param f the factory to use to rebuild if the view has children
435     */

436     public void removeUpdate(DocumentEvent JavaDoc evt, Shape JavaDoc a, ViewFactory JavaDoc f) {
437         try {
438             BaseDocumentEvent bevt = (BaseDocumentEvent)evt;
439             EditorUI editorUI = getEditorUI();
440             int y = getYFromPos(evt.getOffset());
441             int lineHeight = editorUI.getLineHeight();
442             if (bevt.getLFCount() > 0) { // one or more lines removed
443
int removeHeight = bevt.getLFCount() * lineHeight;
444                 mainHeight -= removeHeight;
445                 editorUI.repaint(y);
446
447             } else { // removing on one line
448
int syntaxY = getYFromPos(bevt.getSyntaxUpdateOffset());
449                 // !!! patch for case when DocMarksOp.eolMark is at the end of document
450
if (bevt.getSyntaxUpdateOffset() == evt.getDocument().getLength()) {
451                     syntaxY += lineHeight;
452                 }
453
454                 if (getComponent().isShowing()) {
455                     editorUI.repaint(y, Math.max(lineHeight, syntaxY - y));
456                 }
457             }
458
459         } catch (BadLocationException JavaDoc ex) {
460             Utilities.annotateLoggable(ex);
461         }
462     }
463
464     /** Attributes were changed in the are this view is responsible for.
465     * @param e the change information from the associated document
466     * @param a the current allocation of the view
467     * @param f the factory to use to rebuild if the view has children
468     */

469     public void changedUpdate(DocumentEvent JavaDoc evt, Shape JavaDoc a, ViewFactory JavaDoc f) {
470         try {
471             if (getComponent().isShowing()) {
472                 getEditorUI().repaintBlock(evt.getOffset(), evt.getOffset() + evt.getLength());
473             }
474         } catch (BadLocationException JavaDoc ex) {
475             Utilities.annotateLoggable(ex);
476         }
477     }
478
479     /** Get child view's y base value. Invalid in this case. */
480     protected int getViewStartY(BaseView view, int helperInd) {
481         return 0; // invalid in this case
482
}
483
484     static final class ModelToViewDG extends DrawGraphics.SimpleDG {
485
486         Rectangle JavaDoc r;
487
488         public boolean targetOffsetReached(int pos, char ch, int x,
489                                            int charWidth, DrawContext ctx) {
490             r.x = x;
491             r.y = getY();
492             r.width = charWidth;
493             r.height = getLineHeight();
494             return false;
495         }
496
497     }
498
499     static final class ViewToModelDG extends DrawGraphics.SimpleDG {
500
501         int targetX;
502
503         int offset;
504
505         int eolOffset;
506
507         void setTargetX(int targetX) {
508             this.targetX = targetX;
509         }
510
511         void setEOLOffset(int eolOffset) {
512             this.eolOffset = eolOffset;
513             this.offset = eolOffset;
514         }
515
516         int getOffset() {
517             return offset;
518         }
519
520         public boolean targetOffsetReached(int offset, char ch, int x,
521         int charWidth, DrawContext ctx) {
522             if (offset <= eolOffset) {
523                 if (x + charWidth < targetX) {
524                     this.offset = offset;
525                     return true;
526
527                 } else { // target position inside the char
528
this.offset = offset;
529                     if (targetX > x + charWidth / 2) {
530                         Document JavaDoc doc = ctx.getEditorUI().getDocument();
531                         if (ch != '\n' && doc != null && offset < doc.getLength()) {
532                             this.offset++;
533                         }
534                     }
535
536                     return false;
537                 }
538             }
539             return false;
540         }
541
542     }
543
544 }
545
Popular Tags