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.Group;
14 
15 import java.lang.all;
16 
17 
18 import org.eclipse.swt.SWT;
19 import org.eclipse.swt.internal.gtk.OS;
20 import org.eclipse.swt.graphics.Point;
21 import org.eclipse.swt.graphics.Rectangle;
22 import org.eclipse.swt.widgets.Composite;
23 
24 
25 /**
26  * Instances of this class provide an etched border
27  * with an optional title.
28  * <p>
29  * Shadow styles are hints and may not be honoured
30  * by the platform.  To create a group with the
31  * default shadow style for the platform, do not
32  * specify a shadow style.
33  * <dl>
34  * <dt><b>Styles:</b></dt>
35  * <dd>SHADOW_ETCHED_IN, SHADOW_ETCHED_OUT, SHADOW_IN, SHADOW_OUT, SHADOW_NONE</dd>
36  * <dt><b>Events:</b></dt>
37  * <dd>(none)</dd>
38  * </dl>
39  * <p>
40  * Note: Only one of the above styles may be specified.
41  * </p><p>
42  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
43  * </p>
44  * 
45  * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
46  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
47  */
48 public class Group : Composite {
49 
50     alias Composite.computeSize computeSize;
51     alias Composite.createHandle createHandle;
52     alias Composite.mnemonicHit mnemonicHit;
53     alias Composite.mnemonicMatch mnemonicMatch;
54     alias Composite.setBackgroundColor setBackgroundColor;
55     alias Composite.setForegroundColor setForegroundColor;
56 
57     GtkWidget* clientHandle_, labelHandle;
58     String text = "";
59 
60 /**
61  * Constructs a new instance of this class given its parent
62  * and a style value describing its behavior and appearance.
63  * <p>
64  * The style value is either one of the style constants defined in
65  * class <code>SWT</code> which is applicable to instances of this
66  * class, or must be built by <em>bitwise OR</em>'ing together
67  * (that is, using the <code>int</code> "|" operator) two or more
68  * of those <code>SWT</code> style constants. The class description
69  * lists the style constants that are applicable to the class.
70  * Style bits are also inherited from superclasses.
71  * </p>
72  *
73  * @param parent a composite control which will be the parent of the new instance (cannot be null)
74  * @param style the style of control to construct
75  *
76  * @exception IllegalArgumentException <ul>
77  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
78  * </ul>
79  * @exception SWTException <ul>
80  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
81  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
82  * </ul>
83  *
84  * @see SWT#SHADOW_ETCHED_IN
85  * @see SWT#SHADOW_ETCHED_OUT
86  * @see SWT#SHADOW_IN
87  * @see SWT#SHADOW_OUT
88  * @see SWT#SHADOW_NONE
89  * @see Widget#checkSubclass
90  * @see Widget#getStyle
91  */
92 public this (Composite parent, int style) {
93     super (parent, checkStyle (style));
94 }
95 
96 static int checkStyle (int style) {
97     style |= SWT.NO_FOCUS;
98     /*
99     * Even though it is legal to create this widget
100     * with scroll bars, they serve no useful purpose
101     * because they do not automatically scroll the
102     * widget's client area.  The fix is to clear
103     * the SWT style.
104     */
105     return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
106 }
107 
108 protected override void checkSubclass () {
109     if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
110 }
111 
112 override GtkWidget* clientHandle () {
113     return clientHandle_;
114 }
115 
116 public override Point computeSize (int wHint, int hHint, bool changed) {
117     Point size = super.computeSize(wHint, hHint, changed);
118     int width = computeNativeSize (handle, SWT.DEFAULT, SWT.DEFAULT, false).x;
119     size.x = Math.max (size.x, width);
120     return size;
121 }
122 public override Rectangle computeTrim (int x, int y, int width, int height) {
123     checkWidget();
124     forceResize ();
125     ptrdiff_t clientX = OS.GTK_WIDGET_X (clientHandle_);
126     ptrdiff_t clientY = OS.GTK_WIDGET_Y (clientHandle_);
127     x -= clientX;
128     y -= clientY;
129     width += clientX + clientX;
130     height += clientX + clientY;
131     return new Rectangle (x, y, width, height);
132 }
133 
134 override void createHandle(int index) {
135     state |= HANDLE | THEME_BACKGROUND;
136     fixedHandle = cast(GtkWidget*)OS.g_object_new (display.gtk_fixed_get_type (), null);
137     if (fixedHandle is null) error (SWT.ERROR_NO_HANDLES);
138     OS.gtk_fixed_set_has_window (cast(GtkFixed*)fixedHandle, true);
139     handle = OS.gtk_frame_new (null);
140     if (handle is null) error (SWT.ERROR_NO_HANDLES);
141     labelHandle = cast(GtkWidget*)OS.gtk_label_new (null);
142     if (labelHandle is null) error (SWT.ERROR_NO_HANDLES);
143     OS.g_object_ref (labelHandle);
144     OS.gtk_object_sink (cast(GtkObject*)labelHandle);
145     clientHandle_ = cast(GtkWidget*)OS.g_object_new (display.gtk_fixed_get_type (), null);
146     if (clientHandle_ is null) error (SWT.ERROR_NO_HANDLES);
147     OS.gtk_container_add (cast(GtkContainer*)fixedHandle, handle);
148     OS.gtk_container_add (cast(GtkContainer*)handle, clientHandle_);
149     if ((style & SWT.SHADOW_IN) !is 0) {
150         OS.gtk_frame_set_shadow_type (cast(GtkFrame*)handle, OS.GTK_SHADOW_IN);
151     }
152     if ((style & SWT.SHADOW_OUT) !is 0) {
153         OS.gtk_frame_set_shadow_type (cast(GtkFrame*)handle, OS.GTK_SHADOW_OUT);
154     }
155     if ((style & SWT.SHADOW_ETCHED_IN) !is 0) {
156         OS.gtk_frame_set_shadow_type (cast(GtkFrame*)handle, OS.GTK_SHADOW_ETCHED_IN);
157     }
158     if ((style & SWT.SHADOW_ETCHED_OUT) !is 0) {
159         OS.gtk_frame_set_shadow_type (cast(GtkFrame*)handle, OS.GTK_SHADOW_ETCHED_OUT);
160     }
161 }
162 
163 override void deregister () {
164     super.deregister ();
165     display.removeWidget (clientHandle_);
166     display.removeWidget (labelHandle);
167 }
168 
169 override void enableWidget (bool enabled) {
170     OS.gtk_widget_set_sensitive (labelHandle, enabled);
171 }
172 
173 override GtkWidget* eventHandle () {
174     return fixedHandle;
175 }
176 
177 override String getNameText () {
178     return getText ();
179 }
180 
181 /**
182  * Returns the receiver's text, which is the string that the
183  * is used as the <em>title</em>. If the text has not previously
184  * been set, returns an empty string.
185  *
186  * @return the text
187  *
188  * @exception SWTException <ul>
189  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
190  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
191  * </ul>
192  */
193 public String getText () {
194     checkWidget();
195     return text;
196 }
197 
198 override void hookEvents () {
199     super.hookEvents();
200     if (labelHandle !is null) {
201         OS.g_signal_connect_closure_by_id (labelHandle, display.signalIds [MNEMONIC_ACTIVATE], 0, display.closures [MNEMONIC_ACTIVATE], false);
202     }
203 }
204 
205 override bool mnemonicHit (wchar key) {
206     if (labelHandle is null) return false;
207     bool result = super.mnemonicHit (labelHandle, key);
208     if (result) setFocus ();
209     return result;
210 }
211 
212 override bool mnemonicMatch (wchar key) {
213     if (labelHandle is null) return false;
214     return mnemonicMatch (labelHandle, key);
215 }
216 
217 override GtkWidget* parentingHandle() {
218     return fixedHandle;
219 }
220 
221 override void register () {
222     super.register ();
223     display.addWidget (clientHandle_, this);
224     display.addWidget (labelHandle, this);
225 }
226 
227 override void releaseHandle () {
228     super.releaseHandle ();
229     clientHandle_ = labelHandle = null;
230 }
231 
232 override void releaseWidget () {
233     super.releaseWidget ();
234     if (labelHandle !is null) OS.g_object_unref (labelHandle);
235     text = null;
236 }
237 
238 override void setBackgroundColor (GdkColor* color) {
239     super.setBackgroundColor (color);
240     setBackgroundColor(fixedHandle, color);
241 }
242 
243 override void setFontDescription (PangoFontDescription* font) {
244     super.setFontDescription (font);
245     OS.gtk_widget_modify_font (labelHandle, font);
246 }
247 
248 override void setForegroundColor (GdkColor* color) {
249     super.setForegroundColor (color);
250     setForegroundColor (labelHandle, color);
251 }
252 
253 override void setOrientation () {
254     super.setOrientation ();
255     if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
256         OS.gtk_widget_set_direction (labelHandle, OS.GTK_TEXT_DIR_RTL);
257     }
258 }
259 
260 /**
261  * Sets the receiver's text, which is the string that will
262  * be displayed as the receiver's <em>title</em>, to the argument,
263  * which may not be null. The string may include the mnemonic character.
264  * </p>
265  * Mnemonics are indicated by an '&amp;' that causes the next
266  * character to be the mnemonic.  When the user presses a
267  * key sequence that matches the mnemonic, focus is assigned
268  * to the first child of the group. On most platforms, the
269  * mnemonic appears underlined but may be emphasised in a
270  * platform specific manner.  The mnemonic indicator character
271  * '&amp;' can be escaped by doubling it in the string, causing
272  * a single '&amp;' to be displayed.
273  * </p>
274  * @param string the new text
275  *
276  * @exception SWTException <ul>
277  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
278  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
279  * </ul>
280  */
281 public void setText (String string) {
282     checkWidget();
283     // SWT extension: allow null for zero length string
284     //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
285     text = string;
286     char [] chars = fixMnemonic (string);
287     OS.gtk_label_set_text_with_mnemonic (cast(GtkLabel*)labelHandle, chars.toStringzValidPtr());
288     if (string.length !is 0) {
289         if (OS.gtk_frame_get_label_widget (cast(GtkFrame*)handle) is null) {
290             OS.gtk_frame_set_label_widget (cast(GtkFrame*)handle, labelHandle);
291         }
292     } else {
293         OS.gtk_frame_set_label_widget (cast(GtkFrame*)handle, null);
294     }
295 }
296 
297 override void showWidget () {
298     super.showWidget ();
299     if (clientHandle_ !is null) OS.gtk_widget_show (clientHandle_);
300     if (labelHandle !is null) OS.gtk_widget_show (labelHandle);
301 }
302 }