1 // GTK_APP.CPP
2
3 // Copyright (C) 2003 Tommi Hassinen.
4
5 // This package is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9
10 // This package 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
13 // GNU General Public License for more details.
14
15 // You should have received a copy of the GNU General Public License
16 // along with this package; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 /*################################################################################################*/
20
21 #include "gtk_app.h"
22
23 #include <ghemical/notice.h>
24
25 #include "gtk_setup_dialog.h"
26
27 #include <ghemical/utility.h>
28
29 #ifndef WIN32
30 #include <X11/Xlib.h> // DisplayString()
31 #endif // WIN32
32
33 #include "res_gtk/draw.xpm"
34 #include "res_gtk/erase.xpm"
35 #include "res_gtk/select.xpm"
36 #include "res_gtk/zoom.xpm"
37 #include "res_gtk/clipping.xpm"
38 #include "res_gtk/transl_xy.xpm"
39 #include "res_gtk/transl_z.xpm"
40 #include "res_gtk/orbit_xy.xpm"
41 #include "res_gtk/orbit_z.xpm"
42 #include "res_gtk/rotate_xy.xpm"
43 #include "res_gtk/rotate_z.xpm"
44 #include "res_gtk/measure.xpm"
45
46 #include "res_gtk/element.xpm"
47 #include "res_gtk/bondtype.xpm"
48 #include "res_gtk/setup.xpm"
49
50 #include "gtk_wnd.h"
51
52 #include "local_i18n.h"
53
54 #include <cstring>
55 #include <sstream>
56 using namespace std;
57
58 /*################################################################################################*/
59
60 const char * tb_mousetool_labels[] =
61 #ifdef USE_SHORT_TOOLBAR_LABELS
62 // http://library.gnome.org/devel/glib/stable/glib-I18N.html
63 // what about using Q_() ; tbl_s|d = toolbarlabel_short_d ??? need to cut away the prefix?
64 // 2009-04-16 ; THERE IS NO NEED TO TRANSLATE THESE AT ALL ; just use the translated tooltips...
65 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66 {
67 "d", "e", "s", "z", "c",
68 "t", "tz", "o", "oz", "r",
69 "rz", "m", NULL
70 };
71 #else // USE_SHORT_TOOLBAR_LABELS
72 {
73 "draw\n", "erase\n", "select\n", "zoom\n", "clip\n",
74 "trans\nXY", "trans\nZ", "orbit\nXY", "orbit\nZ", "rotate\nXY",
75 "rotate\nZ", "measure\n", NULL
76 };
77 #endif // USE_SHORT_TOOLBAR_LABELS
78
79 const char * tb_shortcut_labels[] =
80 #ifdef USE_SHORT_TOOLBAR_LABELS
81 {
82 "el", "bt", "su", NULL
83 };
84 #else // USE_SHORT_TOOLBAR_LABELS
85 {
86 "element\n", "bond\ntype", "setup\n", NULL
87 };
88 #endif // USE_SHORT_TOOLBAR_LABELS
89
90 GtkActionEntry gtk_app::entries1[] =
91 {
92 { "FileMenu", NULL, N_("File") },
93 { "HelpMenu", NULL, N_("Help") },
94
95 { "New", GTK_STOCK_NEW, N_("New"), NULL, N_("Create a new file."), (GCallback) gtk_app::mainmenu_FileNew }, //<control>N
96 { "Open", GTK_STOCK_OPEN, N_("Open"), NULL, N_("Open an existing file."), (GCallback) gtk_app::mainmenu_FileOpen }, //<control>O
97 { "SaveAs", GTK_STOCK_OPEN, N_("Save as..."), NULL, N_("Save a file."), (GCallback) gtk_app::mainmenu_FileSaveAs }, //<control>S
98 { "Close", GTK_STOCK_QUIT, N_("Close"), NULL, N_("Quit the program."), (GCallback) gtk_app::mainmenu_FileClose }, //<control>C
99
100 { "Help", GTK_STOCK_HELP, N_("Contents"), NULL, N_("View the User's Manual."), (GCallback) gtk_app::mainmenu_HelpHelp }, //<control>H
101 { "About", GTK_STOCK_ABOUT, N_("About"), NULL, N_("Information about this program."), (GCallback) gtk_app::mainmenu_HelpAbout }, //<control>A
102
103 // the rest are toolbar actions...
104 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
105
106 { "Element", "MY_ELEMENT_ICON", tb_shortcut_labels[0], NULL, N_("Set the current element."), (GCallback) gtk_app::maintb_dial_Element },
107 { "BondType", "MY_BONDTYPE_ICON", tb_shortcut_labels[1], NULL, N_("Set the current bondtype."), (GCallback) gtk_app::maintb_dial_BondType },
108 { "Setup", "MY_SETUP_ICON", tb_shortcut_labels[2], NULL, N_("Setup or change the comp.chem. method in use."), (GCallback) gtk_app::maintb_dial_Setup }
109 };
110
111 GtkToggleActionEntry gtk_app::entries2[] =
112 {
113 { "Draw", "MY_DRAW_ICON", tb_mousetool_labels[0], NULL, N_("Draw ; add atoms and bonds to the model."), (GCallback) gtk_app::maintb_tool_Draw, FALSE },
114 { "Erase", "MY_ERASE_ICON", tb_mousetool_labels[1], NULL, N_("Erase ; remove atoms and bonds from the model."), (GCallback) gtk_app::maintb_tool_Erase, FALSE },
115 { "Select", "MY_SELECT_ICON", tb_mousetool_labels[2], NULL, N_("Select ; make selections in the model, and also select objects."), (GCallback) gtk_app::maintb_tool_Select, FALSE },
116 { "Zoom", "MY_ZOOM_ICON", tb_mousetool_labels[3], NULL, N_("Zoom ; zoom the view."), (GCallback) gtk_app::maintb_tool_Zoom, FALSE },
117 { "Clip", "MY_CLIPPING_ICON", tb_mousetool_labels[4], NULL, N_("Clipping ; set the near and far clipping planes for graphics rendering."), (GCallback) gtk_app::maintb_tool_Clipping, FALSE },
118 { "TransXY", "MY_TRANSL_XY_ICON", tb_mousetool_labels[5], NULL, N_("TranslateXY ; translate the camera or a selected object in XY-direction."), (GCallback) gtk_app::maintb_tool_TranslateXY, FALSE },
119 { "TransZ", "MY_TRANSL_Z_ICON", tb_mousetool_labels[6], NULL, N_("TranslateZ ; translate the camera or a selected object in Z-direction."), (GCallback) gtk_app::maintb_tool_TranslateZ, FALSE },
120 { "OrbXY", "MY_ORBIT_XY_ICON", tb_mousetool_labels[7], NULL, N_("OrbitXY ; orbit the camera or a selected object around the focus point in XY-direction."), (GCallback) gtk_app::maintb_tool_OrbitXY, TRUE },
121 { "OrbZ", "MY_ORBIT_Z_ICON", tb_mousetool_labels[8], NULL, N_("OrbitZ ; orbit the camera or a selected object around the focus point in Z-direction."), (GCallback) gtk_app::maintb_tool_OrbitZ, FALSE },
122 { "RotXY", "MY_ROTATE_XY_ICON", tb_mousetool_labels[9], NULL, N_("RotateXY ; turn the camera or a selected object in XY-direction."), (GCallback) gtk_app::maintb_tool_RotateXY, FALSE },
123 { "RotZ", "MY_ROTATE_Z_ICON", tb_mousetool_labels[10], NULL, N_("RotateZ ; turn the camera or a selected object in Z-direction."), (GCallback) gtk_app::maintb_tool_RotateZ, FALSE },
124 { "Measure", "MY_MEASURE_ICON", tb_mousetool_labels[11], NULL, N_("Measure ; measure distances, angles and torsions."), (GCallback) gtk_app::maintb_tool_Measure, FALSE },
125 };
126
127 const char * gtk_app::ui_description =
128 "<ui>"
129 " <menubar name='MainMenu'>"
130 " <menu action='FileMenu'>"
131 " <menuitem action='New'/>"
132 " <menuitem action='Open'/>"
133 " <separator/>"
134 " <menuitem action='SaveAs'/>"
135 " <separator/>"
136 " <menuitem action='Close'/>"
137 " </menu>"
138 " <menu action='HelpMenu'>"
139 " <menuitem action='Help'/>"
140 " <menuitem action='About'/>"
141 " </menu>"
142 " </menubar>"
143 " <toolbar name='MainTB'>"
144 " <placeholder name='MainTools'>"
145 " <separator/>"
146 " <toolitem name='dr' action='Draw'/>"
147 " <toolitem name='er' action='Erase'/>"
148 " <toolitem name='se' action='Select'/>"
149 " <toolitem name='zm' action='Zoom'/>"
150 " <toolitem name='cp' action='Clip'/>"
151 " <toolitem name='tt' action='TransXY'/>"
152 " <toolitem name='tz' action='TransZ'/>"
153 " <toolitem name='oo' action='OrbXY'/>"
154 " <toolitem name='oz' action='OrbZ'/>"
155 " <toolitem name='rr' action='RotXY'/>"
156 " <toolitem name='rz' action='RotZ'/>"
157 " <toolitem name='ms' action='Measure'/>"
158 " <separator/>"
159 " <toolitem name='el' action='Element'/>"
160 " <toolitem name='bt' action='BondType'/>"
161 " <separator/>"
162 " <toolitem name='su' action='Setup'/>"
163 " <separator/>"
164 " </placeholder>"
165 " </toolbar>"
166 "</ui>";
167
168 GtkUIManager * gtk_app::ui_manager = NULL;
169
170 GtkWidget * gtk_app::main_window = NULL;
171 GtkWidget * gtk_app::main_vbox = NULL;
172
173 GtkWidget * gtk_app::main_menubar = NULL;
174 GtkWidget * gtk_app::main_toolbar = NULL;
175
176 GtkWidget * gtk_app::mtb_mtool_draw = NULL;
177 GtkWidget * gtk_app::mtb_mtool_erase = NULL;
178 GtkWidget * gtk_app::mtb_mtool_select = NULL;
179 GtkWidget * gtk_app::mtb_mtool_zoom = NULL;
180 GtkWidget * gtk_app::mtb_mtool_clipping = NULL;
181 GtkWidget * gtk_app::mtb_mtool_translate_xy = NULL;
182 GtkWidget * gtk_app::mtb_mtool_translate_z = NULL;
183 GtkWidget * gtk_app::mtb_mtool_orbit_xy = NULL;
184 GtkWidget * gtk_app::mtb_mtool_orbit_z = NULL;
185 GtkWidget * gtk_app::mtb_mtool_rotate_xy = NULL;
186 GtkWidget * gtk_app::mtb_mtool_rotate_z = NULL;
187 GtkWidget * gtk_app::mtb_mtool_measure = NULL;
188
189 GtkWidget * gtk_app::paned_widget = NULL;
190
191 GtkWidget * gtk_app::notebook_widget = NULL;
192
193 GtkTextBuffer * gtk_app::txt_buffer = NULL;
194 GtkTextMark * gtk_app::end_mark = NULL;
195
196 GtkWidget * gtk_app::scroll_widget = NULL;
197 GtkWidget * gtk_app::txt_widget = NULL;
198
199 GtkWidget * gtk_app::pv_view_widget = NULL;
200 GtkWidget * gtk_app::pv_label_widget = NULL;
201
202 // the views/objects-menu...
203 // ^^^^^^^^^^^^^^^^^^^^^^^^^
204
205 GtkActionEntry gtk_app::pv_viewsobjs_entries[] =
206 {
207 { "viewsobjs_SetCurrent", NULL, N_("Set to Current Object"), NULL, N_("Set this object to Current Object"), (GCallback) gtk_app::viewsobjs_SetCurrent },
208 { "viewsobjs_Delete", NULL, N_("Delete Object/View"), NULL, N_("Delete this object or view"), (GCallback) gtk_app::viewsobjs_Delete },
209 };
210
211 const char * gtk_app::pv_viewsobjs_ui_description =
212 "<ui>"
213 " <popup name='gpvViewsObjsMenu'>"
214 " <menuitem action='viewsobjs_SetCurrent'/>"
215 " <separator/>"
216 " <menuitem action='viewsobjs_Delete'/>"
217 " </popup>"
218 "</ui>";
219
220 // the chains-menu...
221 // ^^^^^^^^^^^^^^^^^^
222
223 GtkActionEntry gtk_app::pv_chains_entries[] =
224 {
225 { "chains_UpdateView", NULL, N_("Update View"), NULL, N_("Rebuild the chains info for this view"), (GCallback) gtk_app::chains_UpdateView },
226 { "chains_SelectItem", NULL, N_("Select Item"), NULL, N_("Select/unselect this chain/residue"), (GCallback) gtk_app::chains_SelectItem },
227 };
228
229 const char * gtk_app::pv_chains_ui_description =
230 "<ui>"
231 " <popup name='gpvChainsMenu'>"
232 " <menuitem action='chains_UpdateView'/>"
233 " <separator/>"
234 " <menuitem action='chains_SelectItem'/>"
235 " </popup>"
236 "</ui>";
237
238 // the atoms-menu...
239 // ^^^^^^^^^^^^^^^^^
240
241 GtkActionEntry gtk_app::pv_atoms_entries[] =
242 {
243 { "atoms_SelectAtom", NULL, N_("Select Atom"), NULL, N_("Select/unselect this atom"), (GCallback) gtk_app::atoms_SelectAtom },
244 };
245
246 const char * gtk_app::pv_atoms_ui_description =
247 "<ui>"
248 " <popup name='gpvAtomsMenu'>"
249 " <menuitem action='atoms_SelectAtom'/>"
250 " </popup>"
251 "</ui>";
252
253 // the bonds-menu...
254 // ^^^^^^^^^^^^^^^^^
255
256 GtkActionEntry gtk_app::pv_bonds_entries[] =
257 {
258 { "bonds_SelectBond", NULL, N_("Select Bond"), NULL, N_("Select/unselect this bond"), (GCallback) gtk_app::bonds_SelectBond },
259 };
260
261 const char * gtk_app::pv_bonds_ui_description =
262 "<ui>"
263 " <popup name='gpvBondsMenu'>"
264 " <menuitem action='bonds_SelectBond'/>"
265 " </popup>"
266 "</ui>";
267
268 // end of pv-pages.
269 // ^^^^^^^^^^^^^^^^
270
gtk_app(void)271 gtk_app::gtk_app(void) :
272 custom_app()
273 {
274 // register some new stock icons...
275 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
276
277 GtkIconFactory * icon_factory = gtk_icon_factory_new();
278 GtkIconSet * icon_set; GdkPixbuf * pixbuf; GtkIconSource * icon_source;
279 const int num_icons = 12 + 3;
280
281 const char ** icondata[num_icons] =
282 {
283 (const char **) draw_xpm,
284 (const char **) erase_xpm,
285 (const char **) select_xpm,
286 (const char **) zoom_xpm,
287 (const char **) clipping_xpm,
288 (const char **) transl_xy_xpm,
289 (const char **) transl_z_xpm,
290 (const char **) orbit_xy_xpm,
291 (const char **) orbit_z_xpm,
292 (const char **) rotate_xy_xpm,
293 (const char **) rotate_z_xpm,
294 (const char **) measure_xpm,
295
296 (const char **) element_xpm,
297 (const char **) bondtype_xpm,
298 (const char **) setup_xpm
299 };
300
301 const char * icon_id[num_icons] =
302 {
303 "MY_DRAW_ICON",
304 "MY_ERASE_ICON",
305 "MY_SELECT_ICON",
306 "MY_ZOOM_ICON",
307 "MY_CLIPPING_ICON",
308 "MY_TRANSL_XY_ICON",
309 "MY_TRANSL_Z_ICON",
310 "MY_ORBIT_XY_ICON",
311 "MY_ORBIT_Z_ICON",
312 "MY_ROTATE_XY_ICON",
313 "MY_ROTATE_Z_ICON",
314 "MY_MEASURE_ICON",
315
316 "MY_ELEMENT_ICON",
317 "MY_BONDTYPE_ICON",
318 "MY_SETUP_ICON"
319 };
320
321 for (int ii = 0;ii < num_icons;ii++)
322 {
323 pixbuf = gdk_pixbuf_new_from_xpm_data(icondata[ii]);
324 icon_set = gtk_icon_set_new_from_pixbuf(pixbuf);
325
326 icon_source = gtk_icon_source_new();
327 gtk_icon_source_set_pixbuf(icon_source, pixbuf);
328 gtk_icon_set_add_source(icon_set, icon_source);
329 gtk_icon_source_free (icon_source);
330
331 gtk_icon_factory_add(icon_factory, icon_id[ii], icon_set);
332 gtk_icon_set_unref (icon_set);
333 }
334
335 gtk_icon_factory_add_default(icon_factory);
336
337 // create the main window...
338 // ^^^^^^^^^^^^^^^^^^^^^^^^^
339
340 main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
341
342 gtk_window_set_default_size(GTK_WINDOW(main_window), 845, 640);
343
344 gchar * tmp_title = g_strconcat(_("Ghemical"), " ", APPVERSION, NULL );
345 gtk_window_set_title(GTK_WINDOW(main_window), tmp_title);
346 free(tmp_title); tmp_title = NULL;
347
348 ostringstream icon_fn;
349 icon_fn << project::appdata_path << DIR_SEPARATOR << APPVERSION << DIR_SEPARATOR << "pixmaps" << DIR_SEPARATOR << "ghemical.png" << ends;
350 pixbuf = gdk_pixbuf_new_from_file(icon_fn.str().c_str(), NULL);
351 if (pixbuf == NULL) printf(_("ERROR : Icon loading failed : %s\n"), icon_fn.str().c_str());
352 else gtk_window_set_icon(GTK_WINDOW(main_window), pixbuf);
353
354 gtk_container_set_border_width(GTK_CONTAINER(main_window), 1);
355
356 g_signal_connect(G_OBJECT(main_window), "delete_event", G_CALLBACK(gtk_app::DeleteEventHandler), NULL);
357 g_signal_connect(G_OBJECT(main_window), "destroy", G_CALLBACK(gtk_app::DestroyHandler), NULL);
358
359 main_vbox = gtk_vbox_new(FALSE, 0);
360 gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 1);
361 gtk_container_add(GTK_CONTAINER(main_window), main_vbox);
362
363 // add the user interface elements...
364 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
365
366 GtkActionGroup * action_group1 = gtk_action_group_new("MainWindowActions");
367 gtk_action_group_set_translation_domain(action_group1, GETTEXT_PACKAGE);
368 gtk_action_group_add_actions(action_group1, entries1, G_N_ELEMENTS(entries1), NULL);
369
370 GtkActionGroup * action_group2 = gtk_action_group_new("MouseToolToggleActions");
371 gtk_action_group_set_translation_domain(action_group2, GETTEXT_PACKAGE);
372 gtk_action_group_add_toggle_actions(action_group2, entries2, G_N_ELEMENTS(entries2), NULL);
373
374 ui_manager = gtk_ui_manager_new();
375 gtk_ui_manager_insert_action_group(ui_manager, action_group1, 0);
376 gtk_ui_manager_insert_action_group(ui_manager, action_group2, 0);
377
378 GError * error = NULL;
379 if (!gtk_ui_manager_add_ui_from_string(ui_manager, ui_description, -1, & error))
380 {
381 g_message(_("ERROR : Building main menu failed : %s"), error->message);
382 g_error_free(error); exit(EXIT_FAILURE);
383 }
384
385 // todo : tooltips do not appear to the main menu?!?!?
386 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
387 // but they DO appear in the toolbar??? TOOLTIPS NEEDED FOR I18N!!!
388 // gedit shows tooltips in the statusbar. at GtkUIManager documentation
389 // "connect-proxy" -signal is defined which may have something to do with this.
390
391 main_menubar = gtk_ui_manager_get_widget(ui_manager, "/MainMenu");
392 gtk_box_pack_start(GTK_BOX(main_vbox), main_menubar, FALSE, FALSE, 0);
393
394 main_toolbar = gtk_ui_manager_get_widget(ui_manager, "/MainTB");
395 gtk_box_pack_start(GTK_BOX(main_vbox), main_toolbar, FALSE, FALSE, 0);
396
397 mtb_mtool_draw = gtk_ui_manager_get_widget(ui_manager, "/MainTB/MainTools/dr");
398 mtb_mtool_erase = gtk_ui_manager_get_widget(ui_manager, "/MainTB/MainTools/er");
399 mtb_mtool_select = gtk_ui_manager_get_widget(ui_manager, "/MainTB/MainTools/se");
400 mtb_mtool_zoom = gtk_ui_manager_get_widget(ui_manager, "/MainTB/MainTools/zm");
401 mtb_mtool_clipping = gtk_ui_manager_get_widget(ui_manager, "/MainTB/MainTools/cp");
402 mtb_mtool_translate_xy = gtk_ui_manager_get_widget(ui_manager, "/MainTB/MainTools/tt");
403 mtb_mtool_translate_z = gtk_ui_manager_get_widget(ui_manager, "/MainTB/MainTools/tz");
404 mtb_mtool_orbit_xy = gtk_ui_manager_get_widget(ui_manager, "/MainTB/MainTools/oo");
405 mtb_mtool_orbit_z = gtk_ui_manager_get_widget(ui_manager, "/MainTB/MainTools/oz");
406 mtb_mtool_rotate_xy = gtk_ui_manager_get_widget(ui_manager, "/MainTB/MainTools/rr");
407 mtb_mtool_rotate_z = gtk_ui_manager_get_widget(ui_manager, "/MainTB/MainTools/rz");
408 mtb_mtool_measure = gtk_ui_manager_get_widget(ui_manager, "/MainTB/MainTools/ms");
409
410 paned_widget = gtk_vpaned_new();
411
412 notebook_widget = gtk_notebook_new();
413
414 txt_widget = gtk_text_view_new();
415 gtk_text_view_set_editable(GTK_TEXT_VIEW(txt_widget), false);
416
417 txt_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txt_widget));
418 GtkTextIter txt_iter; gtk_text_buffer_get_end_iter(txt_buffer, & txt_iter);
419 end_mark = gtk_text_buffer_create_mark(txt_buffer, NULL, & txt_iter, FALSE); // right_gravity!
420
421 scroll_widget = gtk_scrolled_window_new(NULL, NULL);
422 gtk_container_add(GTK_CONTAINER(scroll_widget), GTK_WIDGET(txt_widget));
423
424 gtk_widget_show(txt_widget);
425
426 gtk_paned_add1(GTK_PANED(paned_widget), GTK_WIDGET(notebook_widget));
427 gtk_paned_add2(GTK_PANED(paned_widget), GTK_WIDGET(scroll_widget));
428
429 gtk_box_pack_start(GTK_BOX(main_vbox), paned_widget, TRUE, TRUE, 0);
430
431 gtk_widget_show(notebook_widget);
432 gtk_widget_show(scroll_widget);
433
434 gtk_widget_show(paned_widget);
435
436 InitPV(); // build and show the project_view...
437
438 // show the widgets and enter in the main loop.
439 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
440
441 gtk_widget_show(main_menubar);
442 gtk_widget_show(main_toolbar);
443
444 gtk_widget_show(main_vbox);
445 gtk_widget_show(main_window);
446
447 // set a new default project.
448 // ^^^^^^^^^^^^^^^^^^^^^^^^^^
449
450 SetNewProject();
451
452 // when leaving this stage, the program
453 // will (soon) enter in the main loop...
454 }
455
~gtk_app(void)456 gtk_app::~gtk_app(void)
457 {
458 // need to release memory etc...
459 }
460
GetAppX(void)461 gtk_app * gtk_app::GetAppX(void)
462 {
463 base_app * app = base_app::GetAppB();
464 if (app != NULL) return dynamic_cast<gtk_app *>(app);
465 else return new gtk_app();
466 }
467
GetPrjX(void)468 gtk_project * gtk_app::GetPrjX(void)
469 {
470 project * p = custom_app::GetPrj();
471 if (!p) return NULL;
472
473 gtk_project * gp = dynamic_cast<gtk_project *>(p);
474 return gp;
475 }
476
AttachDetachView(base_wcl * wcl)477 void gtk_app::AttachDetachView(base_wcl * wcl)
478 {
479 // this is a gtk-notebook-related special feature,
480 // so it will duplicate some functionality from the
481 // generic implementations (project-class???).
482
483 // so also see these:
484 // ^^^^^^^^^^^^^^^^^^
485 // project::AddGraphicsClient()
486 // project::RemoveGraphicsClient()
487
488 base_wnd * wndB = wcl->GetWnd();
489 gtk_wnd * wndX = dynamic_cast<gtk_wnd *>(wndB);
490
491 if (wndB == NULL || wndX == NULL)
492 {
493 assertion_failed(__FILE__, __LINE__, "no wnd!");
494 }
495
496 bool detached = !wndX->IsDetached();
497 wndX = NULL; // no longer needed...
498
499 // unlink the old window, and destroy it.
500 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
501
502 wcl->UnlinkWnd();
503
504 // then create a new window, and link it.
505 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
506 // determine the window class using the client...
507
508 if (dynamic_cast<oglview_wcl *>(wcl) != NULL)
509 {
510 GetPrj()->DestroyGraphicsWnd(wndB);
511 wndB = NULL;
512
513 wndB = GetPrj()->CreateGraphicsWnd(detached);
514 }
515 else
516 {
517 GetPrj()->DestroyPlottingWnd(wndB);
518 wndB = NULL;
519
520 // handle the various plotting wnd types here...
521
522 if (dynamic_cast<p1dview_wcl *>(wcl) != NULL) wndB = GetPrj()->CreatePlot1DWnd(detached);
523 else if (dynamic_cast<p2dview_wcl *>(wcl) != NULL) wndB = GetPrj()->CreatePlot2DWnd(detached);
524 else if (dynamic_cast<eldview_wcl *>(wcl) != NULL) wndB = GetPrj()->CreateEnergyLevelDiagramWnd(detached);
525 else if (dynamic_cast<rcpview_wcl *>(wcl) != NULL) wndB = GetPrj()->CreateReactionCoordinatePlotWnd(detached);
526 else if (dynamic_cast<gpcview_wcl *>(wcl) != NULL) wndB = GetPrj()->CreateGenericProteinChainWnd(detached);
527 else
528 {
529 assertion_failed(__FILE__, __LINE__, "wcl class unknown.");
530 }
531 }
532
533 wcl->LinkWnd(wndB);
534
535 UpdateAllWindowTitles(); // attach/detach status texts...
536 }
537
SetTransientForMainWnd(GtkWindow * other_window)538 void gtk_app::SetTransientForMainWnd(GtkWindow * other_window)
539 {
540 gtk_window_set_transient_for(other_window, GTK_WINDOW(main_window));
541 }
542
AddTabToNB(GtkWidget * widget,GtkWidget * label)543 void gtk_app::AddTabToNB(GtkWidget * widget, GtkWidget * label)
544 {
545 gtk_notebook_append_page(GTK_NOTEBOOK(notebook_widget), widget, label);
546
547 // activate the last page ; makes the new view visible.
548 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
549
550 gtk_notebook_set_page(GTK_NOTEBOOK(notebook_widget), -1);
551 }
552
RemoveTabFromNB(GtkWidget * widget)553 void gtk_app::RemoveTabFromNB(GtkWidget * widget)
554 {
555 gint page = gtk_notebook_page_num(GTK_NOTEBOOK(notebook_widget), widget);
556 gtk_notebook_remove_page(GTK_NOTEBOOK(notebook_widget), page);
557 }
558
SetTabTitleNB(GtkWidget * widget,GtkWidget * label)559 void gtk_app::SetTabTitleNB(GtkWidget * widget, GtkWidget * label)
560 {
561 gtk_notebook_set_tab_label(GTK_NOTEBOOK(notebook_widget), widget, label);
562 }
563
InitPV(void)564 void gtk_app::InitPV(void)
565 {
566 pv_label_widget = gtk_label_new(_("project view"));
567
568 pv_view_widget = gtk_notebook_new();
569 gtk_widget_set_size_request(pv_view_widget, 640, 400); // minimum size...
570
571 GtkCellRenderer * renderer;
572 GtkTreeViewColumn * column;
573
574 GtkActionGroup * action_group = NULL;
575 GError * error = NULL;
576
577 // "views/objects"-page
578
579 pv_viewsobjs_store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
580 pv_viewsobjs_widget = gtk_tree_view_new_with_model(GTK_TREE_MODEL(pv_viewsobjs_store));
581 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(pv_viewsobjs_widget), TRUE); // optional : draw the stripes to background.
582
583 renderer = gtk_cell_renderer_text_new(); // ??? (string)
584 column = gtk_tree_view_column_new_with_attributes(_("Object"), renderer, "text", 0, NULL);
585 gtk_tree_view_append_column(GTK_TREE_VIEW(pv_viewsobjs_widget), column);
586
587 renderer = gtk_cell_renderer_text_new(); // ??? (string)
588 column = gtk_tree_view_column_new_with_attributes(_("Sub-Objects"), renderer, "text", 1, NULL);
589 gtk_tree_view_append_column(GTK_TREE_VIEW(pv_viewsobjs_widget), column);
590
591 pv_viewsobjs_label = gtk_label_new(_("Views/Objects"));
592 pv_viewsobjs_sw = gtk_scrolled_window_new (NULL, NULL);
593 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(pv_viewsobjs_sw), GTK_SHADOW_ETCHED_IN); // optional : ???
594 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(pv_viewsobjs_sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
595 gtk_container_add(GTK_CONTAINER(pv_viewsobjs_sw), pv_viewsobjs_widget);
596 gtk_notebook_append_page(GTK_NOTEBOOK(pv_view_widget), pv_viewsobjs_sw, pv_viewsobjs_label);
597 action_group = gtk_action_group_new("gpvViewsObjsActions");
598 gtk_action_group_set_translation_domain(action_group, GETTEXT_PACKAGE);
599 gtk_action_group_add_actions(action_group, pv_viewsobjs_entries, G_N_ELEMENTS(pv_viewsobjs_entries), GTK_WIDGET(pv_view_widget));
600 gtk_ui_manager_insert_action_group(gtk_app::GetUIManager(), action_group, 0);
601 error = NULL;
602 if (!gtk_ui_manager_add_ui_from_string(gtk_app::GetUIManager(), pv_viewsobjs_ui_description, -1, & error))
603 {
604 g_message(_("ERROR : Building Views/Objects menu in project view failed : %s"), error->message);
605 g_error_free(error); exit(EXIT_FAILURE);
606 }
607 pv_viewsobjs_menu = gtk_ui_manager_get_widget(gtk_app::GetUIManager(), "/gpvViewsObjsMenu");
608 g_signal_connect_swapped(GTK_OBJECT(pv_viewsobjs_widget), "button_press_event", G_CALLBACK(ViewsObjsPopupHandler), GTK_WIDGET(pv_viewsobjs_widget));
609 gtk_widget_show(pv_viewsobjs_widget);
610 gtk_widget_show(pv_viewsobjs_label);
611 gtk_widget_show(pv_viewsobjs_sw);
612
613 // "chains"-page
614
615 pv_chains_store = gtk_tree_store_new (5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
616 pv_chains_widget = gtk_tree_view_new_with_model(GTK_TREE_MODEL(pv_chains_store));
617 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(pv_chains_widget), TRUE); // optional : draw the stripes to background.
618
619 renderer = gtk_cell_renderer_text_new(); // chain_info (string)
620 column = gtk_tree_view_column_new_with_attributes(_("Chain Description"), renderer, "text", 0, NULL);
621 gtk_tree_view_append_column(GTK_TREE_VIEW(pv_chains_widget), column);
622
623 renderer = gtk_cell_renderer_text_new(); // res_num (string)
624 column = gtk_tree_view_column_new_with_attributes(_("Residue Number"), renderer, "text", 1, NULL);
625 gtk_tree_view_append_column(GTK_TREE_VIEW(pv_chains_widget), column);
626
627 renderer = gtk_cell_renderer_text_new(); // res_id (string)
628 column = gtk_tree_view_column_new_with_attributes(_("Residue ID"), renderer, "text", 2, NULL);
629 gtk_tree_view_append_column(GTK_TREE_VIEW(pv_chains_widget), column);
630
631 renderer = gtk_cell_renderer_text_new(); // res_state1 (string)
632 column = gtk_tree_view_column_new_with_attributes(_("Sec-Str State"), renderer, "text", 3, NULL);
633 gtk_tree_view_append_column(GTK_TREE_VIEW(pv_chains_widget), column);
634
635 renderer = gtk_cell_renderer_text_new(); // res_state2 (string)
636 column = gtk_tree_view_column_new_with_attributes(_("Protonation State"), renderer, "text", 4, NULL);
637 gtk_tree_view_append_column(GTK_TREE_VIEW(pv_chains_widget), column);
638
639 pv_chains_label = gtk_label_new(_("Chains"));
640 pv_chains_sw = gtk_scrolled_window_new (NULL, NULL);
641 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(pv_chains_sw), GTK_SHADOW_ETCHED_IN); // optional : ???
642 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(pv_chains_sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
643 gtk_container_add(GTK_CONTAINER(pv_chains_sw), pv_chains_widget);
644 gtk_notebook_append_page(GTK_NOTEBOOK(pv_view_widget), pv_chains_sw, pv_chains_label);
645 action_group = gtk_action_group_new("gpvChainsActions");
646 gtk_action_group_set_translation_domain(action_group, GETTEXT_PACKAGE);
647 gtk_action_group_add_actions(action_group, pv_chains_entries, G_N_ELEMENTS(pv_chains_entries), GTK_WIDGET(pv_view_widget));
648 gtk_ui_manager_insert_action_group(gtk_app::GetUIManager(), action_group, 0);
649 error = NULL;
650 if (!gtk_ui_manager_add_ui_from_string(gtk_app::GetUIManager(), pv_chains_ui_description, -1, & error))
651 {
652 g_message(_("ERROR : Building Chains menu in project view failed : %s"), error->message);
653 g_error_free(error); exit(EXIT_FAILURE);
654 }
655 pv_chains_menu = gtk_ui_manager_get_widget(gtk_app::GetUIManager(), "/gpvChainsMenu");
656 g_signal_connect_swapped(GTK_OBJECT(pv_chains_widget), "button_press_event", G_CALLBACK(ChainsPopupHandler), GTK_WIDGET(pv_chains_widget));
657 gtk_widget_show(pv_chains_widget);
658 gtk_widget_show(pv_chains_label);
659 gtk_widget_show(pv_chains_sw);
660
661 // "atoms"-page
662
663 pv_atoms_store = gtk_list_store_new (3, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_BOOLEAN);
664 pv_atoms_widget = gtk_tree_view_new_with_model(GTK_TREE_MODEL(pv_atoms_store));
665 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(pv_atoms_widget), TRUE); // optional : draw the stripes to background.
666
667 renderer = gtk_cell_renderer_text_new(); // index1
668 column = gtk_tree_view_column_new_with_attributes(_("Atom Index"), renderer, "text", 0, NULL);
669 gtk_tree_view_append_column(GTK_TREE_VIEW(pv_atoms_widget), column);
670
671 renderer = gtk_cell_renderer_text_new(); // element
672 column = gtk_tree_view_column_new_with_attributes(_("Element"), renderer, "text", 1, NULL);
673 gtk_tree_view_append_column(GTK_TREE_VIEW(pv_atoms_widget), column);
674
675 renderer = gtk_cell_renderer_toggle_new(); // locked
676 g_object_set(renderer, "activatable", TRUE, NULL);
677 g_signal_connect(GTK_OBJECT(renderer), "toggled", G_CALLBACK(atoms_ToggleLocked), (gpointer *) pv_atoms_store);
678 column = gtk_tree_view_column_new_with_attributes(_("Locked"), renderer, "active", 2, NULL);
679 gtk_tree_view_append_column(GTK_TREE_VIEW(pv_atoms_widget), column);
680
681 pv_atoms_label = gtk_label_new(_("Atoms"));
682 pv_atoms_sw = gtk_scrolled_window_new (NULL, NULL);
683 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(pv_atoms_sw), GTK_SHADOW_ETCHED_IN); // optional : ???
684 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(pv_atoms_sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
685 gtk_container_add(GTK_CONTAINER(pv_atoms_sw), pv_atoms_widget);
686 gtk_notebook_append_page(GTK_NOTEBOOK(pv_view_widget), pv_atoms_sw, pv_atoms_label);
687 action_group = gtk_action_group_new("gpvAtomsActions");
688 gtk_action_group_set_translation_domain(action_group, GETTEXT_PACKAGE);
689 gtk_action_group_add_actions(action_group, pv_atoms_entries, G_N_ELEMENTS(pv_atoms_entries), GTK_WIDGET(pv_view_widget));
690 gtk_ui_manager_insert_action_group(gtk_app::GetUIManager(), action_group, 0);
691 error = NULL;
692 if (!gtk_ui_manager_add_ui_from_string(gtk_app::GetUIManager(), pv_atoms_ui_description, -1, & error))
693 {
694 g_message(_("ERROR : Building Atoms menu in project view failed : %s"), error->message);
695 g_error_free(error); exit(EXIT_FAILURE);
696 }
697 pv_atoms_menu = gtk_ui_manager_get_widget(gtk_app::GetUIManager(), "/gpvAtomsMenu");
698 g_signal_connect_swapped(GTK_OBJECT(pv_atoms_widget), "button_press_event", G_CALLBACK(AtomsPopupHandler), GTK_WIDGET(pv_atoms_widget));
699 gtk_widget_show(pv_atoms_widget);
700 gtk_widget_show(pv_atoms_label);
701 gtk_widget_show(pv_atoms_sw);
702
703 // "bonds"-page
704
705 pv_bonds_store = gtk_list_store_new (3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
706 pv_bonds_widget = gtk_tree_view_new_with_model(GTK_TREE_MODEL(pv_bonds_store));
707 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(pv_bonds_widget), TRUE); // optional : draw the stripes to background.
708
709 renderer = gtk_cell_renderer_text_new(); // index1
710 column = gtk_tree_view_column_new_with_attributes(_("Atom Index #1"), renderer, "text", 0, NULL);
711 gtk_tree_view_append_column(GTK_TREE_VIEW(pv_bonds_widget), column);
712
713 renderer = gtk_cell_renderer_text_new(); // index2
714 column = gtk_tree_view_column_new_with_attributes(_("Atom Index #2"), renderer, "text", 1, NULL);
715 gtk_tree_view_append_column(GTK_TREE_VIEW(pv_bonds_widget), column);
716
717 renderer = gtk_cell_renderer_text_new(); // bondtype
718 column = gtk_tree_view_column_new_with_attributes(_("BondType"), renderer, "text", 2, NULL);
719 gtk_tree_view_append_column(GTK_TREE_VIEW(pv_bonds_widget), column);
720
721 pv_bonds_label = gtk_label_new(_("Bonds"));
722 pv_bonds_sw = gtk_scrolled_window_new (NULL, NULL);
723 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(pv_bonds_sw), GTK_SHADOW_ETCHED_IN); // optional : ???
724 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(pv_bonds_sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
725 gtk_container_add(GTK_CONTAINER(pv_bonds_sw), pv_bonds_widget);
726 gtk_notebook_append_page(GTK_NOTEBOOK(pv_view_widget), pv_bonds_sw, pv_bonds_label);
727 action_group = gtk_action_group_new("gpvBondsActions");
728 gtk_action_group_set_translation_domain(action_group, GETTEXT_PACKAGE);
729 gtk_action_group_add_actions(action_group, pv_bonds_entries, G_N_ELEMENTS(pv_bonds_entries), GTK_WIDGET(pv_view_widget));
730 gtk_ui_manager_insert_action_group(gtk_app::GetUIManager(), action_group, 0);
731 error = NULL;
732 if (!gtk_ui_manager_add_ui_from_string(gtk_app::GetUIManager(), pv_bonds_ui_description, -1, & error))
733 {
734 g_message(_("ERROR : Building Bonds menu in project view failed : %s"), error->message);
735 g_error_free(error); exit(EXIT_FAILURE);
736 }
737 pv_bonds_menu = gtk_ui_manager_get_widget(gtk_app::GetUIManager(), "/gpvBondsMenu");
738 g_signal_connect_swapped(GTK_OBJECT(pv_bonds_widget), "button_press_event", G_CALLBACK(BondsPopupHandler), GTK_WIDGET(pv_bonds_widget));
739 gtk_widget_show(pv_bonds_widget);
740 gtk_widget_show(pv_bonds_label);
741 gtk_widget_show(pv_bonds_sw);
742
743 // ready...
744 // ready...
745 // ready...
746
747 gtk_notebook_append_page(GTK_NOTEBOOK(notebook_widget), pv_view_widget, pv_label_widget);
748
749 gtk_widget_show(GTK_WIDGET(pv_view_widget));
750 gtk_widget_show(GTK_WIDGET(pv_label_widget));
751 }
752
SetNewProject(void)753 void gtk_app::SetNewProject(void)
754 {
755 if (prj != NULL)
756 {
757 prj->ClearAll();
758 delete prj; prj = NULL;
759 }
760
761 custom_app::SetNewProject();
762 gtk_project * tmpprj = new gtk_project();
763
764 prj = tmpprj;
765 tmpprj->DoSafeStart();
766 }
767
DeleteEventHandler(GtkWidget * widget,GdkEvent * event,gpointer data)768 gboolean gtk_app::DeleteEventHandler(GtkWidget * widget, GdkEvent * event, gpointer data)
769 {
770 if (project::background_job_running) return TRUE; // protect the model-data during background jobs...
771
772 bool quit = sQuestion(_("Are you sure that you\nwant to quit the program?"));
773 if (quit) return FALSE; else return TRUE;
774 }
775
DestroyHandler(GtkWidget * widget,gpointer data)776 void gtk_app::DestroyHandler(GtkWidget * widget, gpointer data)
777 {
778 prj->ClearAll();
779 delete prj; prj = NULL;
780
781 gtk_main_quit();
782 }
783
784 // Print the message (no problems).
sMessage(const char * msg)785 void gtk_app::sMessage(const char * msg)
786 {
787 GtkWidget * message_dialog = gtk_message_dialog_new(NULL,
788 GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", msg);
789
790 gtk_dialog_run(GTK_DIALOG(message_dialog));
791 gtk_widget_destroy(message_dialog);
792 }
793
794 // Print the message (lower severity).
sWarningMessage(const char * msg)795 void gtk_app::sWarningMessage(const char * msg)
796 {
797 GtkWidget * message_dialog = gtk_message_dialog_new(NULL,
798 GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "%s", msg);
799
800 gtk_dialog_run(GTK_DIALOG(message_dialog));
801 gtk_widget_destroy(message_dialog);
802 }
803
804 // Print the message (higher severity).
sErrorMessage(const char * msg)805 void gtk_app::sErrorMessage(const char * msg)
806 {
807 GtkWidget * message_dialog = gtk_message_dialog_new(NULL,
808 GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", msg);
809
810 gtk_dialog_run(GTK_DIALOG(message_dialog));
811 gtk_widget_destroy(message_dialog);
812 }
813
814 // Print the message and wait for a yes/no response.
sQuestion(const char * msg)815 bool gtk_app::sQuestion(const char * msg)
816 {
817 GtkWidget * question_dialog = gtk_message_dialog_new(NULL,
818 GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s", msg);
819
820 gint response = gtk_dialog_run(GTK_DIALOG(question_dialog));
821 gtk_widget_destroy(question_dialog);
822
823 switch (response)
824 {
825 case GTK_RESPONSE_YES:
826 return true;
827
828 default:
829 return false;
830 }
831 }
832
833 #define MSG_BUFF_SZ 65536
834
sPrintToLog(const char * msg)835 void gtk_app::sPrintToLog(const char * msg)
836 {
837 if (strlen(msg) > MSG_BUFF_SZ)
838 {
839 cout << _("gtk_app::sPrintToLog() : message is too long!") << endl;
840 return;
841 }
842
843 static char msgbuff[MSG_BUFF_SZ];
844 strcpy(msgbuff, msg);
845
846 GtkTextIter txt_iter;
847 gtk_text_buffer_get_iter_at_mark(txt_buffer, & txt_iter, end_mark);
848
849 gtk_text_buffer_insert(txt_buffer, & txt_iter, msgbuff, -1);
850
851 gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(txt_widget), end_mark);
852
853 cout << "PrintToLog : " << msg;
854 }
855
Message(const char * msg)856 void gtk_app::Message(const char * msg)
857 {
858 sMessage(msg);
859 }
860
WarningMessage(const char * msg)861 void gtk_app::WarningMessage(const char * msg)
862 {
863 sWarningMessage(msg);
864 }
865
ErrorMessage(const char * msg)866 void gtk_app::ErrorMessage(const char * msg)
867 {
868 sErrorMessage(msg);
869 }
870
Question(const char * msg)871 bool gtk_app::Question(const char * msg)
872 {
873 return sQuestion(msg);
874 }
875
PrintToLog(const char * msg)876 void gtk_app::PrintToLog(const char * msg)
877 {
878 sPrintToLog(msg);
879 }
880
UpdateAllWindowTitles(void)881 void gtk_app::UpdateAllWindowTitles(void)
882 {
883 list<pv_viewsobjs_record *>::iterator it = pv_viewsobjs_data.begin();
884 while (it != pv_viewsobjs_data.end())
885 {
886 if ((* it)->refV2 != NULL)
887 {
888 base_wcl * wcl = (* it)->refV2;
889
890 ostringstream vts; // view title stream (in PV)
891 ostringstream wts; // window title stream
892
893 oglview_wcl * oglwcl = dynamic_cast<oglview_wcl *>(wcl);
894 if (oglwcl != NULL)
895 {
896 gtk_wnd * wnd = dynamic_cast<gtk_wnd *>(oglwcl->GetWnd());
897
898 vts << _("window ") << oglwcl->my_wnd_number;
899 vts << (wnd->IsDetached() ? _(" (detached)") : _(" (attached)")) << ends;
900
901 wts << _("cam ") << oglwcl->GetCCam()->GetCCamI() << " ";
902 wts << _("wnd ") << oglwcl->my_wnd_number;
903 wts << (wnd->IsDetached() ? _(" (detached)") : "") << ends;
904
905 oglwcl->SetTitle(wts.str().c_str());
906 }
907 else
908 {
909 // it's a plotting client...
910 // ^^^^^^^^^^^^^^^^^^^^^^^^^
911
912 bool has_name = false;
913
914 if (dynamic_cast<ac_stor_wcl *>(wcl) != NULL)
915 {
916 if (dynamic_cast<p1dview_wcl *>(wcl) != NULL)
917 {
918 if (dynamic_cast<rcpview_wcl *>(wcl) != NULL)
919 {
920 has_name = true;
921 vts << _("RC plot view") << ends;
922 wts << _("RC plot view") << ends;
923 }
924 else
925 {
926 has_name = true;
927 vts << _("1D plot view") << ends;
928 wts << _("1D plot view") << ends;
929 }
930 }
931 else if (dynamic_cast<p2dview_wcl *>(wcl) != NULL)
932 {
933 has_name = true;
934 vts << _("2D plot view") << ends;
935 wts << _("2D plot view") << ends;
936 }
937 }
938 else if (dynamic_cast<eldview_wcl *>(wcl) != NULL)
939 {
940 has_name = true;
941 vts << _("energy-level diagram view") << ends;
942 wts << _("energy-level diagram view") << ends;
943 }
944 else if (dynamic_cast<gpcview_wcl *>(wcl) != NULL)
945 {
946 has_name = true;
947 vts << _("generic protein chain view") << ends;
948 wts << _("generic protein chain view") << ends;
949 }
950
951 if (!has_name)
952 {
953 vts << _("<unknown view>") << ends;
954 wts << _("<unknown view>") << ends;
955 }
956
957 wcl->SetTitle(wts.str().c_str());
958 }
959
960 gtk_tree_store_set(pv_viewsobjs_store, & (* it)->iter, 0, vts.str().c_str(), 1, FALSE, -1);
961 }
962
963 it++;
964 }
965 }
966
CameraAdded(custom_camera * p1)967 void gtk_app::CameraAdded(custom_camera * p1)
968 {
969 pv_viewsobjs_record * vo_rec = new pv_viewsobjs_record;
970
971 vo_rec->owner = NULL;
972 vo_rec->refV1 = p1;
973 vo_rec->refV2 = NULL;
974 vo_rec->refO = NULL;
975
976 gtk_tree_store_append(pv_viewsobjs_store, & vo_rec->iter, NULL);
977 pv_viewsobjs_data.push_back(vo_rec);
978
979 ostringstream name;
980 name << _("camera ") << p1->GetCCamI() << ends;
981 const char * name_str = name.str().c_str();
982
983 gtk_tree_store_set(pv_viewsobjs_store, & vo_rec->iter, 0, name_str, 1, FALSE, -1);
984 }
985
CameraRemoved(custom_camera * p1)986 void gtk_app::CameraRemoved(custom_camera * p1)
987 {
988 list<pv_viewsobjs_record *>::iterator it = pv_viewsobjs_data.begin();
989 while (it != pv_viewsobjs_data.end()) { if ((* it)->refV1 == (ogl_dummy_object *) p1) break; else it++; }
990
991 if (it == pv_viewsobjs_data.end())
992 {
993 assertion_failed(__FILE__, __LINE__, "object not found.");
994 }
995
996 gtk_tree_store_remove(pv_viewsobjs_store, & (* it)->iter);
997
998 pv_viewsobjs_data.erase(it);
999 delete (* it);
1000 }
1001
LightAdded(ogl_light * p1)1002 void gtk_app::LightAdded(ogl_light * p1)
1003 {
1004 bool is_local_light = (p1->owner != NULL);
1005 if (is_local_light)
1006 {
1007 list<pv_viewsobjs_record *>::iterator it = pv_viewsobjs_data.begin();
1008 while (it != pv_viewsobjs_data.end()) { if ((* it)->refV1 == (ogl_dummy_object *) p1->owner) break; else it++; }
1009
1010 if (it == pv_viewsobjs_data.end())
1011 {
1012 assertion_failed(__FILE__, __LINE__, "owner not found.");
1013 }
1014
1015 custom_camera * ccam = dynamic_cast<custom_camera *>(p1->owner);
1016 if (!ccam)
1017 {
1018 assertion_failed(__FILE__, __LINE__, "ccam cast failed.");
1019 }
1020
1021 pv_viewsobjs_record * vo_rec = new pv_viewsobjs_record;
1022
1023 vo_rec->owner = ccam;
1024 vo_rec->refV1 = p1;
1025 vo_rec->refV2 = NULL;
1026 vo_rec->refO = NULL;
1027
1028 gtk_tree_store_append(pv_viewsobjs_store, & vo_rec->iter, & (* it)->iter);
1029 pv_viewsobjs_data.push_back(vo_rec);
1030
1031 const char * object_name = p1->GetObjectName();
1032
1033 gtk_tree_store_set(pv_viewsobjs_store, & vo_rec->iter, 0, object_name, 1, FALSE, -1);
1034
1035 // expand the newly created row...
1036
1037 GtkTreePath * path = gtk_tree_model_get_path(GTK_TREE_MODEL(pv_viewsobjs_store), & vo_rec->iter);
1038 gtk_tree_view_expand_to_path(GTK_TREE_VIEW(pv_viewsobjs_widget), path);
1039 gtk_tree_path_free(path);
1040 }
1041 else
1042 {
1043 pv_viewsobjs_record * vo_rec = new pv_viewsobjs_record;
1044
1045 vo_rec->owner = NULL;
1046 vo_rec->refV1 = p1;
1047 vo_rec->refV2 = NULL;
1048 vo_rec->refO = NULL;
1049
1050 gtk_tree_store_append(pv_viewsobjs_store, & vo_rec->iter, NULL);
1051 pv_viewsobjs_data.push_back(vo_rec);
1052
1053 const char * object_name = p1->GetObjectName();
1054
1055 gtk_tree_store_set(pv_viewsobjs_store, & vo_rec->iter, 0, object_name, 1, FALSE, -1);
1056 }
1057 }
1058
LightRemoved(ogl_light * p1)1059 void gtk_app::LightRemoved(ogl_light * p1)
1060 {
1061 list<pv_viewsobjs_record *>::iterator it = pv_viewsobjs_data.begin();
1062 while (it != pv_viewsobjs_data.end()) { if ((* it)->refV1 == (ogl_dummy_object *) p1) break; else it++; }
1063
1064 if (it == pv_viewsobjs_data.end())
1065 {
1066 assertion_failed(__FILE__, __LINE__, "object not found.");
1067 }
1068
1069 gtk_tree_store_remove(pv_viewsobjs_store, & (* it)->iter);
1070
1071 pv_viewsobjs_data.erase(it);
1072 delete (* it);
1073 }
1074
GraphicsClientAdded(oglview_wcl * p1)1075 void gtk_app::GraphicsClientAdded(oglview_wcl * p1)
1076 {
1077 list<pv_viewsobjs_record *>::iterator it = pv_viewsobjs_data.begin();
1078 while (it != pv_viewsobjs_data.end()) { if ((* it)->refV1 == (ogl_dummy_object *) p1->GetCam()) break; else it++; }
1079
1080 if (it == pv_viewsobjs_data.end())
1081 {
1082 assertion_failed(__FILE__, __LINE__, "camera not found.");
1083 }
1084
1085 custom_camera * ccam = dynamic_cast<custom_camera *>(p1->GetCam());
1086 if (!ccam)
1087 {
1088 assertion_failed(__FILE__, __LINE__, "ccam cast failed.");
1089 }
1090
1091 pv_viewsobjs_record * vo_rec = new pv_viewsobjs_record;
1092
1093 vo_rec->owner = ccam;
1094 vo_rec->refV1 = NULL;
1095 vo_rec->refV2 = p1;
1096 vo_rec->refO = NULL;
1097
1098 gtk_tree_store_append(pv_viewsobjs_store, & vo_rec->iter, & (* it)->iter);
1099 pv_viewsobjs_data.push_back(vo_rec);
1100
1101 const char * object_name = "a graphics client ; THIS IS NEVER DISPLAYED?";
1102
1103 gtk_tree_store_set(pv_viewsobjs_store, & vo_rec->iter, 0, object_name, 1, FALSE, -1);
1104
1105 // expand the newly created row...
1106
1107 GtkTreePath * path = gtk_tree_model_get_path(GTK_TREE_MODEL(pv_viewsobjs_store), & vo_rec->iter);
1108 gtk_tree_view_expand_to_path(GTK_TREE_VIEW(pv_viewsobjs_widget), path);
1109 gtk_tree_path_free(path);
1110 }
1111
GraphicsClientRemoved(oglview_wcl * p1)1112 void gtk_app::GraphicsClientRemoved(oglview_wcl * p1)
1113 {
1114 list<pv_viewsobjs_record *>::iterator it = pv_viewsobjs_data.begin();
1115 while (it != pv_viewsobjs_data.end()) { if ((* it)->refV2 == (base_wcl *) p1) break; else it++; }
1116
1117 if (it == pv_viewsobjs_data.end())
1118 {
1119 assertion_failed(__FILE__, __LINE__, "object not found.");
1120 }
1121
1122 gtk_tree_store_remove(pv_viewsobjs_store, & (* it)->iter);
1123
1124 pv_viewsobjs_data.erase(it);
1125 delete (* it);
1126 }
1127
PlottingClientAdded(base_wcl * p1)1128 void gtk_app::PlottingClientAdded(base_wcl * p1)
1129 {
1130 //cout << "called gtk_app::PlottingClientAdded()" << endl;
1131 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1132 pv_viewsobjs_record * vo_rec = new pv_viewsobjs_record;
1133
1134 vo_rec->owner = NULL;
1135 vo_rec->refV1 = NULL;
1136 vo_rec->refV2 = p1;
1137 vo_rec->refO = NULL;
1138
1139 gtk_tree_store_append(pv_viewsobjs_store, & vo_rec->iter, NULL);
1140 pv_viewsobjs_data.push_back(vo_rec);
1141
1142 const char * object_name = "a plotting client ; THIS IS NEVER DISPLAYED?";
1143
1144 gtk_tree_store_set(pv_viewsobjs_store, & vo_rec->iter, 0, object_name, 1, FALSE, -1);
1145 }
1146
PlottingClientRemoved(base_wcl * p1)1147 void gtk_app::PlottingClientRemoved(base_wcl * p1)
1148 {
1149 //cout << "called gtk_app::PlottingClientRemoved()" << endl;
1150 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1151 list<pv_viewsobjs_record *>::iterator it = pv_viewsobjs_data.begin();
1152 while (it != pv_viewsobjs_data.end()) { if ((* it)->refV2 == (base_wcl *) p1) break; else it++; }
1153
1154 if (it == pv_viewsobjs_data.end())
1155 {
1156 assertion_failed(__FILE__, __LINE__, "object not found.");
1157 }
1158
1159 gtk_tree_store_remove(pv_viewsobjs_store, & (* it)->iter);
1160
1161 pv_viewsobjs_data.erase(it);
1162 delete (* it);
1163 }
1164
ObjectAdded(ogl_smart_object * p1)1165 void gtk_app::ObjectAdded(ogl_smart_object * p1)
1166 {
1167 pv_viewsobjs_record * vo_rec = new pv_viewsobjs_record;
1168
1169 vo_rec->owner = NULL;
1170 vo_rec->refV1 = NULL;
1171 vo_rec->refV2 = NULL;
1172 vo_rec->refO = p1;
1173
1174 gtk_tree_store_append(pv_viewsobjs_store, & vo_rec->iter, NULL);
1175 pv_viewsobjs_data.push_back(vo_rec);
1176
1177 const char * object_name = p1->GetObjectName();
1178
1179 gtk_tree_store_set(pv_viewsobjs_store, & vo_rec->iter, 0, object_name, 1, FALSE, -1);
1180 }
1181
ObjectRemoved(ogl_smart_object * p1)1182 void gtk_app::ObjectRemoved(ogl_smart_object * p1)
1183 {
1184 list<pv_viewsobjs_record *>::iterator it = pv_viewsobjs_data.begin();
1185 while (it != pv_viewsobjs_data.end()) { if ((* it)->refO == p1) break; else it++; }
1186
1187 if (it == pv_viewsobjs_data.end())
1188 {
1189 assertion_failed(__FILE__, __LINE__, "object_not_found.");
1190 }
1191
1192 gtk_tree_store_remove(pv_viewsobjs_store, & (* it)->iter);
1193
1194 pv_viewsobjs_data.erase(it);
1195 delete (* it);
1196 }
1197
ViewsObjsPopupHandler(GtkWidget * widget,GdkEvent * event)1198 gint gtk_app::ViewsObjsPopupHandler(GtkWidget * widget, GdkEvent * event)
1199 {
1200 if (project::background_job_running) return TRUE; // protect the model-data during background jobs...
1201
1202 if (event->type == GDK_BUTTON_PRESS)
1203 {
1204 GdkEventButton * event_button = (GdkEventButton *) event;
1205 if (event_button->button == 3)
1206 {
1207 GtkMenu * menu = GTK_MENU(gtk_app::GetAppX()->pv_viewsobjs_menu);
1208 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event_button->button, event_button->time);
1209 return TRUE;
1210 }
1211 }
1212
1213 return FALSE;
1214 }
1215
viewsobjs_SetCurrent(GtkWidget * widget,gpointer data)1216 void gtk_app::viewsobjs_SetCurrent(GtkWidget * widget, gpointer data)
1217 {
1218 gtk_app * app = gtk_app::GetAppX();
1219
1220 // assume that tsel is in mode GTK_SELECTION_SINGLE (as it seems to be); this is the simplest case...
1221 // here the equivalence test of GtkTreeIter is a bit uncertain... need to test any other records???
1222
1223 GtkTreeSelection * tsel = gtk_tree_view_get_selection(GTK_TREE_VIEW(app->pv_viewsobjs_widget));
1224 GtkTreeModel * tm = gtk_tree_view_get_model(GTK_TREE_VIEW(app->pv_viewsobjs_widget));
1225 GtkTreeIter iter;
1226
1227 bool has_item = gtk_tree_selection_get_selected(tsel, & tm, & iter);
1228 if (has_item)
1229 {
1230 list<pv_viewsobjs_record *>::iterator it = app->pv_viewsobjs_data.begin();
1231 while (it != app->pv_viewsobjs_data.end()) { if ((* it)->iter.user_data == iter.user_data) break; else it++; }
1232
1233 if (it == app->pv_viewsobjs_data.end())
1234 {
1235 cout << "ERROR : gtk_app::viewsobjs_SetCurrent() failed." << endl;
1236 exit(EXIT_FAILURE);
1237 }
1238
1239 bool is_light = ((* it)->refV1 != NULL && dynamic_cast<ogl_light *>((* it)->refV1) != NULL);
1240 bool is_obj = ((* it)->refO != NULL);
1241
1242 if (is_light)
1243 {
1244 gtk_app::GetPrjX()->selected_object = (* it)->refV1;
1245
1246 ostringstream mstr;
1247 mstr << _("Object ") << gtk_app::GetPrjX()->selected_object->GetObjectName() << _(" is set to current object.") << endl << ends;
1248 gtk_app::GetPrjX()->PrintToLog(mstr.str().c_str());
1249 }
1250 else if (is_obj)
1251 {
1252 gtk_app::GetPrjX()->selected_object = (* it)->refO;
1253
1254 ostringstream mstr;
1255 mstr << _("Object ") << gtk_app::GetPrjX()->selected_object->GetObjectName() << _(" is set to current object.") << endl << ends;
1256 gtk_app::GetPrjX()->PrintToLog(mstr.str().c_str());
1257 }
1258 else gtk_app::GetPrjX()->Message(_("Sorry, this operation is not yet implemented."));
1259 }
1260 }
1261
viewsobjs_Delete(GtkWidget *,gpointer data)1262 void gtk_app::viewsobjs_Delete(GtkWidget *, gpointer data)
1263 {
1264 gtk_app * app = gtk_app::GetAppX();
1265
1266 // assume that tsel is in mode GTK_SELECTION_SINGLE (as it seems to be); this is the simplest case...
1267 // here the equivalence test of GtkTreeIter is a bit uncertain... need to test any other records???
1268
1269 GtkTreeSelection * tsel = gtk_tree_view_get_selection(GTK_TREE_VIEW(app->pv_viewsobjs_widget));
1270 GtkTreeModel * tm = gtk_tree_view_get_model(GTK_TREE_VIEW(app->pv_viewsobjs_widget));
1271 GtkTreeIter iter;
1272
1273 bool has_item = gtk_tree_selection_get_selected(tsel, & tm, & iter);
1274 if (has_item)
1275 {
1276 list<pv_viewsobjs_record *>::iterator it = app->pv_viewsobjs_data.begin();
1277 while (it != app->pv_viewsobjs_data.end()) { if ((* it)->iter.user_data == iter.user_data) break; else it++; }
1278
1279 if (it == app->pv_viewsobjs_data.end())
1280 {
1281 assertion_failed(__FILE__, __LINE__, "object not found.");
1282 }
1283
1284 bool is_light = ((* it)->refV1 != NULL && dynamic_cast<ogl_light *>((* it)->refV1) != NULL);
1285 bool is_view = ((* it)->refV2 != NULL);
1286 bool is_obj = ((* it)->refO != NULL);
1287
1288 if (is_light)
1289 {
1290 ostringstream mstr;
1291 mstr << _("Object ") << (* it)->refV1->GetObjectName() << _(" is deleted.") << endl << ends;
1292 gtk_app::GetPrjX()->PrintToLog(mstr.str().c_str());
1293
1294 if (project::selected_object == (* it)->refV1) project::selected_object = NULL;
1295 base_app::GetAppB()->RemoveLight((* it)->refV1);
1296
1297 gtk_app::GetPrjX()->UpdateAllGraphicsViews();
1298 }
1299 else if (is_view)
1300 {
1301 base_wcl * wcl = (* it)->refV2;
1302 oglview_wcl * oglwcl = dynamic_cast<oglview_wcl *>(wcl);
1303
1304 if (oglwcl != NULL)
1305 {
1306 gtk_app::GetPrjX()->RemoveGraphicsClient(oglwcl, false);
1307 }
1308 else
1309 {
1310 gtk_app::GetPrjX()->RemovePlottingClient(wcl);
1311 }
1312 }
1313 else if (is_obj)
1314 {
1315 ostringstream mstr;
1316 mstr << _("Object ") << (* it)->refO->GetObjectName() << _(" is deleted.") << endl << ends;
1317 gtk_app::GetPrjX()->PrintToLog(mstr.str().c_str());
1318
1319 if (project::selected_object == (* it)->refO) project::selected_object = NULL;
1320 gtk_app::GetPrjX()->RemoveObject((* it)->refO);
1321
1322 gtk_app::GetPrjX()->UpdateAllGraphicsViews();
1323 }
1324 else gtk_app::GetPrjX()->Message(_("Sorry, this operation is not yet implemented."));
1325 }
1326 }
1327
BuildChainsView(void)1328 void gtk_app::BuildChainsView(void)
1329 {
1330 if (pv_chains_data.size() != 0)
1331 {
1332 ClearChainsView();
1333 }
1334
1335 if (gtk_app::GetPrjX()->GetCI() != NULL)
1336 {
1337 vector<chn_info> & ci_vector = (* gtk_app::GetPrjX()->GetCI());
1338
1339 for (i32u n1 = 0;n1 < ci_vector.size();n1++)
1340 {
1341 pv_chains_record * c_rec1 = new pv_chains_record;
1342 c_rec1->c_r_ind = (n1 << 16) + 0xFFFF; gtk_tree_store_append(pv_chains_store, & c_rec1->iter, NULL);
1343
1344 pv_chains_data.push_back(c_rec1);
1345
1346 ostringstream cis;
1347
1348 // if (ci_vector[n1].description... // this is not implemented at the moment...
1349
1350 // show chain index 1,2,3,... to user ; it is 0,1,2,... internally!
1351 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1352
1353 cis << _("chain #") << (n1 + 1) << " (";
1354
1355 switch (ci_vector[n1].GetType())
1356 {
1357 case chn_info::amino_acid: cis << "AA"; break;
1358 case chn_info::nucleic_acid: cis << "NA"; break;
1359 default: cis << "??";
1360 }
1361 cis << _(" chain).") << ends;
1362
1363 gtk_tree_store_set(pv_chains_store, & c_rec1->iter, 0, cis.str().c_str(), 1, FALSE, 2, FALSE, 3, FALSE, 4, FALSE, -1);
1364
1365 const char * seq1_buff = ci_vector[n1].GetSequence1();
1366 for (i32s n2 = 0;n2 < ci_vector[n1].GetLength();n2++)
1367 {
1368 pv_chains_record * c_rec2 = new pv_chains_record;
1369 c_rec2->c_r_ind = (n1 << 16) + n2; gtk_tree_store_append(pv_chains_store, & c_rec2->iter, & c_rec1->iter);
1370
1371 pv_chains_data.push_back(c_rec2);
1372
1373 // show residue index 1,2,3,... to user ; it is 0,1,2,... internally!
1374 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1375
1376 ostringstream rns;
1377 rns << (n2 + 1) << ends;
1378
1379 char res_id[8] = "?";
1380 res_id[0] = seq1_buff[n2];
1381
1382 gtk_tree_store_set(pv_chains_store, & c_rec2->iter, 0, FALSE, 1, rns.str().c_str(), 2, res_id, 3, "???", 4, "???", -1);
1383 }
1384 }
1385 }
1386 }
1387
ClearChainsView(void)1388 void gtk_app::ClearChainsView(void)
1389 {
1390 list<pv_chains_record *>::iterator it;
1391
1392 it = pv_chains_data.begin(); // first remove the residue records...
1393 while (it != pv_chains_data.end()) // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1394 {
1395 if (((* it)->c_r_ind & 0xFFFF) != 0xFFFF)
1396 {
1397 gtk_tree_store_remove(pv_chains_store, & (* it)->iter);
1398
1399 delete (* it);
1400 pv_chains_data.erase(it);
1401
1402 it = pv_chains_data.begin();
1403 }
1404
1405 it++;
1406 }
1407
1408 it = pv_chains_data.begin(); // ...and then the chain records!
1409 while (it != pv_chains_data.end()) // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1410 {
1411 gtk_tree_store_remove(pv_chains_store, & (* it)->iter);
1412
1413 delete (* it);
1414 pv_chains_data.erase(it);
1415
1416 it = pv_chains_data.begin();
1417 }
1418 }
1419
ChainsPopupHandler(GtkWidget * widget,GdkEvent * event)1420 gint gtk_app::ChainsPopupHandler(GtkWidget * widget, GdkEvent * event)
1421 {
1422 if (project::background_job_running) return TRUE; // protect the model-data during background jobs...
1423
1424 if (event->type == GDK_BUTTON_PRESS)
1425 {
1426 GdkEventButton * event_button = (GdkEventButton *) event;
1427 if (event_button->button == 3)
1428 {
1429 GtkMenu * menu = GTK_MENU(gtk_app::GetAppX()->pv_chains_menu);
1430 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event_button->button, event_button->time);
1431 return TRUE;
1432 }
1433 }
1434
1435 return FALSE;
1436 }
1437
chains_UpdateView(GtkWidget *,gpointer data)1438 void gtk_app::chains_UpdateView(GtkWidget *, gpointer data)
1439 {
1440 gtk_app * app = gtk_app::GetAppX();
1441
1442 // update the data only if it's necessary ; there might be some extra info stored in the chains data!
1443 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1444
1445 if (gtk_app::GetPrjX()->GetCI() == NULL)
1446 {
1447 gtk_app::GetPrjX()->UpdateChains();
1448 }
1449 }
1450
chains_SelectItem(GtkWidget *,gpointer data)1451 void gtk_app::chains_SelectItem(GtkWidget *, gpointer data)
1452 {
1453 gtk_app * app = gtk_app::GetAppX();
1454
1455 // assume that tsel is in mode GTK_SELECTION_SINGLE (as it seems to be); this is the simplest case...
1456 // here the equivalence test of GtkTreeIter is a bit uncertain... need to test any other records???
1457
1458 GtkTreeSelection * tsel = gtk_tree_view_get_selection(GTK_TREE_VIEW(app->pv_chains_widget));
1459 GtkTreeModel * tm = gtk_tree_view_get_model(GTK_TREE_VIEW(app->pv_chains_widget));
1460 GtkTreeIter iter;
1461
1462 bool has_item = gtk_tree_selection_get_selected(tsel, & tm, & iter);
1463 if (has_item)
1464 {
1465 list<pv_chains_record *>::iterator it = app->pv_chains_data.begin();
1466 while (it != app->pv_chains_data.end()) { if ((* it)->iter.user_data == iter.user_data) break; else it++; }
1467
1468 if (it == app->pv_chains_data.end())
1469 {
1470 assertion_failed(__FILE__, __LINE__, "object not found.");
1471 }
1472
1473 i32s c_ind = ((* it)->c_r_ind >> 16);
1474 i32s r_ind = ((* it)->c_r_ind & 0xFFFF);
1475
1476 iter_al c_rng[2]; gtk_app::GetPrjX()->GetRange(1, c_ind, c_rng);
1477
1478 if (r_ind == 0xFFFF) // select chain
1479 {
1480 for (iter_al iter = c_rng[0]; iter != c_rng[1];iter++)
1481 {
1482 (* iter).flags |= ATOMFLAG_USER_SELECTED;
1483 }
1484 }
1485 else // select residue
1486 {
1487 iter_al r_rng[2]; gtk_app::GetPrjX()->GetRange(2, c_rng, r_ind, r_rng);
1488
1489 for (iter_al iter = r_rng[0]; iter != r_rng[1];iter++)
1490 {
1491 (* iter).flags |= ATOMFLAG_USER_SELECTED;
1492 }
1493 }
1494
1495 gtk_app::GetPrjX()->UpdateAllGraphicsViews();
1496 }
1497 }
1498
AtomAdded(atom * p1)1499 void gtk_app::AtomAdded(atom * p1)
1500 {
1501 pv_atoms_record * a_rec = new pv_atoms_record;
1502 a_rec->ref = p1; gtk_list_store_append(pv_atoms_store, & a_rec->iter);
1503
1504 pv_atoms_data.push_back(a_rec);
1505
1506 AtomUpdateItem(p1);
1507 }
1508
AtomUpdateItem(atom * p1)1509 void gtk_app::AtomUpdateItem(atom * p1)
1510 {
1511 list<pv_atoms_record *>::iterator it = pv_atoms_data.begin();
1512 while (it != pv_atoms_data.end()) { if ((* it)->ref == p1) break; else it++; }
1513
1514 if (it == pv_atoms_data.end())
1515 {
1516 assertion_failed(__FILE__, __LINE__, "object not found.");
1517 }
1518
1519 // show atom index 1,2,3,... to user ; it is 0,1,2,... internally!
1520 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1521
1522 const i32s atmi = (p1->index + 1);
1523 const char * ele = p1->el.GetSymbol();
1524 const bool locked = p1->flags & ATOMFLAG_USER_LOCKED;
1525
1526 gtk_list_store_set(pv_atoms_store, & (* it)->iter, 0, atmi, 1, ele, 2, locked, -1);
1527 }
1528
AtomRemoved(atom * p1)1529 void gtk_app::AtomRemoved(atom * p1)
1530 {
1531 list<pv_atoms_record *>::iterator it = pv_atoms_data.begin();
1532 while (it != pv_atoms_data.end()) { if ((* it)->ref == p1) break; else it++; }
1533
1534 if (it == pv_atoms_data.end())
1535 {
1536 assertion_failed(__FILE__, __LINE__, "object not found.");
1537 }
1538
1539 gtk_list_store_remove(pv_atoms_store, & (* it)->iter);
1540
1541 delete (* it);
1542 pv_atoms_data.erase(it);
1543 }
1544
AtomsPopupHandler(GtkWidget * widget,GdkEvent * event)1545 gint gtk_app::AtomsPopupHandler(GtkWidget * widget, GdkEvent * event)
1546 {
1547 if (project::background_job_running) return TRUE; // protect the model-data during background jobs...
1548
1549 if (event->type == GDK_BUTTON_PRESS)
1550 {
1551 GdkEventButton * event_button = (GdkEventButton *) event;
1552 if (event_button->button == 3)
1553 {
1554 GtkMenu * menu = GTK_MENU(gtk_app::GetAppX()->pv_atoms_menu);
1555 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event_button->button, event_button->time);
1556 return TRUE;
1557 }
1558 }
1559
1560 return FALSE;
1561 }
1562
atoms_SelectAtom(GtkWidget *,gpointer data)1563 void gtk_app::atoms_SelectAtom(GtkWidget *, gpointer data)
1564 {
1565 gtk_app * app = gtk_app::GetAppX();
1566
1567 // assume that tsel is in mode GTK_SELECTION_SINGLE (as it seems to be); this is the simplest case...
1568 // here the equivalence test of GtkTreeIter is a bit uncertain... need to test any other records???
1569
1570 GtkTreeSelection * tsel = gtk_tree_view_get_selection(GTK_TREE_VIEW(app->pv_atoms_widget));
1571 GtkTreeModel * tm = gtk_tree_view_get_model(GTK_TREE_VIEW(app->pv_atoms_widget));
1572 GtkTreeIter iter;
1573
1574 bool has_item = gtk_tree_selection_get_selected(tsel, & tm, & iter);
1575 if (has_item)
1576 {
1577 list<pv_atoms_record *>::iterator it = app->pv_atoms_data.begin();
1578 while (it != app->pv_atoms_data.end()) { if ((* it)->iter.user_data == iter.user_data) break; else it++; }
1579
1580 if (it == app->pv_atoms_data.end())
1581 {
1582 assertion_failed(__FILE__, __LINE__, "object not found.");
1583 }
1584
1585 (* it)->ref->flags ^= ATOMFLAG_USER_SELECTED;
1586 gtk_app::GetPrjX()->UpdateAllGraphicsViews();
1587 }
1588 }
1589
atoms_ToggleLocked(GtkWidget * widget,gchar * path,gpointer * data)1590 gint gtk_app::atoms_ToggleLocked(GtkWidget * widget, gchar * path, gpointer * data)
1591 {
1592 gtk_app * app = gtk_app::GetAppX();
1593
1594 GtkTreeIter iter;
1595 if (!gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(data), &iter, path))
1596 {
1597 assertion_failed(__FILE__, __LINE__, "iter search failed.");
1598 }
1599
1600 list<pv_atoms_record *>::iterator it = app->pv_atoms_data.begin();
1601 while (it != app->pv_atoms_data.end())
1602 {
1603 if ((* it)->iter.user_data == iter.user_data) break;
1604 else it++;
1605 }
1606
1607 if (it == app->pv_atoms_data.end())
1608 {
1609 assertion_failed(__FILE__, __LINE__, "object not found.");
1610 }
1611
1612 atom * p1 = (* it)->ref;
1613 p1->SetLocked(!(p1->GetLocked()));
1614 gtk_list_store_set(GTK_LIST_STORE(data), &iter, 2, p1->GetLocked(), -1);
1615
1616 app->AtomUpdateItem(p1); // make the list show the updated information...
1617
1618 printf(_("Atom locking changed : %s\n"), p1->GetLocked() ? _("yes") : _("no"));
1619 return FALSE;
1620 }
1621
BondAdded(bond * p1)1622 void gtk_app::BondAdded(bond * p1)
1623 {
1624 pv_bonds_record * b_rec = new pv_bonds_record;
1625 b_rec->ref = p1; gtk_list_store_append(pv_bonds_store, & b_rec->iter);
1626
1627 pv_bonds_data.push_back(b_rec);
1628
1629 BondUpdateItem(p1);
1630 }
1631
BondUpdateItem(bond * p1)1632 void gtk_app::BondUpdateItem(bond * p1)
1633 {
1634 list<pv_bonds_record *>::iterator it = pv_bonds_data.begin();
1635 while (it != pv_bonds_data.end()) { if ((* it)->ref == p1) break; else it++; }
1636
1637 if (it == pv_bonds_data.end())
1638 {
1639 assertion_failed(__FILE__, __LINE__, "object not found.");
1640 }
1641
1642 const char * bt_strings[4] =
1643 {
1644 _("Conjugated"),
1645 _("Single"),
1646 _("Double"),
1647 _("Triple")
1648 };
1649
1650 // show atom index 1,2,3,... to user ; it is 0,1,2,... internally!
1651 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1652
1653 const i32s atmi1 = (p1->atmr[0]->index + 1);
1654 const i32s atmi2 = (p1->atmr[1]->index + 1);
1655 const char * btype = bt_strings[p1->bt.GetValue()];
1656
1657 gtk_list_store_set(pv_bonds_store, & (* it)->iter, 0, atmi1, 1, atmi2, 2, btype, -1);
1658 }
1659
BondRemoved(bond * p1)1660 void gtk_app::BondRemoved(bond * p1)
1661 {
1662 list<pv_bonds_record *>::iterator it = pv_bonds_data.begin();
1663 while (it != pv_bonds_data.end()) { if ((* it)->ref == p1) break; else it++; }
1664
1665 if (it == pv_bonds_data.end())
1666 {
1667 assertion_failed(__FILE__, __LINE__, "object not found.");
1668 }
1669
1670 gtk_list_store_remove(pv_bonds_store, & (* it)->iter);
1671
1672 delete (* it);
1673 pv_bonds_data.erase(it);
1674 }
1675
BondsPopupHandler(GtkWidget * widget,GdkEvent * event)1676 gint gtk_app::BondsPopupHandler(GtkWidget * widget, GdkEvent * event)
1677 {
1678 if (project::background_job_running) return TRUE; // protect the model-data during background jobs...
1679
1680 if (event->type == GDK_BUTTON_PRESS)
1681 {
1682 GdkEventButton * event_button = (GdkEventButton *) event;
1683 if (event_button->button == 3)
1684 {
1685 GtkMenu * menu = GTK_MENU(gtk_app::GetAppX()->pv_bonds_menu);
1686 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event_button->button, event_button->time);
1687 return TRUE;
1688 }
1689 }
1690
1691 return FALSE;
1692 }
1693
bonds_SelectBond(GtkWidget *,gpointer data)1694 void gtk_app::bonds_SelectBond(GtkWidget *, gpointer data)
1695 {
1696 gtk_app * app = gtk_app::GetAppX();
1697
1698 // assume that tsel is in mode GTK_SELECTION_SINGLE (as it seems to be); this is the simplest case...
1699 // here the equivalence test of GtkTreeIter is a bit uncertain... need to test any other records???
1700
1701 GtkTreeSelection * tsel = gtk_tree_view_get_selection(GTK_TREE_VIEW(app->pv_bonds_widget));
1702 GtkTreeModel * tm = gtk_tree_view_get_model(GTK_TREE_VIEW(app->pv_bonds_widget));
1703 GtkTreeIter iter;
1704
1705 bool has_item = gtk_tree_selection_get_selected(tsel, & tm, & iter);
1706 if (has_item)
1707 {
1708 list<pv_bonds_record *>::iterator it = app->pv_bonds_data.begin();
1709 while (it != app->pv_bonds_data.end()) { if ((* it)->iter.user_data == iter.user_data) break; else it++; }
1710
1711 if (it == app->pv_bonds_data.end())
1712 {
1713 assertion_failed(__FILE__, __LINE__, "object not found.");
1714 }
1715
1716 bool both_selected = (((* it)->ref->atmr[0]->flags & ATOMFLAG_USER_SELECTED) && ((* it)->ref->atmr[1]->flags & ATOMFLAG_USER_SELECTED));
1717 if (!both_selected) // select...
1718 {
1719 (* it)->ref->atmr[0]->flags |= ATOMFLAG_USER_SELECTED;
1720 (* it)->ref->atmr[1]->flags |= ATOMFLAG_USER_SELECTED;
1721 }
1722 else // un-select...
1723 {
1724 (* it)->ref->atmr[0]->flags &= (~ATOMFLAG_USER_SELECTED);
1725 (* it)->ref->atmr[1]->flags &= (~ATOMFLAG_USER_SELECTED);
1726 }
1727
1728 gtk_app::GetPrjX()->UpdateAllGraphicsViews();
1729 }
1730 }
1731
1732 // the toolbar-button callbacks start here ; the toolbar-button callbacks start here
1733 // the toolbar-button callbacks start here ; the toolbar-button callbacks start here
1734 // the toolbar-button callbacks start here ; the toolbar-button callbacks start here
1735
1736 static int toggle_event_ignore_counter = 0;
HandleToggleButtons(custom_app::mtool old_mt)1737 void gtk_app::HandleToggleButtons(custom_app::mtool old_mt)
1738 {
1739 // a static event counter is set up and used so that a cascade of button events is prevented.
1740 // the same thing could be done by disabling/enabling the callbacks in GTK, but this is simpler.
1741
1742 gboolean state = TRUE;
1743 if (old_mt != current_mouse_tool) state = FALSE;
1744
1745 if (old_mt == custom_app::mtDraw)
1746 {
1747 toggle_event_ignore_counter++;
1748 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_draw), state);
1749 }
1750
1751 if (old_mt == custom_app::mtErase)
1752 {
1753 toggle_event_ignore_counter++;
1754 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_erase), state);
1755 }
1756
1757 if (old_mt == custom_app::mtSelect)
1758 {
1759 toggle_event_ignore_counter++;
1760 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_select), state);
1761 }
1762
1763 if (old_mt == custom_app::mtZoom)
1764 {
1765 toggle_event_ignore_counter++;
1766 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_zoom), state);
1767 }
1768
1769 if (old_mt == custom_app::mtClipping)
1770 {
1771 toggle_event_ignore_counter++;
1772 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_clipping), state);
1773 }
1774
1775 if (old_mt == custom_app::mtTranslateXY)
1776 {
1777 toggle_event_ignore_counter++;
1778 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_translate_xy), state);
1779 }
1780
1781 if (old_mt == custom_app::mtTranslateZ)
1782 {
1783 toggle_event_ignore_counter++;
1784 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_translate_z), state);
1785 }
1786
1787 if (old_mt == custom_app::mtOrbitXY)
1788 {
1789 toggle_event_ignore_counter++;
1790 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_orbit_xy), state);
1791 }
1792
1793 if (old_mt == custom_app::mtOrbitZ)
1794 {
1795 toggle_event_ignore_counter++;
1796 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_orbit_z), state);
1797 }
1798
1799 if (old_mt == custom_app::mtRotateXY)
1800 {
1801 toggle_event_ignore_counter++;
1802 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_rotate_xy), state);
1803 }
1804
1805 if (old_mt == custom_app::mtRotateZ)
1806 {
1807 toggle_event_ignore_counter++;
1808 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_rotate_z), state);
1809 }
1810
1811 if (old_mt == custom_app::mtMeasure)
1812 {
1813 toggle_event_ignore_counter++;
1814 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_measure), state);
1815 }
1816 }
1817
maintb_tool_Draw(gpointer p1,guint p2,GtkWidget * p3)1818 void gtk_app::maintb_tool_Draw(gpointer p1, guint p2, GtkWidget * p3)
1819 {
1820 if (toggle_event_ignore_counter > 0)
1821 {
1822 cout << "DEBUG : draw skipped ; counter = " << toggle_event_ignore_counter << endl;
1823 toggle_event_ignore_counter--;
1824 }
1825 else
1826 {
1827 cout << "DEBUG : draw state is " << gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_draw)) << endl;
1828
1829 custom_app::mtool old_mt = custom_app::current_mouse_tool;
1830 custom_app::current_mouse_tool = custom_app::mtDraw;
1831 HandleToggleButtons(old_mt);
1832 }
1833 }
1834
maintb_tool_Erase(gpointer,guint,GtkWidget *)1835 void gtk_app::maintb_tool_Erase(gpointer, guint, GtkWidget *)
1836 {
1837 if (toggle_event_ignore_counter > 0)
1838 {
1839 cout << "DEBUG : erase skipped ; counter = " << toggle_event_ignore_counter << endl;
1840 toggle_event_ignore_counter--;
1841 }
1842 else
1843 {
1844 cout << "DEBUG : erase state is " << gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_erase)) << endl;
1845
1846 custom_app::mtool old_mt = custom_app::current_mouse_tool;
1847 custom_app::current_mouse_tool = custom_app::mtErase;
1848 HandleToggleButtons(old_mt);
1849 }
1850 }
1851
maintb_tool_Select(gpointer,guint,GtkWidget *)1852 void gtk_app::maintb_tool_Select(gpointer, guint, GtkWidget *)
1853 {
1854 if (toggle_event_ignore_counter > 0)
1855 {
1856 cout << "DEBUG : select skipped ; counter = " << toggle_event_ignore_counter << endl;
1857 toggle_event_ignore_counter--;
1858 }
1859 else
1860 {
1861 cout << "DEBUG : select state is " << gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_select)) << endl;
1862
1863 custom_app::mtool old_mt = custom_app::current_mouse_tool;
1864 custom_app::current_mouse_tool = custom_app::mtSelect;
1865 HandleToggleButtons(old_mt);
1866 }
1867 }
1868
maintb_tool_Zoom(gpointer,guint,GtkWidget *)1869 void gtk_app::maintb_tool_Zoom(gpointer, guint, GtkWidget *)
1870 {
1871 if (toggle_event_ignore_counter > 0)
1872 {
1873 cout << "DEBUG : zoom skipped ; counter = " << toggle_event_ignore_counter << endl;
1874 toggle_event_ignore_counter--;
1875 }
1876 else
1877 {
1878 cout << "DEBUG : zoom state is " << gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_zoom)) << endl;
1879
1880 custom_app::mtool old_mt = custom_app::current_mouse_tool;
1881 custom_app::current_mouse_tool = custom_app::mtZoom;
1882 HandleToggleButtons(old_mt);
1883 }
1884 }
1885
maintb_tool_Clipping(gpointer,guint,GtkWidget *)1886 void gtk_app::maintb_tool_Clipping(gpointer, guint, GtkWidget *)
1887 {
1888 if (toggle_event_ignore_counter > 0)
1889 {
1890 cout << "DEBUG : clipping skipped ; counter = " << toggle_event_ignore_counter << endl;
1891 toggle_event_ignore_counter--;
1892 }
1893 else
1894 {
1895 cout << "DEBUG : clipping state is " << gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_clipping)) << endl;
1896
1897 custom_app::mtool old_mt = custom_app::current_mouse_tool;
1898 custom_app::current_mouse_tool = custom_app::mtClipping;
1899 HandleToggleButtons(old_mt);
1900 }
1901 }
1902
maintb_tool_TranslateXY(gpointer,guint,GtkWidget *)1903 void gtk_app::maintb_tool_TranslateXY(gpointer, guint, GtkWidget *)
1904 {
1905 if (toggle_event_ignore_counter > 0)
1906 {
1907 cout << "DEBUG : transl_xy skipped ; counter = " << toggle_event_ignore_counter << endl;
1908 toggle_event_ignore_counter--;
1909 }
1910 else
1911 {
1912 cout << "DEBUG : transl_xy state is " << gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_translate_xy)) << endl;
1913
1914 custom_app::mtool old_mt = custom_app::current_mouse_tool;
1915 custom_app::current_mouse_tool = custom_app::mtTranslateXY;
1916 HandleToggleButtons(old_mt);
1917 }
1918 }
1919
maintb_tool_TranslateZ(gpointer,guint,GtkWidget *)1920 void gtk_app::maintb_tool_TranslateZ(gpointer, guint, GtkWidget *)
1921 {
1922 if (toggle_event_ignore_counter > 0)
1923 {
1924 cout << "DEBUG : transl_z skipped ; counter = " << toggle_event_ignore_counter << endl;
1925 toggle_event_ignore_counter--;
1926 }
1927 else
1928 {
1929 cout << "DEBUG : transl_z state is " << gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_translate_z)) << endl;
1930
1931 custom_app::mtool old_mt = custom_app::current_mouse_tool;
1932 custom_app::current_mouse_tool = custom_app::mtTranslateZ;
1933 HandleToggleButtons(old_mt);
1934 }
1935 }
1936
maintb_tool_OrbitXY(gpointer,guint,GtkWidget *)1937 void gtk_app::maintb_tool_OrbitXY(gpointer, guint, GtkWidget *)
1938 {
1939 if (toggle_event_ignore_counter > 0)
1940 {
1941 cout << "DEBUG : orbit_xy skipped ; counter = " << toggle_event_ignore_counter << endl;
1942 toggle_event_ignore_counter--;
1943 }
1944 else
1945 {
1946 cout << "DEBUG : orbit_xy state is " << gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_orbit_xy)) << endl;
1947
1948 custom_app::mtool old_mt = custom_app::current_mouse_tool;
1949 custom_app::current_mouse_tool = custom_app::mtOrbitXY;
1950 HandleToggleButtons(old_mt);
1951 }
1952 }
1953
maintb_tool_OrbitZ(gpointer,guint,GtkWidget *)1954 void gtk_app::maintb_tool_OrbitZ(gpointer, guint, GtkWidget *)
1955 {
1956 if (toggle_event_ignore_counter > 0)
1957 {
1958 cout << "DEBUG : orbit_z skipped ; counter = " << toggle_event_ignore_counter << endl;
1959 toggle_event_ignore_counter--;
1960 }
1961 else
1962 {
1963 cout << "DEBUG : orbit_z state is " << gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_orbit_z)) << endl;
1964
1965 custom_app::mtool old_mt = custom_app::current_mouse_tool;
1966 custom_app::current_mouse_tool = custom_app::mtOrbitZ;
1967 HandleToggleButtons(old_mt);
1968 }
1969 }
1970
maintb_tool_RotateXY(gpointer,guint,GtkWidget *)1971 void gtk_app::maintb_tool_RotateXY(gpointer, guint, GtkWidget *)
1972 {
1973 if (toggle_event_ignore_counter > 0)
1974 {
1975 cout << "DEBUG : rotate_xy skipped ; counter = " << toggle_event_ignore_counter << endl;
1976 toggle_event_ignore_counter--;
1977 }
1978 else
1979 {
1980 cout << "DEBUG : rotate_xy state is " << gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_rotate_xy)) << endl;
1981
1982 custom_app::mtool old_mt = custom_app::current_mouse_tool;
1983 custom_app::current_mouse_tool = custom_app::mtRotateXY;
1984 HandleToggleButtons(old_mt);
1985 }
1986 }
1987
maintb_tool_RotateZ(gpointer,guint,GtkWidget *)1988 void gtk_app::maintb_tool_RotateZ(gpointer, guint, GtkWidget *)
1989 {
1990 if (toggle_event_ignore_counter > 0)
1991 {
1992 cout << "DEBUG : rotate_z skipped ; counter = " << toggle_event_ignore_counter << endl;
1993 toggle_event_ignore_counter--;
1994 }
1995 else
1996 {
1997 cout << "DEBUG : rotate_z state is " << gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_rotate_z)) << endl;
1998
1999 custom_app::mtool old_mt = custom_app::current_mouse_tool;
2000 custom_app::current_mouse_tool = custom_app::mtRotateZ;
2001 HandleToggleButtons(old_mt);
2002 }
2003 }
2004
maintb_tool_Measure(gpointer,guint,GtkWidget *)2005 void gtk_app::maintb_tool_Measure(gpointer, guint, GtkWidget *)
2006 {
2007 if (toggle_event_ignore_counter > 0)
2008 {
2009 cout << "DEBUG : measure skipped ; counter = " << toggle_event_ignore_counter << endl;
2010 toggle_event_ignore_counter--;
2011 }
2012 else
2013 {
2014 cout << "DEBUG : measure state is " << gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mtb_mtool_measure)) << endl;
2015
2016 custom_app::mtool old_mt = custom_app::current_mouse_tool;
2017 custom_app::current_mouse_tool = custom_app::mtMeasure;
2018 HandleToggleButtons(old_mt);
2019 }
2020 }
2021
maintb_dial_Element(gpointer,guint,GtkWidget *)2022 void gtk_app::maintb_dial_Element(gpointer, guint, GtkWidget *)
2023 {
2024 new gtk_element_dialog(); // will call delete itself...
2025 }
2026
maintb_dial_BondType(gpointer,guint,GtkWidget *)2027 void gtk_app::maintb_dial_BondType(gpointer, guint, GtkWidget *)
2028 {
2029 new gtk_bondtype_dialog(); // will call delete itself...
2030 }
2031
maintb_dial_Setup(gpointer,guint,GtkWidget *)2032 void gtk_app::maintb_dial_Setup(gpointer, guint, GtkWidget *)
2033 {
2034 if (project::background_job_running) return; // protect the model-data during background jobs...
2035
2036 new gtk_setup_dialog(GetPrjX()); // will call delete itself...
2037 }
2038
2039 // the main-menu callbacks start here ; the main-menu callbacks start here
2040 // the main-menu callbacks start here ; the main-menu callbacks start here
2041 // the main-menu callbacks start here ; the main-menu callbacks start here
2042
mainmenu_FileNew(gpointer,guint,GtkWidget *)2043 void gtk_app::mainmenu_FileNew(gpointer, guint, GtkWidget *)
2044 {
2045 if (project::background_job_running) return; // protect the model-data during background jobs...
2046
2047 GetAppX()->SetNewProject();
2048 }
2049
mainmenu_FileOpen(gpointer,guint,GtkWidget *)2050 void gtk_app::mainmenu_FileOpen(gpointer, guint, GtkWidget *)
2051 {
2052 if (project::background_job_running) return; // protect the model-data during background jobs...
2053
2054 new gtk_file_open_dialog(GetPrjX()); // will call delete itself...
2055 }
2056
mainmenu_FileSaveAs(gpointer,guint,GtkWidget *)2057 void gtk_app::mainmenu_FileSaveAs(gpointer, guint, GtkWidget *)
2058 {
2059 if (project::background_job_running) return; // protect the model-data during background jobs...
2060
2061 new gtk_file_save_dialog(GetPrjX()); // will call delete itself...
2062 }
2063
mainmenu_FileClose(gpointer,guint,GtkWidget *)2064 void gtk_app::mainmenu_FileClose(gpointer, guint, GtkWidget *)
2065 {
2066 if (project::background_job_running) return; // protect the model-data during background jobs...
2067
2068 // gtk_signal_emit_by_name(GTK_OBJECT(main_window), "delete_event");
2069 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2070 // the above is an "elegant" solution but it segfaults ; why???
2071 // in below the same stuff is done "manually".
2072
2073 if (!DeleteEventHandler(NULL, NULL, NULL)) gtk_widget_destroy(main_window);
2074 }
2075
mainmenu_HelpHelp(gpointer,guint,GtkWidget *)2076 void gtk_app::mainmenu_HelpHelp(gpointer, guint, GtkWidget *)
2077 {
2078 ostringstream str; str << "xdg-open ";
2079 str << project::appdata_path << DIR_SEPARATOR;
2080 str << project::appversion << DIR_SEPARATOR;
2081 str << "user-docs/index.html &" << ends;
2082
2083 cout << _("Displaying the User's Manual using the following command:") << endl;
2084 cout << str.str().c_str() << endl;
2085
2086 system(str.str().c_str());
2087 }
2088
mainmenu_HelpAbout(gpointer,guint,GtkWidget *)2089 void gtk_app::mainmenu_HelpAbout(gpointer, guint, GtkWidget *)
2090 {
2091 ostringstream about_str;
2092
2093 about_str << _("Ghemical-") << APPVERSION << _(" released on ") << APPRELEASEDATE << endl;
2094 about_str << " " << endl;
2095 about_str << _("For more information please visit:") << endl;
2096 about_str << WEBSITE << endl;
2097 about_str << " " << endl;
2098
2099 // leave some lines out to keep the dialog size smaller...
2100 for (i32s n1 = 0;n1 < 16;n1++) about_str << get_copyright_notice_line(n1) << endl;
2101
2102 about_str << " " << endl;
2103 about_str << _("Authors:") << endl;
2104 about_str << "\t\t" << "Tommi Hassinen" << endl;
2105 about_str << "\t\t" << "Geoff Hutchison" << endl;
2106 about_str << "\t\t" << "Mike Cruz" << endl;
2107 about_str << "\t\t" << "Michael Banck" << endl;
2108 about_str << "\t\t" << "Christopher Rowley" << endl;
2109 about_str << "\t\t" << "Jean Brefort" << endl;
2110 about_str << "\t\t" << "Daniel Leidert" << endl;
2111 about_str << "\t\t" << "Vlado Peshov" << endl;
2112
2113 about_str << ends;
2114
2115 static char about[2048];
2116 strcpy(about, about_str.str().c_str());
2117
2118 prj->Message(about);
2119 }
2120
2121 /*################################################################################################*/
2122
2123 // eof
2124