1 /*   EXTRAITS DE LA LICENCE
2 	Copyright CEA, contributeurs : Luc BILLARD et Damien
3 	CALISTE, laboratoire L_Sim, (2001-2005)
4 
5 	Adresse mèl :
6 	BILLARD, non joignable par mèl ;
7 	CALISTE, damien P caliste AT cea P fr.
8 
9 	Ce logiciel est un programme informatique servant à visualiser des
10 	structures atomiques dans un rendu pseudo-3D.
11 
12 	Ce logiciel est régi par la licence CeCILL soumise au droit français et
13 	respectant les principes de diffusion des logiciels libres. Vous pouvez
14 	utiliser, modifier et/ou redistribuer ce programme sous les conditions
15 	de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
16 	sur le site "http://www.cecill.info".
17 
18 	Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
19 	pris connaissance de la licence CeCILL, et que vous en avez accepté les
20 	termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
21 */
22 
23 /*   LICENCE SUM UP
24 	Copyright CEA, contributors : Luc BILLARD et Damien
25 	CALISTE, laboratoire L_Sim, (2001-2005)
26 
27 	E-mail address:
28 	BILLARD, not reachable any more ;
29 	CALISTE, damien P caliste AT cea P fr.
30 
31 	This software is a computer program whose purpose is to visualize atomic
32 	configurations in 3D.
33 
34 	This software is governed by the CeCILL  license under French law and
35 	abiding by the rules of distribution of free software.  You can  use,
36 	modify and/ or redistribute the software under the terms of the CeCILL
37 	license as circulated by CEA, CNRS and INRIA at the following URL
38 	"http://www.cecill.info".
39 
40 	The fact that you are presently reading this means that you have had
41 	knowledge of the CeCILL license and that you accept its terms. You can
42 	find a copy of this licence shipped with this software at Documentation/licence.en.txt.
43 */
44 #include "gtkAtomic.h"
45 
46 #include <extraGtkFunctions/gtk_numericalEntryWidget.h>
47 #include <gtk_main.h>
48 #include <visu_gtk.h>
49 #include <support.h>
50 #include <extensions/forces.h>
51 
52 /**
53  * SECTION:gtkAtomic
54  * @short_description: The gtk interface elements that are specific to
55  * the atomic rendering method.
56  *
57  * <para>This part gathers all the routine specific to the widgets
58  * related to the atomic rendering method. For the method itself,
59  * there is no specific widgets. For the #VisuElement part, one can
60  * tune the shape, the radius and the elipsoid orientation (when
61  * selected). There is no specific #GtkFileChooser widget.</para>
62  */
63 
64 /* the spin button to control the radius. */
65 static GtkWidget *checkForces = NULL;
66 static GtkWidget *radioScaleAuto = NULL;
67 static GtkWidget *entryScale = NULL;
68 static VisuNodeValuesVector *model = NULL;
69 static gulong chg_sig;
70 
71 /***************/
72 /* Public part */
73 /***************/
74 
updateLabel(GtkWidget * label,VisuNode * node _U_,VisuNodeValuesVector * vect)75 static void updateLabel(GtkWidget *label, VisuNode *node _U_, VisuNodeValuesVector *vect)
76 {
77   float max;
78   gchar *str;
79 
80   if (!vect)
81     gtk_label_set_text(GTK_LABEL(label), _("(No force data)"));
82   else
83     {
84       max = visu_node_values_farray_max(VISU_NODE_VALUES_FARRAY(vect));
85 
86       str = g_strdup_printf(_("(max. force is %.4g)"), max);
87       gtk_label_set_text(GTK_LABEL(label), str);
88       g_free(str);
89     }
90 }
_setModel(GtkWidget * label,VisuNodeValuesVector * vect)91 static void _setModel(GtkWidget *label, VisuNodeValuesVector *vect)
92 {
93   if (model)
94     {
95       g_signal_handler_disconnect(model, chg_sig);
96       g_object_unref(model);
97     }
98   model = vect;
99   if (vect)
100     {
101       g_object_ref(vect);
102       chg_sig = g_signal_connect_swapped(vect, "changed",
103                                          G_CALLBACK(updateLabel), label);
104     }
105   updateLabel(label, (VisuNode*)0, vect);
106 }
modelNotified(GtkWidget * label,GParamSpec * pspec _U_,VisuGlExtNodeVectors * forces)107 static void modelNotified(GtkWidget *label, GParamSpec *pspec _U_, VisuGlExtNodeVectors *forces)
108 {
109   _setModel(label, VISU_NODE_VALUES_VECTOR(visu_sourceable_getNodeModel(VISU_SOURCEABLE(forces))));
110 }
toAutoRadio(GBinding * bind _U_,const GValue * source_value,GValue * target_value,gpointer data _U_)111 static gboolean toAutoRadio(GBinding *bind _U_, const GValue *source_value,
112                             GValue *target_value, gpointer data _U_)
113 {
114   g_value_set_boolean(target_value, (g_value_get_float(source_value) <= 0.f));
115   return TRUE;
116 }
fromAutoRadio(GBinding * bind _U_,const GValue * source_value,GValue * target_value,gpointer data _U_)117 static gboolean fromAutoRadio(GBinding *bind _U_, const GValue *source_value,
118                               GValue *target_value, gpointer data _U_)
119 {
120   if (!g_value_get_boolean(source_value))
121     return FALSE;
122 
123   g_value_set_float(target_value, 0.f);
124   return TRUE;
125 }
toManualRadio(GBinding * bind _U_,const GValue * source_value,GValue * target_value,gpointer data _U_)126 static gboolean toManualRadio(GBinding *bind _U_, const GValue *source_value,
127                               GValue *target_value, gpointer data _U_)
128 {
129   g_value_set_boolean(target_value, (g_value_get_float(source_value) > 0.f));
130   return TRUE;
131 }
fromManualRadio(GBinding * bind _U_,const GValue * source_value,GValue * target_value,gpointer data _U_)132 static gboolean fromManualRadio(GBinding *bind _U_, const GValue *source_value,
133                                 GValue *target_value, gpointer data _U_)
134 {
135   if (!g_value_get_boolean(source_value))
136     return FALSE;
137 
138   g_value_set_float(target_value, visu_ui_numerical_entry_getValue(VISU_UI_NUMERICAL_ENTRY(entryScale)));
139   return TRUE;
140 }
toEntry(GBinding * bind _U_,const GValue * source_value,GValue * target_value,gpointer data _U_)141 static gboolean toEntry(GBinding *bind _U_, const GValue *source_value,
142                         GValue *target_value, gpointer data _U_)
143 {
144   if (g_value_get_float(source_value) <= 0.f)
145     return FALSE;
146 
147   g_value_set_double(target_value, g_value_get_float(source_value));
148   return TRUE;
149 }
fromEntry(GBinding * bind,const GValue * source_value,GValue * target_value,gpointer data _U_)150 static gboolean fromEntry(GBinding *bind, const GValue *source_value,
151                           GValue *target_value, gpointer data _U_)
152 {
153   if (visu_gl_ext_node_vectors_getNormalisation(VISU_GL_EXT_NODE_VECTORS(g_binding_get_source(bind))) <= 0.f)
154     return FALSE;
155 
156   g_value_set_float(target_value, g_value_get_double(source_value));
157   return TRUE;
158 }
onDestroy(GtkWidget * wd _U_,gpointer data _U_)159 static void onDestroy(GtkWidget *wd _U_, gpointer data _U_)
160 {
161   if (model)
162     {
163       g_signal_handler_disconnect(model, chg_sig);
164       g_object_unref(model);
165     }
166 }
167 /* Creates the vbox displayed in the config panel */
168 /**
169  * visu_ui_panel_method_atomic_create:
170  * @scene: a #VisuGlNodeScene object.
171  *
172  * Creates a widget with the options for atomic rendering.
173  *
174  * Since: 3.8
175  *
176  * Returns: (transfer full): a newly create #GtkVBox object.
177  **/
visu_ui_panel_method_atomic_create(VisuGlNodeScene * scene)178 GtkWidget* visu_ui_panel_method_atomic_create(VisuGlNodeScene *scene)
179 {
180   GtkWidget *vbox, *wd, *hbox, *radio, *vbox2, *label;
181   GSList *lst;
182   VisuGlExtForces *forces;
183 
184   DBG_fprintf(stderr, "Gtk Atomic: building specific widgets for method.\n");
185   forces = visu_gl_node_scene_getForces(scene);
186 
187   vbox = gtk_vbox_new(FALSE, 0);
188 
189   checkForces = gtk_check_button_new_with_mnemonic
190     (_("Display _forces (if available)"));
191   g_object_bind_property(forces, "active", checkForces, "active",
192                          G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
193   g_object_bind_property(forces, "model", checkForces, "sensitive", G_BINDING_SYNC_CREATE);
194   gtk_box_pack_start(GTK_BOX(vbox), checkForces, FALSE, FALSE, 0);
195   vbox2 = gtk_vbox_new(FALSE, 0);
196   gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, FALSE, 0);
197   wd = gtk_label_new(_("Policy to scale arrows:"));
198   gtk_label_set_xalign(GTK_LABEL(wd), 0.);
199   gtk_widget_set_margin_start(wd, 10);
200   gtk_box_pack_start(GTK_BOX(vbox2), wd, FALSE, FALSE, 0);
201 
202   hbox = gtk_hbox_new(FALSE, 0);
203   gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0);
204   radioScaleAuto = gtk_radio_button_new_with_label(NULL, _("automatic"));
205   g_object_bind_property_full(forces, "normalisation", radioScaleAuto, "active",
206                               G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL,
207                               toAutoRadio, fromAutoRadio, (gpointer)0, (GDestroyNotify)0);
208   gtk_radio_button_set_group(GTK_RADIO_BUTTON(radioScaleAuto), (GSList*)0);
209   lst = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioScaleAuto));
210   gtk_box_pack_start(GTK_BOX(hbox), radioScaleAuto, TRUE, TRUE, 15);
211   hbox = gtk_hbox_new(FALSE, 0);
212   gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0);
213   radio = gtk_radio_button_new_with_label(NULL, _("manual"));
214   gtk_radio_button_set_group(GTK_RADIO_BUTTON(radio), lst);
215   g_object_bind_property_full(forces, "normalisation", radio, "active",
216                               G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL,
217                               toManualRadio, fromManualRadio, (gpointer)0, (GDestroyNotify)0);
218 
219   gtk_box_pack_start(GTK_BOX(hbox), radio, FALSE, FALSE, 15);
220   entryScale = visu_ui_numerical_entry_new(1e-2);
221   gtk_entry_set_width_chars(GTK_ENTRY(entryScale), 6);
222   g_object_bind_property_full(forces, "normalisation", entryScale, "value",
223                               G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL,
224                               toEntry, fromEntry, (gpointer)0, (GDestroyNotify)0);
225 
226   gtk_box_pack_start(GTK_BOX(hbox), entryScale, FALSE, FALSE, 0);
227   label = gtk_label_new("");
228   gtk_label_set_xalign(GTK_LABEL(label), 0.);
229   gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 5);
230 
231   g_signal_connect_object(forces, "notify::model", G_CALLBACK(modelNotified),
232                           label, G_CONNECT_SWAPPED);
233   _setModel(label, VISU_NODE_VALUES_VECTOR(visu_sourceable_getNodeModel(VISU_SOURCEABLE(forces))));
234 
235   gtk_widget_show_all(vbox);
236 
237   g_signal_connect(vbox, "destroy", G_CALLBACK(onDestroy), (gpointer)0);
238 
239   return vbox;
240 }
241