1 /*
2  *  Dr Geo an interactive geometry software
3  * (C) Copyright Hilaire Fernandes  1997-2003
4  * hilaire@ofset.org
5  *
6  * This code is copyright Laurent Gauthier 1999
7  * lolo@seul.org
8  *
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public Licences as by published
12  * by the Free Software Foundation; either version 2; or (at your option)
13  * any later version
14  *
15  * This program is distributed in the hope that it will entertaining,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
18  * Publis License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.
22  * 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24 
25 #include <string.h>
26 
27 #include "drgeo_tool.h"
28 #include "drgeo_point.h"
29 
30 drgeoState
getDrgeoState()31 drgeoTool::getDrgeoState ()
32 {
33   return state;
34 }
35 
36 // -------------------------------------------------
37 // Implementation for the Null tool, this tool does nothing.
38 
39 void
initialize(drgeoDrawableUI * drawable)40 drgeoNullTool::initialize (drgeoDrawableUI * drawable)
41 {
42   // Do nothing.
43   g_printerr ("initialize()\n");
44 }
45 
46 void
handlePress(drgeoDrawableUI * drawable,drgeoPoint & where)47 drgeoNullTool::handlePress (drgeoDrawableUI * drawable, drgeoPoint & where)
48 {
49   // Do nothing.
50   g_printerr ("handlePress (%lf,%lf)\n", where.getX (), where.getY ());
51 }
52 
53 void
handleRelease(drgeoDrawableUI * drawable,drgeoPoint & where)54 drgeoNullTool::handleRelease (drgeoDrawableUI * drawable, drgeoPoint & where)
55 {
56   // Do nothing.
57   // printf ("handleRelease (%lf,%lf)\n", where.getX (), where.getY ());
58 }
59 
60 void
handleMouseAt(drgeoDrawableUI * drawable,drgeoPoint & where)61 drgeoNullTool::handleMouseAt (drgeoDrawableUI * drawable, drgeoPoint & where)
62 {
63   // Do nothing.
64   g_printerr ("handleMouseAt (%lf,%lf)\n", where.getX (), where.getY ());
65 }
66 
67 void
68 drgeoNullTool::
handleChoice(drgeoDrawableUI * drawable,geometricObject * item)69 handleChoice (drgeoDrawableUI * drawable, geometricObject * item)
70 {
71   // Do nothing.
72   g_printerr ("HandleChoice()\n");
73 }
74 
75 void
finish(drgeoDrawableUI * drawable)76 drgeoNullTool::finish (drgeoDrawableUI * drawable)
77 {
78   // Do nothing.
79   g_printerr ("finish()\n");
80 }
81 
82 // -------------------------------------------------
83 // Implementation for the Printing Area tool.
84 void
initialize(class drgeoDrawableUI * drawable)85 drgeoPrintingAreaTool::initialize (class drgeoDrawableUI * drawable)
86 {
87   // no corner of the printing area is selected
88   state = drgeoStateNeutral;
89 }
90 
91 void
handlePress(class drgeoDrawableUI * drawable,drgeoPoint & where)92 drgeoPrintingAreaTool::handlePress (class drgeoDrawableUI * drawable,
93 				   drgeoPoint & where)
94 {
95   switch (state)
96     {
97     case drgeoStateNeutral:
98       corner1 = where;
99       state = drgeoState1stCornerSelected;
100       break;
101     case drgeoState1stCornerSelected:
102       corner2 = where;
103       state = drgeoState2ndCornerSelected;
104       // instruct the drawable about the selected printing area
105       drawable->showPrintingArea (corner1, corner2);
106       break;
107     case drgeoState2ndCornerSelected:
108       // does the user wants to reselect the area? in this case
109       // fallback to initial state
110       corner1 = where;
111       state = drgeoState1stCornerSelected;
112       drawable->unsetPrintingArea ();
113       break;
114     default:
115       // We should never reach that point !
116       break;
117     }
118 }
119 
120 void
handleMouseAt(class drgeoDrawableUI * drawable,drgeoPoint & where)121 drgeoPrintingAreaTool::handleMouseAt (class drgeoDrawableUI * drawable,
122 				      drgeoPoint & where)
123 {
124   switch (state)
125     {
126     case drgeoStateNeutral:
127       // nothing to be done
128       break;
129     case drgeoState1stCornerSelected:
130       // we can print the moving printing area
131       drawable->showPrintingArea (corner1, where);
132       break;
133     case drgeoState2ndCornerSelected:
134       // Nothing to be done, the selected drawing area is already
135       // printed
136       break;
137     default:
138       // We should never reach that point !
139       break;
140     }
141 }
142 
143 void
finish(class drgeoDrawableUI * drawable)144 drgeoPrintingAreaTool::finish (class drgeoDrawableUI * drawable)
145 {
146   switch (state)
147     {
148     case drgeoState2ndCornerSelected:
149       // the drawable already now the drawing area
150       break;
151     case drgeoState1stCornerSelected:
152       // unselect the printing area, the 2 corner was not selected
153       drawable->unsetPrintingArea ();
154     }
155 }
156 
157 // -------------------------------------------------
158 // Implementation for the Select tool.
159 
160 void
initialize(drgeoDrawableUI * drawable)161 drgeoSelectTool::initialize (drgeoDrawableUI * drawable)
162 {
163   // This code is invoked when the tool selected.
164   state = drgeoStateNeutral;
165   tipOn = FALSE;
166   last_nb_elem = 0;
167 }
168 
169 void
handlePress(drgeoDrawableUI * drawable,drgeoPoint & where)170 drgeoSelectTool::handlePress (drgeoDrawableUI * drawable, drgeoPoint & where)
171 {
172   liste_elem *list;
173   int i;
174 
175   // Do nothing if no figure is currently associated with this drawable.
176   if (drawable->figure != NULL)
177     {
178       drawable->removeTip ();
179       switch (state)
180 	{
181 	case drgeoStateItemChoice:
182 	  // The user has not chosen any item, so revert to neutral
183 	  // state.
184 	  state = drgeoStateNeutral;
185 	  // Fall through!  This is really what is wanted here.
186 	case drgeoStateNeutral:
187 	  // The mouse button is being pressed, check if there are items
188 	  // near the mouse.
189 	  list = drawable->figure->mouseSelection (where);
190 	  list->init_lire ();
191 	  if (list->nb_elem == 1)
192 	    {
193 	      // Only one item is selected.
194 	      state = drgeoStateItemGrabbed;
195 	      handleChoice (drawable, (geometricObject *) list->lire (0));
196 	      last = where;
197 	    }
198 	  else if (list->nb_elem > 1)
199 	    {
200 	      // Several items are selected at once, we must prompt the
201 	      // user for a choice.  When the user is done with his
202 	      // choice the handleChoice method will be invoked.
203 	      state = drgeoStateItemChoice;
204 	      last = where;
205 	      drawable->chooseItem (list);
206 	    }
207 	  else
208 	    {
209 	      // The user click on the background:
210 	      // clear the selection
211 	      state = drgeoStateNeutral;
212 	      drawable->getFigure ()->clearSelection ();
213 	      itemUnderMouse = NULL;
214 	    }
215 	  break;
216 	case drgeoStateItemSelected:
217 	  // The mouse button is being pressed, check if the last
218 	  // selected item is near the mouse.
219 	  list = drawable->figure->mouseSelection (where);
220 	  list->init_lire ();
221 	  if (list->nb_elem >= 1)
222 	    {
223 	      // Check each item under the mouse to see if the last item
224 	      // selected is there.  If so select it, if not go back to
225 	      // neutral state.
226 	      for (i = 0; i < list->nb_elem; i++)
227 		{
228 		  if (this->item == (geometricObject *) list->lire (0))
229 		    {
230 		      state = drgeoStateItemGrabbed;
231 		      // The following is not necessary because it has
232 		      // already been performed, when the item has been
233 		      // selected among multiple items.
234 		      // handleChoice (drawable, this->item);
235 		      last = where;
236 		      break;	// Get out of the loop!  We found it.
237 
238 		    }
239 		}
240 	      if (state == drgeoStateItemSelected)
241 		{
242 		  // The item last selected is not under the mouse at
243 		  // this point, so we are back to neutral state.
244 		  state = drgeoStateNeutral;
245 		}
246 	    }
247 	  else
248 	    {
249 	      // No item under the mouse go back to the Neutral state.
250 	      state = drgeoStateNeutral;
251 	    }
252 	  break;
253 	default:
254 	  // If we get there, then there's a problem with the event
255 	  // handling code... XXX
256 	  break;
257 	}
258     }
259 }
260 
261 void
262 drgeoSelectTool::
handleRelease(drgeoDrawableUI * drawable,drgeoPoint & where)263 handleRelease (drgeoDrawableUI * drawable, drgeoPoint & where)
264 {
265   // Do nothing if no figure is currently associated with this drawable.
266   if (drawable->figure != NULL)
267     {
268       liste_elem *list;
269       geometricObject *item;
270 
271       drawable->removeTip ();
272       switch (state)
273 	{
274 	case drgeoStateItemChoice:
275 	case drgeoStateItemSelected:
276 	  // The user has not chosen any item, so revert to neutral
277 	  // state.
278 	  state = drgeoStateNeutral;
279 	  // Fall through!  This is really what is wanted here.
280 	case drgeoStateNeutral:
281 	  // The mouse button is just being released with nothing being
282 	  // dragged, so we only show a tip displaying the full name of
283 	  // the nearest item.
284 	  list = drawable->figure->mouseSelection (where);
285 	  list->init_lire ();
286 	  if (list->nb_elem == 1)
287 	    {
288 	      item = (geometricObject *) list->lire (0);
289 	      drawable->showTip (where, item->getTypeName ());
290 	      tipOn = TRUE;
291 	    }
292 	  else if (list->nb_elem > 1)
293 	    {
294 	      // There are several items under the mouse.
295 	      drawable->showTip (where, "???");
296 	      tipOn = TRUE;
297 	    }
298 	  break;
299 	case drgeoStateItemGrabbed:
300 	  // The user is just releasing the mouse.  Reset the state to
301 	  // neutral and that's all.
302 	  state = drgeoStateNeutral;
303 	  break;
304 	case drgeoStateItemDragged:
305 	  // The drag is finished, so we just drop the selected ietms
306 	  // where the mouse currently is.
307 	  state = drgeoStateNeutral;
308 	  drawable->figure->moveItem (NULL, where - start);
309 	  drawable->figure->dropSelection (last, where);
310 	  /* record the drag path */
311 	  drawable->removeTip ();
312 
313 	  // Forget the item when dragged
314 	  drawable->getFigure ()->clearSelection ();
315 	  itemUnderMouse = NULL;
316 
317 	  break;
318 	default:
319 	  // If we get there, then there's a problem with the event
320 	  // handling code... XXX
321 	  break;
322 	}
323     }
324 }
325 void
326 drgeoSelectTool::
handleMouseAt(drgeoDrawableUI * drawable,drgeoPoint & where)327 handleMouseAt (drgeoDrawableUI * drawable, drgeoPoint & where)
328 {
329   int i;
330 
331   // Do nothing if no figure is currently associated with this drawable.
332   if (drawable->figure != NULL)
333     {
334       liste_elem *list;
335 
336       switch (state)
337 	{
338 	case drgeoStateItemChoice:
339 	  // The user has not chosen any item, so revert to neutral
340 	  // state.
341 	  state = drgeoStateNeutral;
342 	  // Fall through!  This is really what is wanted here.
343 	case drgeoStateNeutral:
344 	  // The mouse is just moving over the figure, so we just query
345 	  // the figure to know which items are found near the current
346 	  // mouse position.  And a tooltip is shown displaying the full
347 	  // name of the nearest item.
348 
349 	  list = drawable->figure->mouseSelection (where);
350 	  if (list->nb_elem == 1 &&
351 	      ((geometricObject *) list->lire (1) != itemUnderMouse))
352 	    {
353 	      // The mouse move over another item
354 	      itemUnderMouse = (geometricObject *) list->lire (1);
355 	      drawable->showTip (where, itemUnderMouse->getTypeName ());
356 	      tipOn = TRUE;
357 	      drawable->setCursor (hand);
358 	    }
359 	  else if (list->nb_elem > 1 && last_nb_elem <= 1)
360 	    {
361 	      // There are NOW several items under the mouse.
362 	      drawable->showTip (where, "???");
363 	      tipOn = TRUE;
364 	      drawable->setCursor (hand);
365 	      itemUnderMouse = NULL;
366 	    }
367 	  else if (list->nb_elem == 0 && drawable->tipOn ())
368 	    {
369 	      /* mouse not over object anymore, remove the tip */
370 	      drawable->removeTip ();
371 	      drawable->setCursor (arrow);
372 	      tipOn = FALSE;
373 	      itemUnderMouse = NULL;
374 	    }
375 	  last_nb_elem = list->nb_elem;
376 	  break;
377 	case drgeoStateItemSelected:
378 	  // The mouse is moving over the figure, check if we are moving
379 	  // away from the spot where the last item was selected.  If so
380 	  // go back to neutral state.
381 	  if (away
382 	      && (spot - where).norm () > (last - spot).norm ()
383 	      + 4.0 * drawable->getRange ())
384 	    {
385 	      state = drgeoStateNeutral;
386 	      drawable->figure->clearSelection ();
387 	      drawable->setCursor (arrow);
388 	    }
389 	  else
390 	    {
391 	      // If the last selected item is under the mouse, then show
392 	      // a tip about it.
393 	      list = drawable->figure->mouseSelection (where);
394 	      list->init_lire ();
395 	      if (list->nb_elem >= 1)
396 		{
397 		  // Check each item under the mouse to see if the last item
398 		  // selected is there.  If so show its tip.
399 		  for (i = 0; i < list->nb_elem; i++)
400 		    {
401 		      if (this->item == (geometricObject *) list->lire (0)
402 			  && !tipOn)
403 			{
404 			  drawable->showTip (where,
405 					     this->item->getTypeName ());
406 			  tipOn = TRUE;
407 			  drawable->setCursor (hand);
408 			  break;	// Get out of the loop!  We found it.
409 			}
410 		    }
411 		}
412 	      away = TRUE;
413 	      last = where;
414 	    }
415 	  break;
416 	case drgeoStateItemGrabbed:
417 	  // The user is just starting a mouse move with an item
418 	  // grabbed, this means a drag is starting.  Notify the
419 	  // figure.
420 	  state = drgeoStateItemDragged;
421 	  drawable->figure->dragSelection (last, where);
422 	  drawable->refresh ();
423 	  last = where;
424 	  start = where;
425 	  break;
426 	case drgeoStateItemDragged:
427 	  // The drag is going on.
428 	  drawable->figure->dragSelection (last, where);
429 	  drawable->refresh ();
430 	  last = where;
431 	  break;
432 	default:
433 	  // If we get there, then there's a problem with the event
434 	  // handling code... XXX
435 	  break;
436 	}
437     }
438 }
439 
440 void
441 drgeoSelectTool::
handleChoice(drgeoDrawableUI * drawable,geometricObject * item)442 handleChoice (drgeoDrawableUI * drawable, geometricObject * item)
443 {
444   drgeoPoint xxx;
445 
446   if (drawable->figure)
447     {
448       if (state == drgeoStateItemChoice)
449 	{
450 	  state = drgeoStateItemSelected;
451 	  this->item = item;	// Keep track of the last item
452 	  // selected for later reference.
453 
454 	  away = FALSE;
455 	  spot = last;
456 	}
457       drawable->figure->clearSelection ();
458       drawable->figure->addToSelection (xxx, item);
459     }
460 }
461 
462 void
finish(drgeoDrawableUI * drawable)463 drgeoSelectTool::finish (drgeoDrawableUI * drawable)
464 {
465   // This code is invoked when the tool is deselected.
466 }
467 
468 // -------------------------------------------------
469 // Implementation for the Build tool.
470 
471 void
initialize(drgeoDrawableUI * drawable)472 drgeoBuildTool::initialize (drgeoDrawableUI * drawable)
473 {
474   // This code is invoked when the tool selected.
475   state = drgeoStateNeutral;
476   tipOn = FALSE;
477   last_nb_elem = 0;
478 }
479 
480 void
handlePress(drgeoDrawableUI * drawable,drgeoPoint & where)481 drgeoBuildTool::handlePress (drgeoDrawableUI * drawable, drgeoPoint & where)
482 {
483   liste_elem *list;
484   int i;
485 
486   // Do nothing if no figure is currently associated with this drawable.
487   if (drawable->figure != NULL)
488     {
489       drawable->removeTip ();
490       switch (state)
491 	{
492 	case drgeoStateItemChoice:
493 	  // The user has not chosen any item, so revert to neutral
494 	  // state.
495 	  state = drgeoStateNeutral;
496 	  // Fall through!  This is really what is wanted here.
497 	case drgeoStateNeutral:
498 	  // The mouse button is being pressed, check if there are items
499 	  // near the mouse.
500 	  list = drawable->figure->mouseSelection (where);
501 	  list->init_lire ();
502 	  if (list->nb_elem == 0)
503 	    {
504 	      // no item was selected.  Just invoke handleChoice with a
505 	      // NULL parameter that will be transmitted to
506 	      // figure->addToSelection() for appropriate processing.
507 	      last = where;
508 	      handleChoice (drawable, NULL);
509 	    }
510 	  else if (list->nb_elem == 1)
511 	    {
512 	      // Only one item is selected, add it to the selection.
513 	      last = where;
514 	      handleChoice (drawable, (geometricObject *) list->lire (0));
515 	    }
516 	  else if (list->nb_elem > 1)
517 	    {
518 	      // Several items are selected at once, we must prompt the
519 	      // user for a choice.  When the user is done with his
520 	      // choice the handleChoice method will be invoked.
521 	      state = drgeoStateItemChoice;
522 	      last = where;
523 	      drawable->chooseItem (list);
524 	    }
525 	  break;
526 	default:
527 	  // If we get there, then there's a problem with the event
528 	  // handling code... XXX
529 	  break;
530 	}
531     }
532 }
533 
534 void
handleRelease(drgeoDrawableUI * drawable,drgeoPoint & where)535 drgeoBuildTool::handleRelease (drgeoDrawableUI * drawable, drgeoPoint & where)
536 {
537   // Do nothing if no figure is currently associated with this drawable.
538   if (drawable->figure != NULL)
539     {
540       liste_elem *list;
541       geometricObject *item;
542 
543       drawable->removeTip ();
544       switch (state)
545 	{
546 	case drgeoStateItemChoice:
547 	  // The user has not chosen any item, so revert to neutral
548 	  // state.
549 	  state = drgeoStateNeutral;
550 	  // Fall through!  This is really what is wanted here.
551 	case drgeoStateNeutral:
552 	  // The mouse button is just being released with nothing being
553 	  // dragged, so we only show a tip displaying the full name of
554 	  // the nearest item.
555 	  list = drawable->figure->mouseSelection (where);
556 	  list->init_lire ();
557 	  if (list->nb_elem == 1)
558 	    {
559 	      item = (geometricObject *) list->lire (0);
560 	      drawable->showTip (where, item->getTypeName ());
561 	      tipOn = TRUE;
562 	    }
563 	  else if (list->nb_elem > 1)
564 	    {
565 	      // There are several items under the mouse.
566 	      drawable->showTip (where, "???");
567 	      tipOn = TRUE;
568 	    }
569 	  break;
570 	default:
571 	  // If we get there, then there's a problem with the event
572 	  // handling code... XXX
573 	  break;
574 	}
575     }
576 }
577 
578 void
handleMouseAt(drgeoDrawableUI * drawable,drgeoPoint & where)579 drgeoBuildTool::handleMouseAt (drgeoDrawableUI * drawable, drgeoPoint & where)
580 {
581   int i;
582 
583   // Do nothing if no figure is currently associated with this drawable.
584   if (drawable->figure != NULL)
585     {
586       liste_elem *list;
587       geometricObject *item;
588 
589       switch (state)
590 	{
591 	case drgeoStateItemChoice:
592 	  // The user has not chosen any item, so revert to neutral
593 	  // state.
594 	  state = drgeoStateNeutral;
595 	  // Fall through!  This is really what is wanted here.
596 	case drgeoStateNeutral:
597 	  // The mouse is just moving over the figure, so we just query
598 	  // the figure to know which items are found near the current
599 	  // mouse position.  And a tooltip is shown displaying the full
600 	  // name of the nearest item.
601 	  list = drawable->figure->mouseSelection (where);
602 
603 	  if (list->nb_elem == 1 &&
604 	      ((geometricObject *) list->lire (1) != itemUnderMouse))
605 	    {
606 	      itemUnderMouse = (geometricObject *) list->lire (1);
607 	      drawable->showTip (where, itemUnderMouse->getTypeName ());
608 	      drawable->setCursor (pen);
609 	    }
610 	  else if (list->nb_elem > 1 && last_nb_elem <= 1)
611 	    {
612 	      // There are several items under the mouse.
613 	      drawable->showTip (where, "???");
614 	      drawable->setCursor (pen);
615 	      itemUnderMouse = NULL;
616 	    }
617 	  else if (list->nb_elem == 0 && drawable->tipOn ())
618 	    {
619 	      /* mouse not over object anymore, remove the tip */
620 	      drawable->removeTip ();
621 	      drawable->setCursor (arrow);
622 	      itemUnderMouse = NULL;
623 	    }
624 	  last_nb_elem = list->nb_elem;
625 	  break;
626 	default:
627 	  // If we get there, then there's a problem with the event
628 	  // handling code... XXX
629 	  break;
630 	}
631     }
632 }
633 
634 void
635 drgeoBuildTool::
handleChoice(drgeoDrawableUI * drawable,geometricObject * item)636 handleChoice (drgeoDrawableUI * drawable, geometricObject * item)
637 {
638   if (drawable->figure)
639     {
640       // Add the selected item to the current figure's selection.
641       drawable->figure->addToSelection (last, item);
642     }
643 }
644 
645 void
finish(drgeoDrawableUI * drawable)646 drgeoBuildTool::finish (drgeoDrawableUI * drawable)
647 {
648   // This code is invoked when the tool is deselected.
649 }
650 
651 
652 
653 // -----------------------------------------------------
654 // Macro Build Tool, used for macro creation.
655 // -----------------------------------------------------
656 
657 void
initialize(drgeoDrawableUI * drawable)658 drgeoMacroBuildTool::initialize (drgeoDrawableUI * drawable)
659 {
660   // First invoke the initialize() method of drgeoBuildTool
661   // super-class.
662   drgeoBuildTool::initialize (drawable);
663 
664   // Now let's do our stuff.
665   builder = new drgeoMacroBuilder (drawable->getFigure ());
666 
667   // Create the macro dialog that will control the builder.
668   dialog = drawable->createMacroBuildDialog (builder);
669 }
670 
671 // All the other methods are inherited from drgeoBuildTool.  We only
672 // redefine the handleChoice() method, and of course the initialize()
673 // and finish().
674 
675 void
676 drgeoMacroBuildTool::
handleChoice(drgeoDrawableUI * drawable,geometricObject * item)677 handleChoice (drgeoDrawableUI * drawable, geometricObject * item)
678 {
679   // Forward this item to the macro builder.
680   if (dialog && item)
681     {
682       dialog->add (item);
683     }
684 }
685 
686 void
finish(drgeoDrawableUI * drawable)687 drgeoMacroBuildTool::finish (drgeoDrawableUI * drawable)
688 {
689   // First invoke the initialize() method of drgeoBuildTool
690   // super-class.
691   drgeoBuildTool::finish (drawable);
692 
693   // Remove the macro dialog that is controlling the builder.
694   delete dialog;
695 
696   // Free the drgeoMacroBuilder.
697   delete builder;
698 }
699 
700 // -----------------------------------------------------
701 // Macro Play Tool, used for macro execution.
702 // -----------------------------------------------------
703 
704 void
initialize(drgeoDrawableUI * drawable)705 drgeoMacroPlayTool::initialize (drgeoDrawableUI * drawable)
706 {
707   // First invoke the initialize() method of drgeoBuildTool
708   // super-class.
709   drgeoBuildTool::initialize (drawable);
710 
711   // Now let's do our stuff.
712   player = new drgeoMacroPlayer (drawable->getFigure ());
713 
714   // Create the macro dialog that will control the Player.
715   dialog = drawable->createMacroPlayDialog (player);
716 }
717 
718 // All the other methods are inherited from drgeoBuildTool.  We only
719 // redefine the handleChoice() method, and of course the initialize()
720 // and finish().
721 
722 void
723 drgeoMacroPlayTool::
handleChoice(drgeoDrawableUI * drawable,geometricObject * item)724 handleChoice (drgeoDrawableUI * drawable, geometricObject * item)
725 {
726   drgeoPoint xxx;
727 
728   // Forward this item to the macro Player.
729   if (dialog && item)
730     {
731       dialog->add (item);
732     }
733 }
734 
735 void
finish(drgeoDrawableUI * drawable)736 drgeoMacroPlayTool::finish (drgeoDrawableUI * drawable)
737 {
738   // First invoke the initialize() method of drgeoPlayTool
739   // super-class.
740   drgeoBuildTool::finish (drawable);
741 
742   // Remove the macro dialog that is controlling the Player.
743   delete dialog;
744 
745   // Free the drgeoMacroPlayer.
746   delete player;
747 }
748 
749 
750 // -----------------------------------------------------
751 // Dialog Less Macro Play Tool, used for macro execution.
752 // From the menu barre
753 // -----------------------------------------------------
754 
755 void
initialize(drgeoDrawableUI * drawable)756 drgeoMacroPlayToolDialogLess::initialize (drgeoDrawableUI * drawable)
757 {
758   // First invoke the initialize() method of drgeoBuildTool
759   // super-class.
760   drgeoBuildTool::initialize (drawable);
761 
762   // Now let's do our stuff.
763   player = new drgeoMacroPlayer (drawable->getFigure ());
764 
765   // Instruct the drawable about the Player.
766   drawable->setMacroPlayer (player);
767 }
768 
769 // All the other methods are inherited from drgeoBuildTool.  We only
770 // redefine the handleChoice() method, and of course the initialize()
771 // and finish().
772 
773 void
774 drgeoMacroPlayToolDialogLess::
handleChoice(drgeoDrawableUI * drawable,geometricObject * item)775 handleChoice (drgeoDrawableUI * drawable, geometricObject * item)
776 {
777   // Forward this item to the macro Player.
778   if (player && item)
779     {
780       player->add (item);
781     }
782 }
783 
784 void
785 drgeoMacroPlayToolDialogLess::
finish(drgeoDrawableUI * drawable)786 finish (drgeoDrawableUI * drawable)
787 {
788   // First invoke the initialize() method of drgeoPlayTool
789   // super-class.
790   drgeoBuildTool::finish (drawable);
791 
792   // Free the drgeoMacroPlayer.
793   delete player;
794 }
795 
796 gboolean drgeoMacroPlayToolDialogLess::
selectMacro(const gchar * name)797 selectMacro (const gchar *name)
798 {
799   return player->setMacro (name);
800 }
801 
802 // -----------------------------------------------------
803 // Dialog Less Animation Tool, used for animation.
804 // From the menu barre
805 // -----------------------------------------------------
806 static int
timer_cb(drgeoAnimationDialogLess * tool)807 timer_cb (drgeoAnimationDialogLess * tool)
808 {
809   if (tool->getDrgeoState () == drgeoStateAnimated)
810     tool->animate ();
811   return (TRUE);		// Make sure the CallBack will be
812   // called again and again...
813 }
814 
815 void
initialize(drgeoDrawableUI * drawable)816 drgeoAnimationDialogLess::initialize (drgeoDrawableUI * drawable)
817 {
818   drgeoBuildTool::initialize (drawable);
819   step = 0.05;
820   timeoutTag = 0;
821   itemUnderMouse = NULL;
822   this->drawable = drawable;
823 }
824 
825 void
handlePress(drgeoDrawableUI * drawable,drgeoPoint & where)826 drgeoAnimationDialogLess::handlePress (drgeoDrawableUI * drawable, drgeoPoint & where)
827 {
828   liste_elem *list;
829   int i;
830 
831   // Do nothing if no figure is currently associated with this drawable.
832   if (drawable->figure != NULL)
833     {
834       drawable->removeTip ();
835       switch (state)
836 	{
837 	case drgeoStateAnimated:
838 	  // user click while a point is animated,
839 	  // stop and reset the animation
840 	  reset ();
841 	  state = drgeoStateNeutral;
842 	  break;
843 	case drgeoStateItemChoice:
844 	  // The user has not chosen any item, so revert to neutral
845 	  // state.
846 	  state = drgeoStateNeutral;
847 	  // Fall through!  This is really what is wanted here.
848 	case drgeoStateNeutral:
849 	  // The mouse button is being pressed, check if there are items
850 	  // near the mouse.
851 	  list = drawable->figure->mouseSelection (where);
852 	  list->init_lire ();
853 	  if (list->nb_elem == 1)
854 	    {
855 	      // Only one item is selected, add it to the selection.
856 	      state = drgeoStateAnimated;
857 	      last = where;
858 	      handleChoice (drawable, (geometricObject *) list->lire (0));
859 	    }
860 	  else if (list->nb_elem > 1)
861 	    {
862 	      // Several items are selected at once, we must prompt the
863 	      // user for a choice.  When the user is done with his
864 	      // choice the handleChoice method will be invoked.
865 	      state = drgeoStateItemChoice;
866 	      last = where;
867 	      drawable->chooseItem (list);
868 	    }
869 	  break;
870 	default:
871 	  // If we get there, then there's a problem with the event
872 	  // handling code... XXX
873 	  break;
874 	}
875     }
876 }
877 void
handleChoice(drgeoDrawableUI * drawable,geometricObject * item)878 drgeoAnimationDialogLess::handleChoice (drgeoDrawableUI * drawable,
879 					geometricObject * item)
880 {
881   this->item = item;
882   state = drgeoStateAnimated;
883   animatedAbscissa = initialAbscissa = ((point * )item)->getAbscissa ();
884   timeoutTag =
885     gtk_timeout_add (100, (GtkFunction) timer_cb, (gpointer) this);
886 }
887 
888 void
finish(drgeoDrawableUI * drawable)889 drgeoAnimationDialogLess::finish (drgeoDrawableUI * drawable)
890 {
891   reset ();
892 }
893 
894 void
animate()895 drgeoAnimationDialogLess::animate ()
896 {
897   animatedAbscissa += step;
898   if (step > 0 && animatedAbscissa > 1.)
899     animatedAbscissa -= 1.;
900   if (step < 0 && animatedAbscissa < 0)
901     animatedAbscissa += 1.;
902   if (item)
903     {
904       ((point *) item)->setAbscissa (animatedAbscissa);
905       drawable->getFigure()->updateItems ();
906       drawable->refresh ();
907     }
908 }
909 
910 void
reset()911 drgeoAnimationDialogLess::reset ()
912 {
913   if (timeoutTag)
914     gtk_timeout_remove (timeoutTag);
915   timeoutTag = 0;
916   if (item)
917     ((point *) item)->setAbscissa (initialAbscissa);
918   drawable->getFigure()->updateItems ();
919   drawable->refresh ();
920   itemUnderMouse = NULL;
921 }
922 
923 void
setStep(gdouble aStep)924 drgeoAnimationDialogLess::setStep (gdouble aStep)
925 {
926   step = aStep;
927 }
928 
929 // -----------------------------------------------------
930 // Delete Tool, used for object deletion.
931 // -----------------------------------------------------
932 
933 void
934 drgeoDeleteTool::
handleChoice(drgeoDrawableUI * drawable,geometricObject * myItem)935 handleChoice (drgeoDrawableUI * drawable, geometricObject * myItem)
936 {
937   char *message;
938 
939   // Forward this item to the macro builder.
940   if (drawable->figure && myItem != NULL)
941     {
942       // Hide the removed items just to show the consequence of the
943       // removal.
944       drawable->figure->hideRemovedItems (myItem);
945 
946       // Ask the user if he wants to proceed with the item deletion.
947       if (myItem->getName ())
948 	{
949 	  if (strlen (myItem->getName ()))
950 	    message = g_strdup_printf (_("Remove %s?"), myItem->getName ());
951 	}
952       else
953 	message = g_strdup (_("Remove selected item?"));
954       if (drawable->askOkCancel (message))
955 	{
956 	  // Remove the item if the user wants it.
957 	  drawable->figure->removeItem (myItem);
958 	}
959       g_free (message);
960       // Show again the list of items to be removed.
961       drawable->figure->showRemovedItems ();
962       drawable->figure->redraw (FALSE);
963     }
964 }
965 
966 
967 
968 
969 
970 
971 // -----------------------------------------------------
972 // Style Editor Tool, used to adjust colors, ...
973 // -----------------------------------------------------
974 
975 void
initialize(drgeoDrawableUI * drawable)976 drgeoStyleTool::initialize (drgeoDrawableUI * drawable)
977 {
978   // First invoke the initialize() method of drgeoBuildTool
979   // super-class.
980   drgeoBuildTool::initialize (drawable);
981 
982   dialog = drawable->createStyleDialog ();
983 }
984 
985 // All the other methods are inherited from drgeoBuildTool.  We only
986 // redefine the handleChoice() method, and of course the initialize()
987 // and finish().
988 
989 void
990 drgeoStyleTool::
handleChoice(drgeoDrawableUI * drawable,geometricObject * item)991 handleChoice (drgeoDrawableUI * drawable, geometricObject * item)
992 {
993   drgeoPoint xxx;
994   // Forward this item to the style dialog.
995   if (dialog && item)
996     {
997       // Update the dialog that match the item newly selected.
998       drawable->figure->clearSelection ();
999       drawable->figure->addToSelection (xxx, item);
1000       dialog->edit (item);
1001     }
1002 }
1003 
1004 void
finish(drgeoDrawableUI * drawable)1005 drgeoStyleTool::finish (drgeoDrawableUI * drawable)
1006 {
1007   // First invoke the initialize() method of drgeoBuildTool
1008   // super-class.
1009   drgeoBuildTool::finish (drawable);
1010 
1011   // Remove the macro dialog that is used to adjust style.
1012   if (dialog)
1013     {
1014       delete dialog;
1015     }
1016 }
1017 
1018 // -----------------------------------------------------
1019 // Property Editor Tool, used to adjust properties when
1020 // availables.
1021 // -----------------------------------------------------
1022 
1023 void
initialize(drgeoDrawableUI * drawable)1024 drgeoPropertyTool::initialize (drgeoDrawableUI * drawable)
1025 {
1026   // First invoke the initialize() method of drgeoBuildTool
1027   // super-class.
1028   drgeoBuildTool::initialize (drawable);
1029 
1030   dialog = drawable->createPropertyDialog ();
1031 }
1032 
1033 void
1034 drgeoPropertyTool::
handleChoice(drgeoDrawableUI * drawable,geometricObject * item)1035 handleChoice (drgeoDrawableUI * drawable, geometricObject * item)
1036 {
1037   gint nb;
1038   drgeoPoint xxx;
1039   if (drawable->figure)
1040     {
1041       // Add the selected item to the current figure's selection.
1042       drawable->figure->clearSelection ();
1043       nb = drawable->figure->addToSelection (xxx, item);
1044     }
1045   // Forward this item to the style dialog.
1046   if (dialog && item && nb > 0)
1047     {
1048       // Update the dialog that match the item newly selected.
1049       dialog->edit (item);
1050     }
1051 }
1052 
1053 void
finish(drgeoDrawableUI * drawable)1054 drgeoPropertyTool::finish (drgeoDrawableUI * drawable)
1055 {
1056   // First invoke the initialize() method of drgeoBuildTool
1057   // super-class.
1058   drgeoBuildTool::finish (drawable);
1059 
1060   drawable->figure->clearSelection ();
1061   // Remove the macro dialog that is used to adjust style.
1062   if (dialog)
1063     {
1064       delete dialog;
1065     }
1066 }
1067