comparison dwtx/draw2d/text/BlockFlow.d @ 98:95307ad235d9

Added Draw2d code, still work in progress
author Frank Benoit <benoit@tionex.de>
date Sun, 03 Aug 2008 00:52:14 +0200
parents
children
comparison
equal deleted inserted replaced
96:b492ba44e44d 98:95307ad235d9
1 /*******************************************************************************
2 * Copyright (c) 2000, 2005 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module dwtx.draw2d.text.BlockFlow;
14
15 import dwt.dwthelper.utils;
16 import dwtx.dwtxhelper.Collection;
17
18 import dwt.DWT;
19 import dwtx.draw2d.ColorConstants;
20 import dwtx.draw2d.Graphics;
21 import dwtx.draw2d.IFigure;
22 import dwtx.draw2d.PositionConstants;
23 import dwtx.draw2d.geometry.Insets;
24 import dwtx.draw2d.geometry.Rectangle;
25 import dwtx.draw2d.text.FlowFigure;
26 import dwtx.draw2d.text.BlockBox;
27 import dwtx.draw2d.text.BidiProcessor;
28 import dwtx.draw2d.text.FlowFigureLayout;
29 import dwtx.draw2d.text.BidiChars;
30 import dwtx.draw2d.text.BlockFlowLayout;
31 import dwtx.draw2d.text.FlowBorder;
32
33 /**
34 * A <code>FlowFigure</code> represented by a single {@link BlockBox} containing one or
35 * more lines. A BlockFlow is a creator of LineBoxes, which its children require during
36 * layout. A BlockFlow can be thought of as a foundation for a paragraph.
37 * <P>
38 * BlockFlows must be parented by a <code>FlowFigure</code>. {@link FlowPage} can be
39 * used as a "root" block and can be parented by normal Figures.
40 * <P>
41 * Only {@link FlowFigure}s can be added to a BlockFlow.
42 * <P>
43 * WARNING: This class is not intended to be subclassed by clients.
44 * @author hudsonr
45 * @since 2.1
46 */
47 public class BlockFlow
48 : FlowFigure
49 {
50
51 private const BlockBox blockBox;
52 private int alignment = PositionConstants.NONE;
53 private int orientation = DWT.NONE;
54 private bool bidiValid;
55
56 /**
57 * Constructs a new BlockFlow.
58 */
59 public this() {
60 blockBox = createBlockBox();
61 }
62
63 /**
64 * BlockFlows contribute a paragraph separator so as to keep the Bidi state of the text
65 * on either side of this block from affecting each other. Since each block is like a
66 * different paragraph, it does not contribute any actual text to its containing block.
67 *
68 * @see dwtx.draw2d.text.FlowFigure#contributeBidi(dwtx.draw2d.text.BidiProcessor)
69 */
70 protected void contributeBidi(BidiProcessor proc) {
71 proc.addControlChar(BidiChars.P_SEP);
72 }
73
74 BlockBox createBlockBox() {
75 return new BlockBox(this);
76 }
77
78 /**
79 * @see dwtx.draw2d.text.FlowFigure#createDefaultFlowLayout()
80 */
81 protected FlowFigureLayout createDefaultFlowLayout() {
82 return new BlockFlowLayout(this);
83 }
84
85 /**
86 * Returns the BlockBox associated with this.
87 * @return This BlockFlow's BlockBox
88 */
89 protected BlockBox getBlockBox() {
90 return blockBox;
91 }
92 package BlockBox getBlockBox_package() {
93 return getBlockBox();
94 }
95
96 int getBottomMargin() {
97 int margin = 0;
98 if (auto border = cast(FlowBorder)getBorder() ) {
99 return border.getBottomMargin();
100 }
101 List children = getChildren();
102 int childIndex = children.size() - 1;
103 if (childIndex >= 0 && null !is cast(BlockFlow)children.get(childIndex) ) {
104 margin = Math.max(margin,
105 (cast(BlockFlow)children.get(childIndex)).getBottomMargin());
106 }
107 return margin;
108 }
109
110 /**
111 * Returns the effective horizontal alignment. This method will never return {@link
112 * PositionConstants#NONE}. If the value is none, it will return the inherited alignment.
113 * If no alignment was inherited, it will return the default alignment ({@link
114 * PositionConstants#LEFT}).
115 * @return the effective alignment
116 */
117 public int getHorizontalAligment() {
118 if (alignment !is PositionConstants.NONE)
119 return alignment;
120 IFigure parent = getParent();
121 while (parent !is null && !( null !is cast(BlockFlow)parent ))
122 parent = parent.getParent();
123 if (parent !is null)
124 return (cast(BlockFlow)parent).getHorizontalAligment();
125 return PositionConstants.LEFT;
126 }
127
128 int getLeftMargin() {
129 if ( auto b = cast(FlowBorder)getBorder() )
130 return b.getLeftMargin();
131 return 0;
132 }
133
134 /**
135 * Returns the orientation set on this block.
136 * @return LTR, RTL or NONE
137 * @see #setOrientation(int)
138 * @since 3.1
139 */
140 public int getLocalOrientation() {
141 return orientation;
142 }
143
144 /**
145 * Returns the horizontal alignment set on this block.
146 * @return LEFT, RIGHT, ALWAYS_LEFT, ALWAYS_RIGHT, NONE
147 * @see #setHorizontalAligment(int)
148 * @since 3.1
149 */
150 public int getLocalHorizontalAlignment() {
151 return alignment;
152 }
153
154 /**
155 * Returns this block's Bidi orientation. If none was set on this block, it
156 * will inherit the one from its containing block. If there is no containing block, it
157 * will return the default orientation (DWT.RIGHT_TO_LEFT if mirrored; DWT.LEFT_TO_RIGHT
158 * otherwise).
159 *
160 * @return DWT.RIGHT_TO_LEFT or DWT.LEFT_TO_RIGHT
161 * @see #setOrientation(int)
162 * @since 3.1
163 */
164 public int getOrientation() {
165 if (orientation !is DWT.NONE)
166 return orientation;
167 IFigure parent = getParent();
168 while (parent !is null && !(null !is cast(BlockFlow)parent ))
169 parent = parent.getParent();
170 if (parent !is null)
171 return (cast(BlockFlow)parent).getOrientation();
172 return isMirrored() ? DWT.RIGHT_TO_LEFT : DWT.LEFT_TO_RIGHT;
173 }
174
175 int getRightMargin() {
176 if (auto b = cast(FlowBorder)getBorder() )
177 return b.getRightMargin();
178 return 0;
179 }
180
181 int getTopMargin() {
182 int margin = 0;
183 if (auto border = cast(FlowBorder)getBorder() ) {
184 return border.getTopMargin();
185 }
186 List children = getChildren();
187 if (children.size() > 0 && null !is cast(BlockFlow)children.get(0) ) {
188 margin = Math.max(margin,
189 (cast(BlockFlow)children.get(0)).getTopMargin());
190 }
191 return margin;
192 }
193
194 /**
195 * @see dwtx.draw2d.Figure#paintBorder(dwtx.draw2d.Graphics)
196 */
197 public void paintBorder(Graphics graphics) {
198 if ( auto b = cast(FlowBorder)getBorder() ) {
199 Rectangle where = getBlockBox().toRectangle();
200 where.crop(new Insets(getTopMargin(), getLeftMargin(),
201 getBottomMargin(), getRightMargin()));
202 (cast(FlowBorder)getBorder()).paint(this, graphics, where, DWT.LEAD | DWT.TRAIL);
203 } else
204 super.paintBorder(graphics);
205 if (selectionStart !is -1) {
206 graphics.restoreState();
207 graphics.setXORMode(true);
208 graphics.setBackgroundColor(ColorConstants.white);
209 graphics.fillRectangle(getBounds());
210 }
211 }
212
213 /**
214 * @see dwtx.draw2d.text.FlowFigure#postValidate()
215 */
216 public void postValidate() {
217 Rectangle newBounds = getBlockBox().toRectangle();
218 newBounds.crop(new Insets(getTopMargin(), getLeftMargin(),
219 getBottomMargin(), getRightMargin()));
220 setBounds(newBounds);
221 }
222
223 /**
224 * @see FlowFigure#revalidate()
225 */
226 public void revalidate() {
227 BlockFlowLayout layout = cast(BlockFlowLayout)getLayoutManager();
228 layout.blockContentsChanged();
229 super.revalidate();
230 }
231
232 /**
233 * A Block will invalidate the Bidi state of all its children, so that it is
234 * re-evaluated when this block is next validated.
235 * @see dwtx.draw2d.text.FlowFigure#revalidateBidi(dwtx.draw2d.IFigure)
236 */
237 protected void revalidateBidi(IFigure origin) {
238 if (bidiValid) {
239 bidiValid = false;
240 revalidate();
241 }
242 }
243
244 /**
245 * Sets the horitontal aligment of the block. Valid values are:
246 * <UL>
247 * <LI>{@link PositionConstants#NONE NONE} - (default) Alignment is inherited from
248 * parent. If a parent is not found then LEFT is used.</LI>
249 * <LI>{@link PositionConstants#LEFT} - Alignment is with leading edge</LI>
250 * <LI>{@link PositionConstants#RIGHT} - Alignment is with trailing edge</LI>
251 * <LI>{@link PositionConstants#CENTER}</LI>
252 * <LI>{@link PositionConstants#ALWAYS_LEFT} - Left, irrespective of orientation</LI>
253 * <LI>{@link PositionConstants#ALWAYS_RIGHT} - Right, irrespective of orientation</LI>
254 * </UL>
255 * @param value the aligment
256 * @see #getHorizontalAligment()
257 */
258 public void setHorizontalAligment(int value) {
259 value &= PositionConstants.LEFT | PositionConstants.CENTER | PositionConstants.RIGHT
260 | PositionConstants.ALWAYS_LEFT | PositionConstants.ALWAYS_RIGHT;
261 if (value is alignment)
262 return;
263 alignment = value;
264 revalidate();
265 }
266
267 /**
268 * Sets the orientation for this block. Orientation can be one of:
269 * <UL>
270 * <LI>{@link DWT#LEFT_TO_RIGHT}
271 * <LI>{@link DWT#RIGHT_TO_LEFT}
272 * <LI>{@link DWT#NONE} (default)
273 * </UL>
274 * <code>NONE</code> is used to indicate that orientation should be inherited from the
275 * encompassing block.
276 *
277 * @param orientation LTR, RTL or NONE
278 * @see #getOrientation()
279 * @since 3.1
280 */
281 public void setOrientation(int orientation) {
282 orientation &= DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT;
283 if (this.orientation is orientation)
284 return;
285 this.orientation = orientation;
286 revalidateBidi(this);
287 }
288
289 /**
290 * @see dwtx.draw2d.Figure#useLocalCoordinates()
291 */
292 protected bool useLocalCoordinates() {
293 return true;
294 }
295
296 /**
297 * Re-evaluate the Bidi state of all the fragments if it has been
298 * invalidated.
299 * @see dwtx.draw2d.IFigure#validate()
300 */
301 public void validate() {
302 if (!bidiValid) {
303 BidiProcessor.INSTANCE.setOrientation(getOrientation());
304 if (getOrientation() is DWT.LEFT_TO_RIGHT && isMirrored())
305 BidiProcessor.INSTANCE.addControlChar(BidiChars.LRE);
306 super.contributeBidi(BidiProcessor.INSTANCE);
307 BidiProcessor.INSTANCE.process();
308 bidiValid = true;
309 }
310 super.validate();
311 }
312
313 }