]> git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/meshtex/GetInfoDialog.cpp
Merge branch 'master' into master-merge
[xonotic/netradiant.git] / contrib / meshtex / GetInfoDialog.cpp
1 /**
2  * @file GetInfoDialog.cpp
3  * Implements the GetInfoDialog 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 "GetInfoDialog.h"
30 #include "PluginUIMessages.h"
31
32
33 /**
34  * Constructor. See MeshEntity::GetInfo for details of how these arguments
35  * are interpreted.
36  *
37  * @param refRow             Pointer to reference row number; NULL if none.
38  * @param refCol             Pointer to reference column number; NULL if none.
39  * @param rowTexInfoCallback Pointer to callback for reference row info; NULL
40  *                           if none.
41  * @param colTexInfoCallback Pointer to callback for reference column info;
42  *                           NULL if none.
43  */
44 GetInfoDialog::GetInfoVisitor::GetInfoVisitor(
45    const int *refRow,
46    const int *refCol,
47    const MeshEntity::TexInfoCallback *rowTexInfoCallback,
48    const MeshEntity::TexInfoCallback *colTexInfoCallback) :
49    _refRow(refRow),
50    _refCol(refCol),
51    _rowTexInfoCallback(rowTexInfoCallback),
52    _colTexInfoCallback(colTexInfoCallback)
53 {
54 }
55
56 /**
57  * Visitor action; invoke MeshEntity::GetInfo on a mesh.
58  *
59  * @param [in,out] meshEntity The mesh.
60  *
61  * @return true.
62  */
63 bool
64 GetInfoDialog::GetInfoVisitor::Execute(MeshEntity& meshEntity) const
65 {
66    meshEntity.GetInfo(_refRow, _refCol, _rowTexInfoCallback, _colTexInfoCallback);
67    return true;
68 }
69
70 /**
71  * Constructor. Connect the row and column texture info callbacks to the
72  * appropriate methods on the Set S/T Scale dialog object. Configure the
73  * dialog window and create all the contained widgets. Connect widgets to
74  * callbacks as necessary.
75  *
76  * @param key            The unique key identifying this dialog.
77  * @param setScaleDialog Reference-counted handle on the Set S/T Scale dialog.
78  */
79 GetInfoDialog::GetInfoDialog(const std::string& key,
80                              SmartPointer<SetScaleDialog>& setScaleDialog) :
81    GenericDialog(key),
82    _setScaleDialog(setScaleDialog),
83    _rowTexInfoCallback(
84       MeshEntity::TexInfoCallbackMethod<SetScaleDialog,
85                                         &SetScaleDialog::PopulateSWidgets>(*setScaleDialog)),
86    _colTexInfoCallback(
87       MeshEntity::TexInfoCallbackMethod<SetScaleDialog,
88                                         &SetScaleDialog::PopulateTWidgets>(*setScaleDialog)),
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_GET_INFO_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 *button;
104    GtkWidget *label;
105    GtkWidget *hbox;
106
107    table = gtk_table_new(4, 3, FALSE);
108    gtk_table_set_row_spacing(GTK_TABLE(table), 1, 10);
109    gtk_table_set_row_spacing(GTK_TABLE(table), 2, 15);
110    gtk_container_add(GTK_CONTAINER(_dialog), table);
111    gtk_widget_show(table);
112
113    // Widgets for specifying the reference row if any.
114
115    button = gtk_check_button_new();
116    gtk_object_set_data(GTK_OBJECT(_dialog), "s_apply", button);
117    gtk_table_attach_defaults(GTK_TABLE(table), button, 0, 1, 0, 1);
118    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
119    gtk_widget_show(button);
120
121    label = gtk_label_new(DIALOG_GET_INFO_S_ROW_HEADER);
122    gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
123    gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 0, 1);
124    gtk_widget_show(label);
125
126    entry = gtk_entry_new();
127    gtk_object_set_data(GTK_OBJECT(_dialog), "s_ref_row", entry);
128    gtk_entry_set_text(GTK_ENTRY(entry), "0");
129    gtk_table_attach_defaults(GTK_TABLE(table), entry, 2, 3, 0, 1);
130    gtk_widget_set_usize(entry, 50, -2);
131    gtk_widget_show(entry);
132
133    UIInstance().RegisterWidgetDependence(button, label);
134    UIInstance().RegisterWidgetDependence(button, entry);
135
136    // Widgets for specifying the reference column if any.
137
138    button = gtk_check_button_new();
139    gtk_object_set_data(GTK_OBJECT(_dialog), "t_apply", button);
140    gtk_table_attach_defaults(GTK_TABLE(table), button, 0, 1, 1, 2);
141    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
142    gtk_widget_show(button);
143
144    label = gtk_label_new(DIALOG_GET_INFO_T_COL_HEADER);
145    gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
146    gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 1, 2);
147    gtk_widget_show(label);
148
149    entry = gtk_entry_new();
150    gtk_object_set_data(GTK_OBJECT(_dialog), "t_ref_col", entry);
151    gtk_entry_set_text(GTK_ENTRY(entry), "0");
152    gtk_table_attach_defaults(GTK_TABLE(table), entry, 2, 3, 1, 2);
153    gtk_widget_set_usize(entry, 50, -2);
154    gtk_widget_show(entry);
155
156    UIInstance().RegisterWidgetDependence(button, label);
157    UIInstance().RegisterWidgetDependence(button, entry);
158
159    // Checkbox to enable the callbacks to Set S/T Scale.
160
161    button = gtk_check_button_new_with_label(DIALOG_GET_INFO_XFER_OPT_LABEL);
162    gtk_object_set_data(GTK_OBJECT(_dialog), "transfer", button);
163    gtk_table_attach(GTK_TABLE(table), button, 0, 3, 2, 3, GTK_EXPAND, GTK_EXPAND, 0, 0);
164    gtk_widget_show(button);
165
166    hbox = gtk_hbox_new(FALSE, 0);
167    gtk_table_attach_defaults(GTK_TABLE(table), hbox, 0, 3, 3, 4);
168    gtk_widget_show(hbox);
169
170    // Create Cancel button and hook it to callback.
171
172    button = gtk_button_new_with_label(DIALOG_CANCEL_BUTTON);
173    gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
174    gtk_widget_set_usize(button, 60, -2);
175    gtk_widget_show(button);
176
177    CreateCancelButtonCallback(button);
178
179    // Create Apply button and hook it to callback.
180
181    button = gtk_button_new_with_label(DIALOG_APPLY_BUTTON);
182    gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 10);
183    gtk_widget_set_usize (button, 60, -2);
184    gtk_widget_show(button);
185
186    CreateApplyButtonCallback(button);
187
188    // Create OK button and hook it to callback.
189
190    button = gtk_button_new_with_label(DIALOG_OK_BUTTON);
191    gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
192    gtk_widget_set_usize (button, 60, -2);
193    gtk_widget_show(button);
194
195    CreateOkButtonCallback(button);
196 }
197
198 /**
199  * Destructor.
200  */
201 GetInfoDialog::~GetInfoDialog()
202 {
203 }
204
205 /**
206  * Handler for the Apply logic for this dialog. Interrogate the selected mesh
207  * entities.
208  *
209  * @return false if no meshes are selected, false if multiple meshes are
210  *         selected along with the transfer option, true otherwise.
211  */
212 bool
213 GetInfoDialog::Apply()
214 {
215    // Before doing anything, check to see if there are some meshes selected.
216    _nullVisitor->ResetVisitedCount();
217    GlobalSelectionSystem().foreachSelected(*_nullVisitor);
218    if (_nullVisitor->GetVisitedCount() == 0)
219    {
220       // Nope. Warn and bail out.
221       GenericPluginUI::WarningReportDialog(DIALOG_WARNING_TITLE,
222                                            DIALOG_NOMESHES_MSG);
223       return false;
224    }
225
226    // If the option to transfer info to Set S/T Scale is active, then only one
227    // mesh may be selected.
228    bool transfer = NamedToggleWidgetActive("transfer");
229    if (transfer && _nullVisitor->GetVisitedCount() != 1)
230    {
231       // Multiple selected. Warn and bail out.
232       GenericPluginUI::ErrorReportDialog(DIALOG_ERROR_TITLE,
233                                          DIALOG_MULTIMESHES_ERROR);
234       return false;
235    }
236
237    // OK read the remaining info from the widgets.
238
239    bool sApply = NamedToggleWidgetActive("s_apply");
240    bool tApply = NamedToggleWidgetActive("t_apply");
241
242    int row, col;
243    int *refRow = NULL;
244    int *refCol = NULL;
245    MeshEntity::TexInfoCallback *rowTexInfoCallback = NULL;
246    MeshEntity::TexInfoCallback *colTexInfoCallback = NULL;
247    if (sApply)
248    {
249       // Reference row is specified, so get that info.
250       row = atoi(NamedEntryWidgetText("s_ref_row"));
251       refRow = &row;
252       if (transfer)
253       {
254          // If transferring to Set S/T Scale, get that callback.
255          rowTexInfoCallback = &_rowTexInfoCallback;
256       }
257    }
258    if (tApply)
259    {
260       // Reference column is specified, so get that info.
261       col = atoi(NamedEntryWidgetText("t_ref_col"));
262       refCol = &col;
263       if (transfer)
264       {
265          // If transferring to Set S/T Scale, get that callback.
266          colTexInfoCallback = &_colTexInfoCallback;
267       }
268    }
269
270    // We don't need to instantiate an UndoableCommand since we won't be making
271    // any changes.
272
273    // Interrogate every selected mesh.
274    SmartPointer<GetInfoVisitor> infoVisitor(
275       new GetInfoVisitor(refRow, refCol, rowTexInfoCallback, colTexInfoCallback));
276    GlobalSelectionSystem().foreachSelected(*infoVisitor);
277
278    // If we populated something in the Set S/T Scale dialog, give that dialog a
279    // courtesy raise.
280    if (transfer)
281    {
282       _setScaleDialog->Raise();
283    }
284
285    // Done!
286    return true;
287 }