ok
[xonotic/netradiant.git] / contrib / bkgrnd2d / dialog.cpp
1 /*\r
2 Copyright (C) 2003 Reed Mideke.\r
3 \r
4 This file is part of GtkRadiant.\r
5 \r
6 GtkRadiant is free software; you can redistribute it and/or modify\r
7 it under the terms of the GNU General Public License as published by\r
8 the Free Software Foundation; either version 2 of the License, or\r
9 (at your option) any later version.\r
10 \r
11 GtkRadiant is distributed in the hope that it will be useful,\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 GNU General Public License for more details.\r
15 \r
16 You should have received a copy of the GNU General Public License\r
17 along with GtkRadiant; if not, write to the Free Software\r
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
19 */\r
20 \r
21 //\r
22 // bkgrnd2d Plugin dialog\r
23 //\r
24 // Code by reyalP aka Reed Mideke\r
25 //\r
26 // Based on various other plugins\r
27 //\r
28 \r
29 #include <gtk/gtk.h>\r
30 \r
31 #include "bkgrnd2d.h"\r
32 #include "dialog.h"\r
33 \r
34 // spaces to make label nice and big\r
35 #define NO_FILE_MSG "        (no file loaded)        "\r
36 \r
37 static GtkWidget *pDialogWnd;\r
38 static GtkWidget *pNotebook;\r
39 static GtkTooltips *pTooltips;\r
40 \r
41 class CBackgroundDialogPage\r
42 {\r
43 private:\r
44         GtkWidget *m_pWidget;\r
45         GtkWidget *m_pTabLabel;\r
46         GtkWidget *m_pFileLabel;\r
47         GtkWidget *m_pPosLabel;\r
48         VIEWTYPE m_vt;\r
49         bool m_bValidFile;\r
50 \r
51 public:\r
52         CBackgroundImage *m_pImage;\r
53         CBackgroundDialogPage( VIEWTYPE vt );\r
54         void Append(GtkWidget *notebook);\r
55         void Browse();\r
56         void Reload();\r
57         void SetPosLabel();\r
58 //  ~BackgroundDialogPage();\r
59 };\r
60 \r
61 \r
62 // dialog page callbacks\r
63 static void browse_callback( GtkWidget *widget, gpointer data )\r
64 {\r
65         ((CBackgroundDialogPage *)data)->Browse();\r
66 }\r
67 \r
68 static void reload_callback( GtkWidget *widget, gpointer data )\r
69 {\r
70         ((CBackgroundDialogPage *)data)->Reload();\r
71 }\r
72 \r
73 static void size_sel_callback( GtkWidget *widget, gpointer data )\r
74 {\r
75         CBackgroundDialogPage *pPage = (CBackgroundDialogPage *)data;\r
76         if (pPage->m_pImage->SetExtentsSel())\r
77                 pPage->SetPosLabel();\r
78 }\r
79 \r
80 static void size_mm_callback( GtkWidget *widget, gpointer data )\r
81 {\r
82         CBackgroundDialogPage *pPage = (CBackgroundDialogPage *)data;\r
83         if(pPage->m_pImage->SetExtentsMM())\r
84                 pPage->SetPosLabel();\r
85 }\r
86 \r
87 static void alpha_adjust_callback( GtkWidget *widget, gpointer data )\r
88 {\r
89         CBackgroundDialogPage *pPage = (CBackgroundDialogPage *)data;\r
90         pPage->m_pImage->m_alpha = (float)gtk_range_get_value (GTK_RANGE(widget));\r
91         g_FuncTable.m_pfnSysUpdateWindows(W_XY);\r
92 }\r
93 \r
94 void CBackgroundDialogPage::Reload()\r
95 {\r
96         if(m_bValidFile)\r
97                 m_pImage->Load(gtk_label_get_text(GTK_LABEL(m_pFileLabel)));\r
98 }\r
99 \r
100 void CBackgroundDialogPage::Browse()\r
101 {\r
102         char browsedir[PATH_MAX];\r
103         const char *ct;\r
104         const char *newfile;\r
105         char *t;\r
106         \r
107         //TODO GetMapName saves the map. eeep!\r
108         //also with no map, returns unnamed.map, otherwise returns full path\r
109 //      Syn_Printf(MSG_PREFIX "GetMapName() %s\n",\r
110 //                              g_FuncTable.m_pfnGetMapName());\r
111         \r
112         ct = g_FuncTable.m_pfnReadProjectKey("basepath");\r
113         // TODO shouldn't need this stuff\r
114         if(!ct || !strlen(ct)) {\r
115                 Syn_Printf(MSG_PREFIX "basepath = NULL or empty\n");\r
116                 return;\r
117         }\r
118         Syn_Printf(MSG_PREFIX "basepath: %s\n",ct);\r
119         if(strlen(ct) >= PATH_MAX) {\r
120                 Syn_Printf(MSG_PREFIX "base game dir too long\n");\r
121                 return;\r
122         }\r
123 \r
124         strcpy(browsedir,ct);\r
125         // make sure we have a trailing / \r
126         if(browsedir[strlen(browsedir) - 1] != '/')\r
127                 strcat(browsedir,"/");\r
128 \r
129         //if we dont have a file yet, don't try to use it for default dir\r
130         if(m_bValidFile) {\r
131         // filename should always be a nice clean unix style relative path\r
132                 ct = gtk_label_get_text(GTK_LABEL(m_pFileLabel));\r
133                 strcat(browsedir,ct);\r
134                 Syn_Printf(MSG_PREFIX "full path: %s\n",browsedir);\r
135 \r
136                 // lop off the file part\r
137                 t = browsedir + strlen(browsedir) - 1;\r
138                 while (t != browsedir && *t != '/') \r
139                         t--;\r
140                 *t = 0;\r
141         }\r
142         Syn_Printf(MSG_PREFIX "browse directory %s\n",browsedir);\r
143         \r
144 //does NOT need freeing contrary to include/qerplugin.h comments\r
145 //TODO bug/patch for comments\r
146 //TODO patern gets fucked up sometimes if empty\r
147 //http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=915\r
148         newfile = g_FuncTable.m_pfnFileDialog(pDialogWnd,TRUE,\r
149                                                                   "Load Background Image",browsedir,FILETYPE_KEY);\r
150         if(!newfile) {\r
151                 Syn_Printf(MSG_PREFIX "newfile = NULL\n");\r
152                 return;\r
153         }\r
154         Syn_Printf(MSG_PREFIX "newfile: %s\n",newfile);\r
155         newfile = g_FileSystemTable.m_pfnExtractRelativePath(newfile);\r
156 \r
157         if(!newfile) {\r
158                 Syn_Printf(MSG_PREFIX "newfile = NULL\n");\r
159                 return;\r
160         }\r
161         Syn_Printf(MSG_PREFIX "newfile: %s\n",newfile);\r
162 \r
163         if(m_pImage->Load(newfile)) {\r
164                 m_bValidFile = true;\r
165                 gtk_label_set_text(GTK_LABEL(m_pFileLabel),newfile);\r
166         }\r
167 }\r
168 \r
169 void CBackgroundDialogPage::SetPosLabel()\r
170 {\r
171         char s[64];\r
172         // TODO no snprintf ?\r
173         sprintf(s, "Size/Position (%d,%d) (%d,%d)",(int)(m_pImage->m_xmin),\r
174                         (int)(m_pImage->m_ymin),(int)(m_pImage->m_xmax),(int)(m_pImage->m_ymax));\r
175         gtk_label_set_text(GTK_LABEL(m_pPosLabel),s);\r
176 }\r
177 \r
178 CBackgroundDialogPage::CBackgroundDialogPage(VIEWTYPE vt )\r
179 {\r
180         GtkWidget *frame;\r
181         GtkWidget *hbox;\r
182         GtkWidget *w;\r
183 \r
184         m_vt = vt;\r
185 \r
186         m_bValidFile = false;\r
187 \r
188         switch(m_vt)\r
189         {\r
190                 case XY:\r
191                         m_pTabLabel = gtk_label_new("X/Y");\r
192                         m_pImage = &backgroundXY;\r
193                         break;\r
194                 case XZ:\r
195                         m_pTabLabel = gtk_label_new("X/Z");\r
196                         m_pImage = &backgroundXZ;\r
197                         break;\r
198                 case YZ:\r
199                         m_pTabLabel = gtk_label_new("Y/Z");\r
200                         m_pImage = &backgroundYZ;\r
201                         break;\r
202         }\r
203 // A vbox to hold everything\r
204         m_pWidget = gtk_vbox_new(FALSE,0); \r
205 // Frame for file row\r
206         frame = gtk_frame_new("File");\r
207         gtk_box_pack_start (GTK_BOX (m_pWidget),frame, FALSE, FALSE, 2);\r
208 \r
209 // hbox for first row\r
210         hbox = gtk_hbox_new(FALSE,5);\r
211         gtk_container_set_border_width(GTK_CONTAINER (hbox),4);\r
212         gtk_container_add (GTK_CONTAINER (frame), hbox);\r
213 \r
214 // label to display filename\r
215         m_pFileLabel  = gtk_label_new(NO_FILE_MSG);\r
216         gtk_label_set_selectable(GTK_LABEL(m_pFileLabel),TRUE);\r
217 //TODO set min size ? done with spaces right now\r
218         gtk_box_pack_start (GTK_BOX (hbox),m_pFileLabel, TRUE, TRUE, 5);\r
219 \r
220   gtk_widget_show (m_pFileLabel);\r
221 \r
222         w = gtk_button_new_with_label ("Browse...");\r
223         g_signal_connect (G_OBJECT (w), "clicked", G_CALLBACK (browse_callback),\r
224                                                               (gpointer)this);\r
225         gtk_box_pack_start (GTK_BOX (hbox),w, FALSE, FALSE, 5);\r
226         gtk_tooltips_set_tip (pTooltips, w, "Select a file", NULL);\r
227   gtk_widget_show (w);\r
228         \r
229         w = gtk_button_new_with_label ("Reload");\r
230         g_signal_connect (G_OBJECT (w), "clicked", G_CALLBACK (reload_callback),\r
231                                                               (gpointer)this);\r
232         // TODO disable until we have file\r
233         // gtk_widget_set_sensitive(w,FALSE);\r
234         gtk_tooltips_set_tip (pTooltips, w, "Reload current file", NULL);\r
235         gtk_box_pack_start (GTK_BOX (hbox),w, FALSE, FALSE, 5);\r
236   gtk_widget_show (w);\r
237 \r
238         gtk_widget_show (hbox);\r
239         gtk_widget_show (frame);\r
240 \r
241 // second row (rendering options)\r
242         frame = gtk_frame_new("Rendering");\r
243         gtk_box_pack_start (GTK_BOX (m_pWidget),frame, FALSE, FALSE, 2);\r
244 \r
245         hbox = gtk_hbox_new(FALSE,5);\r
246         gtk_container_set_border_width(GTK_CONTAINER (hbox),4);\r
247         gtk_container_add (GTK_CONTAINER (frame), hbox);\r
248 \r
249         w = gtk_label_new("Vertex alpha:");\r
250         gtk_box_pack_start (GTK_BOX (hbox),w, FALSE, FALSE, 5);\r
251   gtk_widget_show (w);\r
252 \r
253         w = gtk_hscale_new_with_range(0.0,1.0,0.01);\r
254         gtk_range_set_value(GTK_RANGE(w),0.5);\r
255         gtk_scale_set_value_pos(GTK_SCALE(w),GTK_POS_LEFT);\r
256         g_signal_connect (G_OBJECT (w), "value-changed",\r
257                           G_CALLBACK (alpha_adjust_callback), (gpointer)this);\r
258         gtk_box_pack_start (GTK_BOX (hbox),w, TRUE, TRUE, 5);\r
259         gtk_tooltips_set_tip (pTooltips, w, "Set image transparancy", NULL);\r
260   gtk_widget_show (w);\r
261 \r
262         gtk_widget_show (hbox);\r
263         gtk_widget_show (frame);\r
264 // Third row (size and position)\r
265         frame = gtk_frame_new("Size/Position (undefined)");\r
266         m_pPosLabel = gtk_frame_get_label_widget (GTK_FRAME(frame));\r
267         gtk_box_pack_start ( GTK_BOX (m_pWidget), frame, FALSE, FALSE, 2);\r
268 \r
269         hbox = gtk_hbox_new(FALSE,5);\r
270         gtk_container_add (GTK_CONTAINER (frame), hbox);\r
271         gtk_container_set_border_width(GTK_CONTAINER (hbox),4);\r
272 \r
273         w = gtk_button_new_with_label ("from selection");\r
274         gtk_box_pack_start (GTK_BOX (hbox),w, TRUE, FALSE, 5);\r
275         g_signal_connect (G_OBJECT (w), "clicked", G_CALLBACK (size_sel_callback),\r
276                                                                 (gpointer)this);\r
277         gtk_tooltips_set_tip (pTooltips, w, "Set the size of the image to the bounding rectangle of all selected brushes and entities", NULL);\r
278   gtk_widget_show (w);\r
279 \r
280         if(m_vt == XY) {\r
281                 w = gtk_button_new_with_label ("from map mins/maxs");\r
282                 gtk_box_pack_start ( GTK_BOX (hbox),w, TRUE, FALSE, 2);\r
283                 g_signal_connect (G_OBJECT (w), "clicked", G_CALLBACK (size_mm_callback),\r
284                                                                 (gpointer)this);\r
285                 gtk_tooltips_set_tip (pTooltips, w, "Set the size of the image using the mapcoordsmins and mapcoordsmaxs keys of the worldspawn entity", NULL);\r
286                 gtk_widget_show (w);\r
287         }\r
288 \r
289         gtk_widget_show (hbox);\r
290         gtk_widget_show (frame);\r
291 \r
292   gtk_widget_show ( m_pWidget );\r
293 }\r
294 \r
295 void CBackgroundDialogPage::Append(GtkWidget *notebook)\r
296 {\r
297         gtk_notebook_append_page( GTK_NOTEBOOK(notebook), m_pWidget, m_pTabLabel);\r
298 }\r
299 \r
300 // dialog global callbacks\r
301 /*\r
302 static gint expose_callback( GtkWidget *widget, gpointer data )\r
303 {\r
304         return FALSE;\r
305 }\r
306 */\r
307 \r
308 static void response_callback( GtkWidget *widget, gint response, gpointer data )\r
309 {\r
310         if( response == GTK_RESPONSE_CLOSE )\r
311                 gtk_widget_hide( pDialogWnd );\r
312 }\r
313 \r
314 static gint close_callback( GtkWidget *widget, gpointer data )\r
315 {\r
316         gtk_widget_hide( pDialogWnd );\r
317         return TRUE;\r
318 }\r
319 \r
320 void InitBackgroundDialog()\r
321 {\r
322         CBackgroundDialogPage *pPage;\r
323 \r
324         pDialogWnd = gtk_dialog_new_with_buttons ("Background Images",\r
325                               GTK_WINDOW(g_pMainWidget),\r
326                               (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT),\r
327         // TODO dialog with no buttons\r
328         //                                                                                GTK_STOCK_CLOSE,\r
329         //                                                                                GTK_RESPONSE_CLOSE,\r
330                               NULL);\r
331         gtk_signal_connect( GTK_OBJECT (pDialogWnd), "delete_event",\r
332                                     GTK_SIGNAL_FUNC( close_callback ), NULL );\r
333         gtk_signal_connect( GTK_OBJECT (pDialogWnd), "response",\r
334                                   GTK_SIGNAL_FUNC( response_callback ), NULL );\r
335 //      gtk_signal_connect( GTK_OBJECT (pDialogWnd), "expose_event", GTK_SIGNAL_FUNC( ci_expose ), NULL );\r
336 \r
337         pTooltips = gtk_tooltips_new();\r
338 \r
339         pNotebook = gtk_notebook_new();\r
340         pPage = new CBackgroundDialogPage(XY);\r
341         pPage->Append(pNotebook);\r
342         pPage = new CBackgroundDialogPage(XZ);\r
343         pPage->Append(pNotebook);\r
344         pPage = new CBackgroundDialogPage(YZ);\r
345         pPage->Append(pNotebook);\r
346 \r
347         gtk_box_pack_start (GTK_BOX (GTK_DIALOG(pDialogWnd)->vbox), pNotebook, TRUE, TRUE, 0);\r
348 \r
349   gtk_widget_show ( pNotebook );\r
350         \r
351         gtk_widget_realize( pDialogWnd );\r
352 }\r
353 \r
354 void ShowBackgroundDialog()\r
355 {\r
356         gtk_window_present( GTK_WINDOW(pDialogWnd) );\r
357 }\r
358 \r
359 void ShowBackgroundDialogPG(int page)\r
360 {\r
361         gtk_notebook_set_current_page(GTK_NOTEBOOK(pNotebook),page);\r
362         ShowBackgroundDialog();\r
363 }\r
364 \r