1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  * Port to the D programming language:
11  *     Frank Benoit <benoit@tionex.de>
12  *******************************************************************************/
13 module org.eclipse.swt.widgets.TabItem;
14 
15 import java.lang.all;
16 
17 
18 
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.SWTException;
21 import org.eclipse.swt.graphics.Image;
22 import org.eclipse.swt.graphics.Rectangle;
23 import org.eclipse.swt.internal.gtk.OS;
24 import org.eclipse.swt.widgets.Item;
25 import org.eclipse.swt.widgets.Control;
26 import org.eclipse.swt.widgets.TabFolder;
27 import org.eclipse.swt.widgets.ImageList;
28 
29 /**
30  * Instances of this class represent a selectable user interface object
31  * corresponding to a tab for a page in a tab folder.
32  * <dl>
33  * <dt><b>Styles:</b></dt>
34  * <dd>(none)</dd>
35  * <dt><b>Events:</b></dt>
36  * <dd>(none)</dd>
37  * </dl>
38  * <p>
39  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
40  * </p>
41  *
42  * @see <a href="http://www.eclipse.org/swt/snippets/#tabfolder">TabFolder, TabItem snippets</a>
43  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
44  */
45 public class TabItem : Item {
46 
47     alias Item.setForegroundColor setForegroundColor;
48 
49     GtkWidget* labelHandle, imageHandle, pageHandle;
50     Control control;
51     TabFolder parent;
52     String toolTipText;
53 
54 /**
55  * Constructs a new instance of this class given its parent
56  * (which must be a <code>TabFolder</code>) and a style value
57  * describing its behavior and appearance. The item is added
58  * to the end of the items maintained by its parent.
59  * <p>
60  * The style value is either one of the style constants defined in
61  * class <code>SWT</code> which is applicable to instances of this
62  * class, or must be built by <em>bitwise OR</em>'ing together
63  * (that is, using the <code>int</code> "|" operator) two or more
64  * of those <code>SWT</code> style constants. The class description
65  * lists the style constants that are applicable to the class.
66  * Style bits are also inherited from superclasses.
67  * </p>
68  *
69  * @param parent a composite control which will be the parent of the new instance (cannot be null)
70  * @param style the style of control to construct
71  *
72  * @exception IllegalArgumentException <ul>
73  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
74  * </ul>
75  * @exception SWTException <ul>
76  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
77  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
78  * </ul>
79  *
80  * @see SWT
81  * @see Widget#checkSubclass
82  * @see Widget#getStyle
83  */
84 public this (TabFolder parent, int style) {
85     super (parent, style);
86     this.parent = parent;
87     createWidget (parent.getItemCount ());
88 }
89 
90 /**
91  * Constructs a new instance of this class given its parent
92  * (which must be a <code>TabFolder</code>), a style value
93  * describing its behavior and appearance, and the index
94  * at which to place it in the items maintained by its parent.
95  * <p>
96  * The style value is either one of the style constants defined in
97  * class <code>SWT</code> which is applicable to instances of this
98  * class, or must be built by <em>bitwise OR</em>'ing together
99  * (that is, using the <code>int</code> "|" operator) two or more
100  * of those <code>SWT</code> style constants. The class description
101  * lists the style constants that are applicable to the class.
102  * Style bits are also inherited from superclasses.
103  * </p>
104  *
105  * @param parent a composite control which will be the parent of the new instance (cannot be null)
106  * @param style the style of control to construct
107  * @param index the zero-relative index to store the receiver in its parent
108  *
109  * @exception IllegalArgumentException <ul>
110  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
111  *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
112  * </ul>
113  * @exception SWTException <ul>
114  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
115  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
116  * </ul>
117  *
118  * @see SWT
119  * @see Widget#checkSubclass
120  * @see Widget#getStyle
121  */
122 public this (TabFolder parent, int style, int index) {
123     super (parent, style);
124     this.parent = parent;
125     createWidget (index);
126 }
127 
128 protected override void checkSubclass () {
129     if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
130 }
131 
132 override void createWidget (int index) {
133     parent.createItem (this, index);
134     setOrientation ();
135     hookEvents ();
136     register ();
137     text = "";
138 }
139 
140 override void deregister() {
141     super.deregister ();
142     if (labelHandle !is null) display.removeWidget (labelHandle);
143 }
144 
145 override void destroyWidget () {
146     parent.destroyItem (this);
147     releaseHandle ();
148 }
149 
150 /**
151  * Returns a rectangle describing the receiver's size and location
152  * relative to its parent.
153  *
154  * @return the receiver's bounding rectangle
155  *
156  * @exception SWTException <ul>
157  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
158  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
159  * </ul>
160  * 
161  * @since 3.4
162  */
163 public Rectangle getBounds () {
164     checkWidget();
165     int x = OS.GTK_WIDGET_X (handle);
166     int y = OS.GTK_WIDGET_Y (handle);
167     int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (handle);
168     int height = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (handle);
169     if ((parent.style & SWT.MIRRORED) !is 0) x = parent.getClientWidth () - width - x;
170     return new Rectangle (x, y, width, height);
171 }
172 
173 /**
174  * Returns the control that is used to fill the client area of
175  * the tab folder when the user selects the tab item.  If no
176  * control has been set, return <code>null</code>.
177  * <p>
178  * @return the control
179  *
180  * @exception SWTException <ul>
181  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
182  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
183  * </ul>
184  */
185 public Control getControl () {
186     checkWidget ();
187     return control;
188 }
189 
190 /**
191  * Returns the receiver's parent, which must be a <code>TabFolder</code>.
192  *
193  * @return the receiver's parent
194  *
195  * @exception SWTException <ul>
196  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
197  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
198  * </ul>
199  */
200 public TabFolder getParent () {
201     checkWidget ();
202     return parent;
203 }
204 
205 /**
206  * Returns the receiver's tool tip text, or null if it has
207  * not been set.
208  *
209  * @return the receiver's tool tip text
210  *
211  * @exception SWTException <ul>
212  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
213  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
214  * </ul>
215  */
216 public String getToolTipText () {
217     checkWidget ();
218     return toolTipText;
219 }
220 
221 override int gtk_enter_notify_event (GtkWidget* widget, GdkEventCrossing* event) {
222     parent.gtk_enter_notify_event (widget, event);
223     return 0;
224 }
225 
226 override int gtk_mnemonic_activate (GtkWidget* widget, ptrdiff_t arg1) {
227     return parent.gtk_mnemonic_activate (widget, arg1);
228 }
229 
230 override void hookEvents () {
231     super.hookEvents ();
232     if (labelHandle !is null) OS.g_signal_connect_closure_by_id (labelHandle, display.signalIds [MNEMONIC_ACTIVATE], 0, display.closures [MNEMONIC_ACTIVATE], false);
233     OS.g_signal_connect_closure_by_id (handle, display.signalIds [ENTER_NOTIFY_EVENT], 0, display.closures [ENTER_NOTIFY_EVENT], false);
234 }
235 
236 override void register () {
237     super.register ();
238     if (labelHandle !is null) display.addWidget (labelHandle, this);
239 }
240 
241 override void releaseHandle () {
242     super.releaseHandle ();
243     pageHandle = labelHandle = imageHandle = null;
244     parent = null;
245 }
246 
247 override void releaseParent () {
248     super.releaseParent ();
249     int index = parent.indexOf (this);
250     if (index is parent.getSelectionIndex ()) {
251         if (control !is null) control.setVisible (false);
252     }
253 }
254 
255 /**
256  * Sets the control that is used to fill the client area of
257  * the tab folder when the user selects the tab item.
258  * <p>
259  * @param control the new control (or null)
260  *
261  * @exception IllegalArgumentException <ul>
262  *    <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
263  *    <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li>
264  * </ul>
265  * @exception SWTException <ul>
266  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
267  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
268  * </ul>
269  */
270 public void setControl (Control control) {
271     checkWidget ();
272     if (control !is null) {
273         if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
274         if (control.parent !is parent) error (SWT.ERROR_INVALID_PARENT);
275     }
276     Control oldControl = this.control, newControl = control;
277     this.control = control;
278     int index = parent.indexOf (this);
279     if (index !is parent.getSelectionIndex ()) {
280         if (newControl !is null) newControl.setVisible (false);
281         return;
282     }
283     if (newControl !is null) {
284         newControl.setBounds (parent.getClientArea ());
285         newControl.setVisible (true);
286     }
287     if (oldControl !is null) oldControl.setVisible (false);
288 }
289 
290 void setFontDescription (PangoFontDescription* font) {
291     OS.gtk_widget_modify_font (labelHandle, font);
292     OS.gtk_widget_modify_font (imageHandle, font);
293 }
294 
295 void setForegroundColor (GdkColor* color) {
296     /* Don't set the color in vbox handle (it doesn't draw) */
297     setForegroundColor (labelHandle, color);
298     setForegroundColor (imageHandle, color);
299 }
300 
301 public override void setImage (Image image) {
302     checkWidget ();
303     super.setImage (image);
304     if (image !is null) {
305         ImageList imageList = parent.imageList;
306         if (imageList is null) imageList = parent.imageList = new ImageList ();
307         int imageIndex = imageList.indexOf (image);
308         if (imageIndex is -1) {
309             imageIndex = imageList.add (image);
310         } else {
311             imageList.put (imageIndex, image);
312         }
313         auto pixbuf = imageList.getPixbuf (imageIndex);
314         OS.gtk_image_set_from_pixbuf (imageHandle, pixbuf);
315         OS.gtk_widget_show (imageHandle);
316     } else {
317         OS.gtk_image_set_from_pixbuf (imageHandle, null);
318         OS.gtk_widget_hide (imageHandle);
319     }
320 }
321 
322 override void setOrientation () {
323     if ((parent.style & SWT.RIGHT_TO_LEFT) !is 0) {
324         if (handle !is null) OS.gtk_widget_set_direction (handle, OS.GTK_TEXT_DIR_RTL);
325         if (labelHandle !is null) OS.gtk_widget_set_direction (labelHandle, OS.GTK_TEXT_DIR_RTL);
326         if (imageHandle !is null) OS.gtk_widget_set_direction (imageHandle, OS.GTK_TEXT_DIR_RTL);
327         if (pageHandle !is null) OS.gtk_widget_set_direction (pageHandle, OS.GTK_TEXT_DIR_RTL);
328     }
329 }
330 
331 /**
332  * Sets the receiver's text.  The string may include
333  * the mnemonic character.
334  * </p>
335  * <p>
336  * Mnemonics are indicated by an '&amp;' that causes the next
337  * character to be the mnemonic.  When the user presses a
338  * key sequence that matches the mnemonic, a selection
339  * event occurs. On most platforms, the mnemonic appears
340  * underlined but may be emphasised in a platform specific
341  * manner.  The mnemonic indicator character '&amp;' can be
342  * escaped by doubling it in the string, causing a single
343  * '&amp;' to be displayed.
344  * </p>
345  *
346  * @param string the new text
347  *
348  * @exception SWTException <ul>
349  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
350  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
351  * </ul>
352  *
353  */
354 public override void setText (String string) {
355     checkWidget ();
356     // SWT extension: allow null for zero length string
357     //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
358     super.setText (string);
359     char [] chars = fixMnemonic (string);
360     OS.gtk_label_set_text_with_mnemonic (labelHandle, chars.toStringzValidPtr() );
361     if (string.length !is 0) {
362         OS.gtk_widget_show (labelHandle);
363     } else {
364         OS.gtk_widget_hide (labelHandle);
365     }
366 }
367 
368 /**
369  * Sets the receiver's tool tip text to the argument, which
370  * may be null indicating that no tool tip text should be shown.
371  *
372  * @param string the new tool tip text (or null)
373  *
374  * @exception SWTException <ul>
375  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
376  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
377  * </ul>
378  */
379 public void setToolTipText (String string) {
380     checkWidget ();
381     toolTipText = string;
382 }
383 
384 }