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
10 // JLH = James L. Hammons <jlhamm@acm.org>
13 // --- ---------- -----------------------------------------------------------
14 // JLH 05/28/2010 Added this text. :-)
17 #include "eventhandler.h"
19 #include "actioninterface.h"
20 #include "commandevent.h"
22 #include "dialogfactory.h"
23 #include "graphicview.h"
24 #include "mathextra.h"
29 EventHandler::EventHandler(GraphicView * graphicView)
31 this->graphicView = graphicView;
34 for(int i=0; i<RS_MAXACTIONS; ++i)
35 currentActions[i] = NULL;
37 coordinateInputEnabled = true;
44 EventHandler::~EventHandler()
46 DEBUG->print("EventHandler::~EventHandler");
50 defaultAction->finish();
57 DEBUG->print("EventHandler::~EventHandler: Deleting all actions..");
59 for(int i=0; i<RS_MAXACTIONS; ++i)
61 if (currentActions[i] != NULL)
63 currentActions[i]->setFinished();
64 //delete currentActions[i];
65 //currentActions[i] = NULL;
70 DEBUG->print("EventHandler::~EventHandler: Deleting all actions..: OK");
71 DEBUG->print("EventHandler::~EventHandler: OK");
75 * Go back in current action.
77 void EventHandler::back()
79 QMouseEvent e(QEvent::MouseButtonRelease, QPoint(0, 0), Qt::RightButton, Qt::RightButton,
81 mouseReleaseEvent(&e);
85 * Go enter pressed event for current action.
87 void EventHandler::enter()
89 // QKeyEvent e(QEvent::KeyPress, Qt::Key_Enter, '\n', 0);
90 QKeyEvent e(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier, "\n", false, 0);
95 * Called by GraphicView
97 void EventHandler::mousePressEvent(QMouseEvent * e)
99 if (actionIndex >= 0 && currentActions[actionIndex] != NULL)
101 currentActions[actionIndex]->mousePressEvent(e);
108 defaultAction->mousePressEvent(e);
113 DEBUG->print("currently no action defined");
120 * Called by GraphicView
122 void EventHandler::mouseReleaseEvent(QMouseEvent * e)
124 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
125 && !currentActions[actionIndex]->isFinished())
127 DEBUG->print("call action %s", currentActions[actionIndex]->getName().toLatin1().data());
128 currentActions[actionIndex]->mouseReleaseEvent(e);
130 // Clean up actions - one might be finished now
137 defaultAction->mouseReleaseEvent(e);
144 * Called by GraphicView
146 void EventHandler::mouseMoveEvent(QMouseEvent * e)
148 if (actionIndex >= 0 && currentActions[actionIndex]
149 && !currentActions[actionIndex]->isFinished())
151 currentActions[actionIndex]->mouseMoveEvent(e);
158 defaultAction->mouseMoveEvent(e);
163 //DEBUG->print("currently no action defined");
168 Small problem with this approach: Resumes can happen before suspend actions!
169 This can wreak havoc with things like snapper/preview states and the like...
171 Actually, this stuff seems to be pretty useless. Not sure what is accomplished
172 by this crap. The only thing I can think of is that it would cause a preview
173 to be removed if the mouse goes out of the drawing window, could be a legit
174 purpose but this seems too retarded for that. Why wouldn't you just code that
175 into GraphicView itself and be done with it?
178 * Called by GraphicView
180 void EventHandler::mouseLeaveEvent()
183 if (actionIndex >= 0 && currentActions[actionIndex]
184 && !currentActions[actionIndex]->isFinished())
186 currentActions[actionIndex]->suspend();
191 defaultAction->suspend();
192 //DEBUG->print("currently no action defined");
198 * Called by GraphicView
200 void EventHandler::mouseEnterEvent()
203 if (actionIndex >= 0 && currentActions[actionIndex]
204 && !currentActions[actionIndex]->isFinished())
206 currentActions[actionIndex]->resume();
211 defaultAction->resume();
217 * Called by GraphicView
219 void EventHandler::keyPressEvent(QKeyEvent * e)
221 if (actionIndex >= 0 && currentActions[actionIndex]
222 && !currentActions[actionIndex]->isFinished())
224 currentActions[actionIndex]->keyPressEvent(e);
229 defaultAction->keyPressEvent(e);
233 //DEBUG->print("currently no action defined");
238 * Called by GraphicView
240 void EventHandler::keyReleaseEvent(QKeyEvent * e)
242 if (actionIndex >= 0 && currentActions[actionIndex]
243 && !currentActions[actionIndex]->isFinished())
245 currentActions[actionIndex]->keyReleaseEvent(e);
250 defaultAction->keyReleaseEvent(e);
254 //DEBUG->print("currently no action defined");
259 * Handles command line events.
261 void EventHandler::commandEvent(CommandEvent * e)
263 DEBUG->print("EventHandler::commandEvent");
264 QString cmd = e->getCommand();
266 if (coordinateInputEnabled)
268 if (!e->isAccepted())
270 // handle absolute cartesian coordinate input:
271 if (cmd.contains(',') && cmd.at(0) != '@')
273 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
274 && !currentActions[actionIndex]->isFinished())
276 int commaPos = cmd.indexOf(',');
277 DEBUG->print("EventHandler::commandEvent: 001");
279 DEBUG->print("EventHandler::commandEvent: 002");
280 double x = Math::eval(cmd.left(commaPos), &ok1);
281 DEBUG->print("EventHandler::commandEvent: 003a");
282 double y = Math::eval(cmd.mid(commaPos + 1), &ok2);
283 DEBUG->print("EventHandler::commandEvent: 004");
287 // DEBUG->print("EventHandler::commandEvent: 005");
288 // CoordinateEvent ce(Vector(x, y));
289 DEBUG->print("EventHandler::commandEvent: 006");
290 // currentActions[actionIndex]->coordinateEvent(&ce);
292 currentActions[actionIndex]->coordinateEvent(&ce);
296 if (DIALOGFACTORY != NULL)
297 DIALOGFACTORY->commandMessage("Expression Syntax Error");
305 // handle relative cartesian coordinate input:
306 if (!e->isAccepted())
308 if (cmd.contains(',') && cmd.at(0) == '@')
310 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
311 && !currentActions[actionIndex]->isFinished())
313 int commaPos = cmd.indexOf(',');
315 double x = Math::eval(cmd.mid(1, commaPos - 1), &ok1);
316 double y = Math::eval(cmd.mid(commaPos + 1), &ok2);
320 // CoordinateEvent ce(Vector(x,y) + graphicView->getRelativeZero());
321 // currentActions[actionIndex]->coordinateEvent(&ce);
322 Vector ce(Vector(x,y) + graphicView->getRelativeZero());
323 currentActions[actionIndex]->coordinateEvent(&ce);
327 if (DIALOGFACTORY != NULL)
328 DIALOGFACTORY->commandMessage("Expression Syntax Error");
336 // handle absolute polar coordinate input:
337 if (!e->isAccepted())
339 if (cmd.contains('<') && cmd.at(0) != '@')
341 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
342 && !currentActions[actionIndex]->isFinished())
344 int commaPos = cmd.indexOf('<');
346 double r = Math::eval(cmd.left(commaPos), &ok1);
347 double a = Math::eval(cmd.mid(commaPos + 1), &ok2);
352 pos.setPolar(r,Math::deg2rad(a));
353 // CoordinateEvent ce(pos);
354 // currentActions[actionIndex]->coordinateEvent(&ce);
355 currentActions[actionIndex]->coordinateEvent(&pos);
359 if (DIALOGFACTORY != NULL)
360 DIALOGFACTORY->commandMessage("Expression Syntax Error");
368 // handle relative polar coordinate input:
369 if (!e->isAccepted())
371 if (cmd.contains('<') && cmd.at(0) == '@')
373 if (actionIndex >= 0 && currentActions[actionIndex] !=NULL
374 && !currentActions[actionIndex]->isFinished())
376 // int commaPos = cmd.find('<');
377 int commaPos = cmd.indexOf('<');
379 double r = Math::eval(cmd.mid(1, commaPos - 1), &ok1);
380 double a = Math::eval(cmd.mid(commaPos + 1), &ok2);
385 pos.setPolar(r,Math::deg2rad(a));
386 // CoordinateEvent ce(pos + graphicView->getRelativeZero());
387 // currentActions[actionIndex]->coordinateEvent(&ce);
388 Vector ce(pos + graphicView->getRelativeZero());
389 currentActions[actionIndex]->coordinateEvent(&ce);
394 DIALOGFACTORY->commandMessage("Expression Syntax Error");
403 // send command event directly to current action:
404 if (!e->isAccepted())
406 if (actionIndex >= 0 && currentActions[actionIndex]
407 && !currentActions[actionIndex]->isFinished())
409 currentActions[actionIndex]->commandEvent(e);
415 defaultAction->commandEvent(e);
419 DEBUG->print("EventHandler::commandEvent: OK");
423 * Enables coordinate input in the command line.
425 void EventHandler::enableCoordinateInput()
427 coordinateInputEnabled = true;
431 * Enables coordinate input in the command line.
433 void EventHandler::disableCoordinateInput()
435 coordinateInputEnabled = false;
439 * @return Current action.
441 ActionInterface * EventHandler::getCurrentAction()
443 if (actionIndex >= 0 && currentActions[actionIndex]
444 && !currentActions[actionIndex]->isFinished())
445 return currentActions[actionIndex];
447 return defaultAction;
451 * @return The current default action.
453 ActionInterface * EventHandler::getDefaultAction()
455 return defaultAction;
459 * Sets the default action.
461 void EventHandler::setDefaultAction(ActionInterface * action)
465 defaultAction->finish();
466 delete defaultAction;
467 defaultAction = NULL;
470 defaultAction = action;
474 * Sets the current action.
476 void EventHandler::setCurrentAction(ActionInterface * action)
478 DEBUG->print("EventHandler::setCurrentAction");
483 // Predecessor of the new action or NULL:
484 ActionInterface * predecessor = NULL;
486 // Suspend current action:
487 if (actionIndex >= 0 && currentActions[actionIndex]
488 && !currentActions[actionIndex]->isFinished())
490 predecessor = currentActions[actionIndex];
491 predecessor->suspend();
492 predecessor->hideOptions();
498 predecessor = defaultAction;
499 predecessor->suspend();
500 predecessor->hideOptions();
504 // Forget about the oldest action and make space for the new action:
505 if (actionIndex == RS_MAXACTIONS - 1)
507 // delete oldest action if necessary (usually never happens):
508 if (currentActions[0])
510 currentActions[0]->finish();
511 delete currentActions[0];
512 currentActions[0] = NULL;
515 // Move up actionstack (optimize):
516 for(int i=0; i<RS_MAXACTIONS-1; ++i)
517 currentActions[i] = currentActions[i + 1];
519 else if (actionIndex < RS_MAXACTIONS - 1)
522 // Set current action:
523 currentActions[actionIndex] = action;
524 DEBUG->print("EventHandler::setCurrentAction: current action is: %s",
525 currentActions[actionIndex]->getName().toLatin1().data());
527 // Initialisation of our new action:
528 DEBUG->print("EventHandler::setCurrentAction: init current action");
532 if (action->isFinished() == false)
534 DEBUG->print("EventHandler::setCurrentAction: show options");
535 currentActions[actionIndex]->showOptions();
536 DEBUG->print("EventHandler::setCurrentAction: set predecessor");
537 action->setPredecessor(predecessor);
540 DEBUG->print("EventHandler::setCurrentAction: cleaning up..");
543 DEBUG->print("EventHandler::setCurrentAction: debugging actions");
545 DEBUG->print("GraphicView::setCurrentAction: OK");
549 * Kills all running selection actions. Called when a selection action
550 * is launched to reduce confusion.
552 void EventHandler::killSelectActions()
554 for(int c=0; c<RS_MAXACTIONS; ++c)
556 if (currentActions[c])
558 if (currentActions[c]->rtti() == RS2::ActionSelectSingle
559 || currentActions[c]->rtti() == RS2::ActionSelectContour
560 || currentActions[c]->rtti() == RS2::ActionSelectWindow
561 || currentActions[c]->rtti() == RS2::ActionSelectIntersected
562 || currentActions[c]->rtti() == RS2::ActionSelectLayer)
563 currentActions[c]->finish();
569 * Kills all running actions. Called when a window is closed.
571 void EventHandler::killAllActions()
574 for (int c=0; c<RS_MAXACTIONS; ++c) {
575 if (currentActions[c]!=NULL) {
576 currentActions[c]->finish();
584 * @return true if there is at least one action in the action stack.
586 bool EventHandler::hasAction()
588 if (actionIndex != -1 || defaultAction)
595 * Garbage collector for actions.
597 void EventHandler::cleanUp()
599 DEBUG->print("EventHandler::cleanUp");
601 int oldIndex = 0; // old index
602 int newIndex = 0; // new index
603 int resume = 0; // index of action to resume
604 bool doResume = false; // do we need to resume an action
611 // Search first used action (oldIndex)
612 while (currentActions[oldIndex] == NULL && oldIndex < RS_MAXACTIONS)
615 // Delete action if it is finished
616 if (oldIndex < RS_MAXACTIONS && currentActions[oldIndex] != NULL
617 && currentActions[oldIndex]->isFinished())
619 delete currentActions[oldIndex];
620 currentActions[oldIndex] = NULL;
624 // Move a running action up in the stack
625 if (oldIndex < RS_MAXACTIONS && currentActions[oldIndex] != NULL)
627 if (newIndex != oldIndex)
629 currentActions[newIndex] = currentActions[oldIndex];
631 currentActions[oldIndex] = NULL;
635 if (oldIndex < RS_MAXACTIONS)
639 actionIndex = newIndex;
641 if (newIndex < RS_MAXACTIONS - 1)
645 while (oldIndex < RS_MAXACTIONS);
649 // Resume last used action:
652 if (currentActions[resume] && !currentActions[resume]->isFinished())
654 currentActions[resume]->resume();
655 currentActions[resume]->showOptions();
661 defaultAction->resume();
662 defaultAction->showOptions();
667 DEBUG->print("EventHandler::cleanUp: OK");
671 * Sets the snap mode for all currently active actions.
673 void EventHandler::setSnapMode(RS2::SnapMode sm)
676 for(int c=0; c<RS_MAXACTIONS; ++c)
677 if (currentActions[c])
678 currentActions[c]->setSnapMode(sm);
681 defaultAction->setSnapMode(sm);
683 #warning "!!! Not sure if this is going to work correctly..."
685 graphicView->snapper.setSnapMode(sm);
690 * Sets the snap restriction for all currently active actions.
692 void EventHandler::setSnapRestriction(RS2::SnapRestriction sr)
695 for(int c=0; c<RS_MAXACTIONS; ++c)
696 if (currentActions[c])
697 currentActions[c]->setSnapRestriction(sr);
700 defaultAction->setSnapRestriction(sr);
702 #warning "!!! Not sure if this is going to work correctly..."
704 graphicView->snapper.setSnapRestriction(sr);
708 void EventHandler::debugActions()
712 for(int c=0; c<RS_MAXACTIONS; ++c)
714 if (c == actionIndex)
715 DEBUG->print("Current");
717 if (currentActions[c])
718 DEBUG->print("Action %03d: %s [%s]",
719 c, currentActions[c]->getName().toLatin1().data(),
720 currentActions[c]->isFinished() ? "finished" : "active");
722 DEBUG->print("Action %03d: NULL", c);