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 // (C) 2010 Underground Software
8 // JLH = James L. Hammons <jlhamm@acm.org>
11 // --- ---------- -----------------------------------------------------------
12 // JLH 05/28/2010 Added this text. :-)
15 #include "rs_eventhandler.h"
18 #include "rs_actioninterface.h"
19 #include "rs_coordinateevent.h"
24 RS_EventHandler::RS_EventHandler(RS_GraphicView * graphicView)
26 this->graphicView = graphicView;
29 for(int i=0; i<RS_MAXACTIONS; ++i)
30 currentActions[i] = NULL;
32 coordinateInputEnabled = true;
39 RS_EventHandler::~RS_EventHandler()
41 RS_DEBUG->print("RS_EventHandler::~RS_EventHandler");
43 if (defaultAction != NULL)
45 defaultAction->finish();
52 RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: Deleting all actions..");
54 for(int i=0; i<RS_MAXACTIONS; ++i)
56 if (currentActions[i] != NULL)
58 currentActions[i]->setFinished();
59 //delete currentActions[i];
60 //currentActions[i] = NULL;
65 RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: Deleting all actions..: OK");
66 RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: OK");
70 * Go back in current action.
72 void RS_EventHandler::back()
74 QMouseEvent e(QEvent::MouseButtonRelease, QPoint(0, 0), Qt::RightButton, Qt::RightButton,
76 mouseReleaseEvent(&e);
80 * Go enter pressed event for current action.
82 void RS_EventHandler::enter()
84 // QKeyEvent e(QEvent::KeyPress, Qt::Key_Enter, '\n', 0);
85 QKeyEvent e(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier, "\n", false, 0);
90 * Called by RS_GraphicView
92 void RS_EventHandler::mousePressEvent(QMouseEvent * e)
94 if (actionIndex >= 0 && currentActions[actionIndex] != NULL)
96 currentActions[actionIndex]->mousePressEvent(e);
101 if (defaultAction != NULL)
103 defaultAction->mousePressEvent(e);
108 RS_DEBUG->print("currently no action defined");
115 * Called by RS_GraphicView
117 void RS_EventHandler::mouseReleaseEvent(QMouseEvent * e)
119 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
120 && !currentActions[actionIndex]->isFinished())
122 RS_DEBUG->print("call action %s", currentActions[actionIndex]->getName().toLatin1().data());
123 currentActions[actionIndex]->mouseReleaseEvent(e);
125 // Clean up actions - one might be finished now
131 if (defaultAction != NULL)
132 defaultAction->mouseReleaseEvent(e);
139 * Called by RS_GraphicView
141 void RS_EventHandler::mouseMoveEvent(QMouseEvent * e)
143 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
144 && !currentActions[actionIndex]->isFinished())
146 currentActions[actionIndex]->mouseMoveEvent(e);
151 if (defaultAction!=NULL)
153 defaultAction->mouseMoveEvent(e);
158 //RS_DEBUG->print("currently no action defined");
163 * Called by RS_GraphicView
165 void RS_EventHandler::mouseLeaveEvent()
167 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
168 && !currentActions[actionIndex]->isFinished())
170 currentActions[actionIndex]->suspend();
174 if (defaultAction != NULL)
175 defaultAction->suspend();
176 //RS_DEBUG->print("currently no action defined");
181 * Called by RS_GraphicView
183 void RS_EventHandler::mouseEnterEvent()
185 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
186 && !currentActions[actionIndex]->isFinished())
188 currentActions[actionIndex]->resume();
192 if (defaultAction != NULL)
193 defaultAction->resume();
198 * Called by RS_GraphicView
200 void RS_EventHandler::keyPressEvent(QKeyEvent * e)
202 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
203 && !currentActions[actionIndex]->isFinished())
205 currentActions[actionIndex]->keyPressEvent(e);
209 if (defaultAction != NULL)
210 defaultAction->keyPressEvent(e);
214 //RS_DEBUG->print("currently no action defined");
219 * Called by RS_GraphicView
221 void RS_EventHandler::keyReleaseEvent(QKeyEvent* e)
223 if (actionIndex >= 0 && currentActions[actionIndex] != NULL &&
224 !currentActions[actionIndex]->isFinished())
226 currentActions[actionIndex]->keyReleaseEvent(e);
230 if (defaultAction != NULL)
232 defaultAction->keyReleaseEvent(e);
238 //RS_DEBUG->print("currently no action defined");
243 * Handles command line events.
245 void RS_EventHandler::commandEvent(RS_CommandEvent * e)
247 RS_DEBUG->print("RS_EventHandler::commandEvent");
248 QString cmd = e->getCommand();
250 if (coordinateInputEnabled)
252 if (!e->isAccepted())
254 // handle absolute cartesian coordinate input:
255 if (cmd.contains(',') && cmd.at(0) != '@')
257 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
258 && !currentActions[actionIndex]->isFinished())
260 int commaPos = cmd.indexOf(',');
261 RS_DEBUG->print("RS_EventHandler::commandEvent: 001");
263 RS_DEBUG->print("RS_EventHandler::commandEvent: 002");
264 double x = RS_Math::eval(cmd.left(commaPos), &ok1);
265 RS_DEBUG->print("RS_EventHandler::commandEvent: 003a");
266 double y = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
267 RS_DEBUG->print("RS_EventHandler::commandEvent: 004");
271 RS_DEBUG->print("RS_EventHandler::commandEvent: 005");
272 RS_CoordinateEvent ce(Vector(x, y));
273 RS_DEBUG->print("RS_EventHandler::commandEvent: 006");
274 currentActions[actionIndex]->coordinateEvent(&ce);
278 if (RS_DIALOGFACTORY != NULL)
279 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
287 // handle relative cartesian coordinate input:
288 if (!e->isAccepted())
290 if (cmd.contains(',') && cmd.at(0) == '@')
292 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
293 && !currentActions[actionIndex]->isFinished())
295 // int commaPos = cmd.find(',');
296 int commaPos = cmd.indexOf(',');
298 double x = RS_Math::eval(cmd.mid(1, commaPos - 1), &ok1);
299 double y = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
303 RS_CoordinateEvent ce(Vector(x,y) +
304 graphicView->getRelativeZero());
305 currentActions[actionIndex]->coordinateEvent(&ce);
309 if (RS_DIALOGFACTORY != NULL)
310 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
318 // handle absolute polar coordinate input:
319 if (!e->isAccepted())
321 if (cmd.contains('<') && cmd.at(0) != '@')
323 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
324 && !currentActions[actionIndex]->isFinished())
326 // int commaPos = cmd.find('<');
327 int commaPos = cmd.indexOf('<');
329 double r = RS_Math::eval(cmd.left(commaPos), &ok1);
330 double a = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
335 pos.setPolar(r,RS_Math::deg2rad(a));
336 RS_CoordinateEvent ce(pos);
337 currentActions[actionIndex]->coordinateEvent(&ce);
341 if (RS_DIALOGFACTORY != NULL)
342 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
350 // handle relative polar coordinate input:
351 if (!e->isAccepted())
353 if (cmd.contains('<') && cmd.at(0) == '@')
355 if (actionIndex >= 0 && currentActions[actionIndex] !=NULL
356 && !currentActions[actionIndex]->isFinished())
358 // int commaPos = cmd.find('<');
359 int commaPos = cmd.indexOf('<');
361 double r = RS_Math::eval(cmd.mid(1, commaPos - 1), &ok1);
362 double a = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
367 pos.setPolar(r,RS_Math::deg2rad(a));
368 RS_CoordinateEvent ce(pos +
369 graphicView->getRelativeZero());
370 currentActions[actionIndex]->coordinateEvent(&ce);
374 if (RS_DIALOGFACTORY != NULL)
375 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
384 // send command event directly to current action:
385 if (!e->isAccepted())
387 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
388 && !currentActions[actionIndex]->isFinished())
390 currentActions[actionIndex]->commandEvent(e);
395 if (defaultAction != NULL)
397 defaultAction->commandEvent(e);
403 RS_DEBUG->print("RS_EventHandler::commandEvent: OK");
407 * Enables coordinate input in the command line.
409 void RS_EventHandler::enableCoordinateInput()
411 coordinateInputEnabled = true;
415 * Enables coordinate input in the command line.
417 void RS_EventHandler::disableCoordinateInput()
419 coordinateInputEnabled = false;
423 * @return Current action.
425 RS_ActionInterface * RS_EventHandler::getCurrentAction()
427 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
428 && !currentActions[actionIndex]->isFinished())
429 return currentActions[actionIndex];
431 return defaultAction;
435 * @return The current default action.
437 RS_ActionInterface * RS_EventHandler::getDefaultAction()
439 return defaultAction;
443 * Sets the default action.
445 void RS_EventHandler::setDefaultAction(RS_ActionInterface * action)
447 if (defaultAction != NULL)
449 defaultAction->finish();
450 delete defaultAction;
451 defaultAction = NULL;
454 defaultAction = action;
458 * Sets the current action.
460 void RS_EventHandler::setCurrentAction(RS_ActionInterface * action)
462 RS_DEBUG->print("RS_EventHandler::setCurrentAction");
467 // Predecessor of the new action or NULL:
468 RS_ActionInterface * predecessor = NULL;
470 // Suspend current action:
471 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
472 && !currentActions[actionIndex]->isFinished())
474 predecessor = currentActions[actionIndex];
475 predecessor->suspend();
476 predecessor->hideOptions();
480 if (defaultAction != NULL)
482 predecessor = defaultAction;
483 predecessor->suspend();
484 predecessor->hideOptions();
488 // Forget about the oldest action and make space for the new action:
489 if (actionIndex == RS_MAXACTIONS - 1)
491 // delete oldest action if necessary (usually never happens):
492 if (currentActions[0] != NULL)
494 currentActions[0]->finish();
495 delete currentActions[0];
496 currentActions[0] = NULL;
499 // Move up actionstack (optimize):
500 for(int i=0; i<RS_MAXACTIONS-1; ++i)
501 currentActions[i] = currentActions[i + 1];
503 else if (actionIndex < RS_MAXACTIONS - 1)
506 // Set current action:
507 currentActions[actionIndex] = action;
508 RS_DEBUG->print("RS_EventHandler::setCurrentAction: current action is: %s",
509 currentActions[actionIndex]->getName().toLatin1().data());
511 // Initialisation of our new action:
512 RS_DEBUG->print("RS_EventHandler::setCurrentAction: init current action");
516 if (action->isFinished() == false)
518 RS_DEBUG->print("RS_EventHandler::setCurrentAction: show options");
519 currentActions[actionIndex]->showOptions();
520 RS_DEBUG->print("RS_EventHandler::setCurrentAction: set predecessor");
521 action->setPredecessor(predecessor);
524 RS_DEBUG->print("RS_EventHandler::setCurrentAction: cleaning up..");
527 RS_DEBUG->print("RS_EventHandler::setCurrentAction: debugging actions");
529 RS_DEBUG->print("RS_GraphicView::setCurrentAction: OK");
533 * Kills all running selection actions. Called when a selection action
534 * is launched to reduce confusion.
536 void RS_EventHandler::killSelectActions()
538 for(int c=0; c<RS_MAXACTIONS; ++c)
540 if (currentActions[c] != NULL)
542 if (currentActions[c]->rtti() == RS2::ActionSelectSingle
543 || currentActions[c]->rtti() == RS2::ActionSelectContour
544 || currentActions[c]->rtti() == RS2::ActionSelectWindow
545 || currentActions[c]->rtti() == RS2::ActionSelectIntersected
546 || currentActions[c]->rtti() == RS2::ActionSelectLayer)
547 currentActions[c]->finish();
553 * Kills all running actions. Called when a window is closed.
555 void RS_EventHandler::killAllActions()
558 for (int c=0; c<RS_MAXACTIONS; ++c) {
559 if (currentActions[c]!=NULL) {
560 currentActions[c]->finish();
568 * @return true if there is at least one action in the action stack.
570 bool RS_EventHandler::hasAction()
572 if (actionIndex != -1 || defaultAction != NULL)
579 * Garbage collector for actions.
581 void RS_EventHandler::cleanUp()
583 RS_DEBUG->print("RS_EventHandler::cleanUp");
585 int o = 0; // old index
586 int n = 0; // new index
587 int resume = 0; // index of action to resume
588 bool doResume = false; // do we need to resume an action
595 // search first used action (o)
596 while (currentActions[o] == NULL && o < RS_MAXACTIONS)
599 // delete action if it is finished
600 if (o < RS_MAXACTIONS && currentActions[o] != NULL
601 && currentActions[o]->isFinished())
603 delete currentActions[o];
604 currentActions[o] = NULL;
608 // move a running action up in the stack
609 if (o < RS_MAXACTIONS && currentActions[o] != NULL)
613 currentActions[n] = currentActions[o];
615 currentActions[o] = NULL;
619 if (o < RS_MAXACTIONS)
625 if (n < RS_MAXACTIONS - 1)
629 while (o < RS_MAXACTIONS);
633 // Resume last used action:
636 if (currentActions[resume] != NULL && !currentActions[resume]->isFinished())
638 currentActions[resume]->resume();
639 currentActions[resume]->showOptions();
643 if (defaultAction != NULL)
645 defaultAction->resume();
646 defaultAction->showOptions();
651 RS_DEBUG->print("RS_EventHandler::cleanUp: OK");
655 * Sets the snap mode for all currently active actions.
657 void RS_EventHandler::setSnapMode(RS2::SnapMode sm)
659 for(int c=0; c<RS_MAXACTIONS; ++c)
660 if (currentActions[c] != NULL)
661 currentActions[c]->setSnapMode(sm);
663 if (defaultAction!=NULL)
664 defaultAction->setSnapMode(sm);
668 * Sets the snap restriction for all currently active actions.
670 void RS_EventHandler::setSnapRestriction(RS2::SnapRestriction sr)
672 for(int c=0; c<RS_MAXACTIONS; ++c)
673 if (currentActions[c] != NULL)
674 currentActions[c]->setSnapRestriction(sr);
676 if (defaultAction != NULL)
677 defaultAction->setSnapRestriction(sr);
680 void RS_EventHandler::debugActions()
682 RS_DEBUG->print("---");
684 for(int c=0; c<RS_MAXACTIONS; ++c)
686 if (c == actionIndex)
687 RS_DEBUG->print("Current");
689 if (currentActions[c] != NULL)
690 RS_DEBUG->print("Action %03d: %s [%s]",
691 c, currentActions[c]->getName().toLatin1().data(),
692 currentActions[c]->isFinished() ? "finished" : "active");
694 RS_DEBUG->print("Action %03d: NULL", c);