Added
Link Here
|
1 |
/****************************************************************************** |
2 |
* Copyright (c) 2006 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 |
|
12 |
package org.eclipse.gmf.runtime.draw2d.ui.figures; |
13 |
|
14 |
import java.lang.ref.WeakReference; |
15 |
import java.util.ArrayList; |
16 |
import java.util.List; |
17 |
import java.util.Map; |
18 |
import java.util.WeakHashMap; |
19 |
|
20 |
import org.eclipse.draw2d.Figure; |
21 |
import org.eclipse.draw2d.Graphics; |
22 |
import org.eclipse.draw2d.IFigure; |
23 |
import org.eclipse.draw2d.Label; |
24 |
import org.eclipse.draw2d.PositionConstants; |
25 |
import org.eclipse.draw2d.StackLayout; |
26 |
import org.eclipse.draw2d.geometry.Dimension; |
27 |
import org.eclipse.draw2d.geometry.Insets; |
28 |
import org.eclipse.draw2d.geometry.Point; |
29 |
import org.eclipse.draw2d.geometry.Rectangle; |
30 |
import org.eclipse.draw2d.text.BlockFlow; |
31 |
import org.eclipse.draw2d.text.BlockFlowLayout; |
32 |
import org.eclipse.draw2d.text.FlowPage; |
33 |
import org.eclipse.draw2d.text.PageFlowLayout; |
34 |
import org.eclipse.draw2d.text.TextFragmentBox; |
35 |
import org.eclipse.gmf.runtime.draw2d.ui.internal.mapmode.IMapModeHolder; |
36 |
import org.eclipse.gmf.runtime.draw2d.ui.internal.text.FlowUtilitiesEx; |
37 |
import org.eclipse.gmf.runtime.draw2d.ui.internal.text.ParagraphTextLayoutEx; |
38 |
import org.eclipse.gmf.runtime.draw2d.ui.internal.text.SelectableTextFlow; |
39 |
import org.eclipse.gmf.runtime.draw2d.ui.internal.text.SingleLineTextLayoutWithEllipses; |
40 |
import org.eclipse.gmf.runtime.draw2d.ui.internal.text.TextLayoutManagerWithMapMode; |
41 |
import org.eclipse.gmf.runtime.draw2d.ui.mapmode.IMapMode; |
42 |
import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeUtil; |
43 |
import org.eclipse.swt.graphics.Font; |
44 |
import org.eclipse.swt.graphics.Image; |
45 |
|
46 |
/** |
47 |
* An extended label that has the following extra features: <br> |
48 |
* 1. Allows selection, focus feedback, underlined |
49 |
* and striked-through text. |
50 |
* 2. Supports multiple icons. |
51 |
* 3. Enhanced layout functionality for placing icon(s) and text. |
52 |
* 4. Text can be word-wrapped or be truncated with ellipses. <p><br> |
53 |
* |
54 |
* |
55 |
* <b>EXPLANATION OF LAYOUTS</b><br> |
56 |
* |
57 |
* This WrapLabel contains functionality to display many icons alongside text. |
58 |
* The following will describe how the layout of these icons and text |
59 |
* are done. <p><br> |
60 |
* |
61 |
* |
62 |
* <u>Using {@link #setTextPlacement(int)}:</u><p> |
63 |
* |
64 |
* All icons that are set using {@link #setIcon(Image)} are placed horizontally |
65 |
* one after the other. The position of the text <i>relative</i> to icons |
66 |
* depends on {@link #setTextPlacement(int)}. If text placement is set to |
67 |
* {@link PositionConstants#EAST}, then the icon(s) would be placed on the left |
68 |
* of the text. Similarly, if text placement is set to |
69 |
* {@link PositionConstants#WEST}, the icon(s) will be placed on the right of the |
70 |
* text; {@link PositionConstants#NORTH} would put the icons below the text; and |
71 |
* {@link PositionConstants#SOUTH} would place the icons above the text. <p><br> |
72 |
* |
73 |
* <u>Using {@link #setTextAlignment(int)} and {@link #setIconAlignment(int)}:</u><p> |
74 |
* |
75 |
* Use {@link #setTextAlignment(int)} and {@link #setIconAlignment(int)} to |
76 |
* align the text and icons <i>relative</i> to each other for more dynamic control. |
77 |
* If the text placement is on the east or west of the icon(s) |
78 |
* (i.e. the icon(s) on the left or right of the text respectively), then only |
79 |
* {@link PositionConstants#TOP}, {@link PositionConstants#CENTER}, and |
80 |
* {@link PositionConstants#BOTTOM} can be used when calling |
81 |
* {@link #setTextAlignment(int)} and {@link #setIconAlignment(int)}. In this case, |
82 |
* setting the text alignment to {@link PositionConstants#TOP} will make sure |
83 |
* that the top of the text is aligned horizontally with the top of the icon(s) <i>if</i> |
84 |
* the height of the total size of icon(s) is greater than the height of the text. Similarly, |
85 |
* setting the text alignment to {@link PositionConstants#CENTER} will make sure |
86 |
* that the top of the text is aligned horizontally with the vertical center of the total |
87 |
* size of icon(s) <i>if</i> the height of the total size of icon(s) is greater than |
88 |
* the height of the text. Also, setting the text alignment to |
89 |
* {@link PositionConstants#BOTTOM} will make sure |
90 |
* that the bottom of the text is aligned horizontally with the bottom of the total |
91 |
* size of icon(s) <i>if</i> the height of the total size of icon(s) is greater than |
92 |
* the height of the text. <p> |
93 |
* |
94 |
* The other scenario is when the text placement is on the south or north of the icon(s) |
95 |
* (i.e. the icon(s) above or below the text respectively). If this is true, only |
96 |
* {@link PositionConstants#LEFT}, {@link PositionConstants#CENTER}, and |
97 |
* {@link PositionConstants#RIGHT} can be used when calling |
98 |
* {@link #setTextAlignment(int)} and {@link #setIconAlignment(int)}. In this case, |
99 |
* setting the text alignment to {@link PositionConstants#LEFT} will make sure |
100 |
* that the left of the text is aligned vertically with the left of the icon(s) <i>if</i> |
101 |
* the width of the total size of icon(s) is greater than the width of the text. Similarly, |
102 |
* setting the text alignment to {@link PositionConstants#CENTER} will make sure |
103 |
* that the left of the text is aligned vertically with the horizontal center of the total |
104 |
* size of icon(s) <i>if</i> the width of the total size of icon(s) is greater than |
105 |
* the width of the text. Also, setting the text alignment to |
106 |
* {@link PositionConstants#RIGHT} will make sure |
107 |
* that the right of the text is aligned vertically with the right of the total |
108 |
* size of icon(s) <i>if</i> the width of the total size of icon(s) is greater than |
109 |
* the width of the text. <p> |
110 |
* |
111 |
* {@link #setIconAlignment(int)} works identically as {@link #setTextAlignment(int)}, |
112 |
* except the roles of text and icon(s) are switched in the above descriptions. <p><br> |
113 |
* |
114 |
* |
115 |
* <u>Using {@link #setLabelAlignment(int)}:</u><p> |
116 |
* |
117 |
* The entire label, text and icons, can moved into different positions <i>vertically</i>. |
118 |
* {@link PositionConstants#TOP}, {@link PositionConstants#CENTER}, and |
119 |
* {@link PositionConstants#BOTTOM} places the text and icons (no matter how they are arranged |
120 |
* relatively to each other) on the top, center, or bottom of the bounds of |
121 |
* LabelWithTextLayout. <p><br> |
122 |
* |
123 |
* |
124 |
* <u>Using {@link #setTextHorizontalAlignment(int)}:</u><p> |
125 |
* |
126 |
* Use {@link #setTextHorizontalAlignment(int)} with {@link PositionConstants#LEFT}, |
127 |
* {@link PositionConstants#CENTER}, or {@link PositionConstants#RIGHT} to justify |
128 |
* the text accordingly. The icon(s) will move with the text, so this can be |
129 |
* considered a <i>horizontal</i> label alignment equivalent for |
130 |
* {@link #setLabelAlignment(int)}. <p><br> |
131 |
* |
132 |
* |
133 |
* WARNING: User-nested figures are not expected within this WrapLabel. <p> |
134 |
* |
135 |
* Some code taken from the original WrapLabel by melaasar |
136 |
* <p> |
137 |
* |
138 |
* @author satif <p> |
139 |
*/ |
140 |
public class LabelWithTextLayout |
141 |
extends Label |
142 |
implements PositionConstants { |
143 |
|
144 |
private static final Map mapModeConstantsMap = new WeakHashMap(); |
145 |
|
146 |
private static class MapModeConstants { |
147 |
|
148 |
private static final int MAX_IMAGE_INFO = 12; |
149 |
|
150 |
public final WeakReference mapModeRef; |
151 |
|
152 |
public final int nDPtoLP_3; |
153 |
|
154 |
public final int nDPtoLP_2; |
155 |
|
156 |
public final SingleIconInfo[] singleIconInfos = new SingleIconInfo[MAX_IMAGE_INFO]; |
157 |
|
158 |
public MapModeConstants(IMapMode mapMode) { |
159 |
this.mapModeRef = new WeakReference(mapMode); |
160 |
nDPtoLP_2 = mapMode.DPtoLP(2); |
161 |
nDPtoLP_3 = mapMode.DPtoLP(3); |
162 |
} |
163 |
|
164 |
public SingleIconInfo getSingleIconInfo(Image image) { |
165 |
if (image == null) { |
166 |
return SingleIconInfo.NULL_INFO; |
167 |
} |
168 |
SingleIconInfo info; |
169 |
for (int i = 0; i < MAX_IMAGE_INFO; ++i) { |
170 |
info = singleIconInfos[i]; |
171 |
if (info == null) { |
172 |
info = new SingleIconInfo(image); |
173 |
singleIconInfos[i] = info; |
174 |
return info; |
175 |
} |
176 |
if (info.icon == image) { |
177 |
return info; |
178 |
} |
179 |
} |
180 |
int index = SingleIconInfo.count % MAX_IMAGE_INFO; |
181 |
info = new SingleIconInfo(image); |
182 |
singleIconInfos[index] = info; |
183 |
return info; |
184 |
} |
185 |
} |
186 |
|
187 |
private static abstract class IconInfo { |
188 |
/** |
189 |
* Gets the icon at the index location. |
190 |
* |
191 |
* @param i |
192 |
* the index to retrieve the icon of |
193 |
* @return <code>Image</code> that corresponds to the given index. |
194 |
*/ |
195 |
public abstract Image getIcon(int i); |
196 |
|
197 |
/** |
198 |
* Gets the icon size of the icon at the given index. |
199 |
* |
200 |
* @param i |
201 |
* @return the <code>Dimension</code> that is the size of the icon at |
202 |
* the given index. |
203 |
*/ |
204 |
public abstract Dimension getIconSize(IMapMode mapMode, int i); |
205 |
|
206 |
/** |
207 |
* @return the number of icons |
208 |
*/ |
209 |
public abstract int getNumberofIcons(); |
210 |
|
211 |
/** |
212 |
* @return the <code>Dimension</code> that is the total size of all |
213 |
* the icons. |
214 |
*/ |
215 |
public abstract Dimension getTotalIconSize(IMapMode mapMode); |
216 |
|
217 |
public abstract void invalidate(); |
218 |
|
219 |
/** |
220 |
* Sets the icon at the index location. |
221 |
* |
222 |
* @param icon |
223 |
* @param i |
224 |
*/ |
225 |
public abstract void setIcon(Image icon, int i); |
226 |
|
227 |
/** |
228 |
* |
229 |
*/ |
230 |
public abstract int getMaxIcons(); |
231 |
|
232 |
} |
233 |
|
234 |
private static class SingleIconInfo |
235 |
extends IconInfo { |
236 |
|
237 |
static int count; |
238 |
|
239 |
public static final SingleIconInfo NULL_INFO = new SingleIconInfo(){ |
240 |
public int getNumberofIcons() { |
241 |
return 0; |
242 |
} |
243 |
}; |
244 |
|
245 |
final Image icon; |
246 |
|
247 |
/** total icon size */ |
248 |
private Dimension totalIconSize; |
249 |
|
250 |
private SingleIconInfo() { |
251 |
icon = null;//don't increment count, used only for NULL_INFO |
252 |
} |
253 |
|
254 |
public SingleIconInfo(Image icon) { |
255 |
this.icon = icon; |
256 |
++count; |
257 |
} |
258 |
|
259 |
public final int getMaxIcons() { |
260 |
return 1; |
261 |
} |
262 |
|
263 |
|
264 |
public Image getIcon(int i) { |
265 |
if (i == 0) { |
266 |
return icon; |
267 |
} else if (i > 0) { |
268 |
return null; |
269 |
} |
270 |
throw new IndexOutOfBoundsException(); |
271 |
} |
272 |
|
273 |
|
274 |
public void setIcon(Image img, int i) { |
275 |
throw new UnsupportedOperationException(); |
276 |
} |
277 |
|
278 |
|
279 |
public Dimension getIconSize(IMapMode mapMode, int i) { |
280 |
if (i == 0) { |
281 |
return getTotalIconSize(mapMode); |
282 |
} |
283 |
|
284 |
throw new IndexOutOfBoundsException(); |
285 |
} |
286 |
|
287 |
|
288 |
public int getNumberofIcons() { |
289 |
return 1; |
290 |
} |
291 |
|
292 |
|
293 |
public Dimension getTotalIconSize(IMapMode mapMode) { |
294 |
if (totalIconSize != null) |
295 |
return totalIconSize; |
296 |
|
297 |
if (icon != null && !icon.isDisposed()) { |
298 |
org.eclipse.swt.graphics.Rectangle imgBounds = icon.getBounds(); |
299 |
totalIconSize = new Dimension(mapMode.DPtoLP(imgBounds.width), |
300 |
mapMode.DPtoLP(imgBounds.height)); |
301 |
} else { |
302 |
totalIconSize = EMPTY_DIMENSION; |
303 |
} |
304 |
|
305 |
return totalIconSize; |
306 |
} |
307 |
|
308 |
|
309 |
public void invalidate() { |
310 |
totalIconSize = null; |
311 |
} |
312 |
|
313 |
} |
314 |
|
315 |
private static class MultiIconInfo |
316 |
extends IconInfo { |
317 |
|
318 |
/** the label icons */ |
319 |
private ArrayList icons = new ArrayList(2); |
320 |
|
321 |
/** total icon size */ |
322 |
private Dimension totalIconSize; |
323 |
|
324 |
public MultiIconInfo() { |
325 |
super(); |
326 |
} |
327 |
|
328 |
public int getMaxIcons() { |
329 |
return -1; |
330 |
} |
331 |
|
332 |
/** |
333 |
* Gets the icon at the index location. |
334 |
* |
335 |
* @param i |
336 |
* the index to retrieve the icon of |
337 |
* @return <code>Image</code> that corresponds to the given index. |
338 |
*/ |
339 |
public Image getIcon(int i) { |
340 |
if (i >= icons.size()) |
341 |
return null; |
342 |
|
343 |
return (Image) icons.get(i); |
344 |
} |
345 |
|
346 |
/** |
347 |
* Sets the icon at the index location. |
348 |
* |
349 |
* @param icon |
350 |
* @param i |
351 |
*/ |
352 |
public void setIcon(Image icon, int i) { |
353 |
int size = icons.size(); |
354 |
if (i >= size) { |
355 |
for (int j = size; j < i; j++) |
356 |
icons.add(null); |
357 |
icons.add(icon); |
358 |
icons.trimToSize(); |
359 |
} else |
360 |
icons.set(i, icon); |
361 |
} |
362 |
|
363 |
/** |
364 |
* Gets the icon size of the icon at the given index. |
365 |
* |
366 |
* @param i |
367 |
* @return the <code>Dimension</code> that is the size of the icon at |
368 |
* the given index. |
369 |
*/ |
370 |
public Dimension getIconSize(IMapMode mapMode, int i) { |
371 |
Image img = getIcon(i); |
372 |
if (img != null && !img.isDisposed()) { |
373 |
org.eclipse.swt.graphics.Rectangle imgBounds = img.getBounds(); |
374 |
return new Dimension(mapMode.DPtoLP(imgBounds.width), mapMode |
375 |
.DPtoLP(imgBounds.height)); |
376 |
} |
377 |
return EMPTY_DIMENSION; |
378 |
} |
379 |
|
380 |
/** |
381 |
* @return the number of icons |
382 |
*/ |
383 |
public int getNumberofIcons() { |
384 |
return icons.size(); |
385 |
} |
386 |
|
387 |
/** |
388 |
* @return the <code>Dimension</code> that is the total size of all |
389 |
* the icons. |
390 |
*/ |
391 |
public Dimension getTotalIconSize(IMapMode mapMode) { |
392 |
if (totalIconSize != null) |
393 |
return totalIconSize; |
394 |
int iconNum = getNumberofIcons(); |
395 |
if (iconNum == 0) { |
396 |
return totalIconSize = EMPTY_DIMENSION; |
397 |
} |
398 |
|
399 |
totalIconSize = new Dimension(); |
400 |
for (int i = 0; i < iconNum; i++) { |
401 |
Dimension iconSize = getIconSize(mapMode, i); |
402 |
totalIconSize.width += iconSize.width; |
403 |
if (iconSize.height > totalIconSize.height) |
404 |
totalIconSize.height = iconSize.height; |
405 |
} |
406 |
|
407 |
return totalIconSize; |
408 |
} |
409 |
|
410 |
/** |
411 |
* |
412 |
*/ |
413 |
public void invalidate() { |
414 |
totalIconSize = null; |
415 |
} |
416 |
} |
417 |
|
418 |
|
419 |
/** |
420 |
* Lays out children according to the offset bounds provided. |
421 |
* This offset bounds is added to the container figure's client |
422 |
* area and applied to all figures. This allows the positioning |
423 |
* of all child figures in a stack layout but in a specific position |
424 |
* and with a specific dimension. |
425 |
* |
426 |
*/ |
427 |
protected static class OffsetLayout |
428 |
extends StackLayout { |
429 |
|
430 |
// the offset constraint to apply to child figures. |
431 |
private Rectangle offsetConstraint = null; |
432 |
|
433 |
/* (non-Javadoc) |
434 |
* @see org.eclipse.draw2d.StackLayout#layout(org.eclipse.draw2d.IFigure) |
435 |
*/ |
436 |
public void layout(IFigure figure) { |
437 |
List children = figure.getChildren(); |
438 |
IFigure child; |
439 |
for (int i = 0; i < children.size(); i++) { |
440 |
child = (IFigure) children.get(i); |
441 |
Rectangle r = figure.getClientArea().getCopy(); |
442 |
if (offsetConstraint != null) { |
443 |
r.x += offsetConstraint.x; |
444 |
r.y += offsetConstraint.y; |
445 |
|
446 |
r.width += offsetConstraint.width; |
447 |
r.height += offsetConstraint.height; |
448 |
|
449 |
// we don't want the width and height to be |
450 |
// less than zero. |
451 |
if (r.width < 0) |
452 |
r.width = 0; |
453 |
if (r.height < 0) |
454 |
r.height = 0; |
455 |
} |
456 |
|
457 |
child.setBounds(r); |
458 |
} |
459 |
} |
460 |
|
461 |
/** |
462 |
* Set the offset constraint. <p> |
463 |
* |
464 |
* The rectangle parameter represents an offset |
465 |
* that will be added to the container figure's client area |
466 |
* and this will be applied to all child figures. |
467 |
* |
468 |
* @param offsetConstraint the offset constraint rectangle. |
469 |
*/ |
470 |
public void setOffsetConstraint(Rectangle offsetConstraint) { |
471 |
this.offsetConstraint = offsetConstraint; |
472 |
} |
473 |
} |
474 |
|
475 |
private static final Dimension EMPTY_DIMENSION = new Dimension(0, 0); |
476 |
|
477 |
/** |
478 |
* calculateNow is a flag to indicate whether the layout data should be |
479 |
* recalculated before the Label is painted. This avoids recalculation |
480 |
* of layout data upon multiple paintFigure calls when the figure has not |
481 |
* been invalidated. |
482 |
*/ |
483 |
private static int FLAG_CALCULATE_LOCATIONS = MAX_FLAG << 4; |
484 |
|
485 |
/** |
486 |
* @see #setTextWrap(boolean) |
487 |
*/ |
488 |
private static int FLAG_WRAP = MAX_FLAG << 5; |
489 |
|
490 |
/** |
491 |
* @see #setTextAlignment(int) |
492 |
*/ |
493 |
private static int FLAG_TEXT_ALIGN = MAX_FLAG << 6; |
494 |
|
495 |
/** |
496 |
* @see #setIconAlignment(int) |
497 |
*/ |
498 |
private static int FLAG_ICON_ALIGN = MAX_FLAG << 12; |
499 |
|
500 |
/** |
501 |
* @see #setLabelAlignment(int) |
502 |
*/ |
503 |
private static int FLAG_LABEL_ALIGN = MAX_FLAG << 15; |
504 |
|
505 |
/** |
506 |
* @see #setTextPlacement(int) |
507 |
*/ |
508 |
private static int FLAG_TEXT_PLACEMENT = MAX_FLAG << 18; |
509 |
|
510 |
|
511 |
// cache the map mode constants... |
512 |
private MapModeConstants mapModeConstants; |
513 |
|
514 |
private IconInfo iconInfo; |
515 |
|
516 |
private SelectableTextFlow textFlow; |
517 |
|
518 |
private BlockFlow blockFlow; |
519 |
|
520 |
private FlowPage flowPage; |
521 |
|
522 |
// cached location of the icon. |
523 |
private Point iconLocation; |
524 |
|
525 |
/** |
526 |
* textBounds is used as the offsetConstraint in OffsetLayout, |
527 |
* primarily to position flowPage correctly to align it with the |
528 |
* icon(s) |
529 |
*/ |
530 |
private Rectangle textBounds; |
531 |
|
532 |
/** |
533 |
* Cache the preferred width and height parameters. getPreferredSize can get |
534 |
* called multiple times with the same parameters, so cache these to avoid |
535 |
* redundant recalculations. |
536 |
*/ |
537 |
private int cached_PrefWidth = Integer.MIN_VALUE, |
538 |
cached_PrefHeight = Integer.MIN_VALUE; |
539 |
|
540 |
/** |
541 |
* Construct a Label with no text and no icon. |
542 |
* |
543 |
*/ |
544 |
public LabelWithTextLayout() { |
545 |
super(); |
546 |
|
547 |
this.setLayoutManager(new OffsetLayout()); |
548 |
|
549 |
setupTextFigures(false); |
550 |
|
551 |
// default flags... |
552 |
setAlignmentFlags(CENTER, FLAG_TEXT_ALIGN); |
553 |
setAlignmentFlags(CENTER, FLAG_ICON_ALIGN); |
554 |
setAlignmentFlags(CENTER, FLAG_LABEL_ALIGN); |
555 |
blockFlow.setHorizontalAligment(LEFT); |
556 |
|
557 |
setPlacementFlags(EAST, FLAG_TEXT_PLACEMENT); |
558 |
setFlag(FLAG_WRAP, false); |
559 |
} |
560 |
|
561 |
/** |
562 |
* Construct a Label with passed Image as its icon. |
563 |
* |
564 |
* @param i |
565 |
* the label image |
566 |
*/ |
567 |
public LabelWithTextLayout(Image i) { |
568 |
this(); |
569 |
iconInfo = new SingleIconInfo(i); |
570 |
} |
571 |
|
572 |
/** |
573 |
* Construct a Label with passed String as the Label's text. |
574 |
* @param s the String to set as the Label's text. |
575 |
*/ |
576 |
public LabelWithTextLayout(String s) { |
577 |
this(); |
578 |
textFlow.setText(s); |
579 |
} |
580 |
|
581 |
/** |
582 |
* Construct a Label with passed String as text and passed Image as its |
583 |
* icon. |
584 |
* |
585 |
* @param s |
586 |
* the label text |
587 |
* @param i |
588 |
* the label image |
589 |
*/ |
590 |
public LabelWithTextLayout(String s, Image i) { |
591 |
this(); |
592 |
textFlow.setText(s); |
593 |
iconInfo = new SingleIconInfo(i); |
594 |
|
595 |
} |
596 |
|
597 |
/** |
598 |
* Calculates the text alignment relative to the icon.<br/> NOTE: Should be |
599 |
* called by calculateLocations only. |
600 |
* <p> |
601 |
* |
602 |
* @param textPlacement |
603 |
* the text placement relative to the icon. |
604 |
* @param totalIconSize |
605 |
* the total size of all icons. |
606 |
* @param literalTextSize |
607 |
* the size of the text. |
608 |
* |
609 |
*/ |
610 |
private void calculateIconAlignment(int textPlacement, |
611 |
Dimension totalIconSize, Rectangle _literalTextBounds) { |
612 |
switch (textPlacement) { |
613 |
case NORTH: |
614 |
case SOUTH: |
615 |
if (totalIconSize.width < _literalTextBounds.width) { |
616 |
switch (getIconAlignment()) { |
617 |
case LEFT: |
618 |
// nothing to add |
619 |
break; |
620 |
case CENTER: |
621 |
iconLocation.x += _literalTextBounds.x + |
622 |
(_literalTextBounds.width - totalIconSize.width) / 2; |
623 |
break; |
624 |
case RIGHT: |
625 |
iconLocation.x += _literalTextBounds.x + |
626 |
(_literalTextBounds.width - totalIconSize.width); |
627 |
break; |
628 |
} |
629 |
} |
630 |
break; |
631 |
case WEST: |
632 |
case EAST: |
633 |
if (totalIconSize.height < _literalTextBounds.height) { |
634 |
switch (getIconAlignment()) { |
635 |
case TOP: |
636 |
// nothing to add |
637 |
break; |
638 |
case CENTER: |
639 |
iconLocation.y = (_literalTextBounds.height - totalIconSize.height) / 2; |
640 |
break; |
641 |
case BOTTOM: |
642 |
iconLocation.y = (_literalTextBounds.height - totalIconSize.height); |
643 |
break; |
644 |
} |
645 |
} |
646 |
break; |
647 |
} |
648 |
} |
649 |
|
650 |
/** |
651 |
* Calculates the text alignment relative to the icon.<br/> NOTE: Should be |
652 |
* called by calculateLocations only. |
653 |
* <p> |
654 |
* |
655 |
* @param textPlacement |
656 |
* the text placement relative to the icon. |
657 |
* @param totalIconSize |
658 |
* the total size of all icons. |
659 |
* @param literalTextSize |
660 |
* the size of the text. |
661 |
*/ |
662 |
private void calculateTextAlignment(int textPlacement, |
663 |
Dimension totalIconSize, Dimension literalTextSize) { |
664 |
switch (textPlacement) { |
665 |
case NORTH: |
666 |
case SOUTH: |
667 |
if (literalTextSize.width < totalIconSize.width) { |
668 |
switch (getTextAlignment()) { |
669 |
case LEFT: |
670 |
// nothing to add |
671 |
break; |
672 |
case CENTER: |
673 |
textBounds.x += (totalIconSize.width - literalTextSize.width) / 2; |
674 |
break; |
675 |
case RIGHT: |
676 |
textBounds.x += (totalIconSize.width - literalTextSize.width); |
677 |
break; |
678 |
} |
679 |
} |
680 |
break; |
681 |
case WEST: |
682 |
case EAST: |
683 |
if (literalTextSize.height < totalIconSize.height) { |
684 |
switch (getTextAlignment()) { |
685 |
case TOP: |
686 |
// nothing to add |
687 |
break; |
688 |
case CENTER: |
689 |
textBounds.y += (totalIconSize.height - literalTextSize.height) / 2; |
690 |
break; |
691 |
case BOTTOM: |
692 |
textBounds.y += (totalIconSize.height - literalTextSize.height); |
693 |
break; |
694 |
} |
695 |
} |
696 |
break; |
697 |
} |
698 |
} |
699 |
|
700 |
/** |
701 |
* Sets up the layout of text and icons. |
702 |
* |
703 |
*/ |
704 |
private void calculateLocations() { |
705 |
|
706 |
int textPlacement = getTextPlacement(); |
707 |
Dimension totalIconSize = getTotalIconSize(); |
708 |
Rectangle literalSubstringTextSize = textFlow.getLiteralSubstringTextBounds(); |
709 |
|
710 |
layoutTextAndIcons(textPlacement, totalIconSize, getPreferredSize( |
711 |
cached_PrefWidth, -1)); |
712 |
|
713 |
calculateIconAlignment(textPlacement, totalIconSize, |
714 |
literalSubstringTextSize); |
715 |
calculateTextAlignment(textPlacement, totalIconSize, |
716 |
literalSubstringTextSize.getSize()); |
717 |
|
718 |
if (getLayoutManager() instanceof OffsetLayout) { |
719 |
((OffsetLayout)getLayoutManager()).setOffsetConstraint(textBounds); |
720 |
} |
721 |
|
722 |
this.layout(); |
723 |
flowPage.getLayoutManager().layout(textFlow); |
724 |
|
725 |
finalIconAdjustments(textPlacement, literalSubstringTextSize.getSize()); |
726 |
} |
727 |
|
728 |
/** |
729 |
* Returns the bounds of the label's text. Note that the bounds are calculated using the |
730 |
* label's text AFTER it has been laid out by the TextLayoutManager. <p> |
731 |
* |
732 |
* If you want to know the size of the text without any layout style applied, |
733 |
* use {@link #getTextSize()} |
734 |
* |
735 |
* @return the bounds of this label's laid-out text |
736 |
*/ |
737 |
public Rectangle getTextBounds() { |
738 |
calculateLocations(); |
739 |
|
740 |
return calculateTextBounds(false); |
741 |
} |
742 |
|
743 |
/* (non-Javadoc) |
744 |
* @see org.eclipse.draw2d.Label#getIconBounds() |
745 |
*/ |
746 |
public Rectangle getIconBounds() { |
747 |
if (iconLocation == null) |
748 |
calculateLocations(); |
749 |
|
750 |
Point icon_Location = this.iconLocation.getCopy(); |
751 |
translateToParent(icon_Location); |
752 |
Rectangle iconBounds = new Rectangle(icon_Location, getTotalIconSize()); |
753 |
return iconBounds; |
754 |
} |
755 |
|
756 |
/** |
757 |
* Returns the gap between the text and the icon(s). |
758 |
* |
759 |
* @return the gap, or 0 if there is no icon or text. |
760 |
*/ |
761 |
public int getIconTextGap() { |
762 |
if (iconInfo == null || getText().equals("") || getIcon() == null) //$NON-NLS-1$ |
763 |
return 0; |
764 |
return getMapModeConstants().nDPtoLP_3; |
765 |
} |
766 |
|
767 |
/** |
768 |
* Get the text of only the visible area. |
769 |
*/ |
770 |
protected Dimension getSubStringTextSize() { |
771 |
return textFlow.getLiteralSubstringTextBounds().getSize(); |
772 |
} |
773 |
|
774 |
/* |
775 |
* (non-Javadoc) |
776 |
* |
777 |
* @see org.eclipse.draw2d.Label#getTextLocation() |
778 |
*/ |
779 |
protected Point getTextLocation() { |
780 |
return getTextBounds().getLocation(); |
781 |
} |
782 |
|
783 |
/** |
784 |
* not yet supported. Default is to return the entire text. |
785 |
* |
786 |
* @see WrapLabel#getText() |
787 |
*/ |
788 |
public String getSubStringText() { |
789 |
return getText(); |
790 |
} |
791 |
|
792 |
/** |
793 |
* Returns the visible-only or total text size from whatever |
794 |
* the current state of the fragments in textFlow are. <p> |
795 |
* |
796 |
* These bounds represents the bounds of the text and text |
797 |
* only. However, note that since flowPage can be translated by |
798 |
* the OffsetLayout, these will not be the same as the one given |
799 |
* by {@link SelectableTextFlow#getLiteralSubstringTextBounds()}. <p> |
800 |
* |
801 |
* These bounds exclude any area which the text does not occupy. |
802 |
* |
803 |
* @param subStringText |
804 |
* true to stop calculating at non-visible text area. |
805 |
*/ |
806 |
private Rectangle calculateTextBounds(boolean subStringText) { |
807 |
|
808 |
Rectangle refBounds = getBounds(), calRect = new Rectangle( |
809 |
Integer.MAX_VALUE, Integer.MAX_VALUE, 0, 0); |
810 |
|
811 |
if (textFlow == null || blockFlow == null || flowPage == null) |
812 |
return calRect; |
813 |
|
814 |
List fragments = textFlow.getFragments(); |
815 |
|
816 |
int locY = 0; |
817 |
|
818 |
if (textBounds != null) |
819 |
locY = textBounds.y; |
820 |
|
821 |
for (int i = 0; i < fragments.size(); i++) { |
822 |
TextFragmentBox fragment = (TextFragmentBox) fragments.get(i); |
823 |
|
824 |
if (fragment.getLineRoot() == null) |
825 |
continue; |
826 |
|
827 |
int y = fragment.getLineRoot().getVisibleTop(); |
828 |
|
829 |
if (fragment.getX() < calRect.x) |
830 |
calRect.x = fragment.getX(); |
831 |
if (y < calRect.y) |
832 |
calRect.y = y; |
833 |
|
834 |
if (calRect.width < fragment.getWidth()) |
835 |
calRect.width = fragment.getWidth(); |
836 |
|
837 |
y = fragment.getAscent() + fragment.getDescent(); |
838 |
calRect.height += y; |
839 |
|
840 |
// we don't want to continue to non-visible fragments, |
841 |
// resulting in performance improvement |
842 |
if (subStringText && calRect.height + locY > refBounds.height) { |
843 |
if (subStringText) // calculate only substring text. |
844 |
break; |
845 |
} |
846 |
} |
847 |
|
848 |
if (!subStringText) { |
849 |
calRect.resize(getMapModeConstants().nDPtoLP_2, |
850 |
getMapModeConstants().nDPtoLP_2); |
851 |
|
852 |
blockFlow.translateToParent(calRect); |
853 |
flowPage.translateToParent(calRect); |
854 |
translateToParent(calRect); |
855 |
} |
856 |
|
857 |
return calRect; |
858 |
} |
859 |
|
860 |
/** |
861 |
* Calculates the placement of the text relative to the icon. <br> |
862 |
* NOTE: to be used by calculateLocations only.<br> |
863 |
* @see #getTextPlacement() <br> |
864 |
* |
865 |
* <p> |
866 |
* |
867 |
* @param insertionPoint |
868 |
* the <code>Point</code> where the text and icon have to be |
869 |
* inserted. |
870 |
* @param textPlacement |
871 |
* the placement of text relative to the icon. |
872 |
* @param totalIconSize |
873 |
* the total size of all icons. |
874 |
*/ |
875 |
private void calculateTextPlacement(Point insertionPoint, |
876 |
int textPlacement, Dimension totalIconSize) { |
877 |
switch (textPlacement) { |
878 |
case NORTH: |
879 |
textBounds = new Rectangle(new Point(insertionPoint.x, |
880 |
insertionPoint.y), new Dimension(-insertionPoint.x, |
881 |
-insertionPoint.y)); |
882 |
iconLocation = new Point(insertionPoint.x, |
883 |
textFlow.getSize().height + getIconTextGap() |
884 |
+ textFlow.getDescent()); |
885 |
|
886 |
if (textBounds.x < 0) |
887 |
textBounds.x = 0; |
888 |
if (textBounds.y < 0) |
889 |
textBounds.y = 0; |
890 |
|
891 |
break; |
892 |
case SOUTH: |
893 |
textBounds = new Rectangle(new Point(insertionPoint.x, |
894 |
totalIconSize.height + getIconTextGap()), new Dimension( |
895 |
-insertionPoint.x, |
896 |
-(totalIconSize.height + getIconTextGap()))); |
897 |
iconLocation = new Point(insertionPoint.x, insertionPoint.y); |
898 |
|
899 |
if (textBounds.x < 0) |
900 |
textBounds.x = 0; |
901 |
|
902 |
break; |
903 |
case WEST: |
904 |
textBounds = new Rectangle(new Point(insertionPoint.x, |
905 |
insertionPoint.y), new Dimension( |
906 |
-(totalIconSize.width + getIconTextGap() + insertionPoint.x), |
907 |
-insertionPoint.y)); |
908 |
iconLocation = new Point(getSize().width - totalIconSize.width, |
909 |
insertionPoint.y); |
910 |
|
911 |
if (textBounds.x < 0) |
912 |
textBounds.x = 0; |
913 |
if (textBounds.y < 0) |
914 |
textBounds.y = 0; |
915 |
|
916 |
break; |
917 |
case EAST: |
918 |
iconLocation = new Point(insertionPoint.x, insertionPoint.y); |
919 |
textBounds = new Rectangle( |
920 |
new Point(insertionPoint.x + totalIconSize.width |
921 |
+ getIconTextGap(), insertionPoint.y), |
922 |
new Dimension( |
923 |
-(totalIconSize.width + getIconTextGap() + insertionPoint.x), |
924 |
-insertionPoint.y)); |
925 |
|
926 |
if ((textBounds.y < 0) || (textBounds.y > getBounds().height)) |
927 |
textBounds.y = 0; |
928 |
|
929 |
break; |
930 |
} |
931 |
} |
932 |
|
933 |
/** |
934 |
* Clears all cached layout data. Will enable layout recalculation next time |
935 |
* anything is validated or when paintFigure is called. |
936 |
* |
937 |
*/ |
938 |
private void clearLocations() { |
939 |
prefSize = null; |
940 |
minSize = null; |
941 |
iconLocation = null; |
942 |
textBounds = null; |
943 |
setFlag(FLAG_CALCULATE_LOCATIONS, true); |
944 |
} |
945 |
|
946 |
/** |
947 |
* Executes the case exceptions/constraints for icon alignment.<br> |
948 |
* NOTE: to be used by calculateLocations only. |
949 |
* <p> |
950 |
* |
951 |
* @param textPlacement |
952 |
* the text placement (N/S/E/W) |
953 |
* @param literalTextSize |
954 |
* the substring text size. |
955 |
*/ |
956 |
private void finalIconAdjustments(int textPlacement, Dimension literalTextSize) { |
957 |
// the range checks below are to make sure we haven't calculated |
958 |
// anything that can't be displayed... |
959 |
int textHorizontalAlignment = getTextHorizontalAlignment(); |
960 |
|
961 |
switch (textPlacement) { |
962 |
case EAST: |
963 |
// we want the icon to be right next to the text all the time... |
964 |
if (textHorizontalAlignment == CENTER) { |
965 |
iconLocation.x = (blockFlow.getBounds().width / 2) |
966 |
- (literalTextSize.width / 2) - getIconTextGap(); |
967 |
} else if (textHorizontalAlignment == RIGHT) { |
968 |
iconLocation.x = blockFlow.getBounds().width |
969 |
- literalTextSize.width - getIconTextGap(); |
970 |
} |
971 |
|
972 |
if (iconLocation.x < 0) |
973 |
iconLocation.x = 0; |
974 |
if (iconLocation.y < 0) |
975 |
iconLocation.y = 0; |
976 |
break; |
977 |
case WEST: |
978 |
// we want the icon to be right next to the text all the time... |
979 |
if (textHorizontalAlignment == LEFT) { |
980 |
iconLocation.x = literalTextSize.width + getIconTextGap(); |
981 |
} else if (textHorizontalAlignment == CENTER) { |
982 |
iconLocation.x = (flowPage.getBounds().width / 2) |
983 |
+ (literalTextSize.width / 2) + getIconTextGap(); |
984 |
} |
985 |
|
986 |
if (iconLocation.y < 0) |
987 |
iconLocation.y = 0; |
988 |
break; |
989 |
case NORTH: |
990 |
if (iconLocation.x < 0) |
991 |
iconLocation.x = 0; |
992 |
break; |
993 |
case SOUTH: |
994 |
if (iconLocation.x < 0) |
995 |
iconLocation.x = 0; |
996 |
if (iconLocation.y < 0) |
997 |
iconLocation.y = 0; |
998 |
break; |
999 |
} |
1000 |
} |
1001 |
|
1002 |
/** |
1003 |
* Retrieves the alignment value from the flags member. |
1004 |
* |
1005 |
* @param flagOffset |
1006 |
* that is the bitwise value representing the offset. |
1007 |
* @return PositionConstant representing the alignment |
1008 |
*/ |
1009 |
private int getAlignment(int flagOffset) { |
1010 |
int wrapValue = flags & (0x7 * flagOffset); |
1011 |
if (wrapValue == 0x1 * flagOffset) |
1012 |
return CENTER; |
1013 |
else if (wrapValue == 0x2 * flagOffset) |
1014 |
return TOP; |
1015 |
else if (wrapValue == 0x3 * flagOffset) |
1016 |
return LEFT; |
1017 |
else if (wrapValue == 0x4 * flagOffset) |
1018 |
return RIGHT; |
1019 |
else if (wrapValue == 0x5 * flagOffset) |
1020 |
return BOTTOM; |
1021 |
|
1022 |
return CENTER; |
1023 |
} |
1024 |
|
1025 |
/** |
1026 |
* Return the ellipse string. |
1027 |
* |
1028 |
* @return the <code>String</code> that represents the fact that the text |
1029 |
* has been truncated and that more text is available but hidden. |
1030 |
* Usually this is represented by "...". |
1031 |
*/ |
1032 |
protected String getEllipse() { |
1033 |
return FlowUtilitiesEx.ELLIPSIS; |
1034 |
} |
1035 |
|
1036 |
/** |
1037 |
* Returns the Label's icon. |
1038 |
* |
1039 |
* @return the label icon |
1040 |
*/ |
1041 |
public Image getIcon() { |
1042 |
return getIcon(0); |
1043 |
} |
1044 |
|
1045 |
/** |
1046 |
* Returns the label's icon at the given index (provided an icon exists at |
1047 |
* this index). |
1048 |
* <p> |
1049 |
* |
1050 |
* @param index |
1051 |
* @return the icon at the given index. |
1052 |
*/ |
1053 |
public Image getIcon(int index) { |
1054 |
if (iconInfo == null) |
1055 |
return null; |
1056 |
return iconInfo.getIcon(index); |
1057 |
} |
1058 |
|
1059 |
/** |
1060 |
* Returns the current alignment of the Label's icon. The default is |
1061 |
* {@link PositionConstants#CENTER}. |
1062 |
* <p> |
1063 |
* |
1064 |
* @return the icon alignment |
1065 |
*/ |
1066 |
public int getIconAlignment() { |
1067 |
return getAlignment(FLAG_ICON_ALIGN); |
1068 |
} |
1069 |
|
1070 |
/* |
1071 |
* (non-Javadoc) |
1072 |
* |
1073 |
* @see org.eclipse.draw2d.Label#getIconLocation() |
1074 |
*/ |
1075 |
protected Point getIconLocation() { |
1076 |
if (iconLocation == null) |
1077 |
calculateLocations(); |
1078 |
else |
1079 |
finalIconAdjustments(getTextPlacement(), |
1080 |
textFlow.getLiteralSubstringTextBounds().getSize()); |
1081 |
return iconLocation; |
1082 |
} |
1083 |
|
1084 |
/** |
1085 |
* Returns the size of the icon at a given index. |
1086 |
* |
1087 |
* @param index |
1088 |
* of icon to retrieve size of. |
1089 |
* @return Dimension representing the icon size. |
1090 |
*/ |
1091 |
protected Dimension getIconSize(int index) { |
1092 |
if (iconInfo == null) |
1093 |
return EMPTY_DIMENSION; |
1094 |
return iconInfo.getIconSize(getFigureMapMode(), index); |
1095 |
} |
1096 |
|
1097 |
/** |
1098 |
* Returns the current alignment of the entire Label. The default label |
1099 |
* alignment is {@link PositionConstants#LEFT}. |
1100 |
* |
1101 |
* @return the label alignment |
1102 |
*/ |
1103 |
public int getLabelAlignment() { |
1104 |
return getAlignment(FLAG_LABEL_ALIGN); |
1105 |
} |
1106 |
|
1107 |
/** |
1108 |
* @return <code>IMapMode</code> used by this figure. |
1109 |
* <code>IMapMode</code> that allows for the coordinate mapping |
1110 |
* from device to logical units. |
1111 |
*/ |
1112 |
private IMapMode getFigureMapMode() { |
1113 |
return (IMapMode) getMapModeConstants().mapModeRef.get(); |
1114 |
} |
1115 |
|
1116 |
/** |
1117 |
* Returns the stored map mode constants. |
1118 |
* @return MapModeConstants that are cached. |
1119 |
*/ |
1120 |
private MapModeConstants getMapModeConstants() { |
1121 |
if (mapModeConstants == null) { |
1122 |
IMapMode mapMode = MapModeUtil.getMapMode(this); |
1123 |
while (mapMode instanceof IMapModeHolder) { |
1124 |
mapMode = ((IMapModeHolder) mapMode).getMapMode(); |
1125 |
} |
1126 |
mapModeConstants = (MapModeConstants) mapModeConstantsMap |
1127 |
.get(mapMode); |
1128 |
if (mapModeConstants == null) { |
1129 |
mapModeConstants = new MapModeConstants(mapMode); |
1130 |
mapModeConstantsMap.put(mapMode, mapModeConstants); |
1131 |
} |
1132 |
if (textFlow != null) { |
1133 |
((TextLayoutManagerWithMapMode) |
1134 |
textFlow.getLayoutManager()).setMapMode(mapMode); |
1135 |
textFlow.setMapMode(mapMode); |
1136 |
} |
1137 |
} |
1138 |
return mapModeConstants; |
1139 |
} |
1140 |
|
1141 |
/* |
1142 |
* (non-Javadoc) |
1143 |
* |
1144 |
* @see org.eclipse.draw2d.Label#calculateLabelSize(org.eclipse.draw2d.geometry.Dimension) |
1145 |
*/ |
1146 |
protected Dimension calculateLabelSize(Dimension txtSize) { |
1147 |
if (txtSize.equals(EMPTY_DIMENSION)) |
1148 |
return txtSize; // return 0,0 dimension. |
1149 |
|
1150 |
int gap = getIconTextGap(); |
1151 |
Dimension d = new Dimension(0, 0); |
1152 |
switch (getTextPlacement()) { |
1153 |
case WEST: |
1154 |
case EAST: |
1155 |
d.width = getTotalIconSize().width + gap + txtSize.width; |
1156 |
d.height = Math.max(getTotalIconSize().height, txtSize.height); |
1157 |
break; |
1158 |
default: // NORTH or SOUTH |
1159 |
d.width = Math.max(getTotalIconSize().width, txtSize.width); |
1160 |
d.height = getTotalIconSize().height + gap + txtSize.height; |
1161 |
break; |
1162 |
} |
1163 |
|
1164 |
return d; |
1165 |
} |
1166 |
|
1167 |
/* |
1168 |
* (non-Javadoc) |
1169 |
* |
1170 |
* @see org.eclipse.draw2d.Label#calculateTextSize() |
1171 |
*/ |
1172 |
protected Dimension calculateTextSize() { |
1173 |
/* getTextExtent calls GC#stringExtent and this adds |
1174 |
* a blank character before calculating the text size |
1175 |
* if the text's length is zero. However, we do want an |
1176 |
* empty dimension if there is not text. |
1177 |
*/ |
1178 |
|
1179 |
if (getText().length() == 0) { |
1180 |
return EMPTY_DIMENSION.getCopy(); |
1181 |
} |
1182 |
else { |
1183 |
Dimension textExtent = (Dimension) getFigureMapMode().DPtoLP( |
1184 |
FigureUtilities.getTextExtents(getText(), getFont())); |
1185 |
textExtent.height += getMapModeConstants().nDPtoLP_2 / 2; |
1186 |
return textExtent; |
1187 |
} |
1188 |
} |
1189 |
|
1190 |
/* |
1191 |
* (non-Javadoc) |
1192 |
* |
1193 |
* @see org.eclipse.draw2d.IFigure#getPreferredSize(int, int) |
1194 |
*/ |
1195 |
public Dimension getPreferredSize(int wHint, int hHint) { |
1196 |
if (prefSize == null || wHint != cached_PrefWidth |
1197 |
|| hHint != cached_PrefHeight) { |
1198 |
|
1199 |
if (getText().length() == 0) |
1200 |
return prefSize = EMPTY_DIMENSION.getCopy(); |
1201 |
|
1202 |
if (wHint < 0) { |
1203 |
prefSize = calculateLabelSize(getTextSize()); |
1204 |
|
1205 |
Insets insets = getInsets(); |
1206 |
prefSize.expand(insets.getWidth(), insets.getHeight()); |
1207 |
|
1208 |
} else { |
1209 |
int _wHint = wHint; |
1210 |
switch (getTextPlacement()) { |
1211 |
case EAST: |
1212 |
case WEST: |
1213 |
_wHint -= (getTotalIconSize().width + getIconTextGap()); |
1214 |
break; |
1215 |
} |
1216 |
|
1217 |
prefSize = calculateLabelSize(getLayoutManager().getPreferredSize(this, |
1218 |
_wHint, hHint)); |
1219 |
|
1220 |
minSize = null; |
1221 |
prefSize.union(getMinimumSize(wHint, hHint)); |
1222 |
cached_PrefWidth = wHint; |
1223 |
cached_PrefHeight = hHint; |
1224 |
} |
1225 |
|
1226 |
|
1227 |
} |
1228 |
|
1229 |
return prefSize; |
1230 |
} |
1231 |
|
1232 |
/** |
1233 |
* @see IFigure#getMinimumSize(int, int) |
1234 |
*/ |
1235 |
public Dimension getMinimumSize(int w, int h) { |
1236 |
if (minSize != null) |
1237 |
return minSize; |
1238 |
|
1239 |
if (getText().length() == 0) |
1240 |
return minSize = EMPTY_DIMENSION.getCopy(); |
1241 |
|
1242 |
if (w < 0) { |
1243 |
minSize = calculateLabelSize(getTextSize()); |
1244 |
|
1245 |
Insets insets = getInsets(); |
1246 |
minSize.expand(insets.getWidth(), insets.getHeight()); |
1247 |
} else { |
1248 |
minSize = new Dimension(); |
1249 |
|
1250 |
int _wHint = w; |
1251 |
switch (getTextPlacement()) { |
1252 |
case EAST: |
1253 |
case WEST: |
1254 |
_wHint -= (getTotalIconSize().width + getIconTextGap()); |
1255 |
break; |
1256 |
} |
1257 |
|
1258 |
if (getLayoutManager() != null) |
1259 |
minSize.setSize(getLayoutManager().getMinimumSize(this, _wHint, h)); |
1260 |
|
1261 |
Dimension d = FlowUtilitiesEx.getEllipsisSize(textFlow.getFont(), getFigureMapMode()). |
1262 |
getIntersected(getTextSize()); |
1263 |
|
1264 |
Dimension labelSize = calculateLabelSize(d); |
1265 |
|
1266 |
minSize.width = labelSize.width; |
1267 |
|
1268 |
Insets insets = getInsets(); |
1269 |
minSize.expand(insets.getWidth(), insets.getHeight()); |
1270 |
} |
1271 |
|
1272 |
return minSize; |
1273 |
} |
1274 |
|
1275 |
/* |
1276 |
* (non-Javadoc) |
1277 |
* |
1278 |
* @see org.eclipse.draw2d.Figure#getMaximumSize() |
1279 |
*/ |
1280 |
public Dimension getMaximumSize() { |
1281 |
return prefSize; |
1282 |
} |
1283 |
|
1284 |
/** |
1285 |
* Get the maximum size, given width and height hints.<br> |
1286 |
* (Note: defaults to getMaximumSize()) |
1287 |
* <p> |
1288 |
* |
1289 |
* @param w |
1290 |
* the width hint |
1291 |
* @param h |
1292 |
* the height hint |
1293 |
* @return the maximum size. |
1294 |
*/ |
1295 |
public Dimension getMaximumSize(int w, int h) { |
1296 |
return getMaximumSize(); |
1297 |
} |
1298 |
|
1299 |
/* |
1300 |
* (non-Javadoc) |
1301 |
* |
1302 |
* @see org.eclipse.draw2d.Label#calculateSubStringTextSize() |
1303 |
*/ |
1304 |
protected Dimension calculateSubStringTextSize() { |
1305 |
return getSubStringTextSize(); |
1306 |
} |
1307 |
|
1308 |
/** |
1309 |
* Returns the total number of icons being displayed. |
1310 |
* |
1311 |
* @return int number of icons in the wrap label |
1312 |
*/ |
1313 |
protected int getNumberofIcons() { |
1314 |
if (iconInfo == null) |
1315 |
return 0; |
1316 |
return iconInfo.getNumberofIcons(); |
1317 |
} |
1318 |
|
1319 |
/** |
1320 |
* getPlacement |
1321 |
* |
1322 |
* @param flagOffset |
1323 |
* @return PositionConstant representing the placement |
1324 |
*/ |
1325 |
private int getPlacement(int flagOffset) { |
1326 |
int wrapValue = flags & (0x7 * flagOffset); |
1327 |
if (wrapValue == 0x1 * flagOffset) |
1328 |
return EAST; |
1329 |
else if (wrapValue == 0x2 * flagOffset) |
1330 |
return WEST; |
1331 |
else if (wrapValue == 0x3 * flagOffset) |
1332 |
return NORTH; |
1333 |
else if (wrapValue == 0x4 * flagOffset) |
1334 |
return SOUTH; |
1335 |
|
1336 |
return EAST; |
1337 |
} |
1338 |
|
1339 |
/* (non-Javadoc) |
1340 |
* @see org.eclipse.draw2d.Label#getText() |
1341 |
*/ |
1342 |
public String getText() { |
1343 |
return textFlow.getText(); |
1344 |
} |
1345 |
|
1346 |
/** |
1347 |
* Returns the current alignment of the Label's text. The default text |
1348 |
* alignment is {@link PositionConstants#CENTER}. |
1349 |
* |
1350 |
* @return the text alignment |
1351 |
*/ |
1352 |
public int getTextAlignment() { |
1353 |
return getAlignment(FLAG_TEXT_ALIGN); |
1354 |
} |
1355 |
|
1356 |
/** |
1357 |
* Returns the current placement of the label's text relative to its icon. |
1358 |
* The default text placement is {@link PositionConstants#EAST}. |
1359 |
* |
1360 |
* @return the text placement |
1361 |
*/ |
1362 |
public int getTextPlacement() { |
1363 |
return getPlacement(FLAG_TEXT_PLACEMENT); |
1364 |
} |
1365 |
|
1366 |
/** |
1367 |
* Gets the horizontal alignment of the text (Left, Center or Right |
1368 |
* justified). |
1369 |
* <p> |
1370 |
* Default is {@link PositionConstants#CENTER}. Can be either |
1371 |
* {@link PositionConstants#CENTER}, {@link PositionConstants#LEFT}, or |
1372 |
* {@link PositionConstants#RIGHT}. |
1373 |
* |
1374 |
* @return the horizontal alignment. |
1375 |
*/ |
1376 |
public int getTextHorizontalAlignment() { |
1377 |
return blockFlow.getHorizontalAligment(); |
1378 |
} |
1379 |
|
1380 |
/** |
1381 |
* getTotalIconSize Calculates the total union of icon sizes |
1382 |
* |
1383 |
* @return Dimension that is the union of icon sizes |
1384 |
*/ |
1385 |
protected Dimension getTotalIconSize() { |
1386 |
if (iconInfo == null) |
1387 |
return EMPTY_DIMENSION; |
1388 |
return iconInfo.getTotalIconSize(getFigureMapMode()); |
1389 |
} |
1390 |
|
1391 |
/** |
1392 |
* Returns true if the WrapLabel has focus, false otherwise. |
1393 |
* |
1394 |
* @return the focus state of this label |
1395 |
*/ |
1396 |
public boolean hasFocus() { |
1397 |
return textFlow.hasFocus(); |
1398 |
} |
1399 |
|
1400 |
/** |
1401 |
* Returns true if the WrapLabel has icons, false otherwise. |
1402 |
* |
1403 |
* @return |
1404 |
*/ |
1405 |
protected boolean hasIcons() { |
1406 |
return (getNumberofIcons() > 0); |
1407 |
} |
1408 |
|
1409 |
/* |
1410 |
* (non-Javadoc) |
1411 |
* |
1412 |
* @see org.eclipse.draw2d.Label#invalidate() |
1413 |
*/ |
1414 |
public void invalidate() { |
1415 |
clearLocations(); |
1416 |
if (iconInfo != null) |
1417 |
iconInfo.invalidate(); |
1418 |
super.invalidate(); |
1419 |
} |
1420 |
|
1421 |
public void validate() { |
1422 |
super.validate(); |
1423 |
// calculateLocations(); |
1424 |
} |
1425 |
|
1426 |
/** |
1427 |
* @return the selection state of this label |
1428 |
*/ |
1429 |
public boolean isSelected() { |
1430 |
return textFlow.isSelected(); |
1431 |
} |
1432 |
|
1433 |
/** |
1434 |
* @return whether the label text is striked-through |
1435 |
*/ |
1436 |
public boolean isTextStrikedThrough() { |
1437 |
return textFlow.isTextStrikeThrough(); |
1438 |
} |
1439 |
|
1440 |
/** |
1441 |
* Returns <code>true</code> if the label's text is currently truncated, |
1442 |
* <code>false</code> otherwise. |
1443 |
* |
1444 |
* @return <code>true</code> if the label's text is truncated |
1445 |
*/ |
1446 |
public boolean isTextTruncated() { |
1447 |
return (getBounds().width < textFlow.getBounds().width) |
1448 |
|| (getBounds().height < textFlow.getBounds().height); |
1449 |
} |
1450 |
|
1451 |
/** |
1452 |
* @return whether the label text is underlined |
1453 |
*/ |
1454 |
public boolean isTextUnderlined() { |
1455 |
return textFlow.isTextUnderlined(); |
1456 |
} |
1457 |
|
1458 |
/** |
1459 |
* @return wether the label text wrap is on |
1460 |
*/ |
1461 |
public boolean isTextWrapped() { |
1462 |
return (flags & FLAG_WRAP) != 0; |
1463 |
} |
1464 |
|
1465 |
/** |
1466 |
* Determines the insertion points based on the Label Alignment.<br> |
1467 |
* Note: should be called by calculateLocations only. |
1468 |
* <p> |
1469 |
* |
1470 |
* @param textPlacement |
1471 |
* the placement of the text relative to the icon. |
1472 |
* @param totalIconSize |
1473 |
* the total size of all icons. |
1474 |
* @param totalPossibleSize |
1475 |
* the total possible size of icon(s) and text. |
1476 |
*/ |
1477 |
private void layoutTextAndIcons(int textPlacement, Dimension totalIconSize, |
1478 |
Dimension totalPossibleSize) { |
1479 |
switch (getLabelAlignment()) { |
1480 |
case TOP: |
1481 |
calculateTextPlacement(new Point(0, 0), textPlacement, |
1482 |
totalIconSize); |
1483 |
break; |
1484 |
case BOTTOM: |
1485 |
calculateTextPlacement(new Point(0, getBounds().height |
1486 |
- totalPossibleSize.height), textPlacement, totalIconSize); |
1487 |
break; |
1488 |
case CENTER: // RIGHT and LEFT not supported. |
1489 |
case RIGHT: |
1490 |
case LEFT: |
1491 |
calculateTextPlacement(new Point(0, |
1492 |
(getBounds().height - totalPossibleSize.height) / 2), |
1493 |
textPlacement, totalIconSize); |
1494 |
break; |
1495 |
|
1496 |
/* the following commented lines of code obtain original functionality |
1497 |
* of label alignment but the code is buggy. To use, remove CENTER and RIGHT |
1498 |
* cases above and uncomment the lines below. |
1499 |
*/ |
1500 |
// case RIGHT: |
1501 |
// calculateTextBounds(false); |
1502 |
// if (literalTextBounds == null || literalTextBounds.width == 0) { |
1503 |
// calculateTextPlacement(new Point( |
1504 |
// getBounds().width - totalPossibleSize.width, |
1505 |
// (getBounds().height - totalPossibleSize.height) / 2), |
1506 |
// textPlacement, totalIconSize); |
1507 |
// } else { |
1508 |
// Dimension _totalLabelSize = calculateLabelSize(literalTextBounds |
1509 |
// .getSize()); |
1510 |
// calculateTextPlacement(new Point( |
1511 |
// (getBounds().width - _totalLabelSize.width), |
1512 |
// (getBounds().height - _totalLabelSize.height) / 2), |
1513 |
// textPlacement, totalIconSize); |
1514 |
// } |
1515 |
// break; |
1516 |
// default: // CENTER |
1517 |
// calculateTextBounds(false); |
1518 |
// if (literalTextBounds == null || literalTextBounds.width == 0) { |
1519 |
// calculateTextPlacement(new Point( |
1520 |
// (getBounds().width - totalPossibleSize.width) / 2, |
1521 |
// (getBounds().height - totalPossibleSize.height) / 2), |
1522 |
// textPlacement, totalIconSize); |
1523 |
// } else { |
1524 |
// Dimension _totalLabelSize = calculateLabelSize(literalTextBounds |
1525 |
// .getSize()); |
1526 |
// calculateTextPlacement(new Point( |
1527 |
// (getBounds().width - _totalLabelSize.width) / 2, |
1528 |
// (getBounds().height - _totalLabelSize.height) / 2), |
1529 |
// textPlacement, totalIconSize); |
1530 |
// } |
1531 |
} |
1532 |
} |
1533 |
|
1534 |
/** |
1535 |
* @see Figure#paintFigure(Graphics) |
1536 |
*/ |
1537 |
protected void paintFigure(Graphics graphics) { |
1538 |
if (isOpaque()) |
1539 |
super.paintFigure(graphics); |
1540 |
|
1541 |
if ((flags & FLAG_CALCULATE_LOCATIONS) != 0) { |
1542 |
calculateLocations(); |
1543 |
setFlag(FLAG_CALCULATE_LOCATIONS, false); |
1544 |
} |
1545 |
|
1546 |
if (hasIcons()) |
1547 |
paintIcons(graphics); |
1548 |
} |
1549 |
|
1550 |
/** |
1551 |
* Paints the icon(s) |
1552 |
* |
1553 |
* @param graphics |
1554 |
* The graphics context |
1555 |
*/ |
1556 |
private void paintIcons(Graphics graphics) { |
1557 |
Rectangle figBounds = getBounds(); |
1558 |
graphics.translate(figBounds.x, figBounds.y); |
1559 |
|
1560 |
Point p = Point.SINGLETON; |
1561 |
p.setLocation(getIconLocation()); |
1562 |
|
1563 |
int num = getNumberofIcons(); |
1564 |
for (int i = 0; i < num; i++) { |
1565 |
Image tempIcon = getIcon(i); |
1566 |
if (tempIcon != null) { |
1567 |
graphics.drawImage(tempIcon, p); |
1568 |
p.x += getIconSize(i).width; |
1569 |
} |
1570 |
} |
1571 |
|
1572 |
graphics.translate(-figBounds.x, -figBounds.y); |
1573 |
} |
1574 |
|
1575 |
/** |
1576 |
* setAlignmentFlags |
1577 |
* |
1578 |
* @param align |
1579 |
* @param flagOffset |
1580 |
*/ |
1581 |
private void setAlignmentFlags(int align, int flagOffset) { |
1582 |
flags &= ~(0x7 * flagOffset); |
1583 |
switch (align) { |
1584 |
case CENTER: |
1585 |
flags |= 0x1 * flagOffset; |
1586 |
break; |
1587 |
case TOP: |
1588 |
flags |= 0x2 * flagOffset; |
1589 |
break; |
1590 |
case LEFT: |
1591 |
flags |= 0x3 * flagOffset; |
1592 |
break; |
1593 |
case RIGHT: |
1594 |
flags |= 0x4 * flagOffset; |
1595 |
break; |
1596 |
case BOTTOM: |
1597 |
flags |= 0x5 * flagOffset; |
1598 |
break; |
1599 |
} |
1600 |
} |
1601 |
|
1602 |
/** |
1603 |
* Sets the focus state of this label |
1604 |
* |
1605 |
* @param b |
1606 |
* true will cause a focus rectangle to be drawn around the text |
1607 |
* of the Label |
1608 |
*/ |
1609 |
public void setFocus(boolean b) { |
1610 |
textFlow.setFocus(b); |
1611 |
} |
1612 |
|
1613 |
/* |
1614 |
* (non-Javadoc) |
1615 |
* |
1616 |
* @see org.eclipse.draw2d.Figure#setFont(org.eclipse.swt.graphics.Font) |
1617 |
*/ |
1618 |
public void setFont(Font f) { |
1619 |
super.setFont(f); |
1620 |
|
1621 |
/* |
1622 |
* Simply calling revalidate |
1623 |
* may not make textFlow an invalid figure and revalidate it. |
1624 |
* Therefore, when font is changed (e.g. size change, bold, italic), |
1625 |
* the layout manager for textFlow may not get invoked. |
1626 |
*/ |
1627 |
textFlow.revalidate(); |
1628 |
} |
1629 |
|
1630 |
/** |
1631 |
* Sets the label's icon to the passed image. |
1632 |
* |
1633 |
* @param image |
1634 |
* the new label image |
1635 |
*/ |
1636 |
public void setIcon(Image image) { |
1637 |
setIcon(image, 0); |
1638 |
} |
1639 |
|
1640 |
/** |
1641 |
* Sets the label's icon at given index |
1642 |
* |
1643 |
* @param image The icon image or null to remove the icon |
1644 |
* @param index The icon index |
1645 |
*/ |
1646 |
public void setIcon(Image image, int index) { |
1647 |
if (iconInfo == null) { |
1648 |
if (index == 0) { |
1649 |
iconInfo = getMapModeConstants().getSingleIconInfo(image); |
1650 |
} else { |
1651 |
iconInfo = new MultiIconInfo(); |
1652 |
iconInfo.setIcon(image, index); |
1653 |
} |
1654 |
revalidate(); |
1655 |
repaint();// Call repaint, in case the image dimensions are the same. |
1656 |
} else if (iconInfo.getIcon(index) != image) { |
1657 |
if (iconInfo.getMaxIcons() == 1) { |
1658 |
if (index == 0) { |
1659 |
iconInfo = getMapModeConstants().getSingleIconInfo(image); |
1660 |
revalidate(); |
1661 |
repaint();// Call repaint, in case the image dimensions are the same. |
1662 |
return; |
1663 |
} |
1664 |
IconInfo oldIconInfo = iconInfo; |
1665 |
iconInfo = new MultiIconInfo(); |
1666 |
iconInfo.setIcon(oldIconInfo.getIcon(0), 0); |
1667 |
} |
1668 |
iconInfo.setIcon(image, index); |
1669 |
revalidate(); |
1670 |
repaint();// Call repaint, in case the image dimensions are the same. |
1671 |
} |
1672 |
} |
1673 |
|
1674 |
/** |
1675 |
* Sets the icon alignment relative to the text. The default is |
1676 |
* {@link PositionConstants#CENTER}. |
1677 |
* <p> |
1678 |
* |
1679 |
* If the text placement is NORTH/SOUTH, icon alignment should be either |
1680 |
* LEFT, CENTER, or RIGHT to the icon. |
1681 |
* <p> |
1682 |
* |
1683 |
* If the text placement is EAST/WEST, icon alignment should be either TOP, |
1684 |
* CENTER, or BOTTOM to the icon. |
1685 |
* <p> |
1686 |
* |
1687 |
* @param align |
1688 |
* the icon alignment |
1689 |
*/ |
1690 |
public void setIconAlignment(int align) { |
1691 |
if (getIconAlignment() == align) |
1692 |
return; |
1693 |
setAlignmentFlags(align, FLAG_ICON_ALIGN); |
1694 |
revalidate(); |
1695 |
repaint(); |
1696 |
} |
1697 |
|
1698 |
/** |
1699 |
* Sets the Label's alignment to the passed value. The default is |
1700 |
* {@link PositionConstants#TOP}. Other possible values are |
1701 |
* {@link PositionConstants#CENTER},{@link PositionConstants#BOTTOM}. |
1702 |
* <p> |
1703 |
* Note:{@link PositionConstants#LEFT} and {@link PositionConstants#RIGHT} |
1704 |
* are not supported as wrap label occupies the entire client area. Use |
1705 |
* horizontal alignment instead (see WrapLabel#setHorizontalAlignment(int)). |
1706 |
* <p> |
1707 |
* |
1708 |
* @param align |
1709 |
* label alignment |
1710 |
*/ |
1711 |
public void setLabelAlignment(int align) { |
1712 |
if (getLabelAlignment() == align) |
1713 |
return; |
1714 |
|
1715 |
setAlignmentFlags(align, FLAG_LABEL_ALIGN); |
1716 |
|
1717 |
revalidate(); |
1718 |
repaint(); |
1719 |
} |
1720 |
|
1721 |
/** |
1722 |
* setPlacementFlags |
1723 |
* |
1724 |
* @param align |
1725 |
* @param flagOffset |
1726 |
*/ |
1727 |
private void setPlacementFlags(int align, int flagOffset) { |
1728 |
flags &= ~(0x7 * flagOffset); |
1729 |
switch (align) { |
1730 |
case EAST: |
1731 |
flags |= 0x1 * flagOffset; |
1732 |
break; |
1733 |
case WEST: |
1734 |
flags |= 0x2 * flagOffset; |
1735 |
break; |
1736 |
case NORTH: |
1737 |
flags |= 0x3 * flagOffset; |
1738 |
break; |
1739 |
case SOUTH: |
1740 |
flags |= 0x4 * flagOffset; |
1741 |
break; |
1742 |
} |
1743 |
} |
1744 |
|
1745 |
/** |
1746 |
* Sets the selection state of this label |
1747 |
* |
1748 |
* @param b |
1749 |
* true will cause the label to appear selected |
1750 |
*/ |
1751 |
public void setSelected(boolean b) { |
1752 |
textFlow.setSelected(b); |
1753 |
} |
1754 |
|
1755 |
/* |
1756 |
* (non-Javadoc) |
1757 |
* |
1758 |
* @see org.eclipse.draw2d.Label#setText(java.lang.String) |
1759 |
*/ |
1760 |
public void setText(String s) { |
1761 |
if (s == null) |
1762 |
s = "";//$NON-NLS-1$ |
1763 |
if (getText().equals(s)) |
1764 |
return; |
1765 |
textFlow.setText(s); |
1766 |
revalidate(); |
1767 |
repaint(); |
1768 |
} |
1769 |
|
1770 |
/** |
1771 |
* Sets the text alignment of the text relative to the icon. The default is |
1772 |
* {@link PositionConstants#CENTER}. |
1773 |
* <p> |
1774 |
* |
1775 |
* If the text placement is NORTH/SOUTH, text alignment should be either |
1776 |
* LEFT, CENTER, or RIGHT to the icon. |
1777 |
* <p> |
1778 |
* |
1779 |
* If the text placement is EAST/WEST, text alignment should be either TOP, |
1780 |
* CENTER, or BOTTOM to the icon. |
1781 |
* |
1782 |
* @param align |
1783 |
* the text alignment |
1784 |
*/ |
1785 |
public void setTextAlignment(int align) { |
1786 |
if (getTextAlignment() == align) |
1787 |
return; |
1788 |
setAlignmentFlags(align, FLAG_TEXT_ALIGN); |
1789 |
revalidate(); |
1790 |
repaint(); |
1791 |
} |
1792 |
|
1793 |
/** |
1794 |
* Sets the text placement of the label relative to its icon. The default is |
1795 |
* {@link PositionConstants#EAST}. Other possible values are |
1796 |
* {@link PositionConstants#NORTH},{@link PositionConstants#SOUTH}and |
1797 |
* {@link PositionConstants#WEST}. <p> |
1798 |
* |
1799 |
* e.g. PositionConstants#EAST indicates the text is on the east of the icon. <p> |
1800 |
* |
1801 |
* @param where |
1802 |
* the text placement |
1803 |
*/ |
1804 |
public void setTextPlacement(int where) { |
1805 |
if (getTextPlacement() == where) |
1806 |
return; |
1807 |
setPlacementFlags(where, FLAG_TEXT_PLACEMENT); |
1808 |
revalidate(); |
1809 |
repaint(); |
1810 |
} |
1811 |
|
1812 |
/** |
1813 |
* Sets whether the label text should be striked-through |
1814 |
* |
1815 |
* @param b |
1816 |
* Whether the label text should be striked-through |
1817 |
*/ |
1818 |
public void setTextStrikeThrough(boolean b) { |
1819 |
textFlow.setStrikeThrough(b); |
1820 |
} |
1821 |
|
1822 |
/** |
1823 |
* Sets whether the label text should be underlined |
1824 |
* |
1825 |
* @param b |
1826 |
* Whether the label text should be underlined |
1827 |
*/ |
1828 |
public void setTextUnderline(boolean b) { |
1829 |
textFlow.setTextUnderline(b); |
1830 |
} |
1831 |
|
1832 |
/** |
1833 |
* Sets up the flow page, block flow and text flow figures |
1834 |
* with appropriate wrapping layouts. <p> |
1835 |
* |
1836 |
* @param enableWrapping set to true if wrapping should be enabled. |
1837 |
*/ |
1838 |
private void setupTextFigures(boolean enableWrapping) { |
1839 |
|
1840 |
String oldText = ""; //$NON-NLS-1$ |
1841 |
|
1842 |
int oldTextHorizontalAlignment = CENTER; |
1843 |
|
1844 |
if (textFlow != null) { |
1845 |
oldText = textFlow.getText(); |
1846 |
oldTextHorizontalAlignment = blockFlow.getHorizontalAligment(); |
1847 |
remove(flowPage); |
1848 |
} |
1849 |
|
1850 |
flowPage = new FlowPage(); |
1851 |
blockFlow = new BlockFlow(); |
1852 |
textFlow = new SelectableTextFlow(); |
1853 |
|
1854 |
flowPage.setLayoutManager(new PageFlowLayout(flowPage)); |
1855 |
blockFlow.setLayoutManager(new BlockFlowLayout(blockFlow)); |
1856 |
|
1857 |
if (enableWrapping) { |
1858 |
textFlow.setLayoutManager(new ParagraphTextLayoutEx(textFlow, |
1859 |
ParagraphTextLayoutEx.WORD_WRAP_SOFT)); |
1860 |
} else { |
1861 |
textFlow.setLayoutManager(new SingleLineTextLayoutWithEllipses(textFlow)); |
1862 |
} |
1863 |
|
1864 |
blockFlow.add(textFlow); |
1865 |
flowPage.add(blockFlow); |
1866 |
add(flowPage); |
1867 |
|
1868 |
textFlow.setText(oldText); |
1869 |
setTextHorizontalAlignment(oldTextHorizontalAlignment); |
1870 |
} |
1871 |
|
1872 |
/** |
1873 |
* Sets whether the label text should wrap |
1874 |
* |
1875 |
* @param b |
1876 |
* whether the label text should wrap |
1877 |
*/ |
1878 |
public void setTextWrap(boolean b) { |
1879 |
if (isTextWrapped() == b) |
1880 |
return; |
1881 |
setFlag(FLAG_WRAP, b); |
1882 |
|
1883 |
setupTextFigures(b); |
1884 |
|
1885 |
revalidate(); |
1886 |
repaint(); |
1887 |
} |
1888 |
|
1889 |
/** |
1890 |
* Sets the horizontal alignment of the label text. The default is |
1891 |
* {@link PositionConstants#CENTER}. |
1892 |
* <p> |
1893 |
* |
1894 |
* It can be either {@link PositionConstants#LEFT}, |
1895 |
* {@link PositionConstants#CENTER}, or {@link PositionConstants#RIGHT} |
1896 |
* <p> |
1897 |
* |
1898 |
* @param i |
1899 |
* the horizontal alignment. |
1900 |
*/ |
1901 |
public void setTextHorizontalAlignment(int i) { |
1902 |
blockFlow.setHorizontalAligment(i); |
1903 |
|
1904 |
revalidate(); |
1905 |
repaint(); |
1906 |
} |
1907 |
|
1908 |
/** |
1909 |
* Obtains the text offset the caret should be placed given |
1910 |
* the location in absolute coordinates. |
1911 |
* @param location where the caret should be placed in |
1912 |
* absolute pixel coordinates |
1913 |
* @return text offset |
1914 |
*/ |
1915 |
public int getCaretOffset(Point location) { |
1916 |
Rectangle _textBounds = getTextBounds().getCopy(); |
1917 |
translateToAbsolute(_textBounds); |
1918 |
|
1919 |
if (!_textBounds.contains(location)) |
1920 |
return -1; |
1921 |
|
1922 |
return textFlow.getCaretOffset(location); |
1923 |
} |
1924 |
} |