GNU Classpath (0.17) | ||
Frames | No Frames |
1: /* View.java -- 2: Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.swing.text; 40: 41: import java.awt.Container; 42: import java.awt.Graphics; 43: import java.awt.Rectangle; 44: import java.awt.Shape; 45: 46: import javax.swing.JComponent; 47: import javax.swing.SwingConstants; 48: import javax.swing.event.DocumentEvent; 49: 50: public abstract class View implements SwingConstants 51: { 52: public static final int BadBreakWeight = 0; 53: public static final int ExcellentBreakWeight = 2000; 54: public static final int ForcedBreakWeight = 3000; 55: public static final int GoodBreakWeight = 1000; 56: 57: public static final int X_AXIS = 0; 58: public static final int Y_AXIS = 1; 59: 60: private float width, height; 61: private Element elt; 62: private View parent; 63: 64: /** 65: * The child views. 66: */ 67: View[] children; 68: 69: /** 70: * Creates a new <code>View</code> instance. 71: * 72: * @param elem an <code>Element</code> value 73: */ 74: public View(Element elem) 75: { 76: elt = elem; 77: children = new View[0]; 78: } 79: 80: public abstract void paint(Graphics g, Shape s); 81: 82: public void setParent(View parent) 83: { 84: this.parent = parent; 85: } 86: 87: public View getParent() 88: { 89: return parent; 90: } 91: 92: public Container getContainer() 93: { 94: View parent = getParent(); 95: return parent != null ? parent.getContainer() : null; 96: } 97: 98: public Document getDocument() 99: { 100: return getElement().getDocument(); 101: } 102: 103: public Element getElement() 104: { 105: return elt; 106: } 107: 108: public abstract float getPreferredSpan(int axis); 109: 110: public int getResizeWeight(int axis) 111: { 112: return 0; 113: } 114: 115: public float getMaximumSpan(int axis) 116: { 117: if (getResizeWeight(axis) <= 0) 118: return getPreferredSpan(axis); 119: 120: return Integer.MAX_VALUE; 121: } 122: 123: public float getMinimumSpan(int axis) 124: { 125: if (getResizeWeight(axis) <= 0) 126: return getPreferredSpan(axis); 127: 128: return Integer.MAX_VALUE; 129: } 130: 131: public void setSize(float width, float height) 132: { 133: // The default implementation does nothing. 134: } 135: 136: public float getAlignment(int axis) 137: { 138: return 0.5f; 139: } 140: 141: public AttributeSet getAttributes() 142: { 143: return getElement().getAttributes(); 144: } 145: 146: public boolean isVisible() 147: { 148: return true; 149: } 150: 151: public int getViewCount() 152: { 153: return 0; 154: } 155: 156: public View getView(int index) 157: { 158: return null; 159: } 160: 161: public ViewFactory getViewFactory() 162: { 163: View parent = getParent(); 164: return parent != null ? parent.getViewFactory() : null; 165: } 166: 167: public void replace(int offset, int length, View[] views) 168: { 169: // Default implementation does nothing. 170: } 171: 172: public void insert(int offset, View view) 173: { 174: View[] array = { view }; 175: replace(offset, 1, array); 176: } 177: 178: public void append(View view) 179: { 180: View[] array = { view }; 181: replace(getViewCount(), 1, array); 182: } 183: 184: public void removeAll() 185: { 186: replace(0, getViewCount(), null); 187: } 188: 189: public void remove(int index) 190: { 191: replace(index, 1, null); 192: } 193: 194: public View createFragment(int p0, int p1) 195: { 196: // The default implementation doesn't support fragmentation. 197: return this; 198: } 199: 200: public int getStartOffset() 201: { 202: return getElement().getStartOffset(); 203: } 204: 205: public int getEndOffset() 206: { 207: return getElement().getEndOffset(); 208: } 209: 210: public Shape getChildAllocation(int index, Shape a) 211: { 212: return null; 213: } 214: 215: /** 216: * @since 1.4 217: */ 218: public int getViewIndex(float x, float y, Shape allocation) 219: { 220: return -1; 221: } 222: 223: /** 224: * @since 1.4 225: */ 226: public String getToolTipText(float x, float y, Shape allocation) 227: { 228: int index = getViewIndex(x, y, allocation); 229: 230: if (index < -1) 231: return null; 232: 233: Shape childAllocation = getChildAllocation(index, allocation); 234: 235: if (childAllocation.getBounds().contains(x, y)) 236: return getView(index).getToolTipText(x, y, childAllocation); 237: 238: return null; 239: } 240: 241: /** 242: * @since 1.3 243: */ 244: public Graphics getGraphics() 245: { 246: return getContainer().getGraphics(); 247: } 248: 249: public void preferenceChanged(View child, boolean width, boolean height) 250: { 251: if (parent != null) 252: parent.preferenceChanged(this, width, height); 253: else 254: ((JComponent) getContainer()).revalidate(); 255: } 256: 257: public int getBreakWeight(int axis, float pos, float len) 258: { 259: return BadBreakWeight; 260: } 261: 262: public View breakView(int axis, int offset, float pos, float len) 263: { 264: return this; 265: } 266: 267: /** 268: * @since 1.3 269: */ 270: public int getViewIndex(int pos, Position.Bias b) 271: { 272: return -1; 273: } 274: 275: /** 276: * Receive notification about an insert update to the text model. 277: * 278: * The default implementation of this method does the following: 279: * <ul> 280: * <li>Call {@link #updateChildren} if the element that this view is 281: * responsible for has changed. This makes sure that the children can 282: * correctly represent the model.<li> 283: * <li>Call {@link #forwardUpdate}. This forwards the DocumentEvent to 284: * the child views.<li> 285: * <li>Call {@link #updateLayout}. Gives the view a chance to either 286: * repair its layout, reschedule layout or do nothing at all.</li> 287: * </ul> 288: * 289: * @param ev the DocumentEvent that describes the change 290: * @param shape the shape of the view 291: * @param vf the ViewFactory for creating child views 292: */ 293: public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) 294: { 295: Element el = getElement(); 296: DocumentEvent.ElementChange ec = ev.getChange(el); 297: if (ec != null) 298: updateChildren(ec, ev, vf); 299: forwardUpdate(ec, ev, shape, vf); 300: updateLayout(ec, ev, shape); 301: } 302: 303: /** 304: * Receive notification about a remove update to the text model. 305: * 306: * The default implementation of this method does the following: 307: * <ul> 308: * <li>Call {@link #updateChildren} if the element that this view is 309: * responsible for has changed. This makes sure that the children can 310: * correctly represent the model.<li> 311: * <li>Call {@link #forwardUpdate}. This forwards the DocumentEvent to 312: * the child views.<li> 313: * <li>Call {@link #updateLayout}. Gives the view a chance to either 314: * repair its layout, reschedule layout or do nothing at all.</li> 315: * </ul> 316: * 317: * @param ev the DocumentEvent that describes the change 318: * @param shape the shape of the view 319: * @param vf the ViewFactory for creating child views 320: */ 321: public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) 322: { 323: Element el = getElement(); 324: DocumentEvent.ElementChange ec = ev.getChange(el); 325: if (ec != null) 326: updateChildren(ec, ev, vf); 327: forwardUpdate(ec, ev, shape, vf); 328: updateLayout(ec, ev, shape); 329: } 330: 331: /** 332: * Receive notification about a change update to the text model. 333: * 334: * The default implementation of this method does the following: 335: * <ul> 336: * <li>Call {@link #updateChildren} if the element that this view is 337: * responsible for has changed. This makes sure that the children can 338: * correctly represent the model.<li> 339: * <li>Call {@link #forwardUpdate}. This forwards the DocumentEvent to 340: * the child views.<li> 341: * <li>Call {@link #updateLayout}. Gives the view a chance to either 342: * repair its layout, reschedule layout or do nothing at all.</li> 343: * </ul> 344: * 345: * @param ev the DocumentEvent that describes the change 346: * @param shape the shape of the view 347: * @param vf the ViewFactory for creating child views 348: */ 349: public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) 350: { 351: Element el = getElement(); 352: DocumentEvent.ElementChange ec = ev.getChange(el); 353: if (ec != null) 354: updateChildren(ec, ev, vf); 355: forwardUpdate(ec, ev, shape, vf); 356: updateLayout(ec, ev, shape); 357: } 358: 359: /** 360: * Updates the list of children that is returned by {@link #getView} 361: * and {@link #getViewCount}. 362: * 363: * Element that are specified as beeing added in the ElementChange record are 364: * assigned a view for using the ViewFactory. Views of Elements that 365: * are specified as beeing removed are removed from the list. 366: * 367: * @param ec the ElementChange record that describes the change of the 368: * element 369: * @param ev the DocumentEvent describing the change of the document model 370: * @param vf the ViewFactory to use for creating new views 371: * 372: * @return whether or not the child views represent the child elements of 373: * the element that this view is responsible for. Some views may 374: * create views that are responsible only for parts of the element 375: * that they are responsible for and should then return false. 376: * 377: * @since 1.3 378: */ 379: protected boolean updateChildren(DocumentEvent.ElementChange ec, 380: DocumentEvent ev, 381: ViewFactory vf) 382: { 383: Element[] added = ec.getChildrenAdded(); 384: Element[] removed = ec.getChildrenRemoved(); 385: View[] newChildren = new View[children.length + added.length 386: - removed.length]; 387: int index = ec.getIndex(); 388: System.arraycopy(children, 0, newChildren, 0, index); 389: System.arraycopy(children, index, added, 0, added.length); 390: int index2 = index + removed.length; 391: int len2 = children.length - index2; 392: System.arraycopy(children, index2, newChildren, index + added.length, 393: len2); 394: children = newChildren; 395: 396: return true; 397: } 398: 399: /** 400: * Forwards the DocumentEvent to child views that need to get notified 401: * of the change to the model. This calles {@link #forwardUpdateToView} 402: * for each View that must be forwarded to. 403: * 404: * @param ec the ElementChange describing the element changes (may be 405: * <code>null</code> if there were no changes) 406: * @param ev the DocumentEvent describing the changes to the model 407: * @param shape the current allocation of the view 408: * @param vf the ViewFactory used to create new Views 409: * 410: * @since 1.3 411: */ 412: protected void forwardUpdate(DocumentEvent.ElementChange ec, 413: DocumentEvent ev, Shape shape, ViewFactory vf) 414: { 415: for (int i = 0; i < children.length; i++) 416: { 417: View child = children[i]; 418: forwardUpdateToView(child, ev, shape, vf); 419: } 420: } 421: 422: /** 423: * Forwards an update event to the given child view. This calls 424: * {@link #insertUpdate}, {@link #removeUpdate} or {@link #changedUpdate}, 425: * depending on the type of document event. 426: * 427: * @param view the View to forward the event to 428: * @param ev the DocumentEvent to forward 429: * @param shape the current allocation of the View 430: * @param vf the ViewFactory used to create new Views 431: * 432: * @since 1.3 433: */ 434: protected void forwardUpdateToView(View view, DocumentEvent ev, Shape shape, 435: ViewFactory vf) 436: { 437: DocumentEvent.EventType type = ev.getType(); 438: if (type == DocumentEvent.EventType.INSERT) 439: view.insertUpdate(ev, shape, vf); 440: else if (type == DocumentEvent.EventType.REMOVE) 441: view.removeUpdate(ev, shape, vf); 442: else if (type == DocumentEvent.EventType.CHANGE) 443: view.changedUpdate(ev, shape, vf); 444: } 445: 446: /** 447: * Updates the layout. 448: * 449: * @param ec the ElementChange that describes the changes to the element 450: * @param ev the DocumentEvent that describes the changes to the model 451: * @param shape the current allocation for this view 452: * 453: * @since 1.3 454: */ 455: protected void updateLayout(DocumentEvent.ElementChange ec, 456: DocumentEvent ev, Shape shape) 457: { 458: Rectangle b = shape.getBounds(); 459: if (ec != null) 460: preferenceChanged(this, true, true); 461: } 462: }
GNU Classpath (0.17) |