blob: 6d6006b0a6f5f74b6ba48036e82f00df63357423 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2003 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25package javax.swing.text.html;
26
27import java.awt.*;
28import javax.swing.SizeRequirements;
29import javax.swing.event.DocumentEvent;
30import javax.swing.text.Document;
31import javax.swing.text.Element;
32import javax.swing.text.AttributeSet;
33import javax.swing.text.StyleConstants;
34import javax.swing.text.View;
35import javax.swing.text.ViewFactory;
36import javax.swing.text.BadLocationException;
37import javax.swing.text.JTextComponent;
38
39/**
40 * Displays the a paragraph, and uses css attributes for its
41 * configuration.
42 *
43 * @author Timothy Prinzing
44 */
45
46public class ParagraphView extends javax.swing.text.ParagraphView {
47
48 /**
49 * Constructs a ParagraphView for the given element.
50 *
51 * @param elem the element that this view is responsible for
52 */
53 public ParagraphView(Element elem) {
54 super(elem);
55 }
56
57 /**
58 * Establishes the parent view for this view. This is
59 * guaranteed to be called before any other methods if the
60 * parent view is functioning properly.
61 * <p>
62 * This is implemented
63 * to forward to the superclass as well as call the
64 * <a href="#setPropertiesFromAttributes">setPropertiesFromAttributes</a>
65 * method to set the paragraph properties from the css
66 * attributes. The call is made at this time to ensure
67 * the ability to resolve upward through the parents
68 * view attributes.
69 *
70 * @param parent the new parent, or null if the view is
71 * being removed from a parent it was previously added
72 * to
73 */
74 public void setParent(View parent) {
75 super.setParent(parent);
76 if (parent != null) {
77 setPropertiesFromAttributes();
78 }
79 }
80
81 /**
82 * Fetches the attributes to use when rendering. This is
83 * implemented to multiplex the attributes specified in the
84 * model with a StyleSheet.
85 */
86 public AttributeSet getAttributes() {
87 if (attr == null) {
88 StyleSheet sheet = getStyleSheet();
89 attr = sheet.getViewAttributes(this);
90 }
91 return attr;
92 }
93
94 /**
95 * Sets up the paragraph from css attributes instead of
96 * the values found in StyleConstants (i.e. which are used
97 * by the superclass). Since
98 */
99 protected void setPropertiesFromAttributes() {
100 StyleSheet sheet = getStyleSheet();
101 attr = sheet.getViewAttributes(this);
102 painter = sheet.getBoxPainter(attr);
103 if (attr != null) {
104 super.setPropertiesFromAttributes();
105 setInsets((short) painter.getInset(TOP, this),
106 (short) painter.getInset(LEFT, this),
107 (short) painter.getInset(BOTTOM, this),
108 (short) painter.getInset(RIGHT, this));
109 Object o = attr.getAttribute(CSS.Attribute.TEXT_ALIGN);
110 if (o != null) {
111 // set horizontal alignment
112 String ta = o.toString();
113 if (ta.equals("left")) {
114 setJustification(StyleConstants.ALIGN_LEFT);
115 } else if (ta.equals("center")) {
116 setJustification(StyleConstants.ALIGN_CENTER);
117 } else if (ta.equals("right")) {
118 setJustification(StyleConstants.ALIGN_RIGHT);
119 } else if (ta.equals("justify")) {
120 setJustification(StyleConstants.ALIGN_JUSTIFIED);
121 }
122 }
123 // Get the width/height
124 cssWidth = (CSS.LengthValue)attr.getAttribute(
125 CSS.Attribute.WIDTH);
126 cssHeight = (CSS.LengthValue)attr.getAttribute(
127 CSS.Attribute.HEIGHT);
128 }
129 }
130
131 protected StyleSheet getStyleSheet() {
132 HTMLDocument doc = (HTMLDocument) getDocument();
133 return doc.getStyleSheet();
134 }
135
136
137 /**
138 * Calculate the needs for the paragraph along the minor axis.
139 *
140 * <p>If size requirements are explicitly specified for the paragraph,
141 * use that requirements. Otherwise, use the requirements of the
142 * superclass {@link javax.swing.text.ParagraphView}.</p>
143 *
144 * <p>If the {@code axis} parameter is neither {@code View.X_AXIS} nor
145 * {@code View.Y_AXIS}, {@link IllegalArgumentException} is thrown. If the
146 * {@code r} parameter is {@code null,} a new {@code SizeRequirements}
147 * object is created, otherwise the supplied {@code SizeRequirements}
148 * object is returned.</p>
149 *
150 * @param axis the minor axis
151 * @param r the input {@code SizeRequirements} object
152 * @return the new or adjusted {@code SizeRequirements} object
153 * @throw IllegalArgumentException if the {@code axis} parameter is invalid
154 */
155 protected SizeRequirements calculateMinorAxisRequirements(
156 int axis, SizeRequirements r) {
157 r = super.calculateMinorAxisRequirements(axis, r);
158
159 if (BlockView.spanSetFromAttributes(axis, r, cssWidth, cssHeight)) {
160 // Offset by the margins so that pref/min/max return the
161 // right value.
162 int margin = (axis == X_AXIS) ? getLeftInset() + getRightInset() :
163 getTopInset() + getBottomInset();
164 r.minimum -= margin;
165 r.preferred -= margin;
166 r.maximum -= margin;
167 }
168 return r;
169 }
170
171
172 /**
173 * Indicates whether or not this view should be
174 * displayed. If none of the children wish to be
175 * displayed and the only visible child is the
176 * break that ends the paragraph, the paragraph
177 * will not be considered visible. Otherwise,
178 * it will be considered visible and return true.
179 *
180 * @return true if the paragraph should be displayed
181 */
182 public boolean isVisible() {
183
184 int n = getLayoutViewCount() - 1;
185 for (int i = 0; i < n; i++) {
186 View v = getLayoutView(i);
187 if (v.isVisible()) {
188 return true;
189 }
190 }
191 if (n > 0) {
192 View v = getLayoutView(n);
193 if ((v.getEndOffset() - v.getStartOffset()) == 1) {
194 return false;
195 }
196 }
197 // If it's the last paragraph and not editable, it shouldn't
198 // be visible.
199 if (getStartOffset() == getDocument().getLength()) {
200 boolean editable = false;
201 Component c = getContainer();
202 if (c instanceof JTextComponent) {
203 editable = ((JTextComponent)c).isEditable();
204 }
205 if (!editable) {
206 return false;
207 }
208 }
209 return true;
210 }
211
212 /**
213 * Renders using the given rendering surface and area on that
214 * surface. This is implemented to delgate to the superclass
215 * after stashing the base coordinate for tab calculations.
216 *
217 * @param g the rendering surface to use
218 * @param a the allocated region to render into
219 * @see View#paint
220 */
221 public void paint(Graphics g, Shape a) {
222 if (a == null) {
223 return;
224 }
225
226 Rectangle r;
227 if (a instanceof Rectangle) {
228 r = (Rectangle) a;
229 } else {
230 r = a.getBounds();
231 }
232 painter.paint(g, r.x, r.y, r.width, r.height, this);
233 super.paint(g, a);
234 }
235
236 /**
237 * Determines the preferred span for this view. Returns
238 * 0 if the view is not visible, otherwise it calls the
239 * superclass method to get the preferred span.
240 * axis.
241 *
242 * @param axis may be either View.X_AXIS or View.Y_AXIS
243 * @return the span the view would like to be rendered into;
244 * typically the view is told to render into the span
245 * that is returned, although there is no guarantee;
246 * the parent may choose to resize or break the view
247 * @see javax.swing.text.ParagraphView#getPreferredSpan
248 */
249 public float getPreferredSpan(int axis) {
250 if (!isVisible()) {
251 return 0;
252 }
253 return super.getPreferredSpan(axis);
254 }
255
256 /**
257 * Determines the minimum span for this view along an
258 * axis. Returns 0 if the view is not visible, otherwise
259 * it calls the superclass method to get the minimum span.
260 *
261 * @param axis may be either <code>View.X_AXIS</code> or
262 * <code>View.Y_AXIS</code>
263 * @return the minimum span the view can be rendered into
264 * @see javax.swing.text.ParagraphView#getMinimumSpan
265 */
266 public float getMinimumSpan(int axis) {
267 if (!isVisible()) {
268 return 0;
269 }
270 return super.getMinimumSpan(axis);
271 }
272
273 /**
274 * Determines the maximum span for this view along an
275 * axis. Returns 0 if the view is not visible, otherwise
276 * it calls the superclass method ot get the maximum span.
277 *
278 * @param axis may be either <code>View.X_AXIS</code> or
279 * <code>View.Y_AXIS</code>
280 * @return the maximum span the view can be rendered into
281 * @see javax.swing.text.ParagraphView#getMaximumSpan
282 */
283 public float getMaximumSpan(int axis) {
284 if (!isVisible()) {
285 return 0;
286 }
287 return super.getMaximumSpan(axis);
288 }
289
290 private AttributeSet attr;
291 private StyleSheet.BoxPainter painter;
292 private CSS.LengthValue cssWidth;
293 private CSS.LengthValue cssHeight;
294}