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"
17 #include "actioninterface.h"
18 #include "rs_commandevent.h"
20 #include "rs_dialogfactory.h"
21 #include "graphicview.h"
27 RS_EventHandler::RS_EventHandler(GraphicView * graphicView)
29 this->graphicView = graphicView;
32 for(int i=0; i<RS_MAXACTIONS; ++i)
33 currentActions[i] = NULL;
35 coordinateInputEnabled = true;
42 RS_EventHandler::~RS_EventHandler()
44 RS_DEBUG->print("RS_EventHandler::~RS_EventHandler");
46 if (defaultAction != NULL)
48 defaultAction->finish();
55 RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: Deleting all actions..");
57 for(int i=0; i<RS_MAXACTIONS; ++i)
59 if (currentActions[i] != NULL)
61 currentActions[i]->setFinished();
62 //delete currentActions[i];
63 //currentActions[i] = NULL;
68 RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: Deleting all actions..: OK");
69 RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: OK");
73 * Go back in current action.
75 void RS_EventHandler::back()
77 QMouseEvent e(QEvent::MouseButtonRelease, QPoint(0, 0), Qt::RightButton, Qt::RightButton,
79 mouseReleaseEvent(&e);
83 * Go enter pressed event for current action.
85 void RS_EventHandler::enter()
87 // QKeyEvent e(QEvent::KeyPress, Qt::Key_Enter, '\n', 0);
88 QKeyEvent e(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier, "\n", false, 0);
93 * Called by GraphicView
95 void RS_EventHandler::mousePressEvent(QMouseEvent * e)
97 if (actionIndex >= 0 && currentActions[actionIndex] != NULL)
99 currentActions[actionIndex]->mousePressEvent(e);
104 if (defaultAction != NULL)
106 defaultAction->mousePressEvent(e);
111 RS_DEBUG->print("currently no action defined");
118 * Called by GraphicView
120 void RS_EventHandler::mouseReleaseEvent(QMouseEvent * e)
122 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
123 && !currentActions[actionIndex]->isFinished())
125 RS_DEBUG->print("call action %s", currentActions[actionIndex]->getName().toLatin1().data());
126 currentActions[actionIndex]->mouseReleaseEvent(e);
128 // Clean up actions - one might be finished now
135 defaultAction->mouseReleaseEvent(e);
142 * Called by GraphicView
144 void RS_EventHandler::mouseMoveEvent(QMouseEvent * e)
146 if (actionIndex >= 0 && currentActions[actionIndex]
147 && !currentActions[actionIndex]->isFinished())
149 currentActions[actionIndex]->mouseMoveEvent(e);
156 defaultAction->mouseMoveEvent(e);
161 //RS_DEBUG->print("currently no action defined");
166 * Called by GraphicView
168 void RS_EventHandler::mouseLeaveEvent()
170 if (actionIndex >= 0 && currentActions[actionIndex]
171 && !currentActions[actionIndex]->isFinished())
173 currentActions[actionIndex]->suspend();
178 defaultAction->suspend();
179 //RS_DEBUG->print("currently no action defined");
184 * Called by GraphicView
186 void RS_EventHandler::mouseEnterEvent()
188 if (actionIndex >= 0 && currentActions[actionIndex]
189 && !currentActions[actionIndex]->isFinished())
191 currentActions[actionIndex]->resume();
196 defaultAction->resume();
201 * Called by GraphicView
203 void RS_EventHandler::keyPressEvent(QKeyEvent * e)
205 if (actionIndex >= 0 && currentActions[actionIndex]
206 && !currentActions[actionIndex]->isFinished())
208 currentActions[actionIndex]->keyPressEvent(e);
213 defaultAction->keyPressEvent(e);
217 //RS_DEBUG->print("currently no action defined");
222 * Called by GraphicView
224 void RS_EventHandler::keyReleaseEvent(QKeyEvent * e)
226 if (actionIndex >= 0 && currentActions[actionIndex]
227 && !currentActions[actionIndex]->isFinished())
229 currentActions[actionIndex]->keyReleaseEvent(e);
234 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);
276 currentActions[actionIndex]->coordinateEvent(&ce);
280 if (RS_DIALOGFACTORY != NULL)
281 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
289 // handle relative cartesian coordinate input:
290 if (!e->isAccepted())
292 if (cmd.contains(',') && cmd.at(0) == '@')
294 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
295 && !currentActions[actionIndex]->isFinished())
297 int commaPos = cmd.indexOf(',');
299 double x = RS_Math::eval(cmd.mid(1, commaPos - 1), &ok1);
300 double y = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
304 // RS_CoordinateEvent ce(Vector(x,y) + graphicView->getRelativeZero());
305 // currentActions[actionIndex]->coordinateEvent(&ce);
306 Vector ce(Vector(x,y) + graphicView->getRelativeZero());
307 currentActions[actionIndex]->coordinateEvent(&ce);
311 if (RS_DIALOGFACTORY != NULL)
312 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
320 // handle absolute polar coordinate input:
321 if (!e->isAccepted())
323 if (cmd.contains('<') && cmd.at(0) != '@')
325 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
326 && !currentActions[actionIndex]->isFinished())
328 int commaPos = cmd.indexOf('<');
330 double r = RS_Math::eval(cmd.left(commaPos), &ok1);
331 double a = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
336 pos.setPolar(r,RS_Math::deg2rad(a));
337 // RS_CoordinateEvent ce(pos);
338 // currentActions[actionIndex]->coordinateEvent(&ce);
339 currentActions[actionIndex]->coordinateEvent(&pos);
343 if (RS_DIALOGFACTORY != NULL)
344 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
352 // handle relative polar coordinate input:
353 if (!e->isAccepted())
355 if (cmd.contains('<') && cmd.at(0) == '@')
357 if (actionIndex >= 0 && currentActions[actionIndex] !=NULL
358 && !currentActions[actionIndex]->isFinished())
360 // int commaPos = cmd.find('<');
361 int commaPos = cmd.indexOf('<');
363 double r = RS_Math::eval(cmd.mid(1, commaPos - 1), &ok1);
364 double a = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
369 pos.setPolar(r,RS_Math::deg2rad(a));
370 // RS_CoordinateEvent ce(pos + graphicView->getRelativeZero());
371 // currentActions[actionIndex]->coordinateEvent(&ce);
372 Vector ce(pos + graphicView->getRelativeZero());
373 currentActions[actionIndex]->coordinateEvent(&ce);
377 if (RS_DIALOGFACTORY)
378 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
387 // send command event directly to current action:
388 if (!e->isAccepted())
390 if (actionIndex >= 0 && currentActions[actionIndex]
391 && !currentActions[actionIndex]->isFinished())
393 currentActions[actionIndex]->commandEvent(e);
399 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 ActionInterface * RS_EventHandler::getCurrentAction()
427 if (actionIndex >= 0 && currentActions[actionIndex]
428 && !currentActions[actionIndex]->isFinished())
429 return currentActions[actionIndex];
431 return defaultAction;
435 * @return The current default action.
437 ActionInterface * RS_EventHandler::getDefaultAction()
439 return defaultAction;
443 * Sets the default action.
445 void RS_EventHandler::setDefaultAction(ActionInterface * action)
449 defaultAction->finish();
450 delete defaultAction;
451 defaultAction = NULL;
454 defaultAction = action;
458 * Sets the current action.
460 void RS_EventHandler::setCurrentAction(ActionInterface * action)
462 RS_DEBUG->print("RS_EventHandler::setCurrentAction");
467 // Predecessor of the new action or NULL:
468 ActionInterface * predecessor = NULL;
470 // Suspend current action:
471 if (actionIndex >= 0 && currentActions[actionIndex]
472 && !currentActions[actionIndex]->isFinished())
474 predecessor = currentActions[actionIndex];
475 predecessor->suspend();
476 predecessor->hideOptions();
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])
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("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])
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)
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] && !currentActions[resume]->isFinished())
638 currentActions[resume]->resume();
639 currentActions[resume]->showOptions();
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)
660 for(int c=0; c<RS_MAXACTIONS; ++c)
661 if (currentActions[c])
662 currentActions[c]->setSnapMode(sm);
665 defaultAction->setSnapMode(sm);
667 #warning "!!! Not sure if this is going to work correctly..."
668 graphicView->snapper.setSnapMode(sm);
673 * Sets the snap restriction for all currently active actions.
675 void RS_EventHandler::setSnapRestriction(RS2::SnapRestriction sr)
678 for(int c=0; c<RS_MAXACTIONS; ++c)
679 if (currentActions[c])
680 currentActions[c]->setSnapRestriction(sr);
683 defaultAction->setSnapRestriction(sr);
685 #warning "!!! Not sure if this is going to work correctly..."
686 graphicView->snapper.setSnapRestriction(sr);
690 void RS_EventHandler::debugActions()
692 RS_DEBUG->print("---");
694 for(int c=0; c<RS_MAXACTIONS; ++c)
696 if (c == actionIndex)
697 RS_DEBUG->print("Current");
699 if (currentActions[c])
700 RS_DEBUG->print("Action %03d: %s [%s]",
701 c, currentActions[c]->getName().toLatin1().data(),
702 currentActions[c]->isFinished() ? "finished" : "active");
704 RS_DEBUG->print("Action %03d: NULL", c);