blob: d345b348dd657e154dfa771ddbbe803640527654 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2002 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.event.DocumentEvent;
29import javax.swing.text.*;
30import java.util.Enumeration;
31import java.lang.Integer;
32
33/**
34 * A view implementation to display an html horizontal
35 * rule.
36 *
37 * @author Timothy Prinzing
38 * @author Sara Swanson
39 */
40class HRuleView extends View {
41
42 /**
43 * Creates a new view that represents an <hr> element.
44 *
45 * @param elem the element to create a view for
46 */
47 public HRuleView(Element elem) {
48 super(elem);
49 setPropertiesFromAttributes();
50 }
51
52 /**
53 * Update any cached values that come from attributes.
54 */
55 protected void setPropertiesFromAttributes() {
56 StyleSheet sheet = ((HTMLDocument)getDocument()).getStyleSheet();
57 AttributeSet eAttr = getElement().getAttributes();
58 attr = sheet.getViewAttributes(this);
59
60 alignment = StyleConstants.ALIGN_CENTER;
61 size = 0;
62 noshade = null;
63 widthValue = null;
64
65 if (attr != null) {
66 // getAlignment() returns ALIGN_LEFT by default, and HR should
67 // use ALIGN_CENTER by default, so we check if the alignment
68 // attribute is actually defined
69 if (attr.getAttribute(StyleConstants.Alignment) != null) {
70 alignment = StyleConstants.getAlignment(attr);
71 }
72
73 noshade = (String)eAttr.getAttribute(HTML.Attribute.NOSHADE);
74 Object value = eAttr.getAttribute(HTML.Attribute.SIZE);
75 if (value != null && (value instanceof String))
76 size = Integer.parseInt((String)value);
77 value = attr.getAttribute(CSS.Attribute.WIDTH);
78 if (value != null && (value instanceof CSS.LengthValue)) {
79 widthValue = (CSS.LengthValue)value;
80 }
81 topMargin = getLength(CSS.Attribute.MARGIN_TOP, attr);
82 bottomMargin = getLength(CSS.Attribute.MARGIN_BOTTOM, attr);
83 leftMargin = getLength(CSS.Attribute.MARGIN_LEFT, attr);
84 rightMargin = getLength(CSS.Attribute.MARGIN_RIGHT, attr);
85 }
86 else {
87 topMargin = bottomMargin = leftMargin = rightMargin = 0;
88 }
89 size = Math.max(2, size);
90 }
91
92 // This will be removed and centralized at some point, need to unify this
93 // and avoid private classes.
94 private float getLength(CSS.Attribute key, AttributeSet a) {
95 CSS.LengthValue lv = (CSS.LengthValue) a.getAttribute(key);
96 float len = (lv != null) ? lv.getValue() : 0;
97 return len;
98 }
99
100 // --- View methods ---------------------------------------------
101
102 /**
103 * Paints the view.
104 *
105 * @param g the graphics context
106 * @param a the allocation region for the view
107 * @see View#paint
108 */
109 public void paint(Graphics g, Shape a) {
110 Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a :
111 a.getBounds();
112 int x = 0;
113 int y = alloc.y + SPACE_ABOVE + (int)topMargin;
114 int width = alloc.width - (int)(leftMargin + rightMargin);
115 if (widthValue != null) {
116 width = (int)widthValue.getValue((float)width);
117 }
118 int height = alloc.height - (SPACE_ABOVE + SPACE_BELOW +
119 (int)topMargin + (int)bottomMargin);
120 if (size > 0)
121 height = size;
122
123 // Align the rule horizontally.
124 switch (alignment) {
125 case StyleConstants.ALIGN_CENTER:
126 x = alloc.x + (alloc.width / 2) - (width / 2);
127 break;
128 case StyleConstants.ALIGN_RIGHT:
129 x = alloc.x + alloc.width - width - (int)rightMargin;
130 break;
131 case StyleConstants.ALIGN_LEFT:
132 default:
133 x = alloc.x + (int)leftMargin;
134 break;
135 }
136
137 // Paint either a shaded rule or a solid line.
138 if (noshade != null) {
139 g.setColor(Color.black);
140 g.fillRect(x, y, width, height);
141 }
142 else {
143 Color bg = getContainer().getBackground();
144 Color bottom, top;
145 if (bg == null || bg.equals(Color.white)) {
146 top = Color.darkGray;
147 bottom = Color.lightGray;
148 }
149 else {
150 top = Color.darkGray;
151 bottom = Color.white;
152 }
153 g.setColor(bottom);
154 g.drawLine(x + width - 1, y, x + width - 1, y + height - 1);
155 g.drawLine(x, y + height - 1, x + width - 1, y + height - 1);
156 g.setColor(top);
157 g.drawLine(x, y, x + width - 1, y);
158 g.drawLine(x, y, x, y + height - 1);
159 }
160
161 }
162
163
164 /**
165 * Calculates the desired shape of the rule... this is
166 * basically the preferred size of the border.
167 *
168 * @param axis may be either X_AXIS or Y_AXIS
169 * @return the desired span
170 * @see View#getPreferredSpan
171 */
172 public float getPreferredSpan(int axis) {
173 switch (axis) {
174 case View.X_AXIS:
175 return 1;
176 case View.Y_AXIS:
177 if (size > 0) {
178 return size + SPACE_ABOVE + SPACE_BELOW + topMargin +
179 bottomMargin;
180 } else {
181 if (noshade != null) {
182 return 2 + SPACE_ABOVE + SPACE_BELOW + topMargin +
183 bottomMargin;
184 } else {
185 return SPACE_ABOVE + SPACE_BELOW + topMargin +bottomMargin;
186 }
187 }
188 default:
189 throw new IllegalArgumentException("Invalid axis: " + axis);
190 }
191 }
192
193 /**
194 * Gets the resize weight for the axis.
195 * The rule is: rigid vertically and flexible horizontally.
196 *
197 * @param axis may be either X_AXIS or Y_AXIS
198 * @return the weight
199 */
200 public int getResizeWeight(int axis) {
201 if (axis == View.X_AXIS) {
202 return 1;
203 } else if (axis == View.Y_AXIS) {
204 return 0;
205 } else {
206 return 0;
207 }
208 }
209
210 /**
211 * Determines how attractive a break opportunity in
212 * this view is. This is implemented to request a forced break.
213 *
214 * @param axis may be either View.X_AXIS or View.Y_AXIS
215 * @param pos the potential location of the start of the
216 * broken view (greater than or equal to zero).
217 * This may be useful for calculating tab
218 * positions.
219 * @param len specifies the relative length from <em>pos</em>
220 * where a potential break is desired. The value must be greater
221 * than or equal to zero.
222 * @return the weight, which should be a value between
223 * ForcedBreakWeight and BadBreakWeight.
224 */
225 public int getBreakWeight(int axis, float pos, float len) {
226 if (axis == X_AXIS) {
227 return ForcedBreakWeight;
228 }
229 return BadBreakWeight;
230 }
231
232 public View breakView(int axis, int offset, float pos, float len) {
233 return null;
234 }
235
236 /**
237 * Provides a mapping from the document model coordinate space
238 * to the coordinate space of the view mapped to it.
239 *
240 * @param pos the position to convert
241 * @param a the allocated region to render into
242 * @return the bounding box of the given position
243 * @exception BadLocationException if the given position does not
244 * represent a valid location in the associated document
245 * @see View#modelToView
246 */
247 public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException {
248 int p0 = getStartOffset();
249 int p1 = getEndOffset();
250 if ((pos >= p0) && (pos <= p1)) {
251 Rectangle r = a.getBounds();
252 if (pos == p1) {
253 r.x += r.width;
254 }
255 r.width = 0;
256 return r;
257 }
258 return null;
259 }
260
261 /**
262 * Provides a mapping from the view coordinate space to the logical
263 * coordinate space of the model.
264 *
265 * @param x the X coordinate
266 * @param y the Y coordinate
267 * @param a the allocated region to render into
268 * @return the location within the model that best represents the
269 * given point of view
270 * @see View#viewToModel
271 */
272 public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) {
273 Rectangle alloc = (Rectangle) a;
274 if (x < alloc.x + (alloc.width / 2)) {
275 bias[0] = Position.Bias.Forward;
276 return getStartOffset();
277 }
278 bias[0] = Position.Bias.Backward;
279 return getEndOffset();
280 }
281
282 /**
283 * Fetches the attributes to use when rendering. This is
284 * implemented to multiplex the attributes specified in the
285 * model with a StyleSheet.
286 */
287 public AttributeSet getAttributes() {
288 return attr;
289 }
290
291 public void changedUpdate(DocumentEvent changes, Shape a, ViewFactory f) {
292 super.changedUpdate(changes, a, f);
293 int pos = changes.getOffset();
294 if (pos <= getStartOffset() && (pos + changes.getLength()) >=
295 getEndOffset()) {
296 setPropertiesFromAttributes();
297 }
298 }
299
300 // --- variables ------------------------------------------------
301
302 private float topMargin;
303 private float bottomMargin;
304 private float leftMargin;
305 private float rightMargin;
306 private int alignment = StyleConstants.ALIGN_CENTER;
307 private String noshade = null;
308 private int size = 0;
309 private CSS.LengthValue widthValue;
310
311 private static final int SPACE_ABOVE = 3;
312 private static final int SPACE_BELOW = 3;
313
314 /** View Attributes. */
315 private AttributeSet attr;
316}