KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > forms > widgets > Form


1 /*******************************************************************************
2  * Copyright (c) 2000, 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.ui.forms.widgets;
12
13 import org.eclipse.jface.action.IMenuManager;
14 import org.eclipse.jface.action.IToolBarManager;
15 import org.eclipse.swt.SWT;
16 import org.eclipse.swt.dnd.DragSourceListener;
17 import org.eclipse.swt.dnd.DropTargetListener;
18 import org.eclipse.swt.dnd.Transfer;
19 import org.eclipse.swt.graphics.Color;
20 import org.eclipse.swt.graphics.Font;
21 import org.eclipse.swt.graphics.Image;
22 import org.eclipse.swt.graphics.Point;
23 import org.eclipse.swt.graphics.Rectangle;
24 import org.eclipse.swt.widgets.Composite;
25 import org.eclipse.swt.widgets.Control;
26 import org.eclipse.swt.widgets.Layout;
27 import org.eclipse.swt.widgets.Menu;
28 import org.eclipse.ui.forms.IFormColors;
29 import org.eclipse.ui.forms.IMessage;
30 import org.eclipse.ui.forms.events.IHyperlinkListener;
31 import org.eclipse.ui.internal.forms.widgets.FormHeading;
32 import org.eclipse.ui.internal.forms.widgets.FormUtil;
33
34 /**
35  * Form is a custom control that renders a title and an optional background
36  * image above the body composite. It can be used alone when part of parents
37  * that are scrolled. If scrolling is required, use <code>ScrolledForm</code>
38  * instead because it has an instance of <code>Form</code> and adds scrolling
39  * capability.
40  * <p>
41  * Form can have a title if set. If not set, title area will not be left empty -
42  * form body will be resized to fill the entire form. In addition, an optional
43  * title image can be set and is rendered to the left of the title (since 3.2).
44  * <p>
45  * Form can have a title drop down menu if the menu bar manager is not empty
46  * (since 3.3).
47  * <p>
48  * Form title can support drag and drop if drag and drop support methods are
49  * invoked. When used, additional decoration is rendered behind the title to
50  * reinforce the drag and drop ability (since 3.3).
51  * <p>
52  * The form supports status messages. These messages can have various severity
53  * (error, warning, info or none). If status hyperlink handler is specified, the
54  * messages with the specified severity other than none will be rendered as
55  * hyperlinks.
56  * <p>
57  * Form can have a background image behind the title text. The image is tiled as
58  * many times as needed to fill the title area. Alternatively, gradient
59  * background can be painted vertically or horizontally.
60  * <p>
61  * Form can be put in a 'busy' state. While in this state, title image is
62  * replaced with an animation that lasts as long as the 'busy' state is active.
63  * <p>
64  * It is possible to create an optional head client control. When created, this
65  * control is placed in the form heading as a second row.
66  * <p>
67  * Form has a custom layout manager that is wrap-enabled. If a form is placed in
68  * a composite whose layout manager implements ILayoutExtension, the body of the
69  * form will participate in wrapping as long as its layout manager implements
70  * ILayoutExtension as well.
71  * <p>
72  * Children of the form should typically be created using FormToolkit to match
73  * the appearance and behaviour. When creating children, use the form body as a
74  * parent by calling 'getBody()' on the form instance. Example:
75  *
76  * <pre>
77  * FormToolkit toolkit = new FormToolkit(parent.getDisplay());
78  * Form form = toolkit.createForm(parent);
79  * form.setText(&quot;Sample form&quot;);
80  * form.getBody().setLayout(new GridLayout());
81  * toolkit.createButton(form.getBody(), &quot;Checkbox&quot;, SWT.CHECK);
82  * </pre>
83  *
84  * <p>
85  * No layout manager has been set on the body. Clients are required to set the
86  * desired layout manager explicitly.
87  * <p>
88  * Although the class is not final, it should not be subclassed.
89  *
90  * @since 3.0
91  */

