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