]> git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/bobtoolz/dialogs/dialogs-gtk.cpp
Merge commit '70f0925f0000a132c709b935aa5cb0942b5080d9' into master-merge
[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         auto vbox = ui::VBox( FALSE, 10 );
1048         window.add(vbox);
1049         vbox.show();
1050
1051         // ---- vbox ----
1052
1053         auto hbox = ui::HBox( FALSE, 10 );
1054         vbox.pack_start( hbox, FALSE, FALSE, 2 );
1055         hbox.show();
1056
1057         // ---- hbox ----
1058
1059         auto text1 = ui::Entry( 256 );
1060         gtk_entry_set_text( text1, "25" );
1061         hbox.pack_start( text1, FALSE, FALSE, 2 );
1062         text1.show();
1063
1064         w = ui::Label( "Number Of Points" );
1065         hbox.pack_start( w, FALSE, FALSE, 2 );
1066         gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT );
1067         w.show();
1068
1069         // ---- /hbox ----
1070
1071         hbox = ui::HBox( FALSE, 10 );
1072         vbox.pack_start( hbox, FALSE, FALSE, 2 );
1073         hbox.show();
1074
1075         // ---- hbox ----
1076
1077         auto text2 = ui::Entry( 256 );
1078         gtk_entry_set_text( text2, "3" );
1079         hbox.pack_start( text2, FALSE, FALSE, 2 );
1080         text2.show();
1081
1082         w = ui::Label( "Multipler" );
1083         hbox.pack_start( w, FALSE, FALSE, 2 );
1084         gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT );
1085         w.show();
1086
1087         // ---- /hbox ----
1088
1089         w = ui::Label( "Path Distance = dist(start -> apex) * multiplier" );
1090         vbox.pack_start( w, FALSE, FALSE, 0 );
1091         gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT );
1092         w.show();
1093
1094         hbox = ui::HBox( FALSE, 10 );
1095         vbox.pack_start( hbox, FALSE, FALSE, 2 );
1096         hbox.show();
1097
1098         // ---- hbox ----
1099
1100         auto text3 = ui::Entry( 256 );
1101         gtk_entry_set_text( text3, "-800" );
1102         hbox.pack_start( text3, FALSE, FALSE, 2 );
1103         text3.show();
1104
1105         w = ui::Label( "Gravity" );
1106         hbox.pack_start( w, FALSE, FALSE, 2 );
1107         gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT );
1108         w.show();
1109
1110         // ---- /hbox ----
1111
1112         w = ui::Widget::from(gtk_hseparator_new());
1113         vbox.pack_start( w, FALSE, FALSE, 0 );
1114         w.show();
1115
1116         auto check1 = ui::CheckButton( "No Dynamic Update" );
1117         vbox.pack_start( check1, FALSE, FALSE, 0 );
1118         check1.show();
1119
1120         auto check2 = ui::CheckButton( "Show Bounding Lines" );
1121         vbox.pack_start( check2, FALSE, FALSE, 0 );
1122         check2.show();
1123
1124         // ---- /vbox ----
1125
1126
1127         // ----------------- //
1128
1129         w = ui::Widget::from(gtk_hseparator_new());
1130         vbox.pack_start( w, FALSE, FALSE, 0 );
1131         w.show();
1132
1133         // ----------------- //
1134
1135         hbox = ui::HBox( FALSE, 10 );
1136         vbox.pack_start( hbox, FALSE, FALSE, 0 );
1137         hbox.show();
1138
1139         w = ui::Button( "Enable" );
1140         hbox.pack_start( w, TRUE, TRUE, 0 );
1141         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDYES ) );
1142         w.show();
1143
1144         gtk_widget_set_can_default( w, true );
1145         gtk_widget_grab_default( w );
1146
1147         w = ui::Button( "Disable" );
1148         hbox.pack_start( w, TRUE, TRUE, 0 );
1149         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDNO ) );
1150         w.show();
1151
1152         w = ui::Button( "Cancel" );
1153         hbox.pack_start( w, TRUE, TRUE, 0 );
1154         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
1155         w.show();
1156
1157         ret = eIDCANCEL;
1158
1159         // ----------------- //
1160
1161         gtk_window_set_position( window, GTK_WIN_POS_CENTER );
1162         window.show();
1163         gtk_grab_add( window );
1164
1165         bool dialogError = TRUE;
1166         while ( dialogError )
1167         {
1168                 loop = 1;
1169                 while ( loop )
1170                         gtk_main_iteration();
1171
1172                 dialogError = FALSE;
1173
1174                 if ( ret == eIDYES ) {
1175                         if ( !ValidateTextIntRange( gtk_entry_get_text( GTK_ENTRY( text1 ) ), 1, 200, "Number Of Points", &rs->nPoints ) ) {
1176                                 dialogError = TRUE;
1177                         }
1178
1179                         if ( !ValidateTextFloatRange( gtk_entry_get_text( GTK_ENTRY( text2 ) ), 1.0f, 10.0f, "Multiplier", &rs->fMultiplier ) ) {
1180                                 dialogError = TRUE;
1181                         }
1182
1183                         if ( !ValidateTextFloatRange( gtk_entry_get_text( GTK_ENTRY( text3 ) ), -10000.0f, -1.0f, "Gravity", &rs->fGravity ) ) {
1184                                 dialogError = TRUE;
1185                         }
1186
1187                         rs->bNoUpdate = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( check1 ) ) ? true : false;
1188                         rs->bShowExtra = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( check2 ) ) ? true : false;
1189                 }
1190         }
1191
1192         gtk_grab_remove( window );
1193         window.destroy();
1194
1195         return ret;
1196 }
1197
1198 EMessageBoxReturn DoCTFColourChangeBox(){
1199         ui::Widget w{ui::null};
1200         EMessageBoxReturn ret;
1201         int loop = 1;
1202
1203         auto window = ui::Window( ui::window_type::TOP );
1204
1205         window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
1206         window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
1207
1208         gtk_window_set_title( window, "CTF Colour Changer" );
1209         gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
1210
1211         g_object_set_data( G_OBJECT( window ), "loop", &loop );
1212         g_object_set_data( G_OBJECT( window ), "ret", &ret );
1213
1214         gtk_widget_realize( window );
1215
1216
1217
1218         auto vbox = ui::VBox( FALSE, 10 );
1219         window.add(vbox);
1220         vbox.show();
1221
1222         // ---- vbox ----
1223
1224         auto hbox = ui::HBox( FALSE, 10 );
1225         vbox.pack_start( hbox, TRUE, TRUE, 0 );
1226         hbox.show();
1227
1228         // ---- hbox ---- ok/cancel buttons
1229
1230         w = ui::Button( "Red->Blue" );
1231         hbox.pack_start( w, TRUE, TRUE, 0 );
1232         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
1233
1234         gtk_widget_set_can_default( w, true );
1235         gtk_widget_grab_default( w );
1236         w.show();
1237
1238         w = ui::Button( "Blue->Red" );
1239         hbox.pack_start( w, TRUE, TRUE, 0 );
1240         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDYES ) );
1241         w.show();
1242
1243         w = ui::Button( "Cancel" );
1244         hbox.pack_start( w, TRUE, TRUE, 0 );
1245         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
1246         w.show();
1247         ret = eIDCANCEL;
1248
1249         // ---- /hbox ----
1250
1251         // ---- /vbox ----
1252
1253         gtk_window_set_position( window, GTK_WIN_POS_CENTER );
1254         window.show();
1255         gtk_grab_add( window );
1256
1257         while ( loop )
1258                 gtk_main_iteration();
1259
1260         gtk_grab_remove( window );
1261         window.destroy();
1262
1263         return ret;
1264 }
1265
1266 EMessageBoxReturn DoResetTextureBox( ResetTextureRS* rs, ui::Window main_window ){
1267         Str texSelected;
1268
1269         ui::Widget w{ui::null};
1270         ModalDialog dialog;
1271
1272         EMessageBoxReturn ret;
1273         int loop = 1;
1274
1275         auto window = main_window.create_dialog_window( "Texture Reset", G_CALLBACK( custom_dialog_delete_callback ), &dialog );
1276
1277         window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
1278
1279         gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
1280
1281         g_object_set_data( G_OBJECT( window ), "loop", &loop );
1282         g_object_set_data( G_OBJECT( window ), "ret", &ret );
1283
1284         gtk_widget_realize( window );
1285
1286         auto vbox = ui::VBox( FALSE, 10 );
1287         window.add(vbox);
1288         vbox.show();
1289
1290         // ---- vbox ----
1291
1292         auto hbox = ui::HBox( FALSE, 10 );
1293         vbox.pack_start( hbox, FALSE, FALSE, 2 );
1294         hbox.show();
1295
1296         // ---- hbox ----
1297
1298         texSelected = "Currently Selected Texture:   ";
1299         texSelected += GetCurrentTexture();
1300
1301         w = ui::Label( texSelected );
1302         hbox.pack_start( w, FALSE, FALSE, 2 );
1303         gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT );
1304         w.show();
1305
1306         // ---- /hbox ----
1307
1308         auto frame = ui::Frame( "Reset Texture Names" );
1309         frame.show();
1310         vbox.pack_start( frame, FALSE, TRUE, 0 );
1311
1312         auto table = ui::Table( 2, 3, TRUE );
1313         table.show();
1314         frame.add(table);
1315         gtk_table_set_row_spacings(table, 5);
1316         gtk_table_set_col_spacings(table, 5);
1317         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1318
1319         // ---- frame ----
1320
1321         dlgTexReset.cbTexChange = ui::CheckButton( "Enabled" );
1322         dlgTexReset.cbTexChange.connect( "toggled", G_CALLBACK( dialog_button_callback_texreset_update ), NULL );
1323         dlgTexReset.cbTexChange.show();
1324         table.attach(dlgTexReset.cbTexChange, {0, 1, 0, 1}, {GTK_FILL, 0});
1325
1326         w = ui::Label( "Old Name: " );
1327         table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0});
1328         w.show();
1329
1330         dlgTexReset.editTexOld = ui::Entry( 256 );
1331         gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editTexOld ), rs->textureName );
1332         table.attach(dlgTexReset.editTexOld, {2, 3, 0, 1}, {GTK_FILL, 0});
1333         dlgTexReset.editTexOld.show();
1334
1335         w = ui::Label( "New Name: " );
1336         table.attach(w, {1, 2, 1, 2}, {GTK_FILL, 0});
1337         w.show();
1338
1339         dlgTexReset.editTexNew = ui::Entry( 256 );
1340         gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editTexNew ), rs->textureName );
1341         table.attach(dlgTexReset.editTexNew, {2, 3, 1, 2}, {GTK_FILL, 0});
1342         dlgTexReset.editTexNew.show();
1343
1344         // ---- /frame ----
1345
1346         frame = ui::Frame( "Reset Scales" );
1347         frame.show();
1348         vbox.pack_start( frame, FALSE, TRUE, 0 );
1349
1350         table = ui::Table( 2, 3, TRUE );
1351         table.show();
1352         frame.add(table);
1353         gtk_table_set_row_spacings(table, 5);
1354         gtk_table_set_col_spacings(table, 5);
1355         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1356
1357         // ---- frame ----
1358
1359         dlgTexReset.cbScaleHor = ui::CheckButton( "Enabled" );
1360         dlgTexReset.cbScaleHor.connect( "toggled", G_CALLBACK( dialog_button_callback_texreset_update ), NULL );
1361         dlgTexReset.cbScaleHor.show();
1362         table.attach(dlgTexReset.cbScaleHor, {0, 1, 0, 1}, {GTK_FILL, 0});
1363
1364         w = ui::Label( "New Horizontal Scale: " );
1365         table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0});
1366         w.show();
1367
1368         dlgTexReset.editScaleHor = ui::Entry( 256 );
1369         gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editScaleHor ), "0.5" );
1370         table.attach(dlgTexReset.editScaleHor, {2, 3, 0, 1}, {GTK_FILL, 0});
1371         dlgTexReset.editScaleHor.show();
1372
1373
1374         dlgTexReset.cbScaleVert = ui::CheckButton( "Enabled" );
1375         dlgTexReset.cbScaleVert.connect( "toggled", G_CALLBACK( dialog_button_callback_texreset_update ), NULL );
1376         dlgTexReset.cbScaleVert.show();
1377         table.attach(dlgTexReset.cbScaleVert, {0, 1, 1, 2}, {GTK_FILL, 0});
1378
1379         w = ui::Label( "New Vertical Scale: " );
1380         table.attach(w, {1, 2, 1, 2}, {GTK_FILL, 0});
1381         w.show();
1382
1383         dlgTexReset.editScaleVert = ui::Entry( 256 );
1384         gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editScaleVert ), "0.5" );
1385         table.attach(dlgTexReset.editScaleVert, {2, 3, 1, 2}, {GTK_FILL, 0});
1386         dlgTexReset.editScaleVert.show();
1387
1388         // ---- /frame ----
1389
1390         frame = ui::Frame( "Reset Shift" );
1391         frame.show();
1392         vbox.pack_start( frame, FALSE, TRUE, 0 );
1393
1394         table = ui::Table( 2, 3, TRUE );
1395         table.show();
1396         frame.add(table);
1397         gtk_table_set_row_spacings(table, 5);
1398         gtk_table_set_col_spacings(table, 5);
1399         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1400
1401         // ---- frame ----
1402
1403         dlgTexReset.cbShiftHor = ui::CheckButton( "Enabled" );
1404         dlgTexReset.cbShiftHor.connect( "toggled", G_CALLBACK( dialog_button_callback_texreset_update ), NULL );
1405         dlgTexReset.cbShiftHor.show();
1406         table.attach(dlgTexReset.cbShiftHor, {0, 1, 0, 1}, {GTK_FILL, 0});
1407
1408         w = ui::Label( "New Horizontal Shift: " );
1409         table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0});
1410         w.show();
1411
1412         dlgTexReset.editShiftHor = ui::Entry( 256 );
1413         gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editShiftHor ), "0" );
1414         table.attach(dlgTexReset.editShiftHor, {2, 3, 0, 1}, {GTK_FILL, 0});
1415         dlgTexReset.editShiftHor.show();
1416
1417
1418         dlgTexReset.cbShiftVert = ui::CheckButton( "Enabled" );
1419         dlgTexReset.cbShiftVert.connect( "toggled", G_CALLBACK( dialog_button_callback_texreset_update ), NULL );
1420         dlgTexReset.cbShiftVert.show();
1421         table.attach(dlgTexReset.cbShiftVert, {0, 1, 1, 2}, {GTK_FILL, 0});
1422
1423         w = ui::Label( "New Vertical Shift: " );
1424         table.attach(w, {1, 2, 1, 2}, {GTK_FILL, 0});
1425         w.show();
1426
1427         dlgTexReset.editShiftVert = ui::Entry( 256 );
1428         gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editShiftVert ), "0" );
1429         table.attach(dlgTexReset.editShiftVert, {2, 3, 1, 2}, {GTK_FILL, 0});
1430         dlgTexReset.editShiftVert.show();
1431
1432         // ---- /frame ----
1433
1434         frame = ui::Frame( "Reset Rotation" );
1435         frame.show();
1436         vbox.pack_start( frame, FALSE, TRUE, 0 );
1437
1438         table = ui::Table( 1, 3, TRUE );
1439         table.show();
1440         frame.add(table);
1441         gtk_table_set_row_spacings(table, 5);
1442         gtk_table_set_col_spacings(table, 5);
1443         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1444
1445         // ---- frame ----
1446
1447         dlgTexReset.cbRotation = ui::CheckButton( "Enabled" );
1448         dlgTexReset.cbRotation.show();
1449         table.attach(dlgTexReset.cbRotation, {0, 1, 0, 1}, {GTK_FILL, 0});
1450
1451         w = ui::Label( "New Rotation Value: " );
1452         table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0});
1453         w.show();
1454
1455         dlgTexReset.editRotation = ui::Entry( 256 );
1456         gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editRotation ), "0" );
1457         table.attach(dlgTexReset.editRotation, {2, 3, 0, 1}, {GTK_FILL, 0});
1458         dlgTexReset.editRotation.show();
1459
1460         // ---- /frame ----
1461
1462         hbox = ui::HBox( FALSE, 10 );
1463         vbox.pack_start( hbox, FALSE, FALSE, 2 );
1464         hbox.show();
1465
1466         // ---- hbox ----
1467
1468         w = ui::Button( "Use Selected Brushes" );
1469         hbox.pack_start( w, TRUE, TRUE, 0 );
1470         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
1471
1472         gtk_widget_set_can_default( w, true );
1473         gtk_widget_grab_default( w );
1474         w.show();
1475
1476         w = ui::Button( "Use All Brushes" );
1477         hbox.pack_start( w, TRUE, TRUE, 0 );
1478         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDYES ) );
1479         w.show();
1480
1481         w = ui::Button( "Cancel" );
1482         hbox.pack_start( w, TRUE, TRUE, 0 );
1483         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
1484         w.show();
1485         ret = eIDCANCEL;
1486
1487         // ---- /hbox ----
1488
1489         // ---- /vbox ----
1490
1491         window.show();
1492         gtk_grab_add( window );
1493
1494         Update_TextureReseter();
1495
1496         bool dialogError = TRUE;
1497         while ( dialogError )
1498         {
1499                 loop = 1;
1500                 while ( loop )
1501                         gtk_main_iteration();
1502
1503                 dialogError = FALSE;
1504
1505                 if ( ret != eIDCANCEL ) {
1506                         rs->bResetRotation =  gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbRotation ) );
1507                         if ( rs->bResetRotation ) {
1508                                 if ( !ValidateTextInt( gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editRotation ) ), "Rotation", &rs->rotation ) ) {
1509                                         dialogError = TRUE;
1510                                 }
1511                         }
1512
1513                         rs->bResetScale[0] =  gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbScaleHor ) );
1514                         if ( rs->bResetScale[0] ) {
1515                                 if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editScaleHor ) ), "Horizontal Scale", &rs->fScale[0] ) ) {
1516                                         dialogError = TRUE;
1517                                 }
1518                         }
1519
1520                         rs->bResetScale[1] =  gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbScaleVert ) );
1521                         if ( rs->bResetScale[1] ) {
1522                                 if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editScaleVert ) ), "Vertical Scale", &rs->fScale[1] ) ) {
1523                                         dialogError = TRUE;
1524                                 }
1525                         }
1526
1527                         rs->bResetShift[0] =  gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbShiftHor ) );
1528                         if ( rs->bResetShift[0] ) {
1529                                 if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editShiftHor ) ), "Horizontal Shift", &rs->fShift[0] ) ) {
1530                                         dialogError = TRUE;
1531                                 }
1532                         }
1533
1534                         rs->bResetShift[1] =  gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbShiftVert ) );
1535                         if ( rs->bResetShift[1] ) {
1536                                 if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editShiftVert ) ), "Vertical Shift", &rs->fShift[1] ) ) {
1537                                         dialogError = TRUE;
1538                                 }
1539                         }
1540
1541                         rs->bResetTextureName =  gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbTexChange ) );
1542                         if ( rs->bResetTextureName ) {
1543                                 strcpy( rs->textureName,     gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editTexOld ) ) );
1544                                 strcpy( rs->newTextureName,  gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editTexNew ) ) );
1545                         }
1546                 }
1547         }
1548
1549         gtk_grab_remove( window );
1550         window.destroy();
1551
1552         return ret;
1553 }
1554
1555 EMessageBoxReturn DoTrainThingBox( TrainThingRS* rs ){
1556         Str texSelected;
1557
1558         ui::Widget w{ui::null};
1559
1560         ui::Widget radiusX{ui::null}, radiusY{ui::null};
1561         ui::Widget angleStart{ui::null}, angleEnd{ui::null};
1562         ui::Widget heightStart{ui::null}, heightEnd{ui::null};
1563         ui::Widget numPoints{ui::null};
1564
1565         EMessageBoxReturn ret;
1566         int loop = 1;
1567
1568         auto window = ui::Window( ui::window_type::TOP );
1569
1570         window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
1571         window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
1572
1573         gtk_window_set_title( window, "Train Thing" );
1574         gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
1575
1576         g_object_set_data( G_OBJECT( window ), "loop", &loop );
1577         g_object_set_data( G_OBJECT( window ), "ret", &ret );
1578
1579         gtk_widget_realize( window );
1580
1581         auto vbox = ui::VBox( FALSE, 10 );
1582         window.add(vbox);
1583         vbox.show();
1584
1585         // ---- vbox ----
1586
1587         auto hbox = ui::HBox( FALSE, 10 );
1588         vbox.pack_start( hbox, FALSE, FALSE, 2 );
1589         hbox.show();
1590
1591         // ---- /hbox ----
1592
1593         auto frame = ui::Frame( "Radii" );
1594         frame.show();
1595         vbox.pack_start( frame, FALSE, TRUE, 0 );
1596
1597         auto table = ui::Table( 2, 3, TRUE );
1598         table.show();
1599         frame.add(table);
1600         gtk_table_set_row_spacings(table, 5);
1601         gtk_table_set_col_spacings(table, 5);
1602         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1603
1604         // ---- frame ----
1605
1606         w = ui::Label( "X: " );
1607         table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0});
1608         w.show();
1609
1610         radiusX = ui::Entry( 256 );
1611         gtk_entry_set_text( GTK_ENTRY( radiusX ), "100" );
1612         table.attach(radiusX, {1, 2, 0, 1}, {GTK_FILL, 0});
1613         radiusX.show();
1614
1615
1616
1617         w = ui::Label( "Y: " );
1618         table.attach(w, {0, 1, 1, 2}, {GTK_FILL, 0});
1619         w.show();
1620
1621         radiusY = ui::Entry( 256 );
1622         gtk_entry_set_text( GTK_ENTRY( radiusY ), "100" );
1623         table.attach(radiusY, {1, 2, 1, 2}, {GTK_FILL, 0});
1624         radiusY.show();
1625
1626
1627
1628         frame = ui::Frame( "Angles" );
1629         frame.show();
1630         vbox.pack_start( frame, FALSE, TRUE, 0 );
1631
1632         table = ui::Table( 2, 3, TRUE );
1633         table.show();
1634         frame.add(table);
1635         gtk_table_set_row_spacings((table), 5);
1636         gtk_table_set_col_spacings((table), 5);
1637         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1638
1639         // ---- frame ----
1640
1641         w = ui::Label( "Start: " );
1642         table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0});
1643         w.show();
1644
1645         angleStart = ui::Entry( 256 );
1646         gtk_entry_set_text( GTK_ENTRY( angleStart ), "0" );
1647         table.attach(angleStart, {1, 2, 0, 1}, {GTK_FILL, 0});
1648         angleStart.show();
1649
1650
1651
1652         w = ui::Label( "End: " );
1653         table.attach(w, {0, 1, 1, 2}, {GTK_FILL, 0});
1654         w.show();
1655
1656         angleEnd = ui::Entry( 256 );
1657         gtk_entry_set_text( GTK_ENTRY( angleEnd ), "90" );
1658         table.attach(angleEnd, {1, 2, 1, 2}, {GTK_FILL, 0});
1659         angleEnd.show();
1660
1661
1662         frame = ui::Frame( "Height" );
1663         frame.show();
1664         vbox.pack_start( frame, FALSE, TRUE, 0 );
1665
1666         table = ui::Table( 2, 3, TRUE );
1667         table.show();
1668         frame.add(table);
1669         gtk_table_set_row_spacings(table, 5);
1670         gtk_table_set_col_spacings(table, 5);
1671         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1672
1673         // ---- frame ----
1674
1675         w = ui::Label( "Start: " );
1676         table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0});
1677         w.show();
1678
1679         heightStart = ui::Entry( 256 );
1680         gtk_entry_set_text( GTK_ENTRY( heightStart ), "0" );
1681         table.attach(heightStart, {1, 2, 0, 1}, {GTK_FILL, 0});
1682         heightStart.show();
1683
1684
1685
1686         w = ui::Label( "End: " );
1687         table.attach(w, {0, 1, 1, 2}, {GTK_FILL, 0});
1688         w.show();
1689
1690         heightEnd = ui::Entry( 256 );
1691         gtk_entry_set_text( GTK_ENTRY( heightEnd ), "0" );
1692         table.attach(heightEnd, {1, 2, 1, 2}, {GTK_FILL, 0});
1693         heightEnd.show();
1694
1695
1696
1697         frame = ui::Frame( "Points" );
1698         frame.show();
1699         vbox.pack_start( frame, FALSE, TRUE, 0 );
1700
1701         table = ui::Table( 2, 3, TRUE );
1702         table.show();
1703         frame.add(table);
1704         gtk_table_set_row_spacings(table, 5);
1705         gtk_table_set_col_spacings(table, 5);
1706         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1707
1708         // ---- frame ----
1709
1710         w = ui::Label( "Number: " );
1711         table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0});
1712         w.show();
1713
1714         numPoints = ui::Entry( 256 );
1715         gtk_entry_set_text( GTK_ENTRY( numPoints ), "0" );
1716         table.attach(numPoints, {1, 2, 0, 1}, {GTK_FILL, 0});
1717         numPoints.show();
1718
1719
1720         hbox = ui::HBox( FALSE, 10 );
1721         vbox.pack_start( hbox, FALSE, FALSE, 2 );
1722         hbox.show();
1723
1724         // ---- hbox ----
1725
1726         w = ui::Button( "Ok" );
1727         hbox.pack_start( w, TRUE, TRUE, 0 );
1728         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
1729
1730         gtk_widget_set_can_default( w, true );
1731         gtk_widget_grab_default( w );
1732         w.show();
1733
1734         w = ui::Button( "Cancel" );
1735         hbox.pack_start( w, TRUE, TRUE, 0 );
1736         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
1737         w.show();
1738         ret = eIDCANCEL;
1739
1740         // ---- /hbox ----
1741
1742
1743
1744         gtk_window_set_position( window, GTK_WIN_POS_CENTER );
1745         window.show();
1746         gtk_grab_add( window );
1747
1748         bool dialogError = TRUE;
1749         while ( dialogError )
1750         {
1751                 loop = 1;
1752                 while ( loop )
1753                         gtk_main_iteration();
1754
1755                 dialogError = FALSE;
1756
1757                 if ( ret != eIDCANCEL ) {
1758                         if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( radiusX ) ), "Radius (X)", &rs->fRadiusX ) ) {
1759                                 dialogError = TRUE;
1760                         }
1761
1762                         if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( radiusY ) ), "Radius (Y)", &rs->fRadiusY ) ) {
1763                                 dialogError = TRUE;
1764                         }
1765
1766                         if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( angleStart ) ), "Angle (Start)", &rs->fStartAngle ) ) {
1767                                 dialogError = TRUE;
1768                         }
1769
1770                         if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( angleEnd ) ), "Angle (End)", &rs->fEndAngle ) ) {
1771                                 dialogError = TRUE;
1772                         }
1773
1774                         if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( heightStart ) ), "Height (Start)", &rs->fStartHeight ) ) {
1775                                 dialogError = TRUE;
1776                         }
1777
1778                         if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( heightEnd ) ), "Height (End)", &rs->fEndHeight ) ) {
1779                                 dialogError = TRUE;
1780                         }
1781
1782                         if ( !ValidateTextInt( gtk_entry_get_text( GTK_ENTRY( numPoints ) ), "Num Points", &rs->iNumPoints ) ) {
1783                                 dialogError = TRUE;
1784                         }
1785                 }
1786         }
1787
1788         gtk_grab_remove( window );
1789         window.destroy();
1790
1791         return ret;
1792 }
1793 // ailmanki
1794 // add a simple input for the MakeChain thing..
1795 EMessageBoxReturn DoMakeChainBox( MakeChainRS* rs ){
1796         ui::Widget   w{ui::null};
1797         ui::Entry textlinkNum{ui::null}, textlinkName{ui::null};
1798         EMessageBoxReturn ret;
1799         int loop = 1;
1800
1801         const char *text = "Please set a value in the boxes below and press 'OK' to make a chain";
1802
1803         auto window = ui::Window( ui::window_type::TOP );
1804
1805         window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
1806         window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
1807
1808         gtk_window_set_title( window, "Make Chain" );
1809
1810         gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
1811
1812         g_object_set_data( G_OBJECT( window ), "loop", &loop );
1813         g_object_set_data( G_OBJECT( window ), "ret", &ret );
1814
1815         gtk_widget_realize( window );
1816
1817         // new vbox
1818         auto vbox = ui::VBox( FALSE, 10 );
1819         window.add(vbox);
1820         vbox.show();
1821
1822         auto hbox = ui::HBox( FALSE, 10 );
1823         vbox.add(hbox);
1824         hbox.show();
1825
1826         // dunno if you want this text or not ...
1827         w = ui::Label( text );
1828         hbox.pack_start( w, FALSE, FALSE, 0 );
1829         w.show();
1830
1831         w = ui::Widget::from(gtk_hseparator_new());
1832         vbox.pack_start( w, FALSE, FALSE, 0 );
1833         w.show();
1834
1835         // ------------------------- //
1836
1837         // new hbox
1838         hbox = ui::HBox( FALSE, 10 );
1839         vbox.pack_start( hbox, FALSE, FALSE, 0 );
1840         hbox.show();
1841
1842         textlinkNum = ui::Entry( 256 );
1843         hbox.pack_start( textlinkNum, FALSE, FALSE, 1 );
1844         textlinkNum.show();
1845
1846         w = ui::Label( "Number of elements in chain" );
1847         hbox.pack_start( w, FALSE, FALSE, 1 );
1848         w.show();
1849
1850         // -------------------------- //
1851
1852         hbox = ui::HBox( FALSE, 10 );
1853         vbox.pack_start( hbox, FALSE, FALSE, 0 );
1854         hbox.show();
1855
1856         textlinkName = ui::Entry( 256 );
1857         hbox.pack_start( textlinkName, FALSE, FALSE, 0 );
1858         textlinkName.show();
1859
1860         w = ui::Label( "Basename for chain's targetnames." );
1861         hbox.pack_start( w, FALSE, FALSE, 1 );
1862         w.show();
1863
1864
1865         w = ui::Button( "OK" );
1866         hbox.pack_start( w, TRUE, TRUE, 0 );
1867         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
1868         gtk_widget_set_can_default( w, true );
1869         gtk_widget_grab_default( w );
1870         w.show();
1871
1872         w = ui::Button( "Cancel" );
1873         hbox.pack_start( w, TRUE, TRUE, 0 );
1874         w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
1875         w.show();
1876
1877         ret = eIDCANCEL;
1878
1879         gtk_window_set_position(  window, GTK_WIN_POS_CENTER );
1880         window.show();
1881         gtk_grab_add( window );
1882
1883         bool dialogError = TRUE;
1884         while ( dialogError )
1885         {
1886                 loop = 1;
1887                 while ( loop )
1888                         gtk_main_iteration();
1889
1890                 dialogError = FALSE;
1891
1892                 if ( ret == eIDOK ) {
1893                         strcpy( rs->linkName, gtk_entry_get_text( textlinkName ) );
1894                         if ( !ValidateTextInt( gtk_entry_get_text( textlinkNum ), "Elements", &rs->linkNum ) ) {
1895                                 dialogError = TRUE;
1896                         }
1897                 }
1898         }
1899
1900         gtk_grab_remove( window );
1901         window.destroy();
1902
1903         return ret;
1904 }