1 /*
2  *  Dr Geo an interactive geometry software
3  * (C) Copyright Hilaire Fernandes  2001
4  * hilaire@ofset.org
5  *
6  *
7  *
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public Licences as by published
11  * by the Free Software Foundation; either version 2; or (at your option)
12  * any later version
13  *
14  * This program is distributed in the hope that it will entertaining,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17  * Publis License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.
21  * 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23 
24 #include <stdio.h>
25 #include <glade/glade.h>
26 
27 #include "drgeo_gtkproperty.h"
28 #include "drgeo_gtkdrawable.h"
29 #include "drgeo_numeric.h"
30 #include "drgeo_command.h"
31 #include "drgeo_point.h"
32 #include "drgeo_script.h"
33 #include "drgeo_gtkhelpers.h"
34 #include "drgenius_mdi.h"
35 
36 extern drgeniusMDI *mdi;
37 extern const char * drgeniusHelp[];
38 
39 // Callback for the free point property dialog
40 static void
on_freePointAbscissaEntry_activate(GtkWidget * widget,gpointer data)41 on_freePointAbscissaEntry_activate (GtkWidget * widget, gpointer data)
42 {
43   drgeoVector v (0, 0);
44   drgeoGtkPropertyDialog *dialog;
45   point *item;
46   gdouble val;
47 
48   val = strtod (gtk_entry_get_text (GTK_ENTRY (widget)), NULL);
49 
50   dialog = (drgeoGtkPropertyDialog *) data;
51   item = (point *) dialog->getItem ();
52   v.setX (val - item->getCoordinate ().getX ());
53   dialog->moveItem (v);
54 }
55 
56 static void
on_freePointOrdinateEntry_activate(GtkWidget * widget,gpointer data)57 on_freePointOrdinateEntry_activate (GtkWidget * widget, gpointer data)
58 {
59   drgeoVector v (0, 0);
60   drgeoGtkPropertyDialog *dialog;
61   point *item;
62   gdouble val;
63 
64   val = strtod (gtk_entry_get_text (GTK_ENTRY (widget)), NULL);
65 
66   dialog = (drgeoGtkPropertyDialog *) data;
67   item = (point *) dialog->getItem ();
68   v.setY (val - item->getCoordinate ().getY ());
69   dialog->moveItem (v);
70 }
71 
72 static void
movePointWithEntriesValues(GtkWidget * widget,drgeoGtkPropertyDialog * dialog)73 movePointWithEntriesValues (GtkWidget * widget,
74 			    drgeoGtkPropertyDialog * dialog)
75 {
76 
77   GtkEntry *abscissa, *ordinate;
78   drgeoVector v;
79   point *item;
80   gdouble val1, val2;
81 
82   abscissa = (GtkEntry *) gtk_object_get_data (GTK_OBJECT (widget),
83 					       "abscissaEntry");
84   ordinate = (GtkEntry *) gtk_object_get_data (GTK_OBJECT (widget),
85 					       "ordinateEntry");
86   val1 = strtod (gtk_entry_get_text (abscissa), NULL);
87   val2 = strtod (gtk_entry_get_text (ordinate), NULL);
88 
89   item = (point *) dialog->getItem ();
90   v.set (val1 - item->getCoordinate ().getX (),
91 	 val2 - item->getCoordinate ().getY ());
92   dialog->moveItem (v);
93 }
94 
95 static void
on_freePointDialog_reponse(GtkDialog * d,gint r,gpointer data)96 on_freePointDialog_reponse (GtkDialog *d, gint r, gpointer data)
97 {
98   drgeoGtkPropertyDialog *dialog;
99 
100   dialog = (drgeoGtkPropertyDialog *) data;
101 
102   switch (r)
103     {
104     case GTK_RESPONSE_OK:
105       movePointWithEntriesValues (GTK_WIDGET (d), dialog);
106       dialog->hide ();
107       break;
108     case GTK_RESPONSE_APPLY:
109       movePointWithEntriesValues (GTK_WIDGET (d), dialog);
110       break;
111     case GTK_RESPONSE_CANCEL:
112       dialog->hide ();
113       break;
114     }
115 }
116 
117 // Callback for the edit value property dialog
118 static void
on_editValueEntry_activate(GtkWidget * widget,gpointer data)119 on_editValueEntry_activate (GtkWidget * widget, gpointer data)
120 {
121   drgeoGtkPropertyDialog *dialog;
122   gdouble val;
123 
124   val = g_ascii_strtod (gtk_entry_get_text (GTK_ENTRY (widget)), NULL);
125 
126   dialog = (drgeoGtkPropertyDialog *) data;
127   dialog->setValue (val);
128 }
129 
130 static void
on_editValueDialog_response(GtkWidget * widget,gint b,gpointer data)131 on_editValueDialog_response (GtkWidget * widget, gint b, gpointer data)
132 {
133   drgeoGtkPropertyDialog *drgeoDialog;
134   drgeoDialog = (drgeoGtkPropertyDialog *) data;
135   widget = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (widget),
136 					    "valueEntry"));
137   switch (b)
138     {
139     case GTK_RESPONSE_OK:
140       // Ok
141       on_editValueEntry_activate (widget, drgeoDialog);
142       drgeoDialog->hide ();
143       break;
144     case GTK_RESPONSE_APPLY:
145       // Apply
146       on_editValueEntry_activate (widget, drgeoDialog);
147       break;
148     case GTK_RESPONSE_CANCEL:
149       // Cancel
150       drgeoDialog->hide ();
151       break;
152     }
153 }
154 
155 // When the user close the window containing the dialog
156 static gint
on_propertyDialog_delete(GtkWidget * widget,GdkEventAny * e,gpointer data)157 on_propertyDialog_delete (GtkWidget * widget, GdkEventAny * e, gpointer data)
158 {
159   drgeoGtkPropertyDialog *dialog;
160   dialog = (drgeoGtkPropertyDialog *) data;
161   dialog->hide ();
162   return TRUE;
163 }
164 
165 // Callback for the script edit dialog
166 static void
on_scriptDialog_response(GtkWidget * widget,gint b,drgeoGtkPropertyDialog * drgeoDialog)167 on_scriptDialog_response (GtkWidget *widget, gint b,
168 			 drgeoGtkPropertyDialog *drgeoDialog)
169 {
170   GtkTextView *text;
171   gchar *code;
172 
173   text = (GtkTextView *) gtk_object_get_data (GTK_OBJECT (widget),
174 					      "script");
175   code = gtk_text_view_get_text (text);
176 
177   switch (b)
178     {
179     case GTK_RESPONSE_OK:
180       // Ok
181       drgeoDialog->setScript (code);
182       drgeoDialog->hide ();
183       break;
184     case GTK_RESPONSE_APPLY:
185       // Apply
186       drgeoDialog->setScript (code);
187       break;
188     case GTK_RESPONSE_CANCEL:
189       // Cancel
190       drgeoDialog->hide ();
191       break;
192     }
193 }
194 
drgeoGtkPropertyDialog(drgeoGtkDrawable * aDrawable)195 drgeoGtkPropertyDialog::drgeoGtkPropertyDialog (drgeoGtkDrawable * aDrawable)
196 {
197   drawable = aDrawable;
198   dialog = NULL;
199   category = NO_OBJECT;
200   type = NO_TYPE;
201 }
202 
~drgeoGtkPropertyDialog()203 drgeoGtkPropertyDialog::~drgeoGtkPropertyDialog ()
204 {
205   hide ();
206   if (dialog)
207     {
208       gtk_widget_destroy (dialog);
209       dialog = NULL;
210     }
211 }
212 
213 void
show()214 drgeoGtkPropertyDialog::show ()
215 {
216   if (dialog)
217     gtk_widget_show_all (dialog);
218 }
219 
220 void
hide()221 drgeoGtkPropertyDialog::hide ()
222 {
223   if (dialog)
224     {
225       gtk_widget_hide (dialog);
226       /* unselected the selected item so they do no blink
227          anymore */
228       drawable->figure->clearSelection ();
229     }
230 }
231 
232 void
edit(class geometricObject * aItem)233 drgeoGtkPropertyDialog::edit (class geometricObject * aItem)
234 {
235   GladeXML *xml;
236   GtkWidget *widget, *widget2;
237   drgeoPoint p;
238   gchar out[256] = "";
239 
240   if (dialog && (aItem->getCategory () != category)
241       && (aItem->getType () != type))
242     gtk_widget_destroy (dialog);
243 
244   // Acording to the object category, we build the corresponding dialog.
245   switch (aItem->getCategory ())
246     {
247     case FREE_PT:
248 
249       if (category != aItem->getCategory ())
250 	{
251 	  xml = glade_xml_new (DRGEO_GLADEDIR "/drgeo2.glade",
252 			       "freePointPropertyDialog", NULL);
253 
254 	  dialog = glade_xml_get_widget (xml, "freePointPropertyDialog");
255 
256 	  //set transient
257 	  mdi->setTransientDialog (GTK_WINDOW (dialog));
258 
259 	  widget = glade_xml_get_widget (xml, "abscissaEntry");
260 	  gtk_signal_connect (GTK_OBJECT (widget), "activate",
261 			      GTK_SIGNAL_FUNC
262 			      (on_freePointAbscissaEntry_activate),
263 			      (gpointer) this);
264 	  gtk_object_set_data (GTK_OBJECT (dialog), "abscissaEntry", widget);
265 
266 	  widget = glade_xml_get_widget (xml, "ordinateEntry");
267 	  gtk_signal_connect (GTK_OBJECT (widget), "activate",
268 			      GTK_SIGNAL_FUNC
269 			      (on_freePointOrdinateEntry_activate),
270 			      (gpointer) this);
271 	  gtk_object_set_data (GTK_OBJECT (dialog), "ordinateEntry", widget);
272 
273 	  gtk_signal_connect (GTK_OBJECT (dialog), "response",
274 			      GTK_SIGNAL_FUNC (on_freePointDialog_reponse),
275 			      (gpointer) this);
276 
277 	  g_object_unref  (G_OBJECT (xml));
278 	}
279       p = ((point *) aItem)->getCoordinate ();
280       // Update the entries field
281       widget = (GtkWidget *) gtk_object_get_data (GTK_OBJECT (dialog),
282 						  "abscissaEntry");
283       snprintf (out, 255, "%f", p.getX ());
284       gtk_entry_set_text (GTK_ENTRY (widget), out);
285 
286       widget = (GtkWidget *) gtk_object_get_data (GTK_OBJECT (dialog),
287 						  "ordinateEntry");
288       snprintf (out, 255, "%f", p.getY ());
289       gtk_entry_set_text (GTK_ENTRY (widget), out);
290       break;
291     case NUMERIC:
292       // Only free value can be edited
293       if (aItem->getType () == FREE_VALUE)
294 	{
295 	  if (category != aItem->getCategory ())
296 	    {
297 	      xml = glade_xml_new (DRGEO_GLADEDIR "/drgeo2.glade",
298 				   "editValuePropertyDialog", NULL);
299 	      dialog = glade_xml_get_widget (xml, "editValuePropertyDialog");
300 
301 	      //set transient
302 	      mdi->setTransientDialog (GTK_WINDOW (dialog));
303 
304 	      widget = glade_xml_get_widget (xml, "valueEntry");
305 	      gtk_signal_connect (GTK_OBJECT (widget), "activate",
306 				  GTK_SIGNAL_FUNC
307 				  (on_editValueEntry_activate),
308 				  (gpointer) this);
309 	      gtk_object_set_data (GTK_OBJECT (dialog), "valueEntry", widget);
310 
311 	      gtk_signal_connect (GTK_OBJECT (dialog), "response",
312 				  GTK_SIGNAL_FUNC (on_editValueDialog_response),
313 				  (gpointer) this);
314 
315 	      g_object_unref  (G_OBJECT (xml));
316 	    }
317 	  // Update the entries field
318 	  widget = (GtkWidget *) gtk_object_get_data (GTK_OBJECT (dialog),
319 						      "valueEntry");
320 	  snprintf (out, 255, "%f", ((numeric *) aItem)->getValue ());
321 	  gtk_entry_set_text (GTK_ENTRY (widget), out);
322 	  break;
323 	}
324       break;
325     case SCRIPT:
326       if (category != aItem->getCategory ())
327 	{
328 	  // the corresponding dialog is not opened
329 	  xml = glade_xml_new (DRGEO_GLADEDIR "/drgeo2.glade",
330 			       "scriptDialog", NULL);
331 	  dialog = glade_xml_get_widget (xml, "scriptDialog");
332 
333 	  //set transient
334 	  mdi->setTransientDialog (GTK_WINDOW (dialog));
335 
336 	  widget2 = glade_xml_get_widget (xml, "scriptText");
337 	  gtk_object_set_data (GTK_OBJECT (dialog), "script", widget2);
338 
339 	  gtk_signal_connect (GTK_OBJECT (dialog), "response",
340 			      GTK_SIGNAL_FUNC (on_scriptDialog_response),
341 			      (gpointer) this);
342 
343 	  widget = glade_xml_get_widget (xml, "help");
344 	  gtk_signal_connect (GTK_OBJECT (widget), "clicked",
345 			      GTK_SIGNAL_FUNC (open_help_cb),
346 			      (gpointer) (drgeniusHelp[2]));
347 
348 	  gtk_signal_connect (GTK_OBJECT (dialog), "delete_event",
349 			      GTK_SIGNAL_FUNC (on_propertyDialog_delete),
350 			      (gpointer) this);
351 
352 
353 	  g_object_unref  (G_OBJECT (xml));
354 	}
355       // Update the text field with the script
356       // First empty the scriptText dialog
357       widget = (GtkWidget *) gtk_object_get_data (GTK_OBJECT (dialog),
358 						  "script");
359       gtk_text_view_set_text (GTK_TEXT_VIEW (widget),
360 			      ((script *) aItem)->getScript ());
361       break;
362     default:
363       dialog = NULL;
364       return;
365     }
366   // These are the characteristics of the item under edition:
367   item = aItem;
368   category = item->getCategory ();
369   type = item->getType ();
370 
371   show ();
372 }
373 
374 void
moveItem(drgeoVector & v)375 drgeoGtkPropertyDialog::moveItem (drgeoVector & v)
376 {
377   drgeoVector t (0, 0);
378 
379   drawable->getFigure ()->moveItem (item, v);
380   drawable->getFigure ()->dragSelection (t, v);
381   drawable->refresh ();
382 }
383 
384 void
setValue(gdouble value)385 drgeoGtkPropertyDialog::setValue (gdouble value)
386 {
387   gdouble *val;
388 
389   val = (gdouble *) g_malloc (sizeof (gdouble));
390   *val = value;
391   drawable->getFigure ()->setItemAttribute (item, drgeoValue, (gpointer) val);
392 }
393 
394 void
setScript(gchar * script)395 drgeoGtkPropertyDialog::setScript (gchar * script)
396 {
397   drawable->getFigure ()->setItemAttribute (item, drgeoScript,
398 					    (gpointer) script);
399 }
400 
401 void
refresh()402 drgeoGtkPropertyDialog::refresh ()
403 {
404   drawable->refresh ();
405 }
406 
407 geometricObject *
getItem()408 drgeoGtkPropertyDialog::getItem ()
409 {
410   return item;
411 }
412 
413 
getDrawable()414 drgeoDrawable & drgeoGtkPropertyDialog::getDrawable ()
415 {
416   return (*((drgeoDrawable *) drawable));
417 }
418