KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > fieldassist > DecoratedField


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 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.jface.fieldassist;
12
13 import org.eclipse.core.runtime.Assert;
14 import org.eclipse.swt.SWT;
15 import org.eclipse.swt.events.DisposeEvent;
16 import org.eclipse.swt.events.DisposeListener;
17 import org.eclipse.swt.events.FocusEvent;
18 import org.eclipse.swt.events.FocusListener;
19 import org.eclipse.swt.events.MouseAdapter;
20 import org.eclipse.swt.events.MouseEvent;
21 import org.eclipse.swt.events.MouseTrackListener;
22 import org.eclipse.swt.events.PaintEvent;
23 import org.eclipse.swt.events.PaintListener;
24 import org.eclipse.swt.graphics.GC;
25 import org.eclipse.swt.graphics.Image;
26 import org.eclipse.swt.graphics.Point;
27 import org.eclipse.swt.graphics.Region;
28 import org.eclipse.swt.layout.FormAttachment;
29 import org.eclipse.swt.layout.FormData;
30 import org.eclipse.swt.layout.FormLayout;
31 import org.eclipse.swt.widgets.Composite;
32 import org.eclipse.swt.widgets.Control;
33 import org.eclipse.swt.widgets.Display;
34 import org.eclipse.swt.widgets.Label;
35 import org.eclipse.swt.widgets.Shell;
36
37 /**
38  * DecoratedField manages image decorations around a control. It allows clients
39  * to specify an image decoration and a position for the decoration relative to
40  * the field. Decorations may be assigned descriptions, which are shown when the
41  * user hovers over the decoration. Clients can decorate any kind of control by
42  * supplying a {@link IControlCreator} to create the control that is decorated.
43  * <p>
44  * Decorations always appear on either horizontal side of the field, never above
45  * or below it. Decorations can be positioned at the top or bottom of either
46  * side. Future implementations may provide additional positioning options for
47  * decorations.
48  * <p>
49  * By default, DecoratedField will consult the {@link FieldDecorationRegistry}
50  * to determine how much space should be reserved for each decoration. This
51  * allows fields with decorations from different sources to align properly on
52  * the same dialog, since the registry tracks the size of all decorations
53  * registered. Therefore, it is recommended, but not required, that clients of
54  * DecoratedField register the decorations used. In cases where alignment
55  * between different fields is not a concern, clients can use
56  * <code>setUseMaximumDecorationWidth(false)</code> and need not register
57  * their decorations.
58  * <p>
59  * This class is not intended to be subclassed.
60  *
61  * @since 3.2
62  * @deprecated As of 3.3, clients should use {@link ControlDecoration} instead.
63  */

