1
|
/*******************************************************************************
|
2
|
* Copyright (c) 2000, 2010 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
|
*******************************************************************************/
|
11
|
package org.eclipse.draw2d.text;
|
12
|
|
13
|
import java.util.ArrayList;
|
14
|
import java.util.Iterator;
|
15
|
import java.util.List;
|
16
|
|
17
|
|
18
|
import org.eclipse.draw2d.Border;
|
19
|
import org.eclipse.draw2d.ColorConstants;
|
20
|
import org.eclipse.draw2d.Graphics;
|
21
|
import org.eclipse.draw2d.geometry.Rectangle;
|
22
|
import org.eclipse.draw2d.rap.swt.SWT;
|
23
|
|
24
|
/**
|
25
|
* A <code>FlowFigure</code> represented by multiple <code>LineBox</code>
|
26
|
* fragments. An <code>InlineFlow</code>'s parent must be either a
|
27
|
* {@link BlockFlow} or another InlineFlow.
|
28
|
*
|
29
|
* <P>
|
30
|
* An InlineFlow may contain other InlineFlow figures.
|
31
|
*
|
32
|
* <P>
|
33
|
* WARNING: This class is not intended to be subclassed by clients.
|
34
|
*
|
35
|
* @author Randy Hudson
|
36
|
* @since 2.0
|
37
|
*/
|
38
|
public class InlineFlow extends FlowFigure {
|
39
|
|
40
|
List fragments = new ArrayList(1);
|
41
|
|
42
|
/**
|
43
|
* Iterates over the children to find the width before a line-break is
|
44
|
* encountered.
|
45
|
*
|
46
|
* @see org.eclipse.draw2d.text.FlowFigure#addLeadingWordRequirements(int[])
|
47
|
*/
|
48
|
public boolean addLeadingWordRequirements(int[] width) {
|
49
|
Iterator iter = getChildren().iterator();
|
50
|
while (iter.hasNext()) {
|
51
|
if (((FlowFigure) iter.next()).addLeadingWordRequirements(width))
|
52
|
return true;
|
53
|
}
|
54
|
return false;
|
55
|
}
|
56
|
|
57
|
/**
|
58
|
* Extended to return false if the point is not also contained by at least
|
59
|
* one fragment.
|
60
|
*
|
61
|
* @return <code>true</code> if a fragment contains the given point
|
62
|
* @param x
|
63
|
* the relative x coordinate
|
64
|
* @param y
|
65
|
* the relative y coordinate
|
66
|
*/
|
67
|
public boolean containsPoint(int x, int y) {
|
68
|
if (super.containsPoint(x, y)) {
|
69
|
List frags = getFragments();
|
70
|
for (int i = 0; i < frags.size(); i++)
|
71
|
if (((FlowBox) frags.get(i)).containsPoint(x, y))
|
72
|
return true;
|
73
|
}
|
74
|
|
75
|
return false;
|
76
|
}
|
77
|
|
78
|
/**
|
79
|
* @see FlowFigure#createDefaultFlowLayout()
|
80
|
*/
|
81
|
protected FlowFigureLayout createDefaultFlowLayout() {
|
82
|
return new InlineFlowLayout(this);
|
83
|
}
|
84
|
|
85
|
/**
|
86
|
* Returns the <code>FlowBox</code> fragments contained in this InlineFlow.
|
87
|
* The returned list should not be modified.
|
88
|
*
|
89
|
* @return The fragments
|
90
|
*/
|
91
|
public List getFragments() {
|
92
|
return fragments;
|
93
|
}
|
94
|
|
95
|
/**
|
96
|
* Overridden to paint a {@link FlowBorder} if present, and draw selection.
|
97
|
* The border is painted first, followed by selection which is generally
|
98
|
* done in XOR, which still allows the border to be seen.
|
99
|
*
|
100
|
* @param graphics
|
101
|
* the graphics
|
102
|
*/
|
103
|
protected void paintBorder(Graphics graphics) {
|
104
|
if (getBorder() != null) {
|
105
|
FlowBorder fb = (FlowBorder) getBorder();
|
106
|
List frags = getFragments();
|
107
|
Rectangle where = new Rectangle();
|
108
|
int sides;
|
109
|
for (int i = 0; i < frags.size(); i++) {
|
110
|
FlowBox box = (FlowBox) frags.get(i);
|
111
|
|
112
|
where.x = box.getX();
|
113
|
where.width = box.getWidth();
|
114
|
where.y = -box.getAscentWithBorder();
|
115
|
where.height = box.getDescentWithBorder() - where.y;
|
116
|
where.y += box.getBaseline();
|
117
|
sides = 0;
|
118
|
if (i == 0)
|
119
|
sides = SWT.LEAD;
|
120
|
if (i == frags.size() - 1)
|
121
|
sides |= SWT.TRAIL;
|
122
|
fb.paint(this, graphics, where, sides);
|
123
|
}
|
124
|
graphics.restoreState();
|
125
|
}
|
126
|
if (selectionStart != -1)
|
127
|
paintSelection(graphics);
|
128
|
}
|
129
|
|
130
|
/**
|
131
|
* Renders the XOR selection rectangles to the graphics.
|
132
|
*
|
133
|
* @param graphics
|
134
|
* the graphics to paint on
|
135
|
* @since 3.1
|
136
|
*/
|
137
|
protected void paintSelection(Graphics graphics) {
|
138
|
graphics.restoreState();
|
139
|
graphics.setXORMode(true);
|
140
|
graphics.setBackgroundColor(ColorConstants.white);
|
141
|
List list = getFragments();
|
142
|
FlowBox box;
|
143
|
for (int i = 0; i < list.size(); i++) {
|
144
|
box = (FlowBox) list.get(i);
|
145
|
int top = box.getLineRoot().getVisibleTop();
|
146
|
int bottom = box.getLineRoot().getVisibleBottom();
|
147
|
graphics.fillRectangle(box.getX(), top, box.getWidth(), bottom
|
148
|
- top);
|
149
|
}
|
150
|
}
|
151
|
|
152
|
/**
|
153
|
* @see FlowFigure#postValidate()
|
154
|
*/
|
155
|
public void postValidate() {
|
156
|
List list = getFragments();
|
157
|
FlowBox box;
|
158
|
int left = Integer.MAX_VALUE, top = left;
|
159
|
int right = Integer.MIN_VALUE, bottom = right;
|
160
|
|
161
|
for (int i = 0; i < list.size(); i++) {
|
162
|
box = (FlowBox) list.get(i);
|
163
|
left = Math.min(left, box.getX());
|
164
|
right = Math.max(right, box.getX() + box.getWidth());
|
165
|
top = Math.min(top, box.getLineRoot().getVisibleTop());
|
166
|
bottom = Math.max(bottom, box.getLineRoot().getVisibleBottom());
|
167
|
}
|
168
|
|
169
|
setBounds(new Rectangle(left, top, right - left, bottom - top));
|
170
|
repaint();
|
171
|
list = getChildren();
|
172
|
for (int i = 0; i < list.size(); i++)
|
173
|
((FlowFigure) list.get(i)).postValidate();
|
174
|
}
|
175
|
|
176
|
/**
|
177
|
* Overridden to assert that only {@link FlowBorder} is used.
|
178
|
* <code>null</code> is still a valid value as well.
|
179
|
*
|
180
|
* @param border
|
181
|
* <code>null</code> or a FlowBorder
|
182
|
*/
|
183
|
public void setBorder(Border border) {
|
184
|
if (border == null || border instanceof FlowBorder)
|
185
|
super.setBorder(border);
|
186
|
else
|
187
|
throw new RuntimeException(
|
188
|
"Border must be an instance of FlowBorder"); //$NON-NLS-1$
|
189
|
}
|
190
|
|
191
|
}
|