92 public class Form extends Composite {
93     private FormHeading head;
94
95     private Composite body;
96
97     private SizeCache bodyCache = new SizeCache();
98
99     private SizeCache headCache = new SizeCache();
100
101     private FormText selectionText;
102
103     private class FormLayout extends Layout implements ILayoutExtension {
104         public int computeMinimumWidth(Composite composite, boolean flushCache) {
105             return computeSize(composite, 5, SWT.DEFAULT, flushCache).x;
106         }
107
108         public int computeMaximumWidth(Composite composite, boolean flushCache) {
109             return computeSize(composite, SWT.DEFAULT, SWT.DEFAULT, flushCache).x;
110         }
111
112         public Point computeSize(Composite composite, int wHint, int hHint,
113                 boolean flushCache) {
114             if (flushCache) {
115                 bodyCache.flush();
116                 headCache.flush();
117             }
118             bodyCache.setControl(body);
119             headCache.setControl(head);
120
121             int width = 0;
122             int height = 0;
123
124             Point hsize = headCache.computeSize(FormUtil.getWidthHint(wHint,
125                     head), SWT.DEFAULT);
126             width = Math.max(hsize.x, width);
127             height = hsize.y;
128             
129             boolean ignoreBody=getData(FormUtil.IGNORE_BODY)!=null;
130             
131             Point bsize;
132             if (ignoreBody)
133                 bsize = new Point(0,0);
134             else
135                 bsize = bodyCache.computeSize(FormUtil.getWidthHint(wHint,
136                     body), SWT.DEFAULT);
137             width = Math.max(bsize.x, width);
138             height += bsize.y;
139             return new Point(width, height);
140         }
141
142         protected void layout(Composite composite, boolean flushCache) {
143             if (flushCache) {
144                 bodyCache.flush();
145                 headCache.flush();
146             }
147             bodyCache.setControl(body);
148             headCache.setControl(head);
149             Rectangle carea = composite.getClientArea();
150
151             Point hsize = headCache.computeSize(carea.width, SWT.DEFAULT);
152             headCache.setBounds(0, 0, carea.width, hsize.y);
153             bodyCache
154                     .setBounds(0, hsize.y, carea.width, carea.height - hsize.y);
155         }
156     }
157
158     /**
159      * Creates the form content control as a child of the provided parent.
160      *
161      * @param parent
162      * the parent widget
163      */

164     public Form(Composite parent, int style) {
165         super(parent, SWT.NO_BACKGROUND | style);
166         super.setLayout(new FormLayout());
167         head = new FormHeading(this, SWT.NULL);
168         head.setMenu(parent.getMenu());
169         body = new LayoutComposite(this, SWT.NULL);
170         body.setMenu(parent.getMenu());
171     }
172
173     /**
174      * Passes the menu to the form body.
175      *
176      * @param menu
177      * the parent menu
178      */

179     public void setMenu(Menu menu) {
180         super.setMenu(menu);
181         head.setMenu(menu);
182         body.setMenu(menu);
183     }
184
185     /**
186      * Fully delegates the size computation to the internal layout manager.
187      */

188     public final Point computeSize(int wHint, int hHint, boolean changed) {
189         return ((FormLayout) getLayout()).computeSize(this, wHint, hHint,
190                 changed);
191     }
192
193     /**
194      * Prevents from changing the custom control layout.
195      */

196     public final void setLayout(Layout layout) {
197     }
198
199     /**
200      * Returns the title text that will be rendered at the top of the form.
201      *
202      * @return the title text
203      */

204     public String JavaDoc getText() {
205         return head.getText();
206     }
207
208     /**
209      * Returns the title image that will be rendered to the left of the title.
210      *
211      * @return the title image or <code>null</code> if not set.
212      * @since 3.2
213      */

214     public Image getImage() {
215         return head.getImage();
216     }
217
218     /**
219      * Sets the foreground color of the form. This color will also be used for
220      * the body.
221      *
222      * @param fg
223      * the foreground color
224      */

225     public void setForeground(Color fg) {
226         super.setForeground(fg);
227         head.setForeground(fg);
228         body.setForeground(fg);
229     }
230
231     /**
232      * Sets the background color of the form. This color will also be used for
233      * the body.
234      *
235      * @param bg
236      * the background color
237      */

238     public void setBackground(Color bg) {
239         super.setBackground(bg);
240         head.setBackground(bg);
241         body.setBackground(bg);
242     }
243
244     /**
245      * Sets the font of the header text.
246      *
247      * @param font
248      * the new font
249      */

250     public void setFont(Font font) {
251         super.setFont(font);
252         head.setFont(font);
253     }
254
255     /**
256      * Sets the text to be rendered at the top of the form above the body as a
257      * title.
258      * <p>
259      * <strong>Note:</strong> Mnemonics are indicated by an '&amp;' that causes
260      * the next character to be the mnemonic. Mnemonics are not applicable in
261      * the case of the form title but need to be taken into acount due to the
262      * usage of the underlying widget that renders mnemonics in the title area.
263      * The mnemonic indicator character '&amp;' can be escaped by doubling it in
264      * the string, causing a single '&amp;' to be displayed.
265      * </p>
266      *
267      * @param text
268      * the title text
269      */

270     public void setText(String JavaDoc text) {
271         head.setText(text);
272         layout();
273         redraw();
274     }
275
276     /**
277      * Sets the image to be rendered to the left of the title. This image will
278      * be temporarily hidden in two cases:
279      *
280      * <ol>
281      * <li>When the form is busy - replaced with a busy animation</li>
282      * <li>When the form has message set - replaced with the image indicating
283      * message severity</li>
284      * </ol>
285      *
286      * @param image
287      * the title image or <code>null</code> to show no image.
288      * @since 3.2
289      */

290     public void setImage(Image image) {
291         head.setImage(image);
292         layout();
293         redraw();
294     }
295
296     /**
297      * Sets the background colors to be painted behind the title text in a
298      * gradient. Note that this method will reset color previously set by
299      * {@link #setBackground(Color)}. This is necessary for the simulated
300      * transparency of the heading in all of its children control.
301      *
302      * @param gradientColors
303      * the array of colors that form the gradient
304      * @param percents
305      * the partition of the overall space between the gradient colors
306      * @param vertical
307      * of <code>true</code>, the gradient will be rendered
308      * vertically, if <code>false</code> the orientation will be
309      * horizontal.
310      */

311
312     public void setTextBackground(Color[] gradientColors, int[] percents,
313             boolean vertical) {
314         head.setTextBackground(gradientColors, percents, vertical);
315     }
316
317     /**
318      * Returns the optional background image of the form head.
319      *
320      * @return the background image or <code>null</code> if not specified.
321      */

322     public Image getBackgroundImage() {
323         return head.getHeadingBackgroundImage();
324     }
325
326     /**
327      * Sets the optional background image to be rendered behind the title
328      * starting at the position 0,0. If the image is smaller than the container
329      * in any dimension, it will be tiled.
330      *
331      * @since 3.2
332      *
333      * @param backgroundImage
334      * the head background image.
335      *
336      */

337     public void setBackgroundImage(Image backgroundImage) {
338         head.setHeadingBackgroundImage(backgroundImage);
339     }
340
341     /**
342      * Returns the tool bar manager that is used to manage tool items in the
343      * form's title area.
344      *
345      * @return form tool bar manager
346      */

347     public IToolBarManager getToolBarManager() {
348         return head.getToolBarManager();
349     }
350
351     /**
352      * Sets the tool bar vertical alignment relative to the header. Can be
353      * useful when there is more free space at the second row (with the head
354      * client).
355      *
356      * @param alignment
357      * SWT.TOP or SWT.BOTTOM
358      * @since 3.3
359      */

360
361     public void setToolBarVerticalAlignment(int alignment) {
362         head.setToolBarAlignment(alignment);
363     }
364
365     /**
366      * Returns the current tool bar alignment (if used).
367      *
368      * @return SWT.TOP or SWT.BOTTOM
369      * @since 3.3
370      */

371
372     public int getToolBarVerticalAlignment() {
373         return head.getToolBarAlignment();
374     }
375
376     /**
377      * Returns the menu manager that is used to manage title area drop-down menu
378      * items.
379      *
380      * @return title area drop-down menu manager
381      * @since 3.3
382      */

383     public IMenuManager getMenuManager() {
384         return head.getMenuManager();
385     }
386
387     /**
388      * Updates the local tool bar manager if used. Does nothing if local tool
389      * bar manager has not been created yet.
390      */

391     public void updateToolBar() {
392         head.updateToolBar();
393     }
394
395     /**
396      * Returns the container that occupies the head of the form (the form area
397      * above the body). Use this container as a parent for the head client.
398      *
399      * @return the head of the form.
400      * @since 3.2
401      */

402     public Composite getHead() {
403         return head;
404     }
405
406     /**
407      * Returns the optional head client if set.
408      *
409      * @return the head client or <code>null</code> if not set.
410      * @see #setHeadClient(Control)
411      * @since 3.2
412      */

413     public Control getHeadClient() {
414         return head.getHeadClient();
415     }
416
417     /**
418      * Sets the optional head client. Head client is placed after the form
419      * title. This option causes the tool bar to be placed in the second raw of
420      * the header (below the head client).
421      * <p>
422      * The head client must be a child of the composite returned by
423      * <code>getHead()</code> method.
424      *
425      * @param headClient
426      * the optional child of the head
427      * @since 3.2
428      */

429     public void setHeadClient(Control headClient) {
430         head.setHeadClient(headClient);
431         layout();
432     }
433
434     /**
435      * Returns the container that occupies the body of the form (the form area
436      * below the title). Use this container as a parent for the controls that
437      * should be in the form. No layout manager has been set on the form body.
438      *
439      * @return Returns the body of the form.
440      */

441     public Composite getBody() {
442         return body;
443     }
444
445     /**
446      * Tests if the background image is tiled to cover the entire area of the
447      * form heading.
448      *
449      * @return <code>true</code> if heading background image is tiled,
450      * <code>false</code> otherwise.
451      */

452     public boolean isBackgroundImageTiled() {
453         return head.isBackgroundImageTiled();
454     }
455
456     /**
457      * Sets whether the header background image is repeated to cover the entire
458      * heading area or not.
459      *
460      * @param backgroundImageTiled
461      * set <code>true</code> to tile the image, or
462      * <code>false</code> to paint the background image only once
463      * at 0,0
464      */

465     public void setBackgroundImageTiled(boolean backgroundImageTiled) {
466         head.setBackgroundImageTiled(backgroundImageTiled);
467     }
468
469     /**
470      * Returns the background image alignment.
471      *
472      * @deprecated due to the underlying widget limitations, background image is
473      * either painted at 0,0 and/or tiled.
474      * @return SWT.LEFT
475      */

476     public int getBackgroundImageAlignment() {
477         return SWT.LEFT;
478     }
479
480     /**
481      * Sets the background image alignment.
482      *
483      * @deprecated due to the underlying widget limitations, background image is
484      * always tiled and alignment cannot be controlled.
485      * @param backgroundImageAlignment
486      * The backgroundImageAlignment to set.
487      * @since 3.1
488      */

489     public void setBackgroundImageAlignment(int backgroundImageAlignment) {
490     }
491
492     /**
493      * Tests if background image is clipped.
494      *
495      * @deprecated due to the underlying widget limitations, background image is
496      * always clipped.
497      * @return true
498      * @since 3.1
499      */

500     public boolean isBackgroundImageClipped() {
501         return true;
502     }
503
504     /**
505      * Sets whether the background image is clipped.
506      *
507      * @deprecated due to the underlying widget limitations, background image is
508      * always clipped.
509      * @param backgroundImageClipped
510      * the value to set
511      * @since 3.1
512      */

513     public void setBackgroundImageClipped(boolean backgroundImageClipped) {
514     }
515
516     /**
517      * Tests if the form head separator is visible.
518      *
519      * @return <code>true</code> if the head/body separator is visible,
520      * <code>false</code> otherwise
521      * @since 3.2
522      */

523     public boolean isSeparatorVisible() {
524         return head.isSeparatorVisible();
525     }
526
527     /**
528      * If set, adds a separator between the head and body. Since 3.3, the colors
529      * that are used to render it are {@link IFormColors#H_BOTTOM_KEYLINE1} and
530      * {@link IFormColors#H_BOTTOM_KEYLINE2}.
531      *
532      * @param addSeparator
533      * <code>true</code> to make the separator visible,
534      * <code>false</code> otherwise.
535      * @since 3.2
536      */

537     public void setSeparatorVisible(boolean addSeparator) {
538         head.setSeparatorVisible(addSeparator);
539     }
540
541     /**
542      * Returns the color used to render the optional head separator. If gradient
543      * text background is used additional colors from the gradient will be used
544      * to render the separator.
545      *
546      * @return separator color or <code>null</code> if not set.
547      * @since 3.2
548      * @deprecated use <code>getHeadColor(IFormColors.H_BOTTOM_KEYLINE2)</code>
549      */

550
551     public Color getSeparatorColor() {
552         return head.getColor(IFormColors.H_BOTTOM_KEYLINE2);
553     }
554
555     /**
556      * Sets the color to be used to render the optional head separator.
557      *
558      * @param separatorColor
559      * the color to render the head separator or <code>null</code>
560      * to use the default color.
561      * @since 3.2
562      * @deprecated use
563      * <code>setHeadColor(IFormColors.H_BOTTOM_KEYLINE2, separatorColor)</code>
564      */

565     public void setSeparatorColor(Color separatorColor) {
566         head.putColor(IFormColors.H_BOTTOM_KEYLINE2, separatorColor);
567     }
568
569     /**
570      * Sets the color used to paint an aspect of the form heading.
571      *
572      * @param key
573      * a valid form heading color key as defined in
574      * {@link IFormColors}. Relevant keys all start with an H_
575      * prefix.
576      * @param color
577      * the color to use for the provided key
578      * @since 3.3
579      */

580
581     public void setHeadColor(String JavaDoc key, Color color) {
582         head.putColor(key, color);
583     }
584
585     /**
586      * Returns the color that is currently use to paint an aspect of the form
587      * heading, or <code>null</code> if not defined.
588      *
589      * @param key
590      * the color key
591      * @return the color object or <code>null</code> if not set.
592      * @since 3.3
593      */

594
595     public Color getHeadColor(String JavaDoc key) {
596         return head.getColor(key);
597     }
598
599     /**
600      * Sets the message for this form. Message text is rendered in the form head
601      * when shown.
602      *
603      * @param message
604      * the message, or <code>null</code> to clear the message
605      * @see #setMessage(String, int)
606      * @since 3.2
607      */

608     public void setMessage(String JavaDoc message) {
609         this.setMessage(message, 0, null);
610     }
611
612     /**
613      * Sets the message for this form with an indication of what type of message
614      * it is.
615      * <p>
616      * The valid message types are one of <code>NONE</code>,
617      * <code>INFORMATION</code>,<code>WARNING</code>, or
618      * <code>ERROR</code> defined in IMessageProvider interface.
619      * </p>
620      *
621      * @param newMessage
622      * the message, or <code>null</code> to clear the message
623      * @param newType
624      * the message type
625      * @see org.eclipse.jface.dialogs.IMessageProvider
626      * @since 3.2
627      */

628
629     public void setMessage(String JavaDoc newMessage, int newType) {
630         this.setMessage(newMessage, newType, null);
631     }
632
633     /**
634      * Sets the message for this form with an indication of what type of message
635      * it is.
636      * <p>
637      * The valid message types are one of <code>NONE</code>,
638      * <code>INFORMATION</code>,<code>WARNING</code>, or
639      * <code>ERROR</code> defined in IMessageProvider interface.
640      * </p>
641      * <p>
642      * In addition to the summary message, this method also sets an array of
643      * individual messages.
644      *
645      *
646      * @param newMessage
647      * the message, or <code>null</code> to clear the message
648      * @param newType
649      * the message type
650      * @param children
651      * the individual messages that contributed to the overall
652      * message
653      * @see org.eclipse.jface.dialogs.IMessageProvider
654      * @since 3.3
655      */

656
657     public void setMessage(String JavaDoc newMessage, int newType, IMessage[] children) {
658         head.showMessage(newMessage, newType, children);
659         layout();
660     }
661
662     /**
663      * Adds a message hyperlink listener. If at least one listener is present,
664      * messages will be rendered as hyperlinks.
665      *
666      * @param listener
667      * @see #removeMessageHyperlinkListener(IHyperlinkListener)
668      * @since 3.3
669      */

670     public void addMessageHyperlinkListener(IHyperlinkListener listener) {
671         head.addMessageHyperlinkListener(listener);
672     }
673
674     /**
675      * Remove the message hyperlink listener.
676      *
677      * @param listener
678      * @see #addMessageHyperlinkListener(IHyperlinkListener)
679      * @since 3.3
680      */

681     public void removeMessageHyperlinkListener(IHyperlinkListener listener) {
682         head.removeMessageHyperlinkListener(listener);
683     }
684
685     /**
686      * Tests if the form is in the 'busy' state. Busy form displays 'busy'
687      * animation in the area of the title image.
688      *
689      * @return <code>true</code> if busy, <code>false</code> otherwise.
690      * @since 3.2
691      */

692
693     public boolean isBusy() {
694         return head.isBusy();
695     }
696
697     /**
698      * Sets the form's busy state. Busy form will display 'busy' animation in
699      * the area of the title image.
700      *
701      * @param busy
702      * the form's busy state
703      * @since 3.2
704      */

705
706     public void setBusy(boolean busy) {
707         head.setBusy(busy);
708     }
709
710     /**
711      * Adds support for dragging items out of the form title area via a user
712      * drag-and-drop operation.
713      *
714      * @param operations
715      * a bitwise OR of the supported drag and drop operation types (
716      * <code>DROP_COPY</code>,<code>DROP_LINK</code>, and
717      * <code>DROP_MOVE</code>)
718      * @param transferTypes
719      * the transfer types that are supported by the drag operation
720      * @param listener
721      * the callback that will be invoked to set the drag data and to
722      * cleanup after the drag and drop operation finishes
723      * @see org.eclipse.swt.dnd.DND
724      * @since 3.3
725      */

726     public void addTitleDragSupport(int operations, Transfer[] transferTypes,
727             DragSourceListener listener) {
728         head.addDragSupport(operations, transferTypes, listener);
729     }
730
731     /**
732      * Adds support for dropping items into the form title area via a user
733      * drag-and-drop operation.
734      *
735      * @param operations
736      * a bitwise OR of the supported drag and drop operation types (
737      * <code>DROP_COPY</code>,<code>DROP_LINK</code>, and
738      * <code>DROP_MOVE</code>)
739      * @param transferTypes
740      * the transfer types that are supported by the drop operation
741      * @param listener
742      * the callback that will be invoked after the drag and drop
743      * operation finishes
744      * @see org.eclipse.swt.dnd.DND
745      * @since 3.3
746      */

747     public void addTitleDropSupport(int operations, Transfer[] transferTypes,
748             DropTargetListener listener) {
749         head.addDropSupport(operations, transferTypes, listener);
750     }
751
752     /*
753      * (non-Javadoc)
754      *
755      * @see org.eclipse.jface.dialogs.IMessageProvider#getMessage()
756      */

757     public String JavaDoc getMessage() {
758         return head.getMessage();
759     }
760
761     /*
762      * (non-Javadoc)
763      *
764      * @see org.eclipse.jface.dialogs.IMessageProvider#getMessageType()
765      */

766     public int getMessageType() {
767         return head.getMessageType();
768     }
769
770     /**
771      * Returns the children messages that the cause of the summary message
772      * currently set on the form.
773      *
774      * @return an array of children messages or <code>null</code> if not set.
775      * @see #setMessage(String, int, IMessage[])
776      * @since 3.3
777      */

778     public IMessage[] getChildrenMessages() {
779         return head.getChildrenMessages();
780     }
781
782     void setSelectionText(FormText text) {
783         if (selectionText != null && selectionText != text) {
784             selectionText.clearSelection();
785         }
786         this.selectionText = text;
787     }
788 }
Popular Tags