Merge from mainline
[official-gcc.git] / libjava / classpath / javax / swing / text / View.java
blobb835842bc0e74b0ff9a4e4635e8361f12fc44011
1 /* View.java --
2 Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
39 package javax.swing.text;
41 import java.awt.Container;
42 import java.awt.Graphics;
43 import java.awt.Rectangle;
44 import java.awt.Shape;
46 import javax.swing.SwingConstants;
47 import javax.swing.event.DocumentEvent;
49 public abstract class View implements SwingConstants
51 public static final int BadBreakWeight = 0;
52 public static final int ExcellentBreakWeight = 2000;
53 public static final int ForcedBreakWeight = 3000;
54 public static final int GoodBreakWeight = 1000;
56 public static final int X_AXIS = 0;
57 public static final int Y_AXIS = 1;
59 private float width, height;
60 private Element elt;
61 private View parent;
63 /**
64 * Creates a new <code>View</code> instance.
66 * @param elem an <code>Element</code> value
68 public View(Element elem)
70 elt = elem;
73 public abstract void paint(Graphics g, Shape s);
75 public void setParent(View parent)
77 this.parent = parent;
80 public View getParent()
82 return parent;
85 public Container getContainer()
87 View parent = getParent();
88 if (parent == null)
89 return null;
90 else
91 return parent.getContainer();
94 public Document getDocument()
96 return getElement().getDocument();
99 public Element getElement()
101 return elt;
104 public abstract float getPreferredSpan(int axis);
106 public int getResizeWeight(int axis)
108 return 0;
111 public float getMaximumSpan(int axis)
113 if (getResizeWeight(axis) <= 0)
114 return getPreferredSpan(axis);
116 return Integer.MAX_VALUE;
119 public float getMinimumSpan(int axis)
121 if (getResizeWeight(axis) <= 0)
122 return getPreferredSpan(axis);
124 return Integer.MAX_VALUE;
127 public void setSize(float width, float height)
129 // The default implementation does nothing.
132 public float getAlignment(int axis)
134 return 0.5f;
137 public AttributeSet getAttributes()
139 return getElement().getAttributes();
142 public boolean isVisible()
144 return true;
147 public int getViewCount()
149 return 0;
152 public View getView(int index)
154 return null;
157 public ViewFactory getViewFactory()
159 View parent = getParent();
160 return parent != null ? parent.getViewFactory() : null;
163 public void replace(int offset, int length, View[] views)
165 // Default implementation does nothing.
168 public void insert(int offset, View view)
170 View[] array = { view };
171 replace(offset, 1, array);
174 public void append(View view)
176 View[] array = { view };
177 int offset = getViewCount();
178 replace(offset, 0, array);
181 public void removeAll()
183 replace(0, getViewCount(), new View[0]);
186 public void remove(int index)
188 replace(index, 1, null);
191 public View createFragment(int p0, int p1)
193 // The default implementation doesn't support fragmentation.
194 return this;
197 public int getStartOffset()
199 return getElement().getStartOffset();
202 public int getEndOffset()
204 return getElement().getEndOffset();
207 public Shape getChildAllocation(int index, Shape a)
209 return null;
213 * @since 1.4
215 public int getViewIndex(float x, float y, Shape allocation)
217 return -1;
221 * @since 1.4
223 public String getToolTipText(float x, float y, Shape allocation)
225 int index = getViewIndex(x, y, allocation);
227 if (index < -1)
228 return null;
230 Shape childAllocation = getChildAllocation(index, allocation);
232 if (childAllocation.getBounds().contains(x, y))
233 return getView(index).getToolTipText(x, y, childAllocation);
235 return null;
239 * @since 1.3
241 public Graphics getGraphics()
243 return getContainer().getGraphics();
246 public void preferenceChanged(View child, boolean width, boolean height)
248 if (parent != null)
249 parent.preferenceChanged(this, width, height);
252 public int getBreakWeight(int axis, float pos, float len)
254 return BadBreakWeight;
257 public View breakView(int axis, int offset, float pos, float len)
259 return this;
263 * @since 1.3
265 public int getViewIndex(int pos, Position.Bias b)
267 return -1;
271 * Receive notification about an insert update to the text model.
273 * The default implementation of this method does the following:
274 * <ul>
275 * <li>Call {@link #updateChildren} if the element that this view is
276 * responsible for has changed. This makes sure that the children can
277 * correctly represent the model.<li>
278 * <li>Call {@link #forwardUpdate}. This forwards the DocumentEvent to
279 * the child views.<li>
280 * <li>Call {@link #updateLayout}. Gives the view a chance to either
281 * repair its layout, reschedule layout or do nothing at all.</li>
282 * </ul>
284 * @param ev the DocumentEvent that describes the change
285 * @param shape the shape of the view
286 * @param vf the ViewFactory for creating child views
288 public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
290 Element el = getElement();
291 DocumentEvent.ElementChange ec = ev.getChange(el);
292 if (ec != null)
293 updateChildren(ec, ev, vf);
294 forwardUpdate(ec, ev, shape, vf);
295 updateLayout(ec, ev, shape);
299 * Receive notification about a remove update to the text model.
301 * The default implementation of this method does the following:
302 * <ul>
303 * <li>Call {@link #updateChildren} if the element that this view is
304 * responsible for has changed. This makes sure that the children can
305 * correctly represent the model.<li>
306 * <li>Call {@link #forwardUpdate}. This forwards the DocumentEvent to
307 * the child views.<li>
308 * <li>Call {@link #updateLayout}. Gives the view a chance to either
309 * repair its layout, reschedule layout or do nothing at all.</li>
310 * </ul>
312 * @param ev the DocumentEvent that describes the change
313 * @param shape the shape of the view
314 * @param vf the ViewFactory for creating child views
316 public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
318 Element el = getElement();
319 DocumentEvent.ElementChange ec = ev.getChange(el);
320 if (ec != null)
321 updateChildren(ec, ev, vf);
322 forwardUpdate(ec, ev, shape, vf);
323 updateLayout(ec, ev, shape);
327 * Receive notification about a change update to the text model.
329 * The default implementation of this method does the following:
330 * <ul>
331 * <li>Call {@link #updateChildren} if the element that this view is
332 * responsible for has changed. This makes sure that the children can
333 * correctly represent the model.<li>
334 * <li>Call {@link #forwardUpdate}. This forwards the DocumentEvent to
335 * the child views.<li>
336 * <li>Call {@link #updateLayout}. Gives the view a chance to either
337 * repair its layout, reschedule layout or do nothing at all.</li>
338 * </ul>
340 * @param ev the DocumentEvent that describes the change
341 * @param shape the shape of the view
342 * @param vf the ViewFactory for creating child views
344 public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
346 Element el = getElement();
347 DocumentEvent.ElementChange ec = ev.getChange(el);
348 if (ec != null)
349 updateChildren(ec, ev, vf);
350 forwardUpdate(ec, ev, shape, vf);
351 updateLayout(ec, ev, shape);
355 * Updates the list of children that is returned by {@link #getView}
356 * and {@link #getViewCount}.
358 * Element that are specified as beeing added in the ElementChange record are
359 * assigned a view for using the ViewFactory. Views of Elements that
360 * are specified as beeing removed are removed from the list.
362 * @param ec the ElementChange record that describes the change of the
363 * element
364 * @param ev the DocumentEvent describing the change of the document model
365 * @param vf the ViewFactory to use for creating new views
367 * @return whether or not the child views represent the child elements of
368 * the element that this view is responsible for. Some views may
369 * create views that are responsible only for parts of the element
370 * that they are responsible for and should then return false.
372 * @since 1.3
374 protected boolean updateChildren(DocumentEvent.ElementChange ec,
375 DocumentEvent ev,
376 ViewFactory vf)
378 Element[] added = ec.getChildrenAdded();
379 Element[] removed = ec.getChildrenRemoved();
380 int index = ec.getIndex();
382 View[] newChildren = new View[added.length];
383 for (int i = 0; i < added.length; ++i)
384 newChildren[i] = vf.create(added[i]);
385 replace(index, removed.length, newChildren);
387 return true;
391 * Forwards the DocumentEvent to child views that need to get notified
392 * of the change to the model. This calles {@link #forwardUpdateToView}
393 * for each View that must be forwarded to.
395 * @param ec the ElementChange describing the element changes (may be
396 * <code>null</code> if there were no changes)
397 * @param ev the DocumentEvent describing the changes to the model
398 * @param shape the current allocation of the view
399 * @param vf the ViewFactory used to create new Views
401 * @since 1.3
403 protected void forwardUpdate(DocumentEvent.ElementChange ec,
404 DocumentEvent ev, Shape shape, ViewFactory vf)
406 int count = getViewCount();
407 for (int i = 0; i < count; i++)
409 View child = getView(i);
410 forwardUpdateToView(child, ev, shape, vf);
415 * Forwards an update event to the given child view. This calls
416 * {@link #insertUpdate}, {@link #removeUpdate} or {@link #changedUpdate},
417 * depending on the type of document event.
419 * @param view the View to forward the event to
420 * @param ev the DocumentEvent to forward
421 * @param shape the current allocation of the View
422 * @param vf the ViewFactory used to create new Views
424 * @since 1.3
426 protected void forwardUpdateToView(View view, DocumentEvent ev, Shape shape,
427 ViewFactory vf)
429 DocumentEvent.EventType type = ev.getType();
430 if (type == DocumentEvent.EventType.INSERT)
431 view.insertUpdate(ev, shape, vf);
432 else if (type == DocumentEvent.EventType.REMOVE)
433 view.removeUpdate(ev, shape, vf);
434 else if (type == DocumentEvent.EventType.CHANGE)
435 view.changedUpdate(ev, shape, vf);
439 * Updates the layout.
441 * @param ec the ElementChange that describes the changes to the element
442 * @param ev the DocumentEvent that describes the changes to the model
443 * @param shape the current allocation for this view
445 * @since 1.3
447 protected void updateLayout(DocumentEvent.ElementChange ec,
448 DocumentEvent ev, Shape shape)
450 if (ec != null && shape != null)
451 preferenceChanged(null, true, true);
452 Container c = getContainer();
453 if (c != null)
454 c.repaint();
458 * Maps a position in the document into the coordinate space of the View.
459 * The output rectangle usually reflects the font height but has a width
460 * of zero.
462 * @param pos the position of the character in the model
463 * @param a the area that is occupied by the view
464 * @param b either {@link Position.Bias#Forward} or
465 * {@link Position.Bias#Backward} depending on the preferred
466 * direction bias. If <code>null</code> this defaults to
467 * <code>Position.Bias.Forward</code>
469 * @return a rectangle that gives the location of the document position
470 * inside the view coordinate space
472 * @throws BadLocationException if <code>pos</code> is invalid
473 * @throws IllegalArgumentException if b is not one of the above listed
474 * valid values
476 public abstract Shape modelToView(int pos, Shape a, Position.Bias b)
477 throws BadLocationException;
480 * Maps a region in the document into the coordinate space of the View.
482 * @param p1 the beginning position inside the document
483 * @param b1 the direction bias for the beginning position
484 * @param p2 the end position inside the document
485 * @param b2 the direction bias for the end position
486 * @param a the area that is occupied by the view
488 * @return a rectangle that gives the span of the document region
489 * inside the view coordinate space
491 * @throws BadLocationException if <code>p1</code> or <code>p2</code> are
492 * invalid
493 * @throws IllegalArgumentException if b1 or b2 is not one of the above
494 * listed valid values
496 public Shape modelToView(int p1, Position.Bias b1,
497 int p2, Position.Bias b2, Shape a)
498 throws BadLocationException
500 if (b1 != Position.Bias.Forward && b1 != Position.Bias.Backward)
501 throw new IllegalArgumentException
502 ("b1 must be either Position.Bias.Forward or Position.Bias.Backward");
503 if (b2 != Position.Bias.Forward && b2 != Position.Bias.Backward)
504 throw new IllegalArgumentException
505 ("b2 must be either Position.Bias.Forward or Position.Bias.Backward");
506 Shape s1 = modelToView(p1, a, b1);
507 Shape s2 = modelToView(p2, a, b2);
508 return s1.getBounds().union(s2.getBounds());
512 * Maps a position in the document into the coordinate space of the View.
513 * The output rectangle usually reflects the font height but has a width
514 * of zero.
516 * This method is deprecated and calls
517 * {@link #modelToView(int, Position.Bias, int, Position.Bias, Shape)} with
518 * a bias of {@link Position.Bias#Forward}.
520 * @param pos the position of the character in the model
521 * @param a the area that is occupied by the view
523 * @return a rectangle that gives the location of the document position
524 * inside the view coordinate space
526 * @throws BadLocationException if <code>pos</code> is invalid
528 * @deprecated Use {@link #modelToView(int, Shape, Position.Bias)} instead.
530 public Shape modelToView(int pos, Shape a) throws BadLocationException
532 return modelToView(pos, a, Position.Bias.Forward);
536 * Maps coordinates from the <code>View</code>'s space into a position
537 * in the document model.
539 * @param x the x coordinate in the view space
540 * @param y the y coordinate in the view space
541 * @param a the allocation of this <code>View</code>
542 * @param b the bias to use
544 * @return the position in the document that corresponds to the screen
545 * coordinates <code>x, y</code>
547 public abstract int viewToModel(float x, float y, Shape a, Position.Bias[] b);
550 * Maps coordinates from the <code>View</code>'s space into a position
551 * in the document model. This method is deprecated and only there for
552 * compatibility.
554 * @param x the x coordinate in the view space
555 * @param y the y coordinate in the view space
556 * @param a the allocation of this <code>View</code>
558 * @return the position in the document that corresponds to the screen
559 * coordinates <code>x, y</code>
561 * @deprecated Use {@link #viewToModel(float, float, Shape, Position.Bias[])}
562 * instead.
564 public int viewToModel(float x, float y, Shape a)
566 return viewToModel(x, y, a, new Position.Bias[0]);
570 * Dumps the complete View hierarchy. This method can be used for debugging
571 * purposes.
573 void dump()
575 // Climb up the hierarchy to the parent.
576 View parent = getParent();
577 if (parent != null)
578 parent.dump();
579 else
580 dump(0);
584 * Dumps the view hierarchy below this View with the specified indentation
585 * level.
587 * @param indent the indentation level to be used for this view
589 void dump(int indent)
591 for (int i = 0; i < indent; ++i)
592 System.out.print('.');
593 System.out.println(this);
595 int count = getViewCount();
596 for (int i = 0; i < count; ++i)
597 getView(i).dump(indent + 1);
601 * Returns the document position that is (visually) nearest to the given
602 * document position <code>pos</code> in the given direction <code>d</code>.
604 * @param pos the document position
605 * @param b the bias for <code>pos</code>
606 * @param a the allocation for this view
607 * @param d the direction, must be either {@link SwingConstants#NORTH},
608 * {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or
609 * {@link SwingConstants#EAST}
610 * @param biasRet an array of {@link Position.Bias} that can hold at least
611 * one element, which is filled with the bias of the return position
612 * on method exit
614 * @return the document position that is (visually) nearest to the given
615 * document position <code>pos</code> in the given direction
616 * <code>d</code>
618 * @throws BadLocationException if <code>pos</code> is not a valid offset in
619 * the document model
620 * @throws IllegalArgumentException if <code>d</code> is not a valid direction
622 public int getNextVisualPositionFrom(int pos, Position.Bias b,
623 Shape a, int d,
624 Position.Bias[] biasRet)
625 throws BadLocationException
627 int ret = pos;
628 switch (d)
630 case WEST:
631 ret = pos - 1;
632 break;
633 case EAST:
634 ret = pos + 1;
635 break;
636 case NORTH:
637 // TODO: Implement this
638 break;
639 case SOUTH:
640 // TODO: Implement this
641 break;
642 default:
643 throw new IllegalArgumentException("Illegal value for d");
645 return ret;