001: /*
002: * Sun Public License Notice
003: *
004: * The contents of this file are subject to the Sun Public License
005: * Version 1.0 (the "License"). You may not use this file except in
006: * compliance with the License. A copy of the License is available at
007: * http://www.sun.com/
008: *
009: * The Original Code is NetBeans. The Initial Developer of the Original
010: * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
011: * Microsystems, Inc. All Rights Reserved.
012: */
013:
014: package org.netbeans.editor;
015:
016: import java.awt.Graphics;
017: import java.awt.Insets;
018: import java.awt.Rectangle;
019: import java.awt.Shape;
020:
021: import javax.swing.text.BadLocationException;
022: import javax.swing.text.Element;
023: import javax.swing.text.JTextComponent;
024: import javax.swing.text.View;
025:
026: /**
027: * Base abstract view serves as parent for both leaf and branch views.
028: *
029: * @author Miloslav Metelka
030: * @version 1.00
031: */
032:
033: public abstract class BaseView extends View {
034:
035: /** Top insets paint type. */
036: protected static final int INSETS_TOP = 1;
037:
038: /** Main area paint type. */
039: protected static final int MAIN_AREA = 2;
040:
041: /** Bottom insets paint type. */
042: protected static final int INSETS_BOTTOM = 4;
043:
044: /** Is this view packed */
045: protected boolean packed;
046:
047: /**
048: * Index of this view as child view in its parent. This gives the parent
049: * view a hint at which index it should search for this view. If this index
050: * is incorrect, the parent view searches the whole array of children.
051: * However this gives good optimization of child views search process.
052: */
053: protected int helperInd;
054:
055: /** JTextComponent hosting this view */
056: private JTextComponent component;
057:
058: /** Border insets of this view. Can be null */
059: protected Insets insets;
060:
061: /** Start y coord. for this view */
062: private int startY = -1;
063:
064: /** Construct new base view */
065: public BaseView(Element elem) {
066: super (elem);
067: }
068:
069: /** Getter for packed flag */
070: public boolean isPacked() {
071: return packed;
072: }
073:
074: /** Setter for packed flag */
075: public void setPacked(boolean packed) {
076: this .packed = packed;
077: }
078:
079: /** Get aligment along an X_AXIS or Y_AXIS */
080: public float getAlignment(int axis) {
081: return 0f;
082: }
083:
084: public abstract void modelToViewDG(int pos, DrawGraphics dg)
085: throws BadLocationException;
086:
087: /** Get y-coord value from position */
088: protected abstract int getYFromPos(int pos)
089: throws BadLocationException;
090:
091: /** Get position when knowing y-coord */
092: protected abstract int getPosFromY(int y);
093:
094: protected abstract int getBaseX(int y);
095:
096: /**
097: * Returns binary composition of regions that should be painted. It can be
098: * binary composition of INSETS_TOP, MAIN_AREA and INSETS_BOTTOM.
099: *
100: * @param g
101: * Graphics to paint through
102: * @param clip
103: * clipping area of graphics object
104: *
105: */
106: protected abstract int getPaintAreas(Graphics g, int clipY,
107: int clipHeight);
108:
109: /**
110: * Paint either top insets, main area, or bottom insets.
111: *
112: * @param g
113: * Graphics to paint through
114: * @param clip
115: * clipping area of graphics object
116: * @param paintAreas
117: * binary composition of paint areas
118: */
119: protected abstract void paintAreas(Graphics g, int clipY,
120: int clipHeight, int paintAreas);
121:
122: /**
123: * It divides painting into three areas: INSETS_TOP, MAIN_AREA,
124: * INSETS_BOTTOM. It paints them sequentially using <CODE>paintArea()</CODE>
125: * method until it returns false. This implementation also supposes that
126: * <CODE>allocation</CODE> is instance of <CODE>Rectangle</CODE> to save
127: * object creations. The root view in TextUI implementation will take care
128: * to ensure child views will get rectangle instances.
129: */
130: public void paint(Graphics g, Shape allocation) {
131: Rectangle clip = g.getClipBounds();
132: if (clip.height < 0 || clip.width < 0) {
133: return;
134: }
135: int paintAreas = getPaintAreas(g, clip.y, clip.height);
136: if (paintAreas != 0) {
137: paintAreas(g, clip.y, clip.height, paintAreas);
138: }
139: }
140:
141: /** Get component hosting this view. */
142: public JTextComponent getComponent() {
143: if (component == null) {
144: component = (JTextComponent) getContainer();
145: }
146: return component;
147: }
148:
149: /** Get insets of this view. */
150: public Insets getInsets() {
151: return insets;
152: }
153:
154: /**
155: * This function is used to correct information about which index this child
156: * view occupies in parent view's array of children. It is called by parent
157: * view.
158: */
159: protected void setHelperInd(int ind) {
160: helperInd = ind;
161: }
162:
163: /**
164: * Get child view's y base value. This function is called by children of
165: * this view to get its y offset.
166: *
167: * @param view
168: * is child view of this view for which the offset should be
169: * computed.
170: * @param helperInd
171: * is index that child view has cached to ease the parent view to
172: * search for it in its children array. If this index is correct,
173: * parent uses it. If it's incorrect parent view searches through
174: * the whole array of its children to find the child. It then
175: * calls children's <CODE>setParentInd()</CODE> to correct its
176: * location index.
177: */
178: protected abstract int getViewStartY(BaseView view, int helperInd);
179:
180: /**
181: * Informs the view that if it had cached start y of itself it should
182: * invalidate it as it is no longer valid and it should call <CODE>getViewStartY()</CODE>
183: * to get updated value.
184: */
185: protected void invalidateStartY() {
186: startY = -1;
187: }
188:
189: /** Get y base value for this view. */
190: protected int getStartY() {
191: if (startY == -1) { // the value is invalid
192: BaseView v = (BaseView) getParent();
193: if (v != null) {
194: startY = v.getViewStartY(this , helperInd);
195: }
196: }
197: return startY;
198: }
199:
200: /** Get height of the view */
201: public abstract int getHeight();
202:
203: /**
204: * Update height of main area as result of some important change. Propagate
205: * to child views if necessary.
206: */
207: public abstract void updateMainHeight();
208:
209: /** Get preferred span over axis */
210: public float getPreferredSpan(int axis) {
211: switch (axis) {
212: case Y_AXIS:
213: return getHeight();
214: }
215: return 0f;
216: }
217:
218: /** Get editor UI */
219: protected EditorUI getEditorUI() {
220: return ((BaseTextUI) getComponent().getUI()).getEditorUI();
221: }
222:
223: /** Display view hierarchy on console. Current view is marked with asterisk. */
224: public void displayHierarchy() {
225: // find the root view
226: BaseView v = this ;
227: while (v.getParent() != null) {
228: v = (BaseView) v.getParent();
229: }
230: v.displayHierarchyHelper(this , 0, 0);
231: }
232:
233: /**
234: * Helper for displaying hierarchy - called recursively.
235: *
236: * @param origView
237: * view for which the displayHierarchy method was originally
238: * called. It is marked by asterisk.
239: * @param col
240: * column offset
241: * @param index
242: * index of this view in parent children[] array
243: */
244: private void displayHierarchyHelper(View origView, int col,
245: int index) {
246: StringBuffer buf = new StringBuffer();
247: buf.append(((this == origView) ? "*" : " ")); // NOI18N
248: for (int i = 0; i < col; i++) {
249: buf.append(' ');
250: }
251: buf.append('[');
252: buf.append(Integer.toString(index));
253: buf.append("] "); // NOI18N
254: buf.append(this .toString());
255: System.out.println(buf);
256: int childrenCnt = getViewCount();
257: if (childrenCnt > 0) {
258: for (int i = 0; i < childrenCnt; i++) {
259: ((BaseView) getView(i)).displayHierarchyHelper(
260: origView, col + 1, i);
261: }
262: }
263:
264: }
265:
266: public String toString() {
267: return "BaseView=" + System.identityHashCode(this ) // NOI18N
268: + ", elem=" + getElement() + ", parent=" // NOI18N
269: + System.identityHashCode(getParent());
270: }
271:
272: }
|