]> git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/bobtoolz/dialogs/dialogs-gtk.cpp
05376e3f0bc58825eb502a8da1b876f9c8d1a64b
[xonotic/netradiant.git] / contrib / bobtoolz / dialogs / dialogs-gtk.cpp
1 /*
2    BobToolz plugin for GtkRadiant
3    Copyright (C) 2001 Gordon Biggans
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include "dialogs-gtk.h"
21 #include "../funchandlers.h"
22
23 #include "str.h"
24 #include <list>
25 #include <gtk/gtk.h>
26 #include "gtkutil/pointer.h"
27 #include "gtkutil/dialog.h"
28
29 #include "../lists.h"
30 #include "../misc.h"
31
32
33 /*--------------------------------
34         Callback Functions
35    ---------------------------------*/
36
37 typedef struct {
38         ui::Widget cbTexChange{ui::null};
39         ui::Widget editTexOld{ui::null}, editTexNew{ui::null};
40
41         ui::Widget cbScaleHor{ui::null}, cbScaleVert{ui::null};
42         ui::Widget editScaleHor{ui::null}, editScaleVert{ui::null};
43
44         ui::Widget cbShiftHor{ui::null}, cbShiftVert{ui::null};
45         ui::Widget editShiftHor{ui::null}, editShiftVert{ui::null};
46
47         ui::Widget cbRotation{ui::null};
48         ui::Widget editRotation{ui::null};
49 }dlg_texReset_t;
50
51 dlg_texReset_t dlgTexReset;
52
53 void Update_TextureReseter();
54
55 static void dialog_button_callback_texreset_update(ui::Widget widget, gpointer data ){
56         Update_TextureReseter();
57 }
58
59 void Update_TextureReseter(){
60         gboolean check;
61
62         check = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbTexChange ) );
63         gtk_editable_set_editable( GTK_EDITABLE( dlgTexReset.editTexNew ), check );
64         gtk_editable_set_editable( GTK_EDITABLE( dlgTexReset.editTexOld ), check );
65
66         check = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbScaleHor ) );
67         gtk_editable_set_editable( GTK_EDITABLE( dlgTexReset.editScaleHor ), check );
68
69         check = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbScaleVert ) );
70         gtk_editable_set_editable( GTK_EDITABLE( dlgTexReset.editScaleVert ), check );
71
72         check = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbShiftHor ) );
73         gtk_editable_set_editable( GTK_EDITABLE( dlgTexReset.editShiftHor ), check );
74
75         check = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbShiftVert ) );
76         gtk_editable_set_editable( GTK_EDITABLE( dlgTexReset.editShiftVert ), check );
77
78         check = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbRotation ) );
79         gtk_editable_set_editable( GTK_EDITABLE( dlgTexReset.editRotation ), check );
80 }
81
82 static void dialog_button_callback( ui::Widget widget, gpointer data ){
83         int *loop;
84         EMessageBoxReturn *ret;
85
86         auto parent = widget.window();
87         loop = (int*)g_object_get_data( G_OBJECT( parent ), "loop" );
88         ret = (EMessageBoxReturn*)g_object_get_data( G_OBJECT( parent ), "ret" );
89
90         *loop = 0;
91         *ret = (EMessageBoxReturn)gpointer_to_int( data );
92 }
93
94 static gint custom_dialog_delete_callback( ui::Widget widget, GdkEvent* event, gpointer data ){
95         widget.hide();
96         int *loop = (int *) g_object_get_data(G_OBJECT(widget), "loop");
97         *loop = 0;
98         return TRUE;
99 }
100
101 static void dialog_button_callback_settex(ui::Widget widget, gpointer data ){
102         TwinWidget* tw = (TwinWidget*)data;
103
104     auto entry = ui::Entry::from( tw->one );
105         auto combo = tw->two;
106
107         const gchar *tex = gtk_entry_get_text(GTK_ENTRY (gtk_bin_get_child(combo)));
108         gtk_entry_set_text( entry, tex );
109 }
110
111 /*--------------------------------
112     Data validation Routines
113    ---------------------------------*/
114
115 bool ValidateTextFloat( const char* pData, const char* error_title, float* value ){
116         if ( pData ) {
117                 float testNum = (float)atof( pData );
118
119                 if ( ( testNum == 0.0f ) && strcmp( pData, "0" ) ) {
120                         DoMessageBox( "Please Enter A Floating Point Number", error_title, eMB_OK );
121                         return FALSE;
122                 }
123                 else
124                 {
125                         *value = testNum;
126                         return TRUE;
127                 }
128         }
129
130         DoMessageBox( "Please Enter A Floating Point Number", error_title, eMB_OK );
131         return FALSE;
132 }
133
134 bool ValidateTextFloatRange( const char* pData, float min, float max, const char* error_title, float* value ){
135         char error_buffer[256];
136         sprintf( error_buffer, "Please Enter A Floating Point Number Between %.3f and %.3f", min, max );
137
138         if ( pData ) {
139                 float testNum = (float)atof( pData );
140
141                 if ( ( testNum < min ) || ( testNum > max ) ) {
142                         DoMessageBox( error_buffer, error_title, eMB_OK );
143                         return FALSE;
144                 }
145                 else
146                 {
147                         *value = testNum;
148                         return TRUE;
149                 }
150         }
151
152         DoMessageBox( error_buffer, error_title, eMB_OK );
153         return FALSE;
154 }
155
156 bool ValidateTextIntRange( const char* pData, int min, int max, const char* error_title, int* value ){
157         char error_buffer[256];
158         sprintf( error_buffer, "Please Enter An Integer Between %i and %i", min, max );
159
160         if ( pData ) {
161                 int testNum = atoi( pData );
162
163                 if ( ( testNum < min ) || ( testNum > max ) ) {
164                         DoMessageBox( error_buffer, error_title, eMB_OK );
165                         return FALSE;
166                 }
167                 else
168                 {
169                         *value = testNum;
170                         return TRUE;
171                 }
172         }
173
174         DoMessageBox( error_buffer, error_title, eMB_OK );
175         return FALSE;
176 }
177
178 bool ValidateTextInt( const char* pData, const char* error_title, int* value ){
179         if ( pData ) {
180                 int testNum = atoi( pData );
181
182                 if ( ( testNum == 0 ) && strcmp( pData, "0" ) ) {
183                         DoMessageBox( "Please Enter An Integer", error_title, eMB_OK );
184                         return FALSE;
185                 }
186                 else
187                 {
188                         *value = testNum;
189                         return TRUE;
190                 }
191         }
192
193         DoMessageBox( "Please Enter An Integer", error_title, eMB_OK );
194         return FALSE;
195 }
196
197 /*--------------------------------
198         Modal Dialog Boxes
199    ---------------------------------*/
200
201 /*
202
203    Major clean up of variable names etc required, excluding Mars's ones,
204    which are nicely done :)
205
206  */
207
208 EMessageBoxReturn DoMessageBox( const char* lpText, const char* lpCaption, EMessageBoxType type ){
209         ui::Widget w{ui::null};
210         EMessageBoxReturn ret;
211         int loop = 1;
212
213         auto window = ui::Window( ui::window_type::TOP );
214         window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
215         window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
216         gtk_window_set_title( window, lpCaption );
217         gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
218         g_object_set_data( G_OBJECT( window ), "loop", &loop );
219         g_object_set_data( G_OBJECT( window ), "ret", &ret );
220         gtk_widget_realize( window );
221
222         auto vbox = ui::VBox( FALSE, 10 );
223         window.add(vbox);
224         vbox.show();
225
226         w = ui::Label( lpText );
227         vbox.pack_start( w, FALSE, FALSE, 2 );
228         gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT );
229         w.show();
230
231         w = ui::Widget::from(gtk_hseparator_new());
232         vbox.pack_start( w, FALSE, FALSE, 2 );
233         w.show();
234
235         auto hbox = ui::HBox( FALSE, 10 );
236         vbox.pack_start( hbox, FALSE, FALSE, 2 );
237         hbox.show();
238
239         if ( type == eMB_OK ) {
240                 w = ui::Button( "Ok" );
241                 hbox.pack_start( w, TRUE, TRUE, 0 );
242                 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
243                 gtk_widget_set_can_default(w, true);
244                 gtk_widget_grab_default( w );
245                 w.show();
246                 ret = eIDOK;
247         }
248         else if ( type ==  eMB_OKCANCEL ) {
249                 w = ui::Button( "Ok" );
250                 hbox.pack_start( w, TRUE, TRUE, 0 );
251                 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
252                 gtk_widget_set_can_default( w, true );
253                 gtk_widget_grab_default( w );
254                 w.show();
255
256                 w = ui::Button( "Cancel" );
257                 hbox.pack_start( w, TRUE, TRUE, 0 );
258                 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
259                 w.show();
260                 ret = eIDCANCEL;
261         }
262         else if ( type == eMB_YESNOCANCEL ) {
263                 w = ui::Button( "Yes" );
264                 hbox.pack_start( w, TRUE, TRUE, 0 );
265                 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDYES ) );
266                 gtk_widget_set_can_default( w, true );
267                 gtk_widget_grab_default( w );
268                 w.show();
269
270                 w = ui::Button( "No" );
271                 hbox.pack_start( w, TRUE, TRUE, 0 );
272                 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDNO ) );
273                 w.show();
274
275                 w = ui::Button( "Cancel" );
276                 hbox.pack_start( w, TRUE, TRUE, 0 );
277                 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
278                 w.show();
279                 ret = eIDCANCEL;
280         }
281         else /* if (mode == MB_YESNO) */
282         {
283                 w = ui::Button( "Yes" );
284                 hbox.pack_start( w, TRUE, TRUE, 0 );
285                 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDYES ) );
286                 gtk_widget_set_can_default( w, true );
287                 gtk_widget_grab_default( w );
288                 w.show();
289
290                 w = ui::Button( "No" );
291                 hbox.pack_start( w, TRUE, TRUE, 0 );
292                 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDNO ) );
293                 w.show();
294                 ret = eIDNO;
295         }
296
297         gtk_window_set_position( window, GTK_WIN_POS_CENTER );
298         window.show();
299         gtk_grab_add( window );
300
301         while ( loop )
302                 gtk_main_iteration();
303
304         gtk_grab_remove( window );
305         window.destroy();
306
307         return ret;
308 }
309
310 EMessageBoxReturn DoIntersectBox( IntersectRS* rs ){
311         EMessageBoxReturn ret;
312         int loop = 1;
313
314         auto window = ui::Window( ui::window_type::TOP );
315
316         window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
317         window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
318
319         gtk_window_set_title( window, "Intersect" );
320         gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
321
322         g_object_set_data( G_OBJECT( window ), "loop", &loop );
323         g_object_set_data( G_OBJECT( window ), "ret", &ret );
324
325         gtk_widget_realize( window );
326
327
328
329         auto vbox = ui::VBox( FALSE, 10 );
330         window.add(vbox);
331         vbox.show();
332
333         // ---- vbox ----
334
335
336         auto radio1 = ui::Widget::from(gtk_radio_button_new_with_label( NULL, "Use Whole Map" ));
337         vbox.pack_start( radio1, FALSE, FALSE, 2 );
338         radio1.show();
339
340         auto radio2 = ui::Widget::from(gtk_radio_button_new_with_label( gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio1)), "Use Selected Brushes" ));
341         vbox.pack_start( radio2, FALSE, FALSE, 2 );
342         radio2.show();
343
344         auto hsep = ui::Widget::from(gtk_hseparator_new());
345         vbox.pack_start( hsep, FALSE, FALSE, 2 );
346         hsep.show();
347
348         auto check1 = ui::CheckButton( "Include Detail Brushes" );
349         vbox.pack_start( check1, FALSE, FALSE, 0 );
350         check1.show();
351
352         auto check2 = ui::CheckButton( "Select Duplicate Brushes Only" );
353         vbox.pack_start( check2, FALSE, FALSE, 0 );
354         check2.show();
355
356         auto hbox = ui::HBox( FALSE, 10 );
357         vbox.pack_start( hbox, FALSE, FALSE, 2 );
358         hbox.show();
359
360         // ---- hbox ---- ok/cancel buttons
361
362         auto w = ui::Button( "Ok" );
363         hbox.pack_start( w, TRUE, TRUE, 0 );
364         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
365
366         gtk_widget_set_can_default( w, true );
367         gtk_widget_grab_default( w );
368         w.show();
369
370         w = ui::Button( "Cancel" );
371         hbox.pack_start( w, TRUE, TRUE, 0 );
372         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
373         w.show();
374         ret = eIDCANCEL;
375
376         // ---- /hbox ----
377
378         // ---- /vbox ----
379
380         gtk_window_set_position( window, GTK_WIN_POS_CENTER );
381         window.show();
382         gtk_grab_add( window );
383
384         while ( loop )
385                 gtk_main_iteration();
386
387         if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radio1) ) ) {
388                 rs->nBrushOptions = BRUSH_OPT_WHOLE_MAP;
389         }
390         else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radio2) ) ) {
391                 rs->nBrushOptions = BRUSH_OPT_SELECTED;
392         }
393
394         rs->bUseDetail = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(check1) ) ? true : false;
395         rs->bDuplicateOnly = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(check2) ) ? true : false;
396
397         gtk_grab_remove( window );
398         window.destroy();
399
400         return ret;
401 }
402
403 EMessageBoxReturn DoPolygonBox( PolygonRS* rs ){
404         EMessageBoxReturn ret;
405         int loop = 1;
406
407         auto window = ui::Window( ui::window_type::TOP );
408
409         window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
410         window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
411
412         gtk_window_set_title( window, "Polygon Builder" );
413         gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
414
415         g_object_set_data( G_OBJECT( window ), "loop", &loop );
416         g_object_set_data( G_OBJECT( window ), "ret", &ret );
417
418         gtk_widget_realize( window );
419
420
421
422         auto vbox = ui::VBox( FALSE, 10 );
423         window.add(vbox);
424         vbox.show();
425
426         // ---- vbox ----
427
428     auto hbox = ui::HBox( FALSE, 10 );
429         vbox.pack_start( hbox, FALSE, FALSE, 2 );
430         hbox.show();
431
432         // ---- hbox ----
433
434
435     auto vbox2 = ui::VBox( FALSE, 10 );
436         hbox.pack_start( vbox2, FALSE, FALSE, 2 );
437         vbox2.show();
438
439         // ---- vbox2 ----
440
441     auto hbox2 = ui::HBox( FALSE, 10 );
442         vbox2.pack_start( hbox2, FALSE, FALSE, 2 );
443         hbox2.show();
444
445         // ---- hbox2 ----
446
447     auto text1 = ui::Entry( 256 );
448         gtk_entry_set_text( text1, "3" );
449         hbox2.pack_start( text1, FALSE, FALSE, 2 );
450         text1.show();
451
452         auto l = ui::Label( "Number Of Sides" );
453         hbox2.pack_start( l, FALSE, FALSE, 2 );
454         gtk_label_set_justify( GTK_LABEL( l ), GTK_JUSTIFY_LEFT );
455         l.show();
456
457         // ---- /hbox2 ----
458
459         hbox2 = ui::HBox( FALSE, 10 );
460         vbox2.pack_start( hbox2, FALSE, FALSE, 2 );
461         hbox2.show();
462
463         // ---- hbox2 ----
464
465     auto text2 = ui::Entry( 256 );
466         gtk_entry_set_text( text2, "8" );
467         hbox2.pack_start( text2, FALSE, FALSE, 2 );
468         text2.show();
469
470         l = ui::Label( "Border Width" );
471         hbox2.pack_start( l, FALSE, FALSE, 2 );
472         gtk_label_set_justify( GTK_LABEL( l ), GTK_JUSTIFY_LEFT );
473         l.show();
474
475         // ---- /hbox2 ----
476
477         // ---- /vbox2 ----
478
479
480
481         vbox2 = ui::VBox( FALSE, 10 );
482         hbox.pack_start( vbox2, FALSE, FALSE, 2 );
483         vbox2.show();
484
485         // ---- vbox2 ----
486
487     auto check1 = ui::CheckButton( "Use Border" );
488         vbox2.pack_start( check1, FALSE, FALSE, 0 );
489         check1.show();
490
491
492     auto check2 = ui::CheckButton( "Inverse Polygon" );
493         vbox2.pack_start( check2, FALSE, FALSE, 0 );
494         check2.show();
495
496
497     auto check3 = ui::CheckButton( "Align Top Edge" );
498         vbox2.pack_start( check3, FALSE, FALSE, 0 );
499         check3.show();
500
501         // ---- /vbox2 ----
502
503         // ---- /hbox ----
504
505         hbox = ui::HBox( FALSE, 10 );
506         vbox.pack_start( hbox, FALSE, FALSE, 2 );
507         hbox.show();
508
509         // ---- hbox ----
510
511         auto w = ui::Button( "Ok" );
512         hbox.pack_start( w, TRUE, TRUE, 0 );
513         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
514
515         gtk_widget_set_can_default( w, true );
516         gtk_widget_grab_default( w );
517         w.show();
518
519         w = ui::Button( "Cancel" );
520         hbox.pack_start( w, TRUE, TRUE, 0 );
521         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
522         w.show();
523         ret = eIDCANCEL;
524
525         // ---- /hbox ----
526
527         // ---- /vbox ----
528
529         gtk_window_set_position( window, GTK_WIN_POS_CENTER );
530         window.show();
531         gtk_grab_add( window );
532
533         bool dialogError = TRUE;
534         while ( dialogError )
535         {
536                 loop = 1;
537                 while ( loop )
538                         gtk_main_iteration();
539
540                 dialogError = FALSE;
541
542                 if ( ret == eIDOK ) {
543                         rs->bUseBorder = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(check1) ) ? true : false;
544                         rs->bInverse = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(check2) ) ? true : false;
545                         rs->bAlignTop = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(check3) ) ? true : false;
546
547                         if ( !ValidateTextIntRange( gtk_entry_get_text( text1 ), 3, 32, "Number Of Sides", &rs->nSides ) ) {
548                                 dialogError = TRUE;
549                         }
550
551                         if ( rs->bUseBorder ) {
552                                 if ( !ValidateTextIntRange( gtk_entry_get_text( text2 ), 8, 256, "Border Width", &rs->nBorderWidth ) ) {
553                                         dialogError = TRUE;
554                                 }
555                         }
556                 }
557         }
558
559         gtk_grab_remove( window );
560         window.destroy();
561
562         return ret;
563 }
564
565 // mars
566 // for stair builder stuck as close as i could to the MFC version
567 // obviously feel free to change it at will :)
568 EMessageBoxReturn DoBuildStairsBox( BuildStairsRS* rs ){
569         GSList      *radioDirection, *radioStyle;
570         EMessageBoxReturn ret;
571         int loop = 1;
572
573         const char *text = "Please set a value in the boxes below and press 'OK' to build the stairs";
574
575         auto window = ui::Window( ui::window_type::TOP );
576
577         window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
578         window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
579
580         gtk_window_set_title( window, "Stair Builder" );
581
582         gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
583
584         g_object_set_data( G_OBJECT( window ), "loop", &loop );
585         g_object_set_data( G_OBJECT( window ), "ret", &ret );
586
587         gtk_widget_realize( window );
588
589         // new vbox
590         auto vbox = ui::VBox( FALSE, 10 );
591         window.add(vbox);
592         vbox.show();
593
594         auto hbox = ui::HBox( FALSE, 10 );
595         vbox.add(hbox);
596         hbox.show();
597
598         // dunno if you want this text or not ...
599         ui::Widget w = ui::Label( text );
600         hbox.pack_start( w, FALSE, FALSE, 0 ); // not entirely sure on all the parameters / what they do ...
601         w.show();
602
603         w = ui::Widget::from(gtk_hseparator_new());
604         vbox.pack_start( w, FALSE, FALSE, 0 );
605         w.show();
606
607         // ------------------------- // indenting == good way of keeping track of lines :)
608
609         // new hbox
610         hbox = ui::HBox( FALSE, 10 );
611         vbox.pack_start( hbox, FALSE, FALSE, 0 );
612         hbox.show();
613
614     auto textStairHeight = ui::Entry( 256 );
615         hbox.pack_start( textStairHeight, FALSE, FALSE, 1 );
616         textStairHeight.show();
617
618         w = ui::Label( "Stair Height" );
619         hbox.pack_start( w, FALSE, FALSE, 1 );
620         w.show();
621
622         // ------------------------- //
623
624         hbox = ui::HBox( FALSE, 10 );
625         vbox.pack_start( hbox, FALSE, FALSE, 0 );
626         hbox.show();
627
628         w = ui::Label( "Direction:" );
629         hbox.pack_start( w, FALSE, FALSE, 5 );
630         w.show();
631
632         // -------------------------- //
633
634         hbox = ui::HBox( FALSE, 10 );
635         vbox.pack_start( hbox, FALSE, FALSE, 0 );
636         hbox.show();
637
638         // radio buttons confuse me ...
639         // but this _looks_ right
640
641         // djbob: actually it looks very nice :), slightly better than the way i did it
642         // edit: actually it doesn't work :P, you must pass the last radio item each time, ugh
643
644     auto radioNorth = ui::Widget::from(gtk_radio_button_new_with_label( NULL, "North" ));
645         hbox.pack_start( radioNorth, FALSE, FALSE, 3 );
646         radioNorth.show();
647
648         radioDirection = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radioNorth ) );
649
650     auto radioSouth = ui::Widget::from(gtk_radio_button_new_with_label( radioDirection, "South" ));
651         hbox.pack_start( radioSouth, FALSE, FALSE, 2 );
652         radioSouth.show();
653
654         radioDirection = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radioSouth ) );
655
656     auto radioEast = ui::Widget::from(gtk_radio_button_new_with_label( radioDirection, "East" ));
657         hbox.pack_start( radioEast, FALSE, FALSE, 1 );
658         radioEast.show();
659
660         radioDirection = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radioEast ) );
661
662     auto radioWest = ui::Widget::from(gtk_radio_button_new_with_label( radioDirection, "West" ));
663         hbox.pack_start( radioWest, FALSE, FALSE, 0 );
664         radioWest.show();
665
666         // --------------------------- //
667
668         hbox = ui::HBox( FALSE, 10 );
669         vbox.pack_start( hbox, FALSE, FALSE, 0 );
670         hbox.show();
671
672         w = ui::Label( "Style:" );
673         hbox.pack_start( w, FALSE, FALSE, 5 );
674         w.show();
675
676         // --------------------------- //
677
678         hbox = ui::HBox( FALSE, 10 );
679         vbox.pack_start( hbox, FALSE, FALSE, 0 );
680         hbox.show();
681
682     auto radioOldStyle = ui::Widget::from(gtk_radio_button_new_with_label( NULL, "Original" ));
683         hbox.pack_start( radioOldStyle, FALSE, FALSE, 0 );
684         radioOldStyle.show();
685
686         radioStyle = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radioOldStyle ) );
687
688     auto radioBobStyle = ui::Widget::from(gtk_radio_button_new_with_label( radioStyle, "Bob's Style" ));
689         hbox.pack_start( radioBobStyle, FALSE, FALSE, 0 );
690         radioBobStyle.show();
691
692         radioStyle = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radioBobStyle ) );
693
694     auto radioCornerStyle = ui::Widget::from(gtk_radio_button_new_with_label( radioStyle, "Corner Style" ));
695         hbox.pack_start( radioCornerStyle, FALSE, FALSE, 0 );
696         radioCornerStyle.show();
697
698         // err, the q3r has an if or something so you need bob style checked before this
699         // is "ungreyed out" but you'll need to do that, as i suck :)
700
701         // djbob: er.... yeah um, im not at all sure how i'm gonna sort this
702         // djbob: think we need some button callback functions or smuffin
703         // FIXME: actually get around to doing what i suggested!!!!
704
705     auto checkUseDetail = ui::CheckButton( "Use Detail Brushes" );
706         hbox.pack_start( checkUseDetail, FALSE, FALSE, 0 );
707         checkUseDetail.show();
708
709         // --------------------------- //
710
711         hbox = ui::HBox( FALSE, 10 );
712         vbox.pack_start( hbox, FALSE, FALSE, 0 );
713         hbox.show();
714
715     auto textMainTex = ui::Entry( 512 );
716         gtk_entry_set_text( GTK_ENTRY( textMainTex ), rs->mainTexture );
717         hbox.pack_start( textMainTex, FALSE, FALSE, 0 );
718         textMainTex.show();
719
720         w = ui::Label( "Main Texture" );
721         hbox.pack_start( w, FALSE, FALSE, 1 );
722         w.show();
723
724         // -------------------------- //
725
726         hbox = ui::HBox( FALSE, 10 );
727         vbox.pack_start( hbox, FALSE, FALSE, 0 );
728         hbox.show();
729
730         auto textRiserTex = ui::Entry( 512 );
731         hbox.pack_start( textRiserTex, FALSE, FALSE, 0 );
732         textRiserTex.show();
733
734         w = ui::Label( "Riser Texture" );
735         hbox.pack_start( w, FALSE, FALSE, 1 );
736         w.show();
737
738         // -------------------------- //
739         w = ui::Widget::from(gtk_hseparator_new());
740         vbox.pack_start( w, FALSE, FALSE, 0 );
741         w.show();
742
743         hbox = ui::HBox( FALSE, 10 );
744         vbox.pack_start( hbox, FALSE, FALSE, 0 );
745         hbox.show();
746
747         w = ui::Button( "OK" );
748         hbox.pack_start( w, TRUE, TRUE, 0 );
749         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
750         gtk_widget_set_can_default( w, true );
751         gtk_widget_grab_default( w );
752         w.show();
753
754         w = ui::Button( "Cancel" );
755         hbox.pack_start( w, TRUE, TRUE, 0 );
756         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
757         w.show();
758
759         ret = eIDCANCEL;
760
761 // +djbob: need our "little" modal loop mars :P
762         gtk_window_set_position( window, GTK_WIN_POS_CENTER );
763         window.show();
764         gtk_grab_add( window );
765
766         bool dialogError = TRUE;
767         while ( dialogError )
768         {
769                 loop = 1;
770                 while ( loop )
771                         gtk_main_iteration();
772
773                 dialogError = FALSE;
774
775                 if ( ret == eIDOK ) {
776                         rs->bUseDetail = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(checkUseDetail) ) ? true : false;
777
778                         strcpy( rs->riserTexture, gtk_entry_get_text( textRiserTex ) );
779                         strcpy( rs->mainTexture, gtk_entry_get_text( textMainTex ) );
780
781                         if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radioNorth) ) ) {
782                                 rs->direction = MOVE_NORTH;
783                         }
784                         else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radioSouth) ) ) {
785                                 rs->direction = MOVE_SOUTH;
786                         }
787                         else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radioEast) ) ) {
788                                 rs->direction = MOVE_EAST;
789                         }
790                         else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radioWest) ) ) {
791                                 rs->direction = MOVE_WEST;
792                         }
793
794                         if ( !ValidateTextInt( gtk_entry_get_text( textStairHeight ), "Stair Height", &rs->stairHeight ) ) {
795                                 dialogError = TRUE;
796                         }
797
798                         if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radioOldStyle) ) ) {
799                                 rs->style = STYLE_ORIGINAL;
800                         }
801                         else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radioBobStyle) ) ) {
802                                 rs->style = STYLE_BOB;
803                         }
804                         else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radioCornerStyle) ) ) {
805                                 rs->style = STYLE_CORNER;
806                         }
807                 }
808         }
809
810         gtk_grab_remove( window );
811         window.destroy();
812
813         return ret;
814 // -djbob
815
816         // there we go, all done ... on my end at least, not bad for a night's work
817 }
818
819 EMessageBoxReturn DoDoorsBox( DoorRS* rs ){
820         GSList      *radioOrientation;
821         TwinWidget tw1, tw2;
822         EMessageBoxReturn ret;
823         int loop = 1;
824
825         auto window = ui::Window( ui::window_type::TOP );
826
827         window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
828         window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
829
830         gtk_window_set_title( window, "Door Builder" );
831
832         gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
833
834         g_object_set_data( G_OBJECT( window ), "loop", &loop );
835         g_object_set_data( G_OBJECT( window ), "ret", &ret );
836
837         gtk_widget_realize( window );
838
839         char buffer[256];
840         auto listMainTextures = ui::ListStore::from(gtk_list_store_new( 1, G_TYPE_STRING ));
841         auto listTrimTextures = ui::ListStore::from(gtk_list_store_new( 1, G_TYPE_STRING ));
842         LoadGList( GetFilename( buffer, "plugins/bt/door-tex.txt" ), listMainTextures );
843         LoadGList( GetFilename( buffer, "plugins/bt/door-tex-trim.txt" ), listTrimTextures );
844
845         auto vbox = ui::VBox( FALSE, 10 );
846         window.add(vbox);
847         vbox.show();
848
849         // -------------------------- //
850
851     auto hbox = ui::HBox( FALSE, 10 );
852         vbox.pack_start( hbox, FALSE, FALSE, 0 );
853         hbox.show();
854
855         auto textFrontBackTex = ui::Entry( 512 );
856         gtk_entry_set_text( GTK_ENTRY( textFrontBackTex ), rs->mainTexture );
857         hbox.pack_start( textFrontBackTex, FALSE, FALSE, 0 );
858         textFrontBackTex.show();
859
860         ui::Widget w = ui::Label( "Door Front/Back Texture" );
861         hbox.pack_start( w, FALSE, FALSE, 0 );
862         w.show();
863
864         // ------------------------ //
865
866         hbox = ui::HBox( FALSE, 10 );
867         vbox.pack_start( hbox, FALSE, FALSE, 0 );
868         hbox.show();
869
870         auto textTrimTex = ui::Entry( 512 );
871         hbox.pack_start( textTrimTex, FALSE, FALSE, 0 );
872         textTrimTex.show();
873
874         w = ui::Label( "Door Trim Texture" );
875         hbox.pack_start( w, FALSE, FALSE, 0 );
876         w.show();
877
878         // ----------------------- //
879
880         hbox = ui::HBox( FALSE, 10 );
881         vbox.pack_start( hbox, FALSE, FALSE, 0 );
882         hbox.show();
883
884         // sp: horizontally ????
885         // djbob: yes mars, u can spell :]
886     auto checkScaleMainH = ui::CheckButton( "Scale Main Texture Horizontally" );
887         gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( checkScaleMainH ), TRUE );
888         hbox.pack_start( checkScaleMainH, FALSE, FALSE, 0 );
889         checkScaleMainH.show();
890
891     auto checkScaleTrimH = ui::CheckButton( "Scale Trim Texture Horizontally" );
892         gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( checkScaleTrimH ), TRUE );
893         hbox.pack_start( checkScaleTrimH, FALSE, FALSE, 0 );
894         checkScaleTrimH.show();
895
896         // ---------------------- //
897
898         hbox = ui::HBox( FALSE, 10 );
899         vbox.pack_start( hbox, FALSE, FALSE, 0 );
900         hbox.show();
901
902     auto checkScaleMainV = ui::CheckButton( "Scale Main Texture Vertically" );
903         gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( checkScaleMainV ), TRUE );
904         hbox.pack_start( checkScaleMainV, FALSE, FALSE, 0 );
905         checkScaleMainV.show();
906
907     auto checkScaleTrimV = ui::CheckButton( "Scale Trim Texture Vertically" );
908         hbox.pack_start( checkScaleTrimV, FALSE, FALSE, 0 );
909         checkScaleTrimV.show();
910
911         // --------------------- //
912
913         hbox = ui::HBox( FALSE, 10 );
914         vbox.pack_start( hbox, FALSE, FALSE, 0 );
915         hbox.show();
916
917         // djbob: lists added
918
919         auto comboMain = ui::ComboBox::from(gtk_combo_box_new_with_model_and_entry(listMainTextures));
920         gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(comboMain), 0);
921         hbox.pack_start( comboMain, FALSE, FALSE, 0 );
922         comboMain.show();
923
924         tw1.one = textFrontBackTex;
925         tw1.two = comboMain;
926
927         auto buttonSetMain = ui::Button( "Set As Main Texture" );
928         buttonSetMain.connect( "clicked", G_CALLBACK( dialog_button_callback_settex ), &tw1 );
929         hbox.pack_start( buttonSetMain, FALSE, FALSE, 0 );
930         buttonSetMain.show();
931
932         // ------------------- //
933
934         hbox = ui::HBox( FALSE, 10 );
935         vbox.pack_start( hbox, FALSE, FALSE, 0 );
936         hbox.show();
937
938         auto comboTrim = ui::ComboBox::from(gtk_combo_box_new_with_model_and_entry(listTrimTextures));
939         gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(comboMain), 0);
940         hbox.pack_start( comboTrim, FALSE, FALSE, 0 );
941         comboTrim.show();
942
943         tw2.one = textTrimTex;
944         tw2.two = comboTrim;
945
946         auto buttonSetTrim = ui::Button( "Set As Trim Texture" );
947         buttonSetTrim.connect( "clicked", G_CALLBACK( dialog_button_callback_settex ), &tw2 );
948         hbox.pack_start( buttonSetTrim, FALSE, FALSE, 0 );
949         buttonSetTrim.show();
950
951         // ------------------ //
952
953         hbox = ui::HBox( FALSE, 10 );
954         vbox.pack_start( hbox, FALSE, FALSE, 0 );
955         hbox.show();
956
957         w = ui::Label( "Orientation" );
958         hbox.pack_start( w, FALSE, FALSE, 0 );
959         w.show();
960
961         // argh more radio buttons!
962     auto radioNS = ui::Widget::from(gtk_radio_button_new_with_label( NULL, "North - South" ));
963         hbox.pack_start( radioNS, FALSE, FALSE, 0 );
964         radioNS.show();
965
966         radioOrientation = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radioNS ) );
967
968     auto radioEW = ui::Widget::from(gtk_radio_button_new_with_label( radioOrientation, "East - West" ));
969         hbox.pack_start( radioEW, FALSE, FALSE, 0 );
970         radioEW.show();
971
972         // ----------------- //
973
974         w = ui::Widget::from(gtk_hseparator_new());
975         vbox.pack_start( w, FALSE, FALSE, 0 );
976         w.show();
977
978         // ----------------- //
979
980         hbox = ui::HBox( FALSE, 10 );
981         vbox.pack_start( hbox, FALSE, FALSE, 0 );
982         hbox.show();
983
984         w = ui::Button( "OK" );
985         hbox.pack_start( w, TRUE, TRUE, 0 );
986         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
987         gtk_widget_set_can_default( w, true );
988         gtk_widget_grab_default( w );
989         w.show();
990
991         w = ui::Button( "Cancel" );
992         hbox.pack_start( w, TRUE, TRUE, 0 );
993         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
994         w.show();
995         ret = eIDCANCEL;
996
997         // ----------------- //
998
999 //+djbob
1000         gtk_window_set_position( window, GTK_WIN_POS_CENTER );
1001         window.show();
1002         gtk_grab_add( window );
1003
1004         while ( loop )
1005                 gtk_main_iteration();
1006
1007         strcpy( rs->mainTexture, gtk_entry_get_text( GTK_ENTRY( textFrontBackTex ) ) );
1008         strcpy( rs->trimTexture, gtk_entry_get_text( GTK_ENTRY( textTrimTex ) ) );
1009
1010         rs->bScaleMainH = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( checkScaleMainH ) ) ? true : false;
1011         rs->bScaleMainV = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( checkScaleMainV ) ) ? true : false;
1012         rs->bScaleTrimH = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( checkScaleTrimH ) ) ? true : false;
1013         rs->bScaleTrimV = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( checkScaleTrimV ) ) ? true : false;
1014
1015         if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( radioNS ) ) ) {
1016                 rs->nOrientation = DIRECTION_NS;
1017         }
1018         else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( radioEW ) ) ) {
1019                 rs->nOrientation = DIRECTION_EW;
1020         }
1021
1022         gtk_grab_remove( window );
1023         window.destroy();
1024
1025         return ret;
1026 //-djbob
1027 }
1028
1029 EMessageBoxReturn DoPathPlotterBox( PathPlotterRS* rs, ui::Window main_window ){
1030         ui::Widget w{ui::null};
1031         ModalDialog dialog;
1032
1033         EMessageBoxReturn ret;
1034         int loop = 1;
1035
1036         auto window = main_window.create_dialog_window( "Path Plotter", G_CALLBACK( custom_dialog_delete_callback ), &dialog );
1037
1038         window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
1039
1040         gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
1041
1042         g_object_set_data( G_OBJECT( window ), "loop", &loop );
1043         g_object_set_data( G_OBJECT( window ), "ret", &ret );
1044
1045         gtk_widget_realize( window );
1046
1047
1048
1049         auto vbox = ui::VBox( FALSE, 10 );
1050         window.add(vbox);
1051         vbox.show();
1052
1053         // ---- vbox ----
1054
1055         auto hbox = ui::HBox( FALSE, 10 );
1056         vbox.pack_start( hbox, FALSE, FALSE, 2 );
1057         hbox.show();
1058
1059         // ---- hbox ----
1060
1061         auto text1 = ui::Entry( 256 );
1062         gtk_entry_set_text( text1, "25" );
1063         hbox.pack_start( text1, FALSE, FALSE, 2 );
1064         text1.show();
1065
1066         w = ui::Label( "Number Of Points" );
1067         hbox.pack_start( w, FALSE, FALSE, 2 );
1068         gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT );
1069         w.show();
1070
1071         // ---- /hbox ----
1072
1073         hbox = ui::HBox( FALSE, 10 );
1074         vbox.pack_start( hbox, FALSE, FALSE, 2 );
1075         hbox.show();
1076
1077         // ---- hbox ----
1078
1079         auto text2 = ui::Entry( 256 );
1080         gtk_entry_set_text( text2, "3" );
1081         hbox.pack_start( text2, FALSE, FALSE, 2 );
1082         text2.show();
1083
1084         w = ui::Label( "Multipler" );
1085         hbox.pack_start( w, FALSE, FALSE, 2 );
1086         gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT );
1087         w.show();
1088
1089         // ---- /hbox ----
1090
1091         w = ui::Label( "Path Distance = dist(start -> apex) * multiplier" );
1092         vbox.pack_start( w, FALSE, FALSE, 0 );
1093         gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT );
1094         w.show();
1095
1096         hbox = ui::HBox( FALSE, 10 );
1097         vbox.pack_start( hbox, FALSE, FALSE, 2 );
1098         hbox.show();
1099
1100         // ---- hbox ----
1101
1102         auto text3 = ui::Entry( 256 );
1103         gtk_entry_set_text( text3, "-800" );
1104         hbox.pack_start( text3, FALSE, FALSE, 2 );
1105         text3.show();
1106
1107         w = ui::Label( "Gravity" );
1108         hbox.pack_start( w, FALSE, FALSE, 2 );
1109         gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT );
1110         w.show();
1111
1112         // ---- /hbox ----
1113
1114         w = ui::Widget::from(gtk_hseparator_new());
1115         vbox.pack_start( w, FALSE, FALSE, 0 );
1116         w.show();
1117
1118         auto check1 = ui::CheckButton( "No Dynamic Update" );
1119         vbox.pack_start( check1, FALSE, FALSE, 0 );
1120         check1.show();
1121
1122         auto check2 = ui::CheckButton( "Show Bounding Lines" );
1123         vbox.pack_start( check2, FALSE, FALSE, 0 );
1124         check2.show();
1125
1126         // ---- /vbox ----
1127
1128
1129         // ----------------- //
1130
1131         w = ui::Widget::from(gtk_hseparator_new());
1132         vbox.pack_start( w, FALSE, FALSE, 0 );
1133         w.show();
1134
1135         // ----------------- //
1136
1137         hbox = ui::HBox( FALSE, 10 );
1138         vbox.pack_start( hbox, FALSE, FALSE, 0 );
1139         hbox.show();
1140
1141         w = ui::Button( "Enable" );
1142         hbox.pack_start( w, TRUE, TRUE, 0 );
1143         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDYES ) );
1144         w.show();
1145
1146         gtk_widget_set_can_default( w, true );
1147         gtk_widget_grab_default( w );
1148
1149         w = ui::Button( "Disable" );
1150         hbox.pack_start( w, TRUE, TRUE, 0 );
1151         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDNO ) );
1152         w.show();
1153
1154         w = ui::Button( "Cancel" );
1155         hbox.pack_start( w, TRUE, TRUE, 0 );
1156         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
1157         w.show();
1158
1159         ret = eIDCANCEL;
1160
1161         // ----------------- //
1162
1163         gtk_window_set_position( window, GTK_WIN_POS_CENTER );
1164         window.show();
1165         gtk_grab_add( window );
1166
1167         bool dialogError = TRUE;
1168         while ( dialogError )
1169         {
1170                 loop = 1;
1171                 while ( loop )
1172                         gtk_main_iteration();
1173
1174                 dialogError = FALSE;
1175
1176                 if ( ret == eIDYES ) {
1177                         if ( !ValidateTextIntRange( gtk_entry_get_text( GTK_ENTRY( text1 ) ), 1, 200, "Number Of Points", &rs->nPoints ) ) {
1178                                 dialogError = TRUE;
1179                         }
1180
1181                         if ( !ValidateTextFloatRange( gtk_entry_get_text( GTK_ENTRY( text2 ) ), 1.0f, 10.0f, "Multiplier", &rs->fMultiplier ) ) {
1182                                 dialogError = TRUE;
1183                         }
1184
1185                         if ( !ValidateTextFloatRange( gtk_entry_get_text( GTK_ENTRY( text3 ) ), -10000.0f, -1.0f, "Gravity", &rs->fGravity ) ) {
1186                                 dialogError = TRUE;
1187                         }
1188
1189                         rs->bNoUpdate = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( check1 ) ) ? true : false;
1190                         rs->bShowExtra = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( check2 ) ) ? true : false;
1191                 }
1192         }
1193
1194         gtk_grab_remove( window );
1195         window.destroy();
1196
1197         return ret;
1198 }
1199
1200 EMessageBoxReturn DoCTFColourChangeBox(){
1201         ui::Widget w{ui::null};
1202         EMessageBoxReturn ret;
1203         int loop = 1;
1204
1205         auto window = ui::Window( ui::window_type::TOP );
1206
1207         window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
1208         window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
1209
1210         gtk_window_set_title( window, "CTF Colour Changer" );
1211         gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
1212
1213         g_object_set_data( G_OBJECT( window ), "loop", &loop );
1214         g_object_set_data( G_OBJECT( window ), "ret", &ret );
1215
1216         gtk_widget_realize( window );
1217
1218
1219
1220         auto vbox = ui::VBox( FALSE, 10 );
1221         window.add(vbox);
1222         vbox.show();
1223
1224         // ---- vbox ----
1225
1226         auto hbox = ui::HBox( FALSE, 10 );
1227         vbox.pack_start( hbox, TRUE, TRUE, 0 );
1228         hbox.show();
1229
1230         // ---- hbox ---- ok/cancel buttons
1231
1232         w = ui::Button( "Red->Blue" );
1233         hbox.pack_start( w, TRUE, TRUE, 0 );
1234         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
1235
1236         gtk_widget_set_can_default( w, true );
1237         gtk_widget_grab_default( w );
1238         w.show();
1239
1240         w = ui::Button( "Blue->Red" );
1241         hbox.pack_start( w, TRUE, TRUE, 0 );
1242         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDYES ) );
1243         w.show();
1244
1245         w = ui::Button( "Cancel" );
1246         hbox.pack_start( w, TRUE, TRUE, 0 );
1247         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
1248         w.show();
1249         ret = eIDCANCEL;
1250
1251         // ---- /hbox ----
1252
1253         // ---- /vbox ----
1254
1255         gtk_window_set_position( window, GTK_WIN_POS_CENTER );
1256         window.show();
1257         gtk_grab_add( window );
1258
1259         while ( loop )
1260                 gtk_main_iteration();
1261
1262         gtk_grab_remove( window );
1263         window.destroy();
1264
1265         return ret;
1266 }
1267
1268 EMessageBoxReturn DoResetTextureBox( ResetTextureRS* rs, ui::Window main_window ){
1269         Str texSelected;
1270
1271         ui::Widget w{ui::null};
1272         ModalDialog dialog;
1273
1274         EMessageBoxReturn ret;
1275         int loop = 1;
1276
1277         auto window = main_window.create_dialog_window( "Texture Reset", G_CALLBACK( custom_dialog_delete_callback ), &dialog );
1278
1279         window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
1280
1281         gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
1282
1283         g_object_set_data( G_OBJECT( window ), "loop", &loop );
1284         g_object_set_data( G_OBJECT( window ), "ret", &ret );
1285
1286         gtk_widget_realize( window );
1287
1288         auto vbox = ui::VBox( FALSE, 10 );
1289         window.add(vbox);
1290         vbox.show();
1291
1292         // ---- vbox ----
1293
1294         auto hbox = ui::HBox( FALSE, 10 );
1295         vbox.pack_start( hbox, FALSE, FALSE, 2 );
1296         hbox.show();
1297
1298         // ---- hbox ----
1299
1300         texSelected = "Currently Selected Texture:   ";
1301         texSelected += GetCurrentTexture();
1302
1303         w = ui::Label( texSelected );
1304         hbox.pack_start( w, FALSE, FALSE, 2 );
1305         gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT );
1306         w.show();
1307
1308         // ---- /hbox ----
1309
1310         auto frame = ui::Frame( "Reset Texture Names" );
1311         frame.show();
1312         vbox.pack_start( frame, FALSE, TRUE, 0 );
1313
1314         auto table = ui::Table( 2, 3, TRUE );
1315         table.show();
1316         frame.add(table);
1317         gtk_table_set_row_spacings(table, 5);
1318         gtk_table_set_col_spacings(table, 5);
1319         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1320
1321         // ---- frame ----
1322
1323         dlgTexReset.cbTexChange = ui::CheckButton( "Enabled" );
1324         dlgTexReset.cbTexChange.connect( "toggled", G_CALLBACK( dialog_button_callback_texreset_update ), NULL );
1325         dlgTexReset.cbTexChange.show();
1326         table.attach(dlgTexReset.cbTexChange, {0, 1, 0, 1}, {GTK_FILL, 0});
1327
1328         w = ui::Label( "Old Name: " );
1329         table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0});
1330         w.show();
1331
1332         dlgTexReset.editTexOld = ui::Entry( 256 );
1333         gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editTexOld ), rs->textureName );
1334         table.attach(dlgTexReset.editTexOld, {2, 3, 0, 1}, {GTK_FILL, 0});
1335         dlgTexReset.editTexOld.show();
1336
1337         w = ui::Label( "New Name: " );
1338         table.attach(w, {1, 2, 1, 2}, {GTK_FILL, 0});
1339         w.show();
1340
1341         dlgTexReset.editTexNew = ui::Entry( 256 );
1342         gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editTexNew ), rs->textureName );
1343         table.attach(dlgTexReset.editTexNew, {2, 3, 1, 2}, {GTK_FILL, 0});
1344         dlgTexReset.editTexNew.show();
1345
1346         // ---- /frame ----
1347
1348         frame = ui::Frame( "Reset Scales" );
1349         frame.show();
1350         vbox.pack_start( frame, FALSE, TRUE, 0 );
1351
1352         table = ui::Table( 2, 3, TRUE );
1353         table.show();
1354         frame.add(table);
1355         gtk_table_set_row_spacings(table, 5);
1356         gtk_table_set_col_spacings(table, 5);
1357         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1358
1359         // ---- frame ----
1360
1361         dlgTexReset.cbScaleHor = ui::CheckButton( "Enabled" );
1362         dlgTexReset.cbScaleHor.connect( "toggled", G_CALLBACK( dialog_button_callback_texreset_update ), NULL );
1363         dlgTexReset.cbScaleHor.show();
1364         table.attach(dlgTexReset.cbScaleHor, {0, 1, 0, 1}, {GTK_FILL, 0});
1365
1366         w = ui::Label( "New Horizontal Scale: " );
1367         table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0});
1368         w.show();
1369
1370         dlgTexReset.editScaleHor = ui::Entry( 256 );
1371         gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editScaleHor ), "0.5" );
1372         table.attach(dlgTexReset.editScaleHor, {2, 3, 0, 1}, {GTK_FILL, 0});
1373         dlgTexReset.editScaleHor.show();
1374
1375
1376         dlgTexReset.cbScaleVert = ui::CheckButton( "Enabled" );
1377         dlgTexReset.cbScaleVert.connect( "toggled", G_CALLBACK( dialog_button_callback_texreset_update ), NULL );
1378         dlgTexReset.cbScaleVert.show();
1379         table.attach(dlgTexReset.cbScaleVert, {0, 1, 1, 2}, {GTK_FILL, 0});
1380
1381         w = ui::Label( "New Vertical Scale: " );
1382         table.attach(w, {1, 2, 1, 2}, {GTK_FILL, 0});
1383         w.show();
1384
1385         dlgTexReset.editScaleVert = ui::Entry( 256 );
1386         gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editScaleVert ), "0.5" );
1387         table.attach(dlgTexReset.editScaleVert, {2, 3, 1, 2}, {GTK_FILL, 0});
1388         dlgTexReset.editScaleVert.show();
1389
1390         // ---- /frame ----
1391
1392         frame = ui::Frame( "Reset Shift" );
1393         frame.show();
1394         vbox.pack_start( frame, FALSE, TRUE, 0 );
1395
1396         table = ui::Table( 2, 3, TRUE );
1397         table.show();
1398         frame.add(table);
1399         gtk_table_set_row_spacings(table, 5);
1400         gtk_table_set_col_spacings(table, 5);
1401         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1402
1403         // ---- frame ----
1404
1405         dlgTexReset.cbShiftHor = ui::CheckButton( "Enabled" );
1406         dlgTexReset.cbShiftHor.connect( "toggled", G_CALLBACK( dialog_button_callback_texreset_update ), NULL );
1407         dlgTexReset.cbShiftHor.show();
1408         table.attach(dlgTexReset.cbShiftHor, {0, 1, 0, 1}, {GTK_FILL, 0});
1409
1410         w = ui::Label( "New Horizontal Shift: " );
1411         table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0});
1412         w.show();
1413
1414         dlgTexReset.editShiftHor = ui::Entry( 256 );
1415         gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editShiftHor ), "0" );
1416         table.attach(dlgTexReset.editShiftHor, {2, 3, 0, 1}, {GTK_FILL, 0});
1417         dlgTexReset.editShiftHor.show();
1418
1419
1420         dlgTexReset.cbShiftVert = ui::CheckButton( "Enabled" );
1421         dlgTexReset.cbShiftVert.connect( "toggled", G_CALLBACK( dialog_button_callback_texreset_update ), NULL );
1422         dlgTexReset.cbShiftVert.show();
1423         table.attach(dlgTexReset.cbShiftVert, {0, 1, 1, 2}, {GTK_FILL, 0});
1424
1425         w = ui::Label( "New Vertical Shift: " );
1426         table.attach(w, {1, 2, 1, 2}, {GTK_FILL, 0});
1427         w.show();
1428
1429         dlgTexReset.editShiftVert = ui::Entry( 256 );
1430         gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editShiftVert ), "0" );
1431         table.attach(dlgTexReset.editShiftVert, {2, 3, 1, 2}, {GTK_FILL, 0});
1432         dlgTexReset.editShiftVert.show();
1433
1434         // ---- /frame ----
1435
1436         frame = ui::Frame( "Reset Rotation" );
1437         frame.show();
1438         vbox.pack_start( frame, FALSE, TRUE, 0 );
1439
1440         table = ui::Table( 1, 3, TRUE );
1441         table.show();
1442         frame.add(table);
1443         gtk_table_set_row_spacings(table, 5);
1444         gtk_table_set_col_spacings(table, 5);
1445         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1446
1447         // ---- frame ----
1448
1449         dlgTexReset.cbRotation = ui::CheckButton( "Enabled" );
1450         dlgTexReset.cbRotation.show();
1451         table.attach(dlgTexReset.cbRotation, {0, 1, 0, 1}, {GTK_FILL, 0});
1452
1453         w = ui::Label( "New Rotation Value: " );
1454         table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0});
1455         w.show();
1456
1457         dlgTexReset.editRotation = ui::Entry( 256 );
1458         gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editRotation ), "0" );
1459         table.attach(dlgTexReset.editRotation, {2, 3, 0, 1}, {GTK_FILL, 0});
1460         dlgTexReset.editRotation.show();
1461
1462         // ---- /frame ----
1463
1464         hbox = ui::HBox( FALSE, 10 );
1465         vbox.pack_start( hbox, FALSE, FALSE, 2 );
1466         hbox.show();
1467
1468         // ---- hbox ----
1469
1470         w = ui::Button( "Use Selected Brushes" );
1471         hbox.pack_start( w, TRUE, TRUE, 0 );
1472         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
1473
1474         gtk_widget_set_can_default( w, true );
1475         gtk_widget_grab_default( w );
1476         w.show();
1477
1478         w = ui::Button( "Use All Brushes" );
1479         hbox.pack_start( w, TRUE, TRUE, 0 );
1480         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDYES ) );
1481         w.show();
1482
1483         w = ui::Button( "Cancel" );
1484         hbox.pack_start( w, TRUE, TRUE, 0 );
1485         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
1486         w.show();
1487         ret = eIDCANCEL;
1488
1489         // ---- /hbox ----
1490
1491         // ---- /vbox ----
1492
1493         window.show();
1494         gtk_grab_add( window );
1495
1496         Update_TextureReseter();
1497
1498         bool dialogError = TRUE;
1499         while ( dialogError )
1500         {
1501                 loop = 1;
1502                 while ( loop )
1503                         gtk_main_iteration();
1504
1505                 dialogError = FALSE;
1506
1507                 if ( ret != eIDCANCEL ) {
1508                         rs->bResetRotation =  gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbRotation ) );
1509                         if ( rs->bResetRotation ) {
1510                                 if ( !ValidateTextInt( gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editRotation ) ), "Rotation", &rs->rotation ) ) {
1511                                         dialogError = TRUE;
1512                                 }
1513                         }
1514
1515                         rs->bResetScale[0] =  gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbScaleHor ) );
1516                         if ( rs->bResetScale[0] ) {
1517                                 if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editScaleHor ) ), "Horizontal Scale", &rs->fScale[0] ) ) {
1518                                         dialogError = TRUE;
1519                                 }
1520                         }
1521
1522                         rs->bResetScale[1] =  gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbScaleVert ) );
1523                         if ( rs->bResetScale[1] ) {
1524                                 if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editScaleVert ) ), "Vertical Scale", &rs->fScale[1] ) ) {
1525                                         dialogError = TRUE;
1526                                 }
1527                         }
1528
1529                         rs->bResetShift[0] =  gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbShiftHor ) );
1530                         if ( rs->bResetShift[0] ) {
1531                                 if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editShiftHor ) ), "Horizontal Shift", &rs->fShift[0] ) ) {
1532                                         dialogError = TRUE;
1533                                 }
1534                         }
1535
1536                         rs->bResetShift[1] =  gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbShiftVert ) );
1537                         if ( rs->bResetShift[1] ) {
1538                                 if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editShiftVert ) ), "Vertical Shift", &rs->fShift[1] ) ) {
1539                                         dialogError = TRUE;
1540                                 }
1541                         }
1542
1543                         rs->bResetTextureName =  gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbTexChange ) );
1544                         if ( rs->bResetTextureName ) {
1545                                 strcpy( rs->textureName,     gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editTexOld ) ) );
1546                                 strcpy( rs->newTextureName,  gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editTexNew ) ) );
1547                         }
1548                 }
1549         }
1550
1551         gtk_grab_remove( window );
1552         window.destroy();
1553
1554         return ret;
1555 }
1556
1557 EMessageBoxReturn DoTrainThingBox( TrainThingRS* rs ){
1558         Str texSelected;
1559
1560         ui::Widget w{ui::null};
1561
1562         ui::Widget radiusX{ui::null}, radiusY{ui::null};
1563         ui::Widget angleStart{ui::null}, angleEnd{ui::null};
1564         ui::Widget heightStart{ui::null}, heightEnd{ui::null};
1565         ui::Widget numPoints{ui::null};
1566
1567         EMessageBoxReturn ret;
1568         int loop = 1;
1569
1570         auto window = ui::Window( ui::window_type::TOP );
1571
1572         window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
1573         window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
1574
1575         gtk_window_set_title( window, "Train Thing" );
1576         gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
1577
1578         g_object_set_data( G_OBJECT( window ), "loop", &loop );
1579         g_object_set_data( G_OBJECT( window ), "ret", &ret );
1580
1581         gtk_widget_realize( window );
1582
1583         auto vbox = ui::VBox( FALSE, 10 );
1584         window.add(vbox);
1585         vbox.show();
1586
1587         // ---- vbox ----
1588
1589         auto hbox = ui::HBox( FALSE, 10 );
1590         vbox.pack_start( hbox, FALSE, FALSE, 2 );
1591         hbox.show();
1592
1593         // ---- /hbox ----
1594
1595         auto frame = ui::Frame( "Radii" );
1596         frame.show();
1597         vbox.pack_start( frame, FALSE, TRUE, 0 );
1598
1599         auto table = ui::Table( 2, 3, TRUE );
1600         table.show();
1601         frame.add(table);
1602         gtk_table_set_row_spacings(table, 5);
1603         gtk_table_set_col_spacings(table, 5);
1604         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1605
1606         // ---- frame ----
1607
1608         w = ui::Label( "X: " );
1609         table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0});
1610         w.show();
1611
1612         radiusX = ui::Entry( 256 );
1613         gtk_entry_set_text( GTK_ENTRY( radiusX ), "100" );
1614         table.attach(radiusX, {1, 2, 0, 1}, {GTK_FILL, 0});
1615         radiusX.show();
1616
1617
1618
1619         w = ui::Label( "Y: " );
1620         table.attach(w, {0, 1, 1, 2}, {GTK_FILL, 0});
1621         w.show();
1622
1623         radiusY = ui::Entry( 256 );
1624         gtk_entry_set_text( GTK_ENTRY( radiusY ), "100" );
1625         table.attach(radiusY, {1, 2, 1, 2}, {GTK_FILL, 0});
1626         radiusY.show();
1627
1628
1629
1630         frame = ui::Frame( "Angles" );
1631         frame.show();
1632         vbox.pack_start( frame, FALSE, TRUE, 0 );
1633
1634         table = ui::Table( 2, 3, TRUE );
1635         table.show();
1636         frame.add(table);
1637         gtk_table_set_row_spacings((table), 5);
1638         gtk_table_set_col_spacings((table), 5);
1639         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1640
1641         // ---- frame ----
1642
1643         w = ui::Label( "Start: " );
1644         table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0});
1645         w.show();
1646
1647         angleStart = ui::Entry( 256 );
1648         gtk_entry_set_text( GTK_ENTRY( angleStart ), "0" );
1649         table.attach(angleStart, {1, 2, 0, 1}, {GTK_FILL, 0});
1650         angleStart.show();
1651
1652
1653
1654         w = ui::Label( "End: " );
1655         table.attach(w, {0, 1, 1, 2}, {GTK_FILL, 0});
1656         w.show();
1657
1658         angleEnd = ui::Entry( 256 );
1659         gtk_entry_set_text( GTK_ENTRY( angleEnd ), "90" );
1660         table.attach(angleEnd, {1, 2, 1, 2}, {GTK_FILL, 0});
1661         angleEnd.show();
1662
1663
1664         frame = ui::Frame( "Height" );
1665         frame.show();
1666         vbox.pack_start( frame, FALSE, TRUE, 0 );
1667
1668         table = ui::Table( 2, 3, TRUE );
1669         table.show();
1670         frame.add(table);
1671         gtk_table_set_row_spacings(table, 5);
1672         gtk_table_set_col_spacings(table, 5);
1673         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1674
1675         // ---- frame ----
1676
1677         w = ui::Label( "Start: " );
1678         table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0});
1679         w.show();
1680
1681         heightStart = ui::Entry( 256 );
1682         gtk_entry_set_text( GTK_ENTRY( heightStart ), "0" );
1683         table.attach(heightStart, {1, 2, 0, 1}, {GTK_FILL, 0});
1684         heightStart.show();
1685
1686
1687
1688         w = ui::Label( "End: " );
1689         table.attach(w, {0, 1, 1, 2}, {GTK_FILL, 0});
1690         w.show();
1691
1692         heightEnd = ui::Entry( 256 );
1693         gtk_entry_set_text( GTK_ENTRY( heightEnd ), "0" );
1694         table.attach(heightEnd, {1, 2, 1, 2}, {GTK_FILL, 0});
1695         heightEnd.show();
1696
1697
1698
1699         frame = ui::Frame( "Points" );
1700         frame.show();
1701         vbox.pack_start( frame, FALSE, TRUE, 0 );
1702
1703         table = ui::Table( 2, 3, TRUE );
1704         table.show();
1705         frame.add(table);
1706         gtk_table_set_row_spacings(table, 5);
1707         gtk_table_set_col_spacings(table, 5);
1708         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1709
1710         // ---- frame ----
1711
1712         w = ui::Label( "Number: " );
1713         table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0});
1714         w.show();
1715
1716         numPoints = ui::Entry( 256 );
1717         gtk_entry_set_text( GTK_ENTRY( numPoints ), "0" );
1718         table.attach(numPoints, {1, 2, 0, 1}, {GTK_FILL, 0});
1719         numPoints.show();
1720
1721
1722         hbox = ui::HBox( FALSE, 10 );
1723         vbox.pack_start( hbox, FALSE, FALSE, 2 );
1724         hbox.show();
1725
1726         // ---- hbox ----
1727
1728         w = ui::Button( "Ok" );
1729         hbox.pack_start( w, TRUE, TRUE, 0 );
1730         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
1731
1732         gtk_widget_set_can_default( w, true );
1733         gtk_widget_grab_default( w );
1734         w.show();
1735
1736         w = ui::Button( "Cancel" );
1737         hbox.pack_start( w, TRUE, TRUE, 0 );
1738         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
1739         w.show();
1740         ret = eIDCANCEL;
1741
1742         // ---- /hbox ----
1743
1744
1745
1746         gtk_window_set_position( window, GTK_WIN_POS_CENTER );
1747         window.show();
1748         gtk_grab_add( window );
1749
1750         bool dialogError = TRUE;
1751         while ( dialogError )
1752         {
1753                 loop = 1;
1754                 while ( loop )
1755                         gtk_main_iteration();
1756
1757                 dialogError = FALSE;
1758
1759                 if ( ret != eIDCANCEL ) {
1760                         if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( radiusX ) ), "Radius (X)", &rs->fRadiusX ) ) {
1761                                 dialogError = TRUE;
1762                         }
1763
1764                         if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( radiusY ) ), "Radius (Y)", &rs->fRadiusY ) ) {
1765                                 dialogError = TRUE;
1766                         }
1767
1768                         if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( angleStart ) ), "Angle (Start)", &rs->fStartAngle ) ) {
1769                                 dialogError = TRUE;
1770                         }
1771
1772                         if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( angleEnd ) ), "Angle (End)", &rs->fEndAngle ) ) {
1773                                 dialogError = TRUE;
1774                         }
1775
1776                         if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( heightStart ) ), "Height (Start)", &rs->fStartHeight ) ) {
1777                                 dialogError = TRUE;
1778                         }
1779
1780                         if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( heightEnd ) ), "Height (End)", &rs->fEndHeight ) ) {
1781                                 dialogError = TRUE;
1782                         }
1783
1784                         if ( !ValidateTextInt( gtk_entry_get_text( GTK_ENTRY( numPoints ) ), "Num Points", &rs->iNumPoints ) ) {
1785                                 dialogError = TRUE;
1786                         }
1787                 }
1788         }
1789
1790         gtk_grab_remove( window );
1791         window.destroy();
1792
1793         return ret;
1794 }
1795 // ailmanki
1796 // add a simple input for the MakeChain thing..
1797 EMessageBoxReturn DoMakeChainBox( MakeChainRS* rs ){
1798         ui::Widget   w{ui::null};
1799         ui::Entry textlinkNum{ui::null}, textlinkName{ui::null};
1800         EMessageBoxReturn ret;
1801         int loop = 1;
1802
1803         const char *text = "Please set a value in the boxes below and press 'OK' to make a chain";
1804
1805         auto window = ui::Window( ui::window_type::TOP );
1806
1807         window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
1808         window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
1809
1810         gtk_window_set_title( window, "Make Chain" );
1811
1812         gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
1813
1814         g_object_set_data( G_OBJECT( window ), "loop", &loop );
1815         g_object_set_data( G_OBJECT( window ), "ret", &ret );
1816
1817         gtk_widget_realize( window );
1818
1819         // new vbox
1820         auto vbox = ui::VBox( FALSE, 10 );
1821         window.add(vbox);
1822         vbox.show();
1823
1824         auto hbox = ui::HBox( FALSE, 10 );
1825         vbox.add(hbox);
1826         hbox.show();
1827
1828         // dunno if you want this text or not ...
1829         w = ui::Label( text );
1830         hbox.pack_start( w, FALSE, FALSE, 0 );
1831         w.show();
1832
1833         w = ui::Widget::from(gtk_hseparator_new());
1834         vbox.pack_start( w, FALSE, FALSE, 0 );
1835         w.show();
1836
1837         // ------------------------- //
1838
1839         // new hbox
1840         hbox = ui::HBox( FALSE, 10 );
1841         vbox.pack_start( hbox, FALSE, FALSE, 0 );
1842         hbox.show();
1843
1844         textlinkNum = ui::Entry( 256 );
1845         hbox.pack_start( textlinkNum, FALSE, FALSE, 1 );
1846         textlinkNum.show();
1847
1848         w = ui::Label( "Number of elements in chain" );
1849         hbox.pack_start( w, FALSE, FALSE, 1 );
1850         w.show();
1851
1852         // -------------------------- //
1853
1854         hbox = ui::HBox( FALSE, 10 );
1855         vbox.pack_start( hbox, FALSE, FALSE, 0 );
1856         hbox.show();
1857
1858         textlinkName = ui::Entry( 256 );
1859         hbox.pack_start( textlinkName, FALSE, FALSE, 0 );
1860         textlinkName.show();
1861
1862         w = ui::Label( "Basename for chain's targetnames." );
1863         hbox.pack_start( w, FALSE, FALSE, 1 );
1864         w.show();
1865
1866
1867         w = ui::Button( "OK" );
1868         hbox.pack_start( w, TRUE, TRUE, 0 );
1869         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
1870         gtk_widget_set_can_default( w, true );
1871         gtk_widget_grab_default( w );
1872         w.show();
1873
1874         w = ui::Button( "Cancel" );
1875         hbox.pack_start( w, TRUE, TRUE, 0 );
1876         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
1877         w.show();
1878
1879         ret = eIDCANCEL;
1880
1881         gtk_window_set_position(  window, GTK_WIN_POS_CENTER );
1882         window.show();
1883         gtk_grab_add( window );
1884
1885         bool dialogError = TRUE;
1886         while ( dialogError )
1887         {
1888                 loop = 1;
1889                 while ( loop )
1890                         gtk_main_iteration();
1891
1892                 dialogError = FALSE;
1893
1894                 if ( ret == eIDOK ) {
1895                         strcpy( rs->linkName, gtk_entry_get_text( textlinkName ) );
1896                         if ( !ValidateTextInt( gtk_entry_get_text( textlinkNum ), "Elements", &rs->linkNum ) ) {
1897                                 dialogError = TRUE;
1898                         }
1899                 }
1900         }
1901
1902         gtk_grab_remove( window );
1903         window.destroy();
1904
1905         return ret;
1906 }