]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/dialog.cpp
get the basics of a new scons build system together
[xonotic/netradiant.git] / radiant / dialog.cpp
1 /*\r
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.\r
4 \r
5 This file is part of GtkRadiant.\r
6 \r
7 GtkRadiant is free software; you can redistribute it and/or modify\r
8 it under the terms of the GNU General Public License as published by\r
9 the Free Software Foundation; either version 2 of the License, or\r
10 (at your option) any later version.\r
11 \r
12 GtkRadiant is distributed in the hope that it will be useful,\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 GNU General Public License for more details.\r
16 \r
17 You should have received a copy of the GNU General Public License\r
18 along with GtkRadiant; if not, write to the Free Software\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
20 */\r
21 \r
22 //\r
23 // Base dialog class, provides a way to run modal dialogs and\r
24 // set/get the widget values in member variables.\r
25 //\r
26 // Leonardo Zide (leo@lokigames.com)\r
27 //\r
28 \r
29 #include "stdafx.h"\r
30 #include <gtk/gtk.h>\r
31 #include <stdlib.h>\r
32 #include <stdio.h>\r
33 \r
34 typedef struct\r
35 {\r
36   GtkObject     *object;\r
37   void          *buffer;\r
38   DLG_DATA_TYPE type;\r
39 } DLG_DATA;\r
40 \r
41 // =============================================================================\r
42 // Dialog class\r
43 \r
44 Dialog::Dialog ()\r
45 {\r
46   m_pDataList = (GSList*)NULL;\r
47   m_nReturn = IDCANCEL;\r
48   m_bNeedBuild = true;\r
49   m_nLoop = 0;\r
50 }\r
51 \r
52 Dialog::~Dialog ()\r
53 {\r
54   while (m_pDataList)\r
55   {\r
56     free (m_pDataList->data);\r
57     m_pDataList = g_slist_remove (m_pDataList, m_pDataList->data);\r
58   }\r
59 \r
60   if (m_pWidget != NULL)\r
61     gtk_widget_destroy (m_pWidget);\r
62 }\r
63 \r
64 // i suspect that this is redundant - gtk manages to remember the data stored in its widgets across a hide/show\r
65 void Dialog::ShowDlg ()\r
66 {\r
67   Create ();\r
68   UpdateData (FALSE);\r
69   gtk_widget_show (m_pWidget);\r
70 }\r
71 \r
72 void Dialog::HideDlg ()\r
73 {\r
74   UpdateData (TRUE);\r
75   gtk_widget_hide (m_pWidget);\r
76 }\r
77 \r
78 static gint delete_event_callback(GtkWidget *widget, GdkEvent* event, gpointer data)\r
79 {\r
80   reinterpret_cast<Dialog*>(data)->HideDlg();\r
81   reinterpret_cast<Dialog*>(data)->EndModal(IDCANCEL);\r
82   return TRUE;\r
83 }\r
84 \r
85 void Dialog::Create ()\r
86 {\r
87   if (m_bNeedBuild)\r
88   {\r
89     m_pWidget = gtk_window_new (GTK_WINDOW_TOPLEVEL);\r
90     gtk_signal_connect (GTK_OBJECT (m_pWidget), "delete_event",\r
91                         GTK_SIGNAL_FUNC (delete_event_callback), this);\r
92     gtk_signal_connect (GTK_OBJECT (m_pWidget), "destroy",\r
93                         GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);\r
94     g_object_set_data (G_OBJECT (m_pWidget), "loop", &m_nLoop);\r
95     g_object_set_data (G_OBJECT (m_pWidget), "ret", &m_nReturn);\r
96 \r
97     BuildDialog ();\r
98     m_bNeedBuild = false;\r
99   }\r
100 }\r
101 \r
102 void Dialog::Destroy ()\r
103 {\r
104   if (m_pWidget != NULL)\r
105   {\r
106     gtk_widget_destroy (m_pWidget);\r
107     m_pWidget = NULL;\r
108   }\r
109 }\r
110 \r
111 void Dialog::AddDialogData (GtkObject *object, void *buf, DLG_DATA_TYPE type)\r
112 {\r
113   DLG_DATA *data;\r
114 \r
115   data = (DLG_DATA*)qmalloc (sizeof(DLG_DATA));\r
116   data->object = object;\r
117   data->buffer = buf;\r
118   data->type = type;\r
119 \r
120   m_pDataList = g_slist_append (m_pDataList, data);\r
121 }\r
122 \r
123 void Dialog::AddModalButton (GtkWidget *widget, int ret)\r
124 {\r
125   gtk_signal_connect (GTK_OBJECT (widget), "clicked",\r
126                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (ret));\r
127 }\r
128 \r
129 void Dialog::UpdateData (bool retrieve)\r
130   {\r
131   DLG_DATA *data;\r
132   GSList *lst;\r
133   char buf[32];\r
134   \r
135   if (retrieve)\r
136     {\r
137     for (lst = m_pDataList; lst != NULL; lst = g_slist_next (lst))\r
138       {\r
139       data = (DLG_DATA*)lst->data;\r
140       \r
141       switch (data->type)\r
142         {\r
143         case DLG_CHECK_BOOL:\r
144           *(bool*)data->buffer = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->object));\r
145           break;\r
146         case DLG_RADIO_INT:\r
147           {\r
148           GSList *radio = gtk_radio_button_group (GTK_RADIO_BUTTON (data->object));\r
149           *(int*)data->buffer = g_slist_length (radio) - 1;\r
150           for (; radio; radio = g_slist_next (radio))\r
151             if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio->data)))\r
152               break;\r
153             else\r
154               (*(int*)data->buffer)--;\r
155           } break;\r
156         case DLG_ENTRY_TEXT:\r
157           {\r
158           const char *txt;\r
159           Str* str;\r
160           str = (Str*)data->buffer;\r
161           txt = gtk_entry_get_text (GTK_ENTRY (data->object));\r
162           *str = txt;\r
163           } break;\r
164         case DLG_ENTRY_FLOAT:\r
165           *(float*)data->buffer = atof (gtk_entry_get_text (GTK_ENTRY (data->object)));\r
166           break;\r
167         case DLG_ENTRY_INT:\r
168           *(int*)data->buffer = atoi (gtk_entry_get_text (GTK_ENTRY (data->object)));\r
169           break;\r
170         case DLG_SPIN_FLOAT:\r
171           *(float*)data->buffer = gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON (data->object));\r
172           break;\r
173         case DLG_SPIN_INT:\r
174           *(int*)data->buffer = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (data->object));\r
175           break;\r
176         case DLG_ADJ_INT:\r
177           *(int*)data->buffer = (int) GTK_ADJUSTMENT (data->object)->value;\r
178           break;\r
179         case DLG_COMBO_INT:\r
180           {\r
181           GList *lst = GTK_LIST (GTK_COMBO (data->object)->list)->children;\r
182           char *label;\r
183           const char *entry;\r
184           int i;\r
185           \r
186           *(int*)data->buffer = -1;\r
187           entry = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (data->object)->entry));\r
188           \r
189           for (i = 0; lst != NULL; lst = g_list_next (lst))\r
190             {\r
191             gtk_label_get (GTK_LABEL (GTK_BIN (lst->data)->child), &label);\r
192             \r
193             if (strcmp (label, entry) == 0)\r
194               {\r
195               *(int*)data->buffer = i;\r
196               break;\r
197               }\r
198             i++;\r
199             }\r
200           }     break;\r
201         }\r
202       }\r
203     }\r
204   else\r
205     {\r
206     for (lst = m_pDataList; lst != NULL; lst = g_slist_next (lst))\r
207       {\r
208       data = (DLG_DATA*)lst->data;\r
209 \r
210       switch (data->type)\r
211         {\r
212         case DLG_CHECK_BOOL:\r
213           gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->object), *(bool*)data->buffer);\r
214           break;\r
215         case DLG_RADIO_INT:\r
216           {\r
217           GSList *radio = gtk_radio_button_group (GTK_RADIO_BUTTON (data->object));\r
218           gpointer btn =  g_slist_nth_data (radio, g_slist_length (radio) - (*(int*)data->buffer) - 1);\r
219           gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (btn), TRUE);\r
220           } break;\r
221         case DLG_ENTRY_TEXT:\r
222           {\r
223           Str* str;\r
224           str = (Str*)data->buffer;\r
225           const char *txt = str->GetBuffer ();\r
226           gtk_entry_set_text (GTK_ENTRY (data->object), txt);\r
227           } break;\r
228         case DLG_ENTRY_FLOAT:\r
229           sprintf (buf, "%g", (*(float*)data->buffer));\r
230           gtk_entry_set_text (GTK_ENTRY (data->object), buf);\r
231           break;\r
232         case DLG_ENTRY_INT:\r
233           sprintf (buf, "%d", (*(int*)data->buffer));\r
234           gtk_entry_set_text (GTK_ENTRY (data->object), buf);\r
235           break;\r
236         case DLG_SPIN_FLOAT:\r
237           gtk_spin_button_set_value (GTK_SPIN_BUTTON (data->object), (*(float*)data->buffer));\r
238           break;\r
239         case DLG_SPIN_INT:\r
240           gtk_spin_button_set_value (GTK_SPIN_BUTTON (data->object), (*(int*)data->buffer));\r
241           break;\r
242         case DLG_ADJ_INT:\r
243           gtk_adjustment_set_value (GTK_ADJUSTMENT (data->object), (*(int*)data->buffer));\r
244           break;\r
245         case DLG_COMBO_INT:\r
246           {\r
247           GList *lst = GTK_LIST (GTK_COMBO (data->object)->list)->children;\r
248           char *entry = "";\r
249           \r
250           if (*(int*)data->buffer != -1)\r
251             {\r
252             lst = g_list_nth (lst, *(int*)data->buffer);\r
253             if (lst != NULL)\r
254               gtk_label_get (GTK_LABEL (GTK_BIN (lst->data)->child), &entry);\r
255             }\r
256           \r
257           gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (data->object)->entry), entry);\r
258           }     break;\r
259         }\r
260       }\r
261     }\r
262 }\r
263 \r
264 void Dialog::EndModal (int code)\r
265 {\r
266   m_nLoop = 0;\r
267   m_nReturn = code;\r
268 }\r
269 \r
270 int Dialog::DoModal ()\r
271 {\r
272   Create ();\r
273   UpdateData (FALSE);\r
274 \r
275   PreModal();\r
276 \r
277   gtk_grab_add (m_pWidget);\r
278   gtk_widget_show (m_pWidget);\r
279 \r
280   m_nLoop = 1;\r
281   while (m_nLoop)\r
282     gtk_main_iteration ();\r
283 \r
284   if (m_pWidget != NULL)\r
285   {\r
286     UpdateData (TRUE);\r
287 \r
288     gtk_grab_remove (m_pWidget);\r
289     gtk_widget_hide (m_pWidget);\r
290   }\r
291   PostModal (m_nReturn);\r
292 \r
293   return m_nReturn;\r
294 }\r
295 \r