64 public class DecoratedField {
65
66     /**
67      * Cached platform flags for dealing with platform-specific issues.
68      */

69     private static boolean CARBON = "carbon".equals(SWT.getPlatform()); //$NON-NLS-1$
70

71     /**
72      * Constants describing the array indices used to hold the decorations in
73      * array slots.
74      */

75
76     private static final int LEFT_TOP = 0;
77
78     private static final int LEFT_BOTTOM = 1;
79
80     private static final int RIGHT_TOP = 2;
81
82     private static final int RIGHT_BOTTOM = 3;
83
84     private static final int DECORATION_SLOTS = 4;
85
86     /**
87      * Simple data structure class for specifying the internals for a field
88      * decoration. This class contains data specific to the implementation of
89      * field decorations as labels attached to the field. Clients should use
90      * <code>FieldDecoration</code> for specifying a decoration.
91      */

92     private class FieldDecorationData {
93
94         /* Package */FieldDecoration decoration;
95
96         /* Package */Label label;
97
98         /* Package */FormData data;
99
100         /* Package */boolean showOnFocus;
101
102         /* Package */boolean visible = true;
103
104         /**
105          * Create a decoration data representing the specified decoration, using
106          * the specified label and form data for its representation.
107          *
108          * @param decoration
109          * the decoration whose data is kept.
110          * @param label
111          * the label used to represent the decoration.
112          * @param formData
113          * the form data used to attach the decoration to its field.
114          * @param showOnFocus
115          * a boolean specifying whether the decoration should only be
116          * shown when the field has focus.
117          */

118         FieldDecorationData(FieldDecoration decoration, Label label,
119                 FormData formData, boolean showOnFocus) {
120             this.decoration = decoration;
121             this.label = label;
122             this.data = formData;
123             this.showOnFocus = showOnFocus;
124         }
125     }
126
127     /**
128      * Decorations keyed by position.
129      */

130     private FieldDecorationData[] decDatas = new FieldDecorationData[DECORATION_SLOTS];
131
132     /**
133      * The associated control
134      */

135     private Control control;
136
137     /**
138      * The composite with form layout used to manage decorations.
139      */

140     private Composite form;
141
142     /**
143      * The boolean that indicates whether the maximum decoration width is used
144      * when allocating space for decorations.
145      */

146     private boolean useMaxDecorationWidth = true;
147
148     /**
149      * The hover used for showing description text
150      */

151     private Hover hover;
152
153     /**
154      * The hover used to show a decoration image's description.
155      */

156     class Hover {
157         private static final String JavaDoc EMPTY = ""; //$NON-NLS-1$
158

159         /**
160          * Offset of info hover arrow from the left or right side.
161          */

162         private int hao = 10;
163
164         /**
165          * Width of info hover arrow.
166          */

167         private int haw = 8;
168
169         /**
170          * Height of info hover arrow.
171          */

172         private int hah = 10;
173
174         /**
175          * Margin around info hover text.
176          */

177         private int hm = 2;
178
179         /**
180          * This info hover's shell.
181          */

182         Shell hoverShell;
183
184         /**
185          * The info hover text.
186          */

187         String JavaDoc text = EMPTY;
188
189         /**
190          * The region used to manage the shell shape
191          */

192         Region region;
193
194         /**
195          * Boolean indicating whether the last computed polygon location had an
196          * arrow on left. (true if left, false if right).
197          */

198         boolean arrowOnLeft = true;
199
200         /*
201          * Create a hover parented by the specified shell.
202          */

203         Hover(Shell parent) {
204             final Display display = parent.getDisplay();
205             hoverShell = new Shell(parent, SWT.NO_TRIM | SWT.ON_TOP
206                     | SWT.NO_FOCUS);
207             hoverShell.setBackground(display
208                     .getSystemColor(SWT.COLOR_INFO_BACKGROUND));
209             hoverShell.setForeground(display
210                     .getSystemColor(SWT.COLOR_INFO_FOREGROUND));
211             hoverShell.addPaintListener(new PaintListener() {
212                 public void paintControl(PaintEvent pe) {
213                     pe.gc.drawString(text, hm, hm);
214                     if (!CARBON) {
215                         pe.gc.drawPolygon(getPolygon(true));
216                     }
217                 }
218             });
219             hoverShell.addMouseListener(new MouseAdapter() {
220                 public void mouseDown(MouseEvent e) {
221                     hideHover();
222                 }
223             });
224         }
225
226         /*
227          * Compute a polygon that represents a hover with an arrow pointer. If
228          * border is true, compute the polygon inset by 1-pixel border. Consult
229          * the arrowOnLeft flag to determine which side the arrow is on.
230          */

231         int[] getPolygon(boolean border) {
232             Point e = getExtent();
233             int b = border ? 1 : 0;
234             if (arrowOnLeft) {
235                 return new int[] { 0, 0, e.x - b, 0, e.x - b, e.y - b,
236                         hao + haw, e.y - b, hao + haw / 2, e.y + hah - b, hao,
237                         e.y - b, 0, e.y - b, 0, 0 };
238             }
239             return new int[] { 0, 0, e.x - b, 0, e.x - b, e.y - b,
240                     e.x - hao - b, e.y - b, e.x - hao - haw / 2, e.y + hah - b,
241                     e.x - hao - haw, e.y - b, 0, e.y - b, 0, 0 };
242         }
243
244         /*
245          * Dispose the hover, it is no longer needed. Dispose any resources
246          * allocated by the hover.
247          */

248         void dispose() {
249             if (!hoverShell.isDisposed()) {
250                 hoverShell.dispose();
251             }
252             if (region != null) {
253                 region.dispose();
254             }
255         }
256
257         /*
258          * Set the visibility of the hover.
259          */

260         void setVisible(boolean visible) {
261             if (visible) {
262                 if (!hoverShell.isVisible()) {
263                     hoverShell.setVisible(true);
264                 }
265             } else {
266                 if (hoverShell.isVisible()) {
267                     hoverShell.setVisible(false);
268                 }
269             }
270         }
271
272         /*
273          * Set the text of the hover to the specified text. Recompute the size
274          * and location of the hover to hover near the specified control,
275          * pointing the arrow toward the target control.
276          */

277         void setText(String JavaDoc t, Control hoverNear, Control targetControl) {
278             if (t == null) {
279                 t = EMPTY;
280             }
281             if (!t.equals(text)) {
282                 Point oldSize = getExtent();
283                 text = t;
284                 hoverShell.redraw();
285                 Point newSize = getExtent();
286                 if (!oldSize.equals(newSize)) {
287                     // set a flag that indicates the direction of arrow
288
arrowOnLeft = hoverNear.getLocation().x <= targetControl
289                             .getLocation().x;
290                     setNewShape();
291                 }
292             }
293
294             if (hoverNear != null) {
295                 Point extent = getExtent();
296                 int y = -extent.y - hah + 1;
297                 int x = arrowOnLeft ? -hao + haw / 2 : -extent.x + hao + haw
298                         / 2;
299
300                 hoverShell.setLocation(hoverNear.toDisplay(x, y));
301             }
302
303         }
304
305         /*
306          * Return whether or not the hover (shell) is visible.
307          */

308         boolean isVisible() {
309             return hoverShell.isVisible();
310         }
311
312         /*
313          * Compute the extent of the hover for the current text.
314          */

315         Point getExtent() {
316             GC gc = new GC(hoverShell);
317             Point e = gc.textExtent(text);
318             gc.dispose();
319             e.x += hm * 2;
320             e.y += hm * 2;
321             return e;
322         }
323
324         /*
325          * Compute a new shape for the hover shell.
326          */

327         void setNewShape() {
328             Region oldRegion = region;
329             region = new Region();
330             region.add(getPolygon(false));
331             hoverShell.setRegion(region);
332             if (oldRegion != null) {
333                 oldRegion.dispose();
334             }
335
336         }
337     }
338
339     /**
340      * Construct a decorated field which is parented by the specified composite
341      * and has the given style bits. Use the controlCreator to create the
342      * specific kind of control that is decorated inside the field.
343      *
344      * @param parent
345      * the parent of the decorated field.
346      * @param style
347      * the desired style bits for the field.
348      * @param controlCreator
349      * the IControlCreator used to specify the specific kind of
350      * control that is to be decorated.
351      *
352      * @see IControlCreator
353      */

354     public DecoratedField(Composite parent, int style,
355             IControlCreator controlCreator) {
356         this.form = createForm(parent);
357         this.control = controlCreator.createControl(form, style);
358
359         addControlListeners();
360         form.setTabList(new Control[] { control });
361
362         // Set up the initial layout data.
363
FormData data = new FormData();
364         data.left = new FormAttachment(0, 0);
365         data.top = new FormAttachment(0, 0);
366         data.right = new FormAttachment(100, 0);
367         data.bottom = new FormAttachment(100, 0);
368         control.setLayoutData(data);
369
370     }
371
372     /**
373      * Adds an image decoration to the field.
374      *
375      * @param decoration
376      * A FieldDecoration describing the image and description for the
377      * decoration
378      *
379      * @param position
380      * The SWT constant indicating the position of the decoration
381      * relative to the field's control. The position should include
382      * style bits describing both the vertical and horizontal
383      * orientation. <code>SWT.LEFT</code> and
384      * <code>SWT.RIGHT</code> describe the horizontal placement of
385      * the decoration relative to the field, and the constants
386      * <code>SWT.TOP</code> and <code>SWT.BOTTOM</code> describe
387      * the vertical alignment of the decoration relative to the
388      * field. Decorations always appear on either horizontal side of
389      * the field, never above or below it. For example, a decoration
390      * appearing on the left side of the field, at the top, is
391      * specified as SWT.LEFT | SWT.TOP. If an image decoration
392      * already exists in the specified position, it will be replaced
393      * by the one specified.
394      * @param showOnFocus
395      * <code>true</code> if the decoration should only be shown
396      * when the associated control has focus, <code>false</code> if
397      * it should always be shown.
398      *
399      */

400     public void addFieldDecoration(FieldDecoration decoration, int position,
401             boolean showOnFocus) {
402         final Label label;
403         FormData formData;
404         int i = indexForPosition(position);
405         if (decDatas[i] == null) {
406             formData = createFormDataForIndex(i, decoration.getImage());
407             label = new Label(form, SWT.HORIZONTAL | SWT.VERTICAL | SWT.CENTER);
408             label.addMouseTrackListener(new MouseTrackListener() {
409                 public void mouseHover(MouseEvent event) {
410                     FieldDecorationData decData = (FieldDecorationData) event.widget
411                             .getData();
412                     String JavaDoc desc = decData.decoration.getDescription();
413                     if (desc != null) {
414                         showHoverText(desc, label);
415                     }
416                 }
417
418                 public void mouseEnter(MouseEvent event) {
419                 }
420
421                 public void mouseExit(MouseEvent event) {
422                     hideHover();
423                 }
424             });
425             decDatas[i] = new FieldDecorationData(decoration, label, formData,
426                     showOnFocus);
427         } else {
428             label = decDatas[i].label;
429             formData = decDatas[i].data;
430             decDatas[i].decoration = decoration;
431             decDatas[i].showOnFocus = showOnFocus;
432         }
433         label.setImage(decDatas[i].decoration.getImage());
434         label.setData(decDatas[i]);
435         label.setLayoutData(formData);
436         label.setVisible(!showOnFocus);
437
438         // Since sizes may have changed or there could be a new position
439
// defined, we need to update layout data on the control.
440
updateControlAttachments(i, decDatas[i]);
441     }
442
443     /*
444      * A decoration at the specified index has been added. Update the control's
445      * attachments if it has not previously been attached on that side or if it
446      * was attached to a decoration with a lesser width.
447      */

448     private void updateControlAttachments(int index, FieldDecorationData decData) {
449         FormData formData = (FormData) control.getLayoutData();
450         int newWidth = widthOf(decData.decoration.getImage());
451         // opposing represents the location of the decoration above or below
452
// the one in question.
453
int opposing;
454
455         switch (index) {
456         case LEFT_TOP:
457         case LEFT_BOTTOM:
458             if (index == LEFT_TOP) {
459                 opposing = LEFT_BOTTOM;
460             } else {
461                 opposing = LEFT_TOP;
462             }
463             if (decDatas[opposing] == null) {
464                 // No decorator on the opposing side.
465
// Attach the control to this decorator
466
formData.left = new FormAttachment(decData.label);
467             } else if (decDatas[opposing].data.width < newWidth) {
468                 // Decorator on opposing side is the smaller one. Attach
469
// control to the new one.
470
formData.left = new FormAttachment(decData.label);
471                 // Center align the smaller one relative to the larger one.
472
decDatas[opposing].data.left.alignment = SWT.CENTER;
473                 decDatas[opposing].data.left.control = decData.label;
474             } else {
475                 // The new decorator is the smaller one. Keep the
476
// control attached to the opposing one.
477
formData = null;
478                 // Horizontally center the smaller one relative to the larger
479
// one.
480
decData.data.left.alignment = SWT.CENTER;
481                 decData.data.left.control = decDatas[opposing].label;
482             }
483             break;
484         /*
485          * The only real difference in right side cases is that we are attaching
486          * the right side of the control to the wider decoration rather than the
487          * left side of the control. Other concerns (horizontally aligning the
488          * smaller decoration relative to the larger one) are the same.
489          */

490         case RIGHT_TOP:
491         case RIGHT_BOTTOM:
492             if (index == RIGHT_TOP) {
493                 opposing = RIGHT_BOTTOM;
494             } else {
495                 opposing = RIGHT_TOP;
496             }
497             if (decDatas[opposing] == null) {
498                 // No decorator on the opposing side.
499
// Attach the control to this decorator.
500
formData.right = new FormAttachment(decData.label);
501             } else if (decDatas[opposing].data.width < newWidth) {
502                 // Decorator on opposing side is the smaller one. Attach
503
// control to the new one.
504
formData.right = new FormAttachment(decData.label);
505                 // Center align the smaller one to the larger one.
506
// Note that this could be done using the left or right
507
// attachment, we use the right since it is already
508
// created for all right-side decorations.
509
decDatas[opposing].data.right.alignment = SWT.CENTER;
510                 decDatas[opposing].data.right.control = decData.label;
511             } else {
512                 // The new decorator is the smaller one. Keep the
513
// control attached to the opposing one.
514
formData = null;
515                 // Horizontally center align the smaller one to the
516
// larger one.
517
decData.data.right.alignment = SWT.CENTER;
518                 decData.data.right.control = decDatas[opposing].label;
519             }
520             break;
521         default:
522             return;
523         }
524         if (formData != null) {
525             // Form data was updated.
526
control.setLayoutData(formData);
527             form.layout();
528         }
529     }
530
531     /**
532      * Get the control that is decorated by the receiver.
533      *
534      * @return the Control decorated by the receiver, or <code>null</code> if
535      * none has been created yet.
536      */

537     public Control getControl() {
538         return control;
539     }
540
541     /**
542      * Get the control that represents the decorated field. This composite
543      * should be used to lay out the field within its parent.
544      *
545      * @return the Control that should be layed out in the field's parent's
546      * layout. This is typically not the control itself, since
547      * additional controls are used to represent the decorations.
548      */

549     public Control getLayoutControl() {
550         return form;
551     }
552
553     /**
554      * Create the parent composite and a form layout that will be used to manage
555      * decorations.
556      */

557     private Composite createForm(Composite parent) {
558         Composite composite = new Composite(parent, SWT.NO_FOCUS);
559         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=126553
560
composite.setBackgroundMode(SWT.INHERIT_DEFAULT);
561         composite.setLayout(new FormLayout());
562         return composite;
563     }
564
565     /**
566      * Add any listeners needed on the target control.
567      */

568     private void addControlListeners() {
569         control.addDisposeListener(new DisposeListener() {
570             public void widgetDisposed(DisposeEvent event) {
571                 if (hover != null) {
572                     hover.dispose();
573                 }
574             }
575         });
576         control.addFocusListener(new FocusListener() {
577             public void focusGained(FocusEvent event) {
578                 controlFocusGained();
579             }
580
581             public void focusLost(FocusEvent event) {
582                 controlFocusLost();
583             }
584
585         });
586     }
587
588     /*
589      * Return the index in the array of decoration datas that represents the
590      * specified SWT position.
591      *
592      * @param position The SWT constant indicating the position of the
593      * decoration relative to the field's control. The position should include
594      * style bits describing both the vertical and horizontal orientation.
595      * <code>SWT.LEFT</code> and <code>SWT.RIGHT</code> describe the
596      * horizontal placement of the decoration relative to the field, and the
597      * constants <code>SWT.TOP</code> and <code>SWT.BOTTOM</code> describe
598      * the vertical alignment of the decoration relative to the field.
599      * Decorations always appear on either horizontal side of the field, never
600      * above or below it. For example, a decoration appearing on the left side
601      * of the field, at the top, is specified as SWT.LEFT | SWT.TOP.
602      *
603      * @return index the index in the array of decorations that represents the
604      * specified SWT position. If the position is not an expected position, the
605      * index representing the top left position will be returned.
606      *
607      */

608     private int indexForPosition(int position) {
609         switch (position) {
610         case SWT.LEFT | SWT.BOTTOM:
611             return LEFT_BOTTOM;
612         case SWT.RIGHT | SWT.TOP:
613             return RIGHT_TOP;
614         case SWT.RIGHT | SWT.BOTTOM:
615             return RIGHT_BOTTOM;
616         default:
617             return LEFT_TOP;
618         }
619     }
620
621     /*
622      * Create a form data that will place the decoration at the specified
623      * position.
624      *
625      * @param index the index in the decDatas describing the position of the
626      * decoration.
627      *
628      * @param image the image shown in the decoration.
629      *
630      */

631     private FormData createFormDataForIndex(int index, Image image) {
632         Assert.isTrue(index >= 0 && index < DECORATION_SLOTS,
633                 "Index out of range"); //$NON-NLS-1$
634

635         FormData data = new FormData();
636         switch (index) {
637         case LEFT_TOP:
638             data.left = new FormAttachment(0, 0);
639             data.top = new FormAttachment(0, 0);
640             break;
641         case LEFT_BOTTOM:
642             data.left = new FormAttachment(0, 0);
643             data.bottom = new FormAttachment(100, 0);
644             break;
645         case RIGHT_TOP:
646             data.right = new FormAttachment(100, 0);
647             data.top = new FormAttachment(0, 0);
648             break;
649         case RIGHT_BOTTOM:
650             data.right = new FormAttachment(100, 0);
651             data.bottom = new FormAttachment(100, 0);
652             break;
653         }
654         data.width = widthOf(image);
655         data.height = SWT.DEFAULT;
656
657         return data;
658     }
659
660     /**
661      * Show the specified text using the same hover dialog as is used to show
662      * decorator descriptions. Normally, a decoration's description text will be
663      * shown in an info hover over the field's control whenever the mouse hovers
664      * over the decoration. This method can be used to show a decoration's
665      * description text at other times (such as when the control receives
666      * focus), or to show other text associated with the field.
667      *
668      * <p>
669      * If there is currently a hover visible, the hover's text will be replaced
670      * with the specified text.
671      *
672      * @param text
673      * the text to be shown in the info hover, or <code>null</code>
674      * if no text should be shown.
675      */

676     public void showHoverText(String JavaDoc text) {
677         showHoverText(text, control);
678     }
679
680     /**
681      * Hide any hover popups that are currently showing on the control.
682      * Normally, a decoration's description text will be shown in an info hover
683      * over the field's control as long as the mouse hovers over the decoration,
684      * and will be hidden when the mouse exits the control. This method can be
685      * used to hide a hover that was shown using <code>showHoverText</code>,
686      * or to programatically hide the current decoration hover.
687      *
688      * <p>
689      * This message has no effect if there is no current hover.
690      *
691      */

692     public void hideHover() {
693         if (hover != null) {
694             hover.setVisible(false);
695         }
696     }
697
698     /*
699      * The target control gained focus. Any decorations that should show only
700      * when they have the focus should be shown here.
701      */

702     private void controlFocusGained() {
703         for (int i = 0; i < DECORATION_SLOTS; i++) {
704             if (decDatas[i] != null && decDatas[i].showOnFocus) {
705                 setVisible(decDatas[i], true);
706             }
707         }
708     }
709
710     /*
711      * The target control lost focus. Any decorations that should show only when
712      * they have the focus should be hidden here.
713      */

714     private void controlFocusLost() {
715         for (int i = 0; i < DECORATION_SLOTS; i++) {
716             if (decDatas[i] != null && decDatas[i].showOnFocus) {
717                 setVisible(decDatas[i], false);
718             }
719         }
720     }
721
722     /**
723      * Show the specified decoration. This message has no effect if the
724      * decoration is already showing, or was not already added to the field
725      * using <code>addFieldDecoration</code>.
726      *
727      * @param decoration
728      * the decoration to be shown.
729      */

730     public void showDecoration(FieldDecoration decoration) {
731         FieldDecorationData data = getDecorationData(decoration);
732         if (data == null) {
733             return;
734         }
735         // record the fact that client would like it to be visible
736
data.visible = true;
737         // even if it is supposed to be shown, if the field does not have focus,
738
// do not show it (yet)
739
if (!data.showOnFocus || control.isFocusControl()) {
740             setVisible(data, true);
741         }
742     }
743
744     /**
745      * Hide the specified decoration. This message has no effect if the
746      * decoration is already hidden, or was not already added to the field using
747      * <code>addFieldDecoration</code>.
748      *
749      * @param decoration
750      * the decoration to be hidden.
751      */

752     public void hideDecoration(FieldDecoration decoration) {
753         FieldDecorationData data = getDecorationData(decoration);
754         if (data == null) {
755             return;
756         }
757         // Store the desired visibility in the decData. We remember the
758
// client's instructions so that changes in visibility caused by
759
// field focus changes won't violate the client's visibility setting.
760
data.visible = false;
761         setVisible(data, false);
762     }
763
764     /**
765      * Update the specified decoration. This message should be used if the image
766      * or description in the decoration have changed. This message has no
767      * immediate effect if the decoration is not visible, and no effect at all
768      * if the decoration was not previously added to the field.
769      *
770      * @param decoration
771      * the decoration to be hidden.
772      */

773     public void updateDecoration(FieldDecoration decoration) {
774         FieldDecorationData data = getDecorationData(decoration);
775         if (data == null) {
776             return;
777         }
778         if (data.label != null) {
779             data.label.setImage(decoration.getImage());
780             // If the decoration is being shown, and a hover is active,
781
// update the hover text to display the new description.
782
if (data.label.getVisible() == true && hover != null) {
783                 showHoverText(decoration.getDescription(), data.label);
784             }
785         }
786     }
787
788     /*
789      * Set the visibility of the specified decoration data. This method does not
790      * change the visibility value stored in the decData, but instead consults
791      * it to determine how the visibility should be changed. This method is
792      * called any time visibility of a decoration might change, whether by
793      * client API or focus changes.
794      */

795     private void setVisible(FieldDecorationData decData, boolean visible) {
796         // Check the decData visibility flag, since it contains the client's
797
// instructions for visibility.
798
if (visible && decData.visible) {
799             decData.label.setVisible(true);
800         } else {
801             decData.label.setVisible(false);
802         }
803     }
804
805     /*
806      * Get the FieldDecorationData that corresponds to the given decoration.
807      */

808     private FieldDecorationData getDecorationData(FieldDecoration dec) {
809         for (int i = 0; i < DECORATION_SLOTS; i++) {
810             if (decDatas[i] != null && dec == decDatas[i].decoration
811                     && decDatas[i].label != null
812                     && !decDatas[i].label.isDisposed()) {
813                 return decDatas[i];
814             }
815         }
816         return null;
817     }
818
819     /*
820      * Show the specified text in the hover, positioning the hover near the
821      * specified control.
822      */

823     private void showHoverText(String JavaDoc text, Control hoverNear) {
824         if (text == null) {
825             hideHover();
826             return;
827         }
828
829         if (hover == null) {
830             hover = new Hover(hoverNear.getShell());
831         }
832         hover.setText(text, hoverNear, control);
833         hover.setVisible(true);
834     }
835
836     /**
837      * Set a boolean that indicates whether the receiver should use the
838      * decoration registry's maximum decoration width when allocating space for
839      * decorations. The default value is <code>true</code>. Using the maximum
840      * decoration width is useful so that decorated fields on the same dialog
841      * that have different decoration widths will all align. This also allows
842      * client dialogs to align non-decorated fields with decorated fields by
843      * consulting the maximum decoration width.
844      * </p>
845      * <p>
846      * Clients may wish to set this value to <code>false</code> in cases where
847      * space usage is more important than alignment of fields. This value must
848      * be set before the decorations are added in order to ensure proper
849      * alignment.
850      * </p>
851      *
852      * @param useMaximumWidth
853      * <code>true</code> if the maximum decoration width should be
854      * used as the size for all decorations, <code>false</code> if
855      * only the decoration size should be used.
856      *
857      * @see FieldDecorationRegistry#getMaximumDecorationWidth()
858      */

859     public void setUseMaximumDecorationWidth(boolean useMaximumWidth) {
860         useMaxDecorationWidth = useMaximumWidth;
861     }
862
863     /*
864      * Return the width appropriate for the specified decoration image.
865      */

866     private int widthOf(Image image) {
867         if (image == null) {
868             return 0;
869         }
870         return useMaxDecorationWidth ? FieldDecorationRegistry.getDefault()
871                 .getMaximumDecorationWidth() : image.getBounds().width;
872     }
873 }
874
Popular Tags