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()) {
225 currentActions[actionIndex]->keyReleaseEvent(e);
227 if (defaultAction!=NULL) {
228 defaultAction->keyReleaseEvent(e);
233 //RS_DEBUG->print("currently no action defined");
238 * Handles command line events.
240 void RS_EventHandler::commandEvent(RS_CommandEvent * e)
242 RS_DEBUG->print("RS_EventHandler::commandEvent");
243 QString cmd = e->getCommand();
245 if (coordinateInputEnabled)
247 if (!e->isAccepted())
249 // handle absolute cartesian coordinate input:
250 if (cmd.contains(',') && cmd.at(0) != '@')
252 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
253 && !currentActions[actionIndex]->isFinished())
255 // int commaPos = cmd.find(',');
256 int commaPos = cmd.indexOf(',');
257 RS_DEBUG->print("RS_EventHandler::commandEvent: 001");
259 RS_DEBUG->print("RS_EventHandler::commandEvent: 002");
260 double x = RS_Math::eval(cmd.left(commaPos), &ok1);
261 RS_DEBUG->print("RS_EventHandler::commandEvent: 003a");
262 double y = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
263 RS_DEBUG->print("RS_EventHandler::commandEvent: 004");
267 RS_DEBUG->print("RS_EventHandler::commandEvent: 005");
268 RS_CoordinateEvent ce(Vector(x, y));
269 RS_DEBUG->print("RS_EventHandler::commandEvent: 006");
270 currentActions[actionIndex]->coordinateEvent(&ce);
274 if (RS_DIALOGFACTORY != NULL)
275 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
283 // handle relative cartesian coordinate input:
284 if (!e->isAccepted())
286 if (cmd.contains(',') && cmd.at(0) == '@')
288 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
289 && !currentActions[actionIndex]->isFinished())
291 // int commaPos = cmd.find(',');
292 int commaPos = cmd.indexOf(',');
294 double x = RS_Math::eval(cmd.mid(1, commaPos - 1), &ok1);
295 double y = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
299 RS_CoordinateEvent ce(Vector(x,y) +
300 graphicView->getRelativeZero());
301 currentActions[actionIndex]->coordinateEvent(&ce);
305 if (RS_DIALOGFACTORY != NULL)
306 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
314 // handle absolute polar coordinate input:
315 if (!e->isAccepted())
317 if (cmd.contains('<') && cmd.at(0) != '@')
319 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
320 && !currentActions[actionIndex]->isFinished())
322 // int commaPos = cmd.find('<');
323 int commaPos = cmd.indexOf('<');
325 double r = RS_Math::eval(cmd.left(commaPos), &ok1);
326 double a = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
331 pos.setPolar(r,RS_Math::deg2rad(a));
332 RS_CoordinateEvent ce(pos);
333 currentActions[actionIndex]->coordinateEvent(&ce);
337 if (RS_DIALOGFACTORY != NULL)
338 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
346 // handle relative polar coordinate input:
347 if (!e->isAccepted())
349 if (cmd.contains('<') && cmd.at(0) == '@')
351 if (actionIndex >= 0 && currentActions[actionIndex] !=NULL
352 && !currentActions[actionIndex]->isFinished())
354 // int commaPos = cmd.find('<');
355 int commaPos = cmd.indexOf('<');
357 double r = RS_Math::eval(cmd.mid(1, commaPos - 1), &ok1);
358 double a = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
363 pos.setPolar(r,RS_Math::deg2rad(a));
364 RS_CoordinateEvent ce(pos +
365 graphicView->getRelativeZero());
366 currentActions[actionIndex]->coordinateEvent(&ce);
370 if (RS_DIALOGFACTORY != NULL)
371 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
380 // send command event directly to current action:
381 if (!e->isAccepted())
383 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
384 && !currentActions[actionIndex]->isFinished())
386 currentActions[actionIndex]->commandEvent(e);
391 if (defaultAction != NULL)
393 defaultAction->commandEvent(e);
399 RS_DEBUG->print("RS_EventHandler::commandEvent: OK");
403 * Enables coordinate input in the command line.
405 void RS_EventHandler::enableCoordinateInput()
407 coordinateInputEnabled = true;
411 * Enables coordinate input in the command line.
413 void RS_EventHandler::disableCoordinateInput()
415 coordinateInputEnabled = false;
419 * @return Current action.
421 RS_ActionInterface * RS_EventHandler::getCurrentAction()
423 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
424 && !currentActions[actionIndex]->isFinished())
425 return currentActions[actionIndex];
427 return defaultAction;
431 * @return The current default action.
433 RS_ActionInterface * RS_EventHandler::getDefaultAction()
435 return defaultAction;
439 * Sets the default action.
441 void RS_EventHandler::setDefaultAction(RS_ActionInterface * action)
443 if (defaultAction != NULL)
445 defaultAction->finish();
446 delete defaultAction;
447 defaultAction = NULL;
450 defaultAction = action;
454 * Sets the current action.
456 void RS_EventHandler::setCurrentAction(RS_ActionInterface * action)
458 RS_DEBUG->print("RS_EventHandler::setCurrentAction");
463 // Predecessor of the new action or NULL:
464 RS_ActionInterface* predecessor = NULL;
466 // Suspend current action:
467 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
468 && !currentActions[actionIndex]->isFinished())
470 predecessor = currentActions[actionIndex];
471 predecessor->suspend();
472 predecessor->hideOptions();
476 if (defaultAction != NULL)
478 predecessor = defaultAction;
479 predecessor->suspend();
480 predecessor->hideOptions();
484 // Forget about the oldest action and make space for the new action:
485 if (actionIndex == RS_MAXACTIONS - 1)
487 // delete oldest action if necessary (usually never happens):
488 if (currentActions[0] != NULL)
490 currentActions[0]->finish();
491 delete currentActions[0];
492 currentActions[0] = NULL;
495 // Move up actionstack (optimize):
496 for(int i=0; i<RS_MAXACTIONS-1; ++i)
498 currentActions[i] = currentActions[i + 1];
501 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
593 // search first used action (o)
594 while (currentActions[o]==NULL && o<RS_MAXACTIONS) {
598 // delete action if it is finished
599 if (o<RS_MAXACTIONS && currentActions[o]!=NULL &&
600 currentActions[o]->isFinished()) {
601 delete currentActions[o];
602 currentActions[o] = NULL;
607 // move a running action up in the stack
608 if (o<RS_MAXACTIONS && currentActions[o]!=NULL) {
610 currentActions[n] = currentActions[o];
612 currentActions[o] = NULL;
614 if (o<RS_MAXACTIONS) {
619 if (n<RS_MAXACTIONS-1) {
623 } while (o<RS_MAXACTIONS);
627 // Resume last used action:
629 if (currentActions[resume]!=NULL &&
630 !currentActions[resume]->isFinished()) {
632 currentActions[resume]->resume();
633 currentActions[resume]->showOptions();
635 if (defaultAction!=NULL) {
636 defaultAction->resume();
637 defaultAction->showOptions();
641 RS_DEBUG->print("RS_EventHandler::cleanUp: OK");
645 * Sets the snap mode for all currently active actions.
647 void RS_EventHandler::setSnapMode(RS2::SnapMode sm)
649 for(int c=0; c<RS_MAXACTIONS; ++c)
650 if (currentActions[c] != NULL)
651 currentActions[c]->setSnapMode(sm);
653 if (defaultAction!=NULL)
654 defaultAction->setSnapMode(sm);
658 * Sets the snap restriction for all currently active actions.
660 void RS_EventHandler::setSnapRestriction(RS2::SnapRestriction sr)
662 for(int c=0; c<RS_MAXACTIONS; ++c)
663 if (currentActions[c] != NULL)
664 currentActions[c]->setSnapRestriction(sr);
666 if (defaultAction != NULL)
667 defaultAction->setSnapRestriction(sr);
670 void RS_EventHandler::debugActions()
672 RS_DEBUG->print("---");
674 for(int c=0; c<RS_MAXACTIONS; ++c)
676 if (c == actionIndex)
677 RS_DEBUG->print("Current");
679 if (currentActions[c] != NULL)
680 RS_DEBUG->print("Action %03d: %s [%s]",
681 c, currentActions[c]->getName().toLatin1().data(),
682 currentActions[c]->isFinished() ? "finished" : "active");
684 RS_DEBUG->print("Action %03d: NULL", c);