]> Shamusworld >> Repos - architektonas/blob - src/base/rs_eventhandler.cpp
GPL compliance check...
[architektonas] / src / base / rs_eventhandler.cpp
1 // rs_eventhandler.cpp
2 //
3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
9 //
10 // JLH = James L. Hammons <jlhamm@acm.org>
11 //
12 // Who  When        What
13 // ---  ----------  -----------------------------------------------------------
14 // JLH  05/28/2010  Added this text. :-)
15 //
16
17 #include "rs_eventhandler.h"
18
19 #include "actioninterface.h"
20 #include "rs_commandevent.h"
21 #include "rs_debug.h"
22 #include "rs_dialogfactory.h"
23 #include "graphicview.h"
24 #include "rs_math.h"
25
26 /**
27  * Constructor.
28  */
29 RS_EventHandler::RS_EventHandler(GraphicView * graphicView)
30 {
31         this->graphicView = graphicView;
32         actionIndex = -1;
33
34         for(int i=0; i<RS_MAXACTIONS; ++i)
35                 currentActions[i] = NULL;
36
37         coordinateInputEnabled = true;
38         defaultAction = NULL;
39 }
40
41 /**
42  * Destructor.
43  */
44 RS_EventHandler::~RS_EventHandler()
45 {
46         RS_DEBUG->print("RS_EventHandler::~RS_EventHandler");
47
48         if (defaultAction != NULL)
49         {
50                 defaultAction->finish();
51                 delete defaultAction;
52                 defaultAction = NULL;
53         }
54
55         killAllActions();
56
57         RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: Deleting all actions..");
58
59         for(int i=0; i<RS_MAXACTIONS; ++i)
60         {
61                 if (currentActions[i] != NULL)
62                 {
63                         currentActions[i]->setFinished();
64                         //delete currentActions[i];
65                         //currentActions[i] = NULL;
66                 }
67         }
68
69         cleanUp();
70         RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: Deleting all actions..: OK");
71         RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: OK");
72 }
73
74 /**
75  * Go back in current action.
76  */
77 void RS_EventHandler::back()
78 {
79         QMouseEvent e(QEvent::MouseButtonRelease, QPoint(0, 0), Qt::RightButton, Qt::RightButton,
80                 Qt::NoModifier);
81         mouseReleaseEvent(&e);
82 }
83
84 /**
85  * Go enter pressed event for current action.
86  */
87 void RS_EventHandler::enter()
88 {
89 //      QKeyEvent e(QEvent::KeyPress, Qt::Key_Enter, '\n', 0);
90         QKeyEvent e(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier, "\n", false, 0);
91         keyPressEvent(&e);
92 }
93
94 /**
95  * Called by GraphicView
96  */
97 void RS_EventHandler::mousePressEvent(QMouseEvent * e)
98 {
99         if (actionIndex >= 0 && currentActions[actionIndex] != NULL)
100         {
101                 currentActions[actionIndex]->mousePressEvent(e);
102                 e->accept();
103         }
104         else
105         {
106                 if (defaultAction != NULL)
107                 {
108                         defaultAction->mousePressEvent(e);
109                         e->accept();
110                 }
111                 else
112                 {
113                         RS_DEBUG->print("currently no action defined");
114                         e->ignore();
115                 }
116         }
117 }
118
119 /**
120  * Called by GraphicView
121  */
122 void RS_EventHandler::mouseReleaseEvent(QMouseEvent * e)
123 {
124         if (actionIndex >= 0 && currentActions[actionIndex] != NULL
125                 && !currentActions[actionIndex]->isFinished())
126         {
127                 RS_DEBUG->print("call action %s", currentActions[actionIndex]->getName().toLatin1().data());
128                 currentActions[actionIndex]->mouseReleaseEvent(e);
129
130                 // Clean up actions - one might be finished now
131                 cleanUp();
132                 e->accept();
133         }
134         else
135         {
136                 if (defaultAction)
137                         defaultAction->mouseReleaseEvent(e);
138                 else
139                         e->ignore();
140         }
141 }
142
143 /**
144  * Called by GraphicView
145  */
146 void RS_EventHandler::mouseMoveEvent(QMouseEvent * e)
147 {
148         if (actionIndex >= 0 && currentActions[actionIndex]
149                 && !currentActions[actionIndex]->isFinished())
150         {
151                 currentActions[actionIndex]->mouseMoveEvent(e);
152                 e->accept();
153         }
154         else
155         {
156                 if (defaultAction)
157                 {
158                         defaultAction->mouseMoveEvent(e);
159                         e->accept();
160                 }
161                 else
162                         e->ignore();
163                 //RS_DEBUG->print("currently no action defined");
164         }
165 }
166
167 /**
168  * Called by GraphicView
169  */
170 void RS_EventHandler::mouseLeaveEvent()
171 {
172         if (actionIndex >= 0 && currentActions[actionIndex]
173                 && !currentActions[actionIndex]->isFinished())
174         {
175                 currentActions[actionIndex]->suspend();
176         }
177         else
178         {
179                 if (defaultAction)
180                         defaultAction->suspend();
181                 //RS_DEBUG->print("currently no action defined");
182         }
183 }
184
185 /**
186  * Called by GraphicView
187  */
188 void RS_EventHandler::mouseEnterEvent()
189 {
190         if (actionIndex >= 0 && currentActions[actionIndex]
191                 && !currentActions[actionIndex]->isFinished())
192         {
193                 currentActions[actionIndex]->resume();
194         }
195         else
196         {
197                 if (defaultAction)
198                         defaultAction->resume();
199         }
200 }
201
202 /**
203  * Called by GraphicView
204  */
205 void RS_EventHandler::keyPressEvent(QKeyEvent * e)
206 {
207         if (actionIndex >= 0 && currentActions[actionIndex]
208                 && !currentActions[actionIndex]->isFinished())
209         {
210                 currentActions[actionIndex]->keyPressEvent(e);
211         }
212         else
213         {
214                 if (defaultAction)
215                         defaultAction->keyPressEvent(e);
216                 else
217                         e->ignore();
218
219                 //RS_DEBUG->print("currently no action defined");
220         }
221 }
222
223 /**
224  * Called by GraphicView
225  */
226 void RS_EventHandler::keyReleaseEvent(QKeyEvent * e)
227 {
228         if (actionIndex >= 0 && currentActions[actionIndex]
229                 && !currentActions[actionIndex]->isFinished())
230         {
231                 currentActions[actionIndex]->keyReleaseEvent(e);
232         }
233         else
234         {
235                 if (defaultAction)
236                         defaultAction->keyReleaseEvent(e);
237                 else
238                         e->ignore();
239
240                 //RS_DEBUG->print("currently no action defined");
241         }
242 }
243
244 /**
245  * Handles command line events.
246  */
247 void RS_EventHandler::commandEvent(RS_CommandEvent * e)
248 {
249         RS_DEBUG->print("RS_EventHandler::commandEvent");
250         QString cmd = e->getCommand();
251
252         if (coordinateInputEnabled)
253         {
254                 if (!e->isAccepted())
255                 {
256                         // handle absolute cartesian coordinate input:
257                         if (cmd.contains(',') && cmd.at(0) != '@')
258                         {
259                                 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
260                                         && !currentActions[actionIndex]->isFinished())
261                                 {
262                                         int commaPos = cmd.indexOf(',');
263                                         RS_DEBUG->print("RS_EventHandler::commandEvent: 001");
264                                         bool ok1, ok2;
265                                         RS_DEBUG->print("RS_EventHandler::commandEvent: 002");
266                                         double x = RS_Math::eval(cmd.left(commaPos), &ok1);
267                                         RS_DEBUG->print("RS_EventHandler::commandEvent: 003a");
268                                         double y = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
269                                         RS_DEBUG->print("RS_EventHandler::commandEvent: 004");
270
271                                         if (ok1 && ok2)
272                                         {
273 //                                              RS_DEBUG->print("RS_EventHandler::commandEvent: 005");
274 //                                              RS_CoordinateEvent ce(Vector(x, y));
275                                                 RS_DEBUG->print("RS_EventHandler::commandEvent: 006");
276 //                                              currentActions[actionIndex]->coordinateEvent(&ce);
277                                                 Vector ce(x, y);
278                                                 currentActions[actionIndex]->coordinateEvent(&ce);
279                                         }
280                                         else
281                                         {
282                                                 if (RS_DIALOGFACTORY != NULL)
283                                                         RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
284                                         }
285
286                                         e->accept();
287                                 }
288                         }
289                 }
290
291                 // handle relative cartesian coordinate input:
292                 if (!e->isAccepted())
293                 {
294                         if (cmd.contains(',') && cmd.at(0) == '@')
295                         {
296                                 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
297                                         && !currentActions[actionIndex]->isFinished())
298                                 {
299                                         int commaPos = cmd.indexOf(',');
300                                         bool ok1, ok2;
301                                         double x = RS_Math::eval(cmd.mid(1, commaPos - 1), &ok1);
302                                         double y = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
303
304                                         if (ok1 && ok2)
305                                         {
306 //                                              RS_CoordinateEvent ce(Vector(x,y) + graphicView->getRelativeZero());
307 //                                              currentActions[actionIndex]->coordinateEvent(&ce);
308                                                 Vector ce(Vector(x,y) + graphicView->getRelativeZero());
309                                                 currentActions[actionIndex]->coordinateEvent(&ce);
310                                         }
311                                         else
312                                         {
313                                                 if (RS_DIALOGFACTORY != NULL)
314                                                         RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
315                                         }
316
317                                         e->accept();
318                                 }
319                         }
320                 }
321
322                 // handle absolute polar coordinate input:
323                 if (!e->isAccepted())
324                 {
325                         if (cmd.contains('<') && cmd.at(0) != '@')
326                         {
327                                 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
328                                         && !currentActions[actionIndex]->isFinished())
329                                 {
330                                         int commaPos = cmd.indexOf('<');
331                                         bool ok1, ok2;
332                                         double r = RS_Math::eval(cmd.left(commaPos), &ok1);
333                                         double a = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
334
335                                         if (ok1 && ok2)
336                                         {
337                                                 Vector pos;
338                                                 pos.setPolar(r,RS_Math::deg2rad(a));
339 //                                              RS_CoordinateEvent ce(pos);
340 //                                              currentActions[actionIndex]->coordinateEvent(&ce);
341                                                 currentActions[actionIndex]->coordinateEvent(&pos);
342                                         }
343                                         else
344                                         {
345                                                 if (RS_DIALOGFACTORY != NULL)
346                                                         RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
347                                         }
348
349                                         e->accept();
350                                 }
351                         }
352                 }
353
354                 // handle relative polar coordinate input:
355                 if (!e->isAccepted())
356                 {
357                         if (cmd.contains('<') && cmd.at(0) == '@')
358                         {
359                                 if (actionIndex >= 0 && currentActions[actionIndex] !=NULL
360                                         && !currentActions[actionIndex]->isFinished())
361                                 {
362 //                                      int commaPos = cmd.find('<');
363                                         int commaPos = cmd.indexOf('<');
364                                         bool ok1, ok2;
365                                         double r = RS_Math::eval(cmd.mid(1, commaPos - 1), &ok1);
366                                         double a = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
367
368                                         if (ok1 && ok2)
369                                         {
370                                                 Vector pos;
371                                                 pos.setPolar(r,RS_Math::deg2rad(a));
372 //                                              RS_CoordinateEvent ce(pos + graphicView->getRelativeZero());
373 //                                              currentActions[actionIndex]->coordinateEvent(&ce);
374                                                 Vector ce(pos + graphicView->getRelativeZero());
375                                                 currentActions[actionIndex]->coordinateEvent(&ce);
376                                         }
377                                         else
378                                         {
379                                                 if (RS_DIALOGFACTORY)
380                                                         RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
381                                         }
382
383                                         e->accept();
384                                 }
385                         }
386                 }
387         }
388
389         // send command event directly to current action:
390         if (!e->isAccepted())
391         {
392                 if (actionIndex >= 0 && currentActions[actionIndex]
393                         && !currentActions[actionIndex]->isFinished())
394                 {
395                         currentActions[actionIndex]->commandEvent(e);
396                         e->accept();
397                 }
398                 else
399                 {
400                         if (defaultAction)
401                                 defaultAction->commandEvent(e);
402                 }
403         }
404
405         RS_DEBUG->print("RS_EventHandler::commandEvent: OK");
406 }
407
408 /**
409  * Enables coordinate input in the command line.
410  */
411 void RS_EventHandler::enableCoordinateInput()
412 {
413         coordinateInputEnabled = true;
414 }
415
416 /**
417  * Enables coordinate input in the command line.
418  */
419 void RS_EventHandler::disableCoordinateInput()
420 {
421         coordinateInputEnabled = false;
422 }
423
424 /**
425  * @return Current action.
426  */
427 ActionInterface * RS_EventHandler::getCurrentAction()
428 {
429         if (actionIndex >= 0 && currentActions[actionIndex]
430                 && !currentActions[actionIndex]->isFinished())
431                 return currentActions[actionIndex];
432
433         return defaultAction;
434 }
435
436 /**
437  * @return The current default action.
438  */
439 ActionInterface * RS_EventHandler::getDefaultAction()
440 {
441         return defaultAction;
442 }
443
444 /**
445  * Sets the default action.
446  */
447 void RS_EventHandler::setDefaultAction(ActionInterface * action)
448 {
449         if (defaultAction)
450         {
451                 defaultAction->finish();
452                 delete defaultAction;
453                 defaultAction = NULL;
454         }
455
456         defaultAction = action;
457 }
458
459 /**
460  * Sets the current action.
461  */
462 void RS_EventHandler::setCurrentAction(ActionInterface * action)
463 {
464         RS_DEBUG->print("RS_EventHandler::setCurrentAction");
465
466         if (!action)
467                 return;
468
469         // Predecessor of the new action or NULL:
470         ActionInterface * predecessor = NULL;
471
472         // Suspend current action:
473         if (actionIndex >= 0 && currentActions[actionIndex]
474                 && !currentActions[actionIndex]->isFinished())
475         {
476                 predecessor = currentActions[actionIndex];
477                 predecessor->suspend();
478                 predecessor->hideOptions();
479         }
480         else
481         {
482                 if (defaultAction)
483                 {
484                         predecessor = defaultAction;
485                         predecessor->suspend();
486                         predecessor->hideOptions();
487                 }
488         }
489
490         // Forget about the oldest action and make space for the new action:
491         if (actionIndex == RS_MAXACTIONS - 1)
492         {
493                 // delete oldest action if necessary (usually never happens):
494                 if (currentActions[0])
495                 {
496                         currentActions[0]->finish();
497                         delete currentActions[0];
498                         currentActions[0] = NULL;
499                 }
500
501                 // Move up actionstack (optimize):
502                 for(int i=0; i<RS_MAXACTIONS-1; ++i)
503                         currentActions[i] = currentActions[i + 1];
504         }
505         else if (actionIndex < RS_MAXACTIONS - 1)
506                 actionIndex++;
507
508         // Set current action:
509         currentActions[actionIndex] = action;
510         RS_DEBUG->print("RS_EventHandler::setCurrentAction: current action is: %s",
511                 currentActions[actionIndex]->getName().toLatin1().data());
512
513         // Initialisation of our new action:
514         RS_DEBUG->print("RS_EventHandler::setCurrentAction: init current action");
515         action->init();
516
517         // ## new:
518         if (action->isFinished() == false)
519         {
520                 RS_DEBUG->print("RS_EventHandler::setCurrentAction: show options");
521                 currentActions[actionIndex]->showOptions();
522                 RS_DEBUG->print("RS_EventHandler::setCurrentAction: set predecessor");
523                 action->setPredecessor(predecessor);
524         }
525
526         RS_DEBUG->print("RS_EventHandler::setCurrentAction: cleaning up..");
527         cleanUp();
528
529         RS_DEBUG->print("RS_EventHandler::setCurrentAction: debugging actions");
530         debugActions();
531         RS_DEBUG->print("GraphicView::setCurrentAction: OK");
532 }
533
534 /**
535  * Kills all running selection actions. Called when a selection action
536  * is launched to reduce confusion.
537  */
538 void RS_EventHandler::killSelectActions()
539 {
540         for(int c=0; c<RS_MAXACTIONS; ++c)
541         {
542                 if (currentActions[c])
543                 {
544                         if (currentActions[c]->rtti() == RS2::ActionSelectSingle
545                                 || currentActions[c]->rtti() == RS2::ActionSelectContour
546                                 || currentActions[c]->rtti() == RS2::ActionSelectWindow
547                                 || currentActions[c]->rtti() == RS2::ActionSelectIntersected
548                                 || currentActions[c]->rtti() == RS2::ActionSelectLayer)
549                                 currentActions[c]->finish();
550                 }
551         }
552 }
553
554 /**
555  * Kills all running actions. Called when a window is closed.
556  */
557 void RS_EventHandler::killAllActions()
558 {
559         /*
560     for (int c=0; c<RS_MAXACTIONS; ++c) {
561         if (currentActions[c]!=NULL) {
562             currentActions[c]->finish();
563         }
564     }
565     cleanUp();
566         */
567 }
568
569 /**
570  * @return true if there is at least one action in the action stack.
571  */
572 bool RS_EventHandler::hasAction()
573 {
574         if (actionIndex != -1 || defaultAction)
575                 return true;
576
577         return false;
578 }
579
580 /**
581  * Garbage collector for actions.
582  */
583 void RS_EventHandler::cleanUp()
584 {
585         RS_DEBUG->print("RS_EventHandler::cleanUp");
586
587         int o = 0;                              // old index
588         int n = 0;                              // new index
589         int resume = 0;                 // index of action to resume
590         bool doResume = false;  // do we need to resume an action
591         actionIndex = -1;
592
593         debugActions();
594
595         do
596         {
597                 // search first used action (o)
598                 while (currentActions[o] == NULL && o < RS_MAXACTIONS)
599                         o++;
600
601                 // delete action if it is finished
602                 if (o < RS_MAXACTIONS && currentActions[o] != NULL
603                         && currentActions[o]->isFinished())
604                 {
605                         delete currentActions[o];
606                         currentActions[o] = NULL;
607                         doResume = true;
608                 }
609
610                 // move a running action up in the stack
611                 if (o < RS_MAXACTIONS && currentActions[o] != NULL)
612                 {
613                         if (n != o)
614                         {
615                                 currentActions[n] = currentActions[o];
616                                 resume = n;
617                                 currentActions[o] = NULL;
618                         }
619                         else
620                         {
621                                 if (o < RS_MAXACTIONS)
622                                         o++;
623                         }
624
625                         actionIndex = n;
626
627                         if (n < RS_MAXACTIONS - 1)
628                                 n++;
629                 }
630         }
631         while (o < RS_MAXACTIONS);
632
633         debugActions();
634
635         // Resume last used action:
636         if (doResume)
637         {
638                 if (currentActions[resume] && !currentActions[resume]->isFinished())
639                 {
640                         currentActions[resume]->resume();
641                         currentActions[resume]->showOptions();
642                 }
643                 else
644                 {
645                         if (defaultAction)
646                         {
647                                 defaultAction->resume();
648                                 defaultAction->showOptions();
649                         }
650                 }
651         }
652
653         RS_DEBUG->print("RS_EventHandler::cleanUp: OK");
654 }
655
656 /**
657  * Sets the snap mode for all currently active actions.
658  */
659 void RS_EventHandler::setSnapMode(RS2::SnapMode sm)
660 {
661 #if 0
662         for(int c=0; c<RS_MAXACTIONS; ++c)
663                 if (currentActions[c])
664                         currentActions[c]->setSnapMode(sm);
665
666         if (defaultAction)
667                 defaultAction->setSnapMode(sm);
668 #else
669 #warning "!!! Not sure if this is going to work correctly..."
670         graphicView->snapper.setSnapMode(sm);
671 #endif
672 }
673
674 /**
675  * Sets the snap restriction for all currently active actions.
676  */
677 void RS_EventHandler::setSnapRestriction(RS2::SnapRestriction sr)
678 {
679 #if 0
680         for(int c=0; c<RS_MAXACTIONS; ++c)
681                 if (currentActions[c])
682                         currentActions[c]->setSnapRestriction(sr);
683
684         if (defaultAction)
685                 defaultAction->setSnapRestriction(sr);
686 #else
687 #warning "!!! Not sure if this is going to work correctly..."
688         graphicView->snapper.setSnapRestriction(sr);
689 #endif
690 }
691
692 void RS_EventHandler::debugActions()
693 {
694         RS_DEBUG->print("---");
695
696         for(int c=0; c<RS_MAXACTIONS; ++c)
697         {
698                 if (c == actionIndex)
699                         RS_DEBUG->print("Current");
700
701                 if (currentActions[c])
702                         RS_DEBUG->print("Action %03d: %s [%s]",
703                                 c, currentActions[c]->getName().toLatin1().data(),
704                                 currentActions[c]->isFinished() ? "finished" : "active");
705                 else
706                         RS_DEBUG->print("Action %03d: NULL", c);
707         }
708 }