1 /* ParagraphView.java -- A composite View
2 Copyright (C) 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)
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
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
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
.Shape
;
43 import javax
.swing
.SizeRequirements
;
44 import javax
.swing
.event
.DocumentEvent
;
47 * A {@link FlowView} that flows it's children horizontally and boxes the rows
50 * @author Roman Kennke (roman@kennke.org)
52 public class ParagraphView
extends FlowView
implements TabExpander
55 * A specialized horizontal <code>BoxView</code> that represents exactly
56 * one row in a <code>ParagraphView</code>.
58 class Row
extends BoxView
61 * Creates a new instance of <code>Row</code>.
69 * Overridden to adjust when we are the first line, and firstLineIndent
72 public short getLeftInset()
74 short leftInset
= super.getLeftInset();
75 View parent
= getParent();
78 if (parent
.getView(0) == this)
79 leftInset
+= firstLineIndent
;
84 public float getAlignment(int axis
)
88 switch (justification
)
90 case StyleConstants
.ALIGN_RIGHT
:
93 case StyleConstants
.ALIGN_CENTER
:
94 case StyleConstants
.ALIGN_JUSTIFIED
:
97 case StyleConstants
.ALIGN_LEFT
:
102 align
= super.getAlignment(axis
);
107 * Overridden because child views are not necessarily laid out in model
110 protected int getViewIndexAtPosition(int pos
)
113 if (pos
>= getStartOffset() && pos
< getEndOffset())
115 int nviews
= getViewCount();
116 for (int i
= 0; i
< nviews
&& index
== -1; i
++)
118 View child
= getView(i
);
119 if (pos
>= child
.getStartOffset() && pos
< child
.getEndOffset())
128 * Overridden to perform a baseline layout. The normal BoxView layout
129 * isn't completely suitable for rows.
131 protected void layoutMinorAxis(int targetSpan
, int axis
, int[] offsets
,
134 baselineLayout(targetSpan
, axis
, offsets
, spans
);
138 * Overridden to perform a baseline layout. The normal BoxView layout
139 * isn't completely suitable for rows.
141 protected SizeRequirements
calculateMinorAxisRequirements(int axis
,
144 return baselineRequirements(axis
, r
);
147 protected void loadChildren(ViewFactory vf
)
149 // Do nothing here. The children are added while layouting.
153 * Overridden to determine the minimum start offset of the row's children.
155 public int getStartOffset()
157 // Determine minimum start offset of the children.
158 int offset
= Integer
.MAX_VALUE
;
159 int n
= getViewCount();
160 for (int i
= 0; i
< n
; i
++)
163 offset
= Math
.min(offset
, v
.getStartOffset());
169 * Overridden to determine the maximum end offset of the row's children.
171 public int getEndOffset()
173 // Determine minimum start offset of the children.
175 int n
= getViewCount();
176 for (int i
= 0; i
< n
; i
++)
179 offset
= Math
.max(offset
, v
.getEndOffset());
186 * The indentation of the first line of the paragraph.
188 protected int firstLineIndent
;
191 * The justification of the paragraph.
193 private int justification
;
196 * The line spacing of this paragraph.
198 private float lineSpacing
;
201 * The TabSet of this paragraph.
203 private TabSet tabSet
;
206 * Creates a new <code>ParagraphView</code> for the given
207 * <code>Element</code>.
209 * @param element the element that is rendered by this ParagraphView
211 public ParagraphView(Element element
)
213 super(element
, Y_AXIS
);
216 public float nextTabStop(float x
, int tabOffset
)
218 throw new InternalError("Not implemented yet");
222 * Creates a new view that represents a row within a flow.
224 * @return a view for a new row
226 protected View
createRow()
228 return new Row(getElement());
232 * Returns the alignment for this paragraph view for the specified axis.
233 * For the X_AXIS the paragraph view will be aligned at it's left edge
234 * (0.0F). For the Y_AXIS the paragraph view will be aligned at the
235 * center of it's first row.
237 * @param axis the axis which is examined
239 * @return the alignment for this paragraph view for the specified axis
241 public float getAlignment(int axis
)
246 else if (getViewCount() > 0)
248 float prefHeight
= getPreferredSpan(Y_AXIS
);
249 float firstRowHeight
= getView(0).getPreferredSpan(Y_AXIS
);
250 align
= (firstRowHeight
/ 2.F
) / prefHeight
;
258 * Receives notification when some attributes of the displayed element
259 * changes. This triggers a refresh of the cached attributes of this
262 * @param ev the document event
263 * @param a the allocation of this view
264 * @param vf the view factory to use for creating new child views
266 public void changedUpdate(DocumentEvent ev
, Shape a
, ViewFactory vf
)
268 setPropertiesFromAttributes();
269 layoutChanged(X_AXIS
);
270 layoutChanged(Y_AXIS
);
271 super.changedUpdate(ev
, a
, vf
);
275 * Fetches the cached properties from the element's attributes.
277 protected void setPropertiesFromAttributes()
279 Element el
= getElement();
280 AttributeSet atts
= el
.getAttributes();
281 setFirstLineIndent(StyleConstants
.getFirstLineIndent(atts
));
282 setLineSpacing(StyleConstants
.getLineSpacing(atts
));
283 setJustification(StyleConstants
.getAlignment(atts
));
284 tabSet
= StyleConstants
.getTabSet(atts
);
288 * Sets the indentation of the first line of the paragraph.
290 * @param i the indentation to set
292 protected void setFirstLineIndent(float i
)
294 firstLineIndent
= (int) i
;
298 * Sets the justification of the paragraph.
300 * @param j the justification to set
302 protected void setJustification(int j
)
308 * Sets the line spacing for this paragraph.
310 * @param s the line spacing to set
312 protected void setLineSpacing(float s
)
318 * Returns the i-th view from the logical views, before breaking into rows.
320 * @param i the index of the logical view to return
322 * @return the i-th view from the logical views, before breaking into rows
324 protected View
getLayoutView(int i
)
326 return layoutPool
.getView(i
);
330 * Returns the number of logical child views.
332 * @return the number of logical child views
334 protected int getLayoutViewCount()
336 return layoutPool
.getViewCount();
340 * Returns the TabSet used by this ParagraphView.
342 * @return the TabSet used by this ParagraphView
344 protected TabSet
getTabSet()
350 * Finds the next offset in the document that has one of the characters
351 * specified in <code>string</code>. If there is no such character found,
354 * @param string the characters to search for
355 * @param start the start offset
357 * @return the next offset in the document that has one of the characters
358 * specified in <code>string</code>
360 protected int findOffsetToCharactersInString(char[] string
, int start
)
363 Document doc
= getDocument();
364 Segment text
= new Segment();
367 doc
.getText(start
, doc
.getLength() - start
, text
);
373 char ch
= text
.next();
374 if (ch
== Segment
.DONE
)
377 for (int j
= 0; j
< string
.length
; ++j
)
388 catch (BadLocationException ex
)
390 // Ignore this and return -1.
395 protected int getClosestPositionTo(int pos
, Position
.Bias bias
, Shape a
,
396 int direction
, Position
.Bias
[] biasRet
,
398 throws BadLocationException
400 // FIXME: Implement this properly. However, this looks like it might
401 // have been replaced by viewToModel.
406 * Returns the size that is used by this view (or it's child views) between
407 * <code>startOffset</code> and <code>endOffset</code>. If the child views
408 * implement the {@link TabableView} interface, then this is used to
409 * determine the span, otherwise we use the preferred span of the child
412 * @param startOffset the start offset
413 * @param endOffset the end offset
415 * @return the span used by the view between <code>startOffset</code> and
416 * <code>endOffset</cod>
418 protected float getPartialSize(int startOffset
, int endOffset
)
420 int startIndex
= getViewIndex(startOffset
, Position
.Bias
.Backward
);
421 int endIndex
= getViewIndex(endOffset
, Position
.Bias
.Forward
);
423 if (startIndex
== endIndex
)
425 View child
= getView(startIndex
);
426 if (child
instanceof TabableView
)
428 TabableView tabable
= (TabableView
) child
;
429 span
= tabable
.getPartialSpan(startOffset
, endOffset
);
432 span
= child
.getPreferredSpan(X_AXIS
);
434 else if (endIndex
- startIndex
== 1)
436 View child1
= getView(startIndex
);
437 if (child1
instanceof TabableView
)
439 TabableView tabable
= (TabableView
) child1
;
440 span
= tabable
.getPartialSpan(startOffset
, child1
.getEndOffset());
443 span
= child1
.getPreferredSpan(X_AXIS
);
444 View child2
= getView(endIndex
);
445 if (child2
instanceof TabableView
)
447 TabableView tabable
= (TabableView
) child2
;
448 span
+= tabable
.getPartialSpan(child2
.getStartOffset(), endOffset
);
451 span
+= child2
.getPreferredSpan(X_AXIS
);
455 // Start with the first view.
456 View child1
= getView(startIndex
);
457 if (child1
instanceof TabableView
)
459 TabableView tabable
= (TabableView
) child1
;
460 span
= tabable
.getPartialSpan(startOffset
, child1
.getEndOffset());
463 span
= child1
.getPreferredSpan(X_AXIS
);
465 // Add up the view spans between the start and the end view.
466 for (int i
= startIndex
+ 1; i
< endIndex
; i
++)
468 View child
= getView(i
);
469 span
+= child
.getPreferredSpan(X_AXIS
);
472 // Add the span of the last view.
473 View child2
= getView(endIndex
);
474 if (child2
instanceof TabableView
)
476 TabableView tabable
= (TabableView
) child2
;
477 span
+= tabable
.getPartialSpan(child2
.getStartOffset(), endOffset
);
480 span
+= child2
.getPreferredSpan(X_AXIS
);
486 * Returns the location where the tabs are calculated from. This returns
487 * <code>0.0F</code> by default.
489 * @return the location where the tabs are calculated from
491 protected float getTabBase()
497 * @specnote This method is specified to take a Row parameter, which is a
498 * private inner class of that class, which makes it unusable from
499 * application code. Also, this method seems to be replaced by
500 * {@link FlowStrategy#adjustRow(FlowView, int, int, int)}.
503 protected void adjustRow(Row r
, int desiredSpan
, int x
)
508 * @specnote This method's signature differs from the one defined in
509 * {@link View} and is therefore never called. It is probably there
510 * for historical reasons.
512 public View
breakView(int axis
, float len
, Shape a
)
514 // This method is not used.
519 * @specnote This method's signature differs from the one defined in
520 * {@link View} and is therefore never called. It is probably there
521 * for historical reasons.
523 public int getBreakWeight(int axis
, float len
)
525 // This method is not used.