]> git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/meshtex/SetScaleDialog.cpp
* added MeshTex plugin src to project (can't compile)
[xonotic/netradiant.git] / contrib / meshtex / SetScaleDialog.cpp
1 /**
2  * @file SetScaleDialog.cpp
3  * Implements the SetScaleDialog class.
4  * @ingroup meshtex-ui
5  */
6
7 /*
8  * Copyright 2012 Joel Baxter
9  *
10  * This file is part of MeshTex.
11  *
12  * MeshTex is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * MeshTex is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with MeshTex.  If not, see <http://www.gnu.org/licenses/>.
24  */
25
26 #include <gtk/gtk.h>
27
28 #include "GenericPluginUI.h"
29 #include "SetScaleDialog.h"
30 #include "PluginUIMessages.h"
31
32 #include "iundo.h"
33
34
35 /**
36  * Size of buffer for the text conversion of float values written to various
37  * widgets.
38  */
39 #define ENTRY_BUFFER_SIZE 128
40
41
42 /**
43  * Constructor.
44  *
45  * @param rowArgs The row (S axis) arguments; NULL if none.
46  * @param colArgs The column (T axis) arguments; NULL if none.
47  */
48 SetScaleDialog::SetScaleVisitor::SetScaleVisitor(
49    const SliceArgs *rowArgs,
50    const SliceArgs *colArgs) :
51    _rowArgs(rowArgs),
52    _colArgs(colArgs)
53 {
54 }
55
56 /**
57  * Visitor action; invoke MeshEntity::SetScale on a mesh.
58  *
59  * @param [in,out] meshEntity The mesh entity.
60  *
61  * @return true.
62  */
63 bool
64 SetScaleDialog::SetScaleVisitor::Execute(MeshEntity& meshEntity) const
65 {
66    if (_rowArgs != NULL)
67    {
68       meshEntity.SetScale(MeshEntity::ROW_SLICE_TYPE,
69                           _rowArgs->alignSlice, _rowArgs->refSlice,
70                           _rowArgs->naturalScale, _rowArgs->scaleOrTiles);
71    }
72    if (_colArgs != NULL)
73    {
74       meshEntity.SetScale(MeshEntity::COL_SLICE_TYPE,
75                           _colArgs->alignSlice, _colArgs->refSlice,
76                           _colArgs->naturalScale, _colArgs->scaleOrTiles);
77    }
78    return true;
79 }
80
81 /**
82  * Constructor. Configure the dialog window and create all the contained
83  * widgets. Connect widgets to callbacks as necessary.
84  *
85  * @param key The unique key identifying this dialog.
86  */
87 SetScaleDialog::SetScaleDialog(const std::string& key) :
88    GenericDialog(key),
89    _nullVisitor(new MeshVisitor())
90 {
91    // Enable the usual handling of the close event.
92    CreateWindowCloseCallback();
93
94    // Configure the dialog window.
95    gtk_window_set_resizable(GTK_WINDOW(_dialog), FALSE);
96    gtk_window_set_title(GTK_WINDOW(_dialog), DIALOG_SET_SCALE_TITLE);
97    gtk_container_set_border_width(GTK_CONTAINER(_dialog), 10);
98
99    // Create the contained widgets.
100
101    GtkWidget *table;
102    GtkWidget *entry;
103    GtkWidget *applybutton, *refbutton, *button;
104    GtkWidget *label;
105    GtkWidget *mainvbox, *vbox, *hbox;
106    GtkWidget *frame;
107
108    table = gtk_table_new(2, 2, FALSE);
109    gtk_table_set_row_spacing(GTK_TABLE(table), 0, 15);
110    gtk_table_set_col_spacing(GTK_TABLE(table), 0, 10);
111    gtk_container_add(GTK_CONTAINER(_dialog), table);
112    gtk_widget_show(table);
113
114    // Checkbox for the "S" grouping of widgets. All the widgets in that
115    // grouping will have a dependence registered on this checkbox; i.e. they
116    // will only be active when it is checked.
117
118    applybutton = gtk_check_button_new_with_label(DIALOG_SET_SCALE_S_ACTIVE_OPT_LABEL);
119    gtk_object_set_data(GTK_OBJECT(_dialog), "s_apply", applybutton);
120    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(applybutton), TRUE);
121    gtk_widget_show(applybutton);
122
123    frame = gtk_frame_new(NULL);
124    gtk_frame_set_label_widget(GTK_FRAME(frame), applybutton);
125    gtk_table_attach_defaults(GTK_TABLE(table), frame, 0, 1, 0, 1);
126    gtk_widget_show(frame);
127
128    mainvbox = gtk_vbox_new(FALSE, 0);
129    gtk_container_add(GTK_CONTAINER(frame), mainvbox);
130    gtk_widget_show(mainvbox);
131
132    hbox = gtk_hbox_new(FALSE, 0);
133    gtk_box_pack_start(GTK_BOX(mainvbox), hbox, TRUE, TRUE, 5);
134    gtk_widget_show(hbox);
135
136    // Widgets for specifying S scaling.
137
138    label = gtk_label_new(DIALOG_SET_SCALE_METHOD_FRAME_TITLE);
139    gtk_widget_show(label);
140
141    UIInstance().RegisterWidgetDependence(applybutton, label);
142
143    frame = gtk_frame_new(NULL);
144    gtk_frame_set_label_widget(GTK_FRAME(frame), label);
145    gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 5);
146    gtk_widget_show(frame);
147
148    vbox = gtk_vbox_new(FALSE, 0);
149    gtk_container_add(GTK_CONTAINER(frame), vbox);
150    gtk_widget_show(vbox);
151
152    hbox = gtk_hbox_new(FALSE, 0);
153    gtk_box_pack_end(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
154    gtk_widget_show(hbox);
155
156    button = gtk_radio_button_new_with_label(NULL, DIALOG_SET_SCALE_TILES_OPT_LABEL);
157    gtk_object_set_data(GTK_OBJECT(_dialog), "s_tiling", button);
158    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
159    gtk_widget_show(button);
160
161    UIInstance().RegisterWidgetDependence(applybutton, button);
162
163    entry = gtk_entry_new();
164    gtk_object_set_data(GTK_OBJECT(_dialog), "s_tiles", entry);
165    gtk_entry_set_text(GTK_ENTRY(entry), "1");
166    gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
167    gtk_widget_set_usize(entry, 50, -2);
168    gtk_widget_set_sensitive(entry, FALSE);
169    gtk_widget_show(entry);
170
171    UIInstance().RegisterWidgetDependence(applybutton, entry);
172    UIInstance().RegisterWidgetDependence(button, entry);
173
174    hbox = gtk_hbox_new(FALSE, 0);
175    gtk_box_pack_end(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
176    gtk_widget_show(hbox);
177
178    button = gtk_radio_button_new_with_label(
179       gtk_radio_button_group(GTK_RADIO_BUTTON(button)),
180                              DIALOG_SET_SCALE_NATURAL_OPT_LABEL);
181    gtk_object_set_data(GTK_OBJECT(_dialog), "s_natural", button);
182    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
183    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
184    gtk_widget_show(button);
185
186    UIInstance().RegisterWidgetDependence(applybutton, button);
187
188    entry = gtk_entry_new();
189    gtk_object_set_data(GTK_OBJECT(_dialog), "s_scale", entry);
190    gtk_entry_set_text(GTK_ENTRY(entry), "1");
191    gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
192    gtk_widget_set_usize(entry, 50, -2);
193    gtk_widget_set_sensitive(entry, TRUE);
194    gtk_widget_show(entry);
195
196    UIInstance().RegisterWidgetDependence(applybutton, entry);
197    UIInstance().RegisterWidgetDependence(button, entry);
198
199    hbox = gtk_hbox_new(FALSE, 0);
200    gtk_box_pack_start(GTK_BOX(mainvbox), hbox, TRUE, TRUE, 5);
201    gtk_widget_show(hbox);
202
203    // Widgets for specifying the alignment column.
204
205    label = gtk_label_new(DIALOG_SET_SCALE_S_ALIGN_FRAME_TITLE);
206    gtk_widget_show(label);
207
208    UIInstance().RegisterWidgetDependence(applybutton, label);
209
210    frame = gtk_frame_new(NULL);
211    gtk_frame_set_label_widget(GTK_FRAME(frame), label);
212    gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 5);
213    gtk_widget_show(frame);
214
215    vbox = gtk_vbox_new(FALSE, 0);
216    gtk_container_add(GTK_CONTAINER(frame), vbox);
217    gtk_widget_show(vbox);
218
219    hbox = gtk_hbox_new(FALSE, 0);
220    gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
221    gtk_widget_show(hbox);
222
223    button = gtk_radio_button_new(NULL);
224    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
225    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
226    gtk_widget_show(button);
227
228    UIInstance().RegisterWidgetDependence(applybutton, button);
229
230    entry = gtk_entry_new();
231    gtk_object_set_data(GTK_OBJECT(_dialog), "col_num_align", entry);
232    gtk_entry_set_text(GTK_ENTRY(entry), "0");
233    gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
234    gtk_widget_set_usize(entry, 25, -2);
235    gtk_widget_show(entry);
236
237    UIInstance().RegisterWidgetDependence(applybutton, entry);
238    UIInstance().RegisterWidgetDependence(button, entry);
239
240    button = gtk_radio_button_new_with_label(
241       gtk_radio_button_group(GTK_RADIO_BUTTON(button)),
242                              DIALOG_SET_SCALE_MAX_OPT_LABEL);
243    gtk_object_set_data(GTK_OBJECT(_dialog), "col_max_align", button);
244    gtk_box_pack_end(GTK_BOX(hbox), button, TRUE, FALSE, 5);
245    gtk_widget_show(button);
246
247    UIInstance().RegisterWidgetDependence(applybutton, button);
248
249    hbox = gtk_hbox_new(FALSE, 0);
250    gtk_box_pack_start(GTK_BOX(mainvbox), hbox, TRUE, TRUE, 5);
251    gtk_widget_show(hbox);
252
253    // Widgets for specifying the reference row & usage.
254
255    refbutton = gtk_check_button_new_with_label(DIALOG_SET_SCALE_S_REF_ROW_OPT_LABEL);
256    gtk_object_set_data(GTK_OBJECT(_dialog), "row_ref", refbutton);
257    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(refbutton), TRUE);
258    gtk_widget_show(refbutton);
259
260    UIInstance().RegisterWidgetDependence(applybutton, refbutton);
261
262    frame = gtk_frame_new(NULL);
263    gtk_frame_set_label_widget(GTK_FRAME(frame), refbutton);
264    gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 5);
265    gtk_widget_show(frame);
266
267    vbox = gtk_vbox_new(FALSE, 0);
268    gtk_container_add(GTK_CONTAINER(frame), vbox);
269    gtk_widget_show(vbox);
270
271    hbox = gtk_hbox_new(FALSE, 0);
272    gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
273    gtk_widget_show(hbox);
274
275    button = gtk_radio_button_new(NULL);
276    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
277    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
278    gtk_widget_show(button);
279
280    UIInstance().RegisterWidgetDependence(applybutton, button);
281    UIInstance().RegisterWidgetDependence(refbutton, button);
282
283    entry = gtk_entry_new();
284    gtk_object_set_data(GTK_OBJECT(_dialog), "row_num_ref", entry);
285    gtk_entry_set_text(GTK_ENTRY(entry), "0");
286    gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
287    gtk_widget_set_usize(entry, 25, -2);
288    gtk_widget_show(entry);
289
290    UIInstance().RegisterWidgetDependence(applybutton, entry);
291    UIInstance().RegisterWidgetDependence(refbutton, entry);
292    UIInstance().RegisterWidgetDependence(button, entry);
293
294    button = gtk_radio_button_new_with_label(
295       gtk_radio_button_group(GTK_RADIO_BUTTON(button)),
296                              DIALOG_SET_SCALE_MAX_OPT_LABEL);
297    gtk_object_set_data(GTK_OBJECT(_dialog), "row_max_ref", button);
298    gtk_box_pack_end(GTK_BOX(hbox), button, TRUE, FALSE, 5);
299    gtk_widget_show(button);
300
301    UIInstance().RegisterWidgetDependence(applybutton, button);
302    UIInstance().RegisterWidgetDependence(refbutton, button);
303
304    hbox = gtk_hbox_new(FALSE, 0);
305    gtk_box_pack_end(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
306    gtk_widget_show(hbox);
307
308    button = gtk_check_button_new_with_label(DIALOG_SET_SCALE_REF_TOTAL_OPT_LABEL);
309    gtk_object_set_data(GTK_OBJECT(_dialog), "row_ref_total", button);
310    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
311    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
312    gtk_widget_show(button);
313
314    UIInstance().RegisterWidgetDependence(applybutton, button);
315    UIInstance().RegisterWidgetDependence(refbutton, button);
316
317    // Checkbox for the "T" grouping of widgets. All the widgets in that
318    // grouping will have a dependence registered on this checkbox; i.e. they
319    // will only be active when it is checked.
320
321    applybutton = gtk_check_button_new_with_label(DIALOG_SET_SCALE_T_ACTIVE_OPT_LABEL);
322    gtk_object_set_data(GTK_OBJECT(_dialog), "t_apply", applybutton);
323    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(applybutton), TRUE);
324    gtk_widget_show(applybutton);
325
326    frame = gtk_frame_new(NULL);
327    gtk_frame_set_label_widget(GTK_FRAME(frame), applybutton);
328    gtk_table_attach_defaults(GTK_TABLE(table), frame, 1, 2, 0, 1);
329    gtk_widget_show(frame);
330
331    mainvbox = gtk_vbox_new(FALSE, 0);
332    gtk_container_add(GTK_CONTAINER(frame), mainvbox);
333    gtk_widget_show(mainvbox);
334
335    hbox = gtk_hbox_new(FALSE, 0);
336    gtk_box_pack_start(GTK_BOX(mainvbox), hbox, TRUE, TRUE, 5);
337    gtk_widget_show(hbox);
338
339    // Widgets for specifying T scaling.
340
341    label = gtk_label_new(DIALOG_SET_SCALE_METHOD_FRAME_TITLE);
342    gtk_widget_show(label);
343
344    UIInstance().RegisterWidgetDependence(applybutton, label);
345
346    frame = gtk_frame_new(NULL);
347    gtk_frame_set_label_widget(GTK_FRAME(frame), label);
348    gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 5);
349    gtk_widget_show(frame);
350
351    vbox = gtk_vbox_new(FALSE, 0);
352    gtk_container_add(GTK_CONTAINER(frame), vbox);
353    gtk_widget_show(vbox);
354
355    hbox = gtk_hbox_new(FALSE, 0);
356    gtk_box_pack_end(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
357    gtk_widget_show(hbox);
358
359    button = gtk_radio_button_new_with_label(NULL, DIALOG_SET_SCALE_TILES_OPT_LABEL);
360    gtk_object_set_data(GTK_OBJECT(_dialog), "t_tiling", button);
361    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
362    gtk_widget_show(button);
363
364    UIInstance().RegisterWidgetDependence(applybutton, button);
365
366    entry = gtk_entry_new();
367    gtk_object_set_data(GTK_OBJECT(_dialog), "t_tiles", entry);
368    gtk_entry_set_text(GTK_ENTRY(entry), "1");
369    gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
370    gtk_widget_set_usize(entry, 50, -2);
371    gtk_widget_set_sensitive(entry, FALSE);
372    gtk_widget_show(entry);
373
374    UIInstance().RegisterWidgetDependence(applybutton, entry);
375    UIInstance().RegisterWidgetDependence(button, entry);
376
377    hbox = gtk_hbox_new(FALSE, 0);
378    gtk_box_pack_end(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
379    gtk_widget_show(hbox);
380
381    button = gtk_radio_button_new_with_label(
382       gtk_radio_button_group(GTK_RADIO_BUTTON(button)),
383                              DIALOG_SET_SCALE_NATURAL_OPT_LABEL);
384    gtk_object_set_data(GTK_OBJECT(_dialog), "t_natural", button);
385    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
386    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
387    gtk_widget_show(button);
388
389    UIInstance().RegisterWidgetDependence(applybutton, button);
390
391    entry = gtk_entry_new();
392    gtk_object_set_data(GTK_OBJECT(_dialog), "t_scale", entry);
393    gtk_entry_set_text(GTK_ENTRY(entry), "1");
394    gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
395    gtk_widget_set_usize(entry, 50, -2);
396    gtk_widget_set_sensitive(entry, TRUE);
397    gtk_widget_show(entry);
398
399    UIInstance().RegisterWidgetDependence(applybutton, entry);
400    UIInstance().RegisterWidgetDependence(button, entry);
401
402    hbox = gtk_hbox_new(FALSE, 0);
403    gtk_box_pack_start(GTK_BOX(mainvbox), hbox, TRUE, TRUE, 5);
404    gtk_widget_show(hbox);
405
406    // Widgets for specifying the alignment row.
407
408    label = gtk_label_new(DIALOG_SET_SCALE_T_ALIGN_FRAME_TITLE);
409    gtk_widget_show(label);
410
411    UIInstance().RegisterWidgetDependence(applybutton, label);
412
413    frame = gtk_frame_new(NULL);
414    gtk_frame_set_label_widget(GTK_FRAME(frame), label);
415    gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 5);
416    gtk_widget_show(frame);
417
418    vbox = gtk_vbox_new(FALSE, 0);
419    gtk_container_add(GTK_CONTAINER(frame), vbox);
420    gtk_widget_show(vbox);
421
422    hbox = gtk_hbox_new(FALSE, 0);
423    gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
424    gtk_widget_show(hbox);
425
426    button = gtk_radio_button_new(NULL);
427    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
428    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
429    gtk_widget_show(button);
430
431    UIInstance().RegisterWidgetDependence(applybutton, button);
432
433    entry = gtk_entry_new();
434    gtk_object_set_data(GTK_OBJECT(_dialog), "row_num_align", entry);
435    gtk_entry_set_text(GTK_ENTRY(entry), "0");
436    gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
437    gtk_widget_set_usize(entry, 25, -2);
438    gtk_widget_show(entry);
439
440    UIInstance().RegisterWidgetDependence(applybutton, entry);
441    UIInstance().RegisterWidgetDependence(button, entry);
442
443    button = gtk_radio_button_new_with_label(
444       gtk_radio_button_group(GTK_RADIO_BUTTON(button)),
445                              DIALOG_SET_SCALE_MAX_OPT_LABEL);
446    gtk_object_set_data(GTK_OBJECT(_dialog), "row_max_align", button);
447    gtk_box_pack_end(GTK_BOX(hbox), button, TRUE, FALSE, 5);
448    gtk_widget_show(button);
449
450    UIInstance().RegisterWidgetDependence(applybutton, button);
451
452    hbox = gtk_hbox_new(FALSE, 0);
453    gtk_box_pack_start(GTK_BOX(mainvbox), hbox, TRUE, TRUE, 5);
454    gtk_widget_show(hbox);
455
456    // Widgets for specifying the reference column & usage.
457
458    refbutton = gtk_check_button_new_with_label(DIALOG_SET_SCALE_T_REF_COL_OPT_LABEL);
459    gtk_object_set_data(GTK_OBJECT(_dialog), "col_ref", refbutton);
460    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(refbutton), TRUE);
461    gtk_widget_show(refbutton);
462
463    UIInstance().RegisterWidgetDependence(applybutton, refbutton);
464
465    frame = gtk_frame_new(NULL);
466    gtk_frame_set_label_widget(GTK_FRAME(frame), refbutton);
467    gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 5);
468    gtk_widget_show(frame);
469
470    vbox = gtk_vbox_new(FALSE, 0);
471    gtk_container_add(GTK_CONTAINER(frame), vbox);
472    gtk_widget_show(vbox);
473
474    hbox = gtk_hbox_new(FALSE, 0);
475    gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
476    gtk_widget_show(hbox);
477
478    button = gtk_radio_button_new(NULL);
479    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
480    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
481    gtk_widget_show(button);
482
483    UIInstance().RegisterWidgetDependence(applybutton, button);
484    UIInstance().RegisterWidgetDependence(refbutton, button);
485
486    entry = gtk_entry_new();
487    gtk_object_set_data(GTK_OBJECT(_dialog), "col_num_ref", entry);
488    gtk_entry_set_text(GTK_ENTRY(entry), "0");
489    gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
490    gtk_widget_set_usize(entry, 25, -2);
491    gtk_widget_show(entry);
492
493    UIInstance().RegisterWidgetDependence(applybutton, entry);
494    UIInstance().RegisterWidgetDependence(refbutton, entry);
495    UIInstance().RegisterWidgetDependence(button, entry);
496
497    button = gtk_radio_button_new_with_label(
498       gtk_radio_button_group(GTK_RADIO_BUTTON(button)),
499                              DIALOG_SET_SCALE_MAX_OPT_LABEL);
500    gtk_object_set_data(GTK_OBJECT(_dialog), "col_max_ref", button);
501    gtk_box_pack_end(GTK_BOX(hbox), button, TRUE, FALSE, 5);
502    gtk_widget_show(button);
503
504    UIInstance().RegisterWidgetDependence(applybutton, button);
505    UIInstance().RegisterWidgetDependence(refbutton, button);
506
507    hbox = gtk_hbox_new(FALSE, 0);
508    gtk_box_pack_end(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
509    gtk_widget_show(hbox);
510
511    button = gtk_check_button_new_with_label(DIALOG_SET_SCALE_REF_TOTAL_OPT_LABEL);
512    gtk_object_set_data(GTK_OBJECT(_dialog), "col_ref_total", button);
513    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
514    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
515    gtk_widget_show(button);
516
517    UIInstance().RegisterWidgetDependence(applybutton, button);
518    UIInstance().RegisterWidgetDependence(refbutton, button);
519
520    hbox = gtk_hbox_new(FALSE, 0);
521    gtk_table_attach_defaults(GTK_TABLE(table), hbox, 0, 2, 1, 2);
522    gtk_widget_show(hbox);
523
524    // Create Cancel button and hook it to callback.
525
526    button = gtk_button_new_with_label(DIALOG_CANCEL_BUTTON);
527    gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
528    gtk_widget_set_usize(button, 60, -2);
529    gtk_widget_show(button);
530
531    CreateCancelButtonCallback(button);
532
533    // Create Apply button and hook it to callback.
534
535    button = gtk_button_new_with_label(DIALOG_APPLY_BUTTON);
536    gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 10);
537    gtk_widget_set_usize (button, 60, -2);
538    gtk_widget_show(button);
539
540    CreateApplyButtonCallback(button);
541
542    // Create OK button and hook it to callback.
543
544    button = gtk_button_new_with_label(DIALOG_OK_BUTTON);
545    gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
546    gtk_widget_set_usize (button, 60, -2);
547    gtk_widget_show(button);
548
549    CreateOkButtonCallback(button);
550 }
551
552 /**
553  * Destructor.
554  */
555 SetScaleDialog::~SetScaleDialog()
556 {
557 }
558
559 /**
560  * Handler for the Apply logic for this dialog. Apply the specified scaling to
561  * the selected mesh entities.
562  *
563  * @return true if any meshes are selected, false otherwise.
564  */
565 bool
566 SetScaleDialog::Apply()
567 {
568    // Before doing anything, check to see if there are some meshes selected.
569    _nullVisitor->ResetVisitedCount();
570    GlobalSelectionSystem().foreachSelected(*_nullVisitor);
571    if (_nullVisitor->GetVisitedCount() == 0)
572    {
573       // Nope. Warn and bail out.
574       GenericPluginUI::WarningReportDialog(DIALOG_WARNING_TITLE,
575                                            DIALOG_NOMESHES_MSG);
576       return false;
577    }
578
579    // See if we're going to be affecting the S and/or T texture axis.
580    bool sApply = NamedToggleWidgetActive("s_apply");
581    bool tApply = NamedToggleWidgetActive("t_apply");
582
583    if (!sApply && !tApply)
584    {
585       // Not affecting either, so bail out.
586       return true;
587    }
588
589    // OK read the remaining info from the widgets.
590
591    MeshEntity::SliceDesignation alignCol, alignRow;
592    MeshEntity::RefSliceDescriptor refRow, refCol;
593    SetScaleVisitor::SliceArgs row, col;
594    SetScaleVisitor::SliceArgs *rowArgs = NULL;
595    SetScaleVisitor::SliceArgs *colArgs = NULL;
596    if (sApply)
597    {
598       // S axis is affected, so read the S info.
599       row.naturalScale = NamedToggleWidgetActive("s_natural");
600       if (row.naturalScale)
601       {
602          row.scaleOrTiles = (float)atof(NamedEntryWidgetText("s_scale"));
603       }
604       else
605       {
606          row.scaleOrTiles = (float)atof(NamedEntryWidgetText("s_tiles"));
607       }
608       alignCol.maxSlice = NamedToggleWidgetActive("col_max_align");
609       alignCol.index = atoi(NamedEntryWidgetText("col_num_align"));
610       row.alignSlice = &alignCol;
611       row.refSlice = NULL;
612       if (NamedToggleWidgetActive("row_ref"))
613       {
614          // Reference row is specified, so get that info.
615          refRow.designation.maxSlice = NamedToggleWidgetActive("row_max_ref");
616          refRow.designation.index = atoi(NamedEntryWidgetText("row_num_ref"));
617          refRow.totalLengthOnly = NamedToggleWidgetActive("row_ref_total");
618          row.refSlice = &refRow;
619       }
620       rowArgs = &row;
621    }
622    if (tApply)
623    {
624       // T axis is affected, so read the T info.
625       col.naturalScale = NamedToggleWidgetActive("t_natural");
626       if (col.naturalScale)
627       {
628          col.scaleOrTiles = (float)atof(NamedEntryWidgetText("t_scale"));
629       }
630       else
631       {
632          col.scaleOrTiles = (float)atof(NamedEntryWidgetText("t_tiles"));
633       }
634       alignRow.maxSlice = NamedToggleWidgetActive("row_max_align");
635       alignRow.index = atoi(NamedEntryWidgetText("row_num_align"));
636       col.alignSlice = &alignRow;
637       col.refSlice = NULL;
638       if (NamedToggleWidgetActive("col_ref"))
639       {
640          // Reference column is specified, so get that info.
641          refCol.designation.maxSlice = NamedToggleWidgetActive("col_max_ref");
642          refCol.designation.index = atoi(NamedEntryWidgetText("col_num_ref"));
643          refCol.totalLengthOnly = NamedToggleWidgetActive("col_ref_total");
644          col.refSlice = &refCol;
645       }
646       colArgs = &col;
647    }
648
649    // Let Radiant know the name of the operation responsible for the changes
650    // that are about to happen.
651    UndoableCommand undo(_triggerCommand.c_str());
652
653    // Apply the specified scaling to every selected mesh.
654    SmartPointer<SetScaleVisitor> scaleVisitor(new SetScaleVisitor(rowArgs, colArgs));
655    GlobalSelectionSystem().foreachSelected(*scaleVisitor);
656
657    // Done!
658    return true;
659 }
660
661 /**
662  * Allow an external caller to set some of the S-axis entries.
663  *
664  * @param scale Texture scaling.
665  * @param tiles Texture tiles.
666  */
667 void
668 SetScaleDialog::PopulateSWidgets(float scale,
669                                  float tiles)
670 {
671    // Use the texture info to populate some of our widgets.
672    PopulateEntry("s_scale", scale);
673    PopulateEntry("s_tiles", tiles);
674 }
675
676 /**
677  * Allow an external caller to set some of the T-axis entries.
678  *
679  * @param scale Texture scaling.
680  * @param tiles Texture tiles.
681  */
682 void
683 SetScaleDialog::PopulateTWidgets(float scale,
684                                  float tiles)
685 {
686    // Use the texture info to populate some of our widgets.
687    PopulateEntry("t_scale", scale);
688    PopulateEntry("t_tiles", tiles);
689 }
690
691 /**
692  * Populate a text widget with a floating point number.
693  *
694  * @param widgetName Name of the widget.
695  * @param value      The number to write to the widget.
696  */
697 void
698 SetScaleDialog::PopulateEntry(const char *widgetName,
699                               float value)
700 {
701    static char entryBuffer[ENTRY_BUFFER_SIZE + 1] = { 0 };
702    snprintf(entryBuffer, ENTRY_BUFFER_SIZE, "%f", value);
703    gtk_entry_set_text(GTK_ENTRY(NamedWidget(widgetName)), entryBuffer);
704 }