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 RS_EventHandler::RS_EventHandler(GraphicView * graphicView)
31 this->graphicView = graphicView;
34 for(int i=0; i<RS_MAXACTIONS; ++i)
35 currentActions[i] = NULL;
37 coordinateInputEnabled = true;
44 RS_EventHandler::~RS_EventHandler()
46 RS_DEBUG->print("RS_EventHandler::~RS_EventHandler");
48 if (defaultAction != NULL)
50 defaultAction->finish();
57 RS_DEBUG->print("RS_EventHandler::~RS_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 RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: Deleting all actions..: OK");
71 RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: OK");
75 * Go back in current action.
77 void RS_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 RS_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 RS_EventHandler::mousePressEvent(QMouseEvent * e)
99 if (actionIndex >= 0 && currentActions[actionIndex] != NULL)
101 currentActions[actionIndex]->mousePressEvent(e);
108 defaultAction->mousePressEvent(e);
113 RS_DEBUG->print("currently no action defined");
120 * Called by GraphicView
122 void RS_EventHandler::mouseReleaseEvent(QMouseEvent * e)
124 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
125 && !currentActions[actionIndex]->isFinished())
127 RS_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 RS_EventHandler::mouseMoveEvent(QMouseEvent * e)
148 if (actionIndex >= 0 && currentActions[actionIndex]
149 && !currentActions[actionIndex]->isFinished())
151 currentActions[actionIndex]->mouseMoveEvent(e);
158 defaultAction->mouseMoveEvent(e);
163 //RS_DEBUG->print("currently no action defined");
168 * Called by GraphicView
170 void RS_EventHandler::mouseLeaveEvent()
172 if (actionIndex >= 0 && currentActions[actionIndex]
173 && !currentActions[actionIndex]->isFinished())
175 currentActions[actionIndex]->suspend();
180 defaultAction->suspend();
181 //RS_DEBUG->print("currently no action defined");
186 * Called by GraphicView
188 void RS_EventHandler::mouseEnterEvent()
190 if (actionIndex >= 0 && currentActions[actionIndex]
191 && !currentActions[actionIndex]->isFinished())
193 currentActions[actionIndex]->resume();
198 defaultAction->resume();
203 * Called by GraphicView
205 void RS_EventHandler::keyPressEvent(QKeyEvent * e)
207 if (actionIndex >= 0 && currentActions[actionIndex]
208 && !currentActions[actionIndex]->isFinished())
210 currentActions[actionIndex]->keyPressEvent(e);
215 defaultAction->keyPressEvent(e);
219 //RS_DEBUG->print("currently no action defined");
224 * Called by GraphicView
226 void RS_EventHandler::keyReleaseEvent(QKeyEvent * e)
228 if (actionIndex >= 0 && currentActions[actionIndex]
229 && !currentActions[actionIndex]->isFinished())
231 currentActions[actionIndex]->keyReleaseEvent(e);
236 defaultAction->keyReleaseEvent(e);
240 //RS_DEBUG->print("currently no action defined");
245 * Handles command line events.
247 void RS_EventHandler::commandEvent(RS_CommandEvent * e)
249 RS_DEBUG->print("RS_EventHandler::commandEvent");
250 QString cmd = e->getCommand();
252 if (coordinateInputEnabled)
254 if (!e->isAccepted())
256 // handle absolute cartesian coordinate input:
257 if (cmd.contains(',') && cmd.at(0) != '@')
259 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
260 && !currentActions[actionIndex]->isFinished())
262 int commaPos = cmd.indexOf(',');
263 RS_DEBUG->print("RS_EventHandler::commandEvent: 001");
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");
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);
278 currentActions[actionIndex]->coordinateEvent(&ce);
282 if (RS_DIALOGFACTORY != NULL)
283 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
291 // handle relative cartesian coordinate input:
292 if (!e->isAccepted())
294 if (cmd.contains(',') && cmd.at(0) == '@')
296 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
297 && !currentActions[actionIndex]->isFinished())
299 int commaPos = cmd.indexOf(',');
301 double x = RS_Math::eval(cmd.mid(1, commaPos - 1), &ok1);
302 double y = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
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);
313 if (RS_DIALOGFACTORY != NULL)
314 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
322 // handle absolute polar coordinate input:
323 if (!e->isAccepted())
325 if (cmd.contains('<') && cmd.at(0) != '@')
327 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
328 && !currentActions[actionIndex]->isFinished())
330 int commaPos = cmd.indexOf('<');
332 double r = RS_Math::eval(cmd.left(commaPos), &ok1);
333 double a = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
338 pos.setPolar(r,RS_Math::deg2rad(a));
339 // RS_CoordinateEvent ce(pos);
340 // currentActions[actionIndex]->coordinateEvent(&ce);
341 currentActions[actionIndex]->coordinateEvent(&pos);
345 if (RS_DIALOGFACTORY != NULL)
346 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
354 // handle relative polar coordinate input:
355 if (!e->isAccepted())
357 if (cmd.contains('<') && cmd.at(0) == '@')
359 if (actionIndex >= 0 && currentActions[actionIndex] !=NULL
360 && !currentActions[actionIndex]->isFinished())
362 // int commaPos = cmd.find('<');
363 int commaPos = cmd.indexOf('<');
365 double r = RS_Math::eval(cmd.mid(1, commaPos - 1), &ok1);
366 double a = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
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);
379 if (RS_DIALOGFACTORY)
380 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
389 // send command event directly to current action:
390 if (!e->isAccepted())
392 if (actionIndex >= 0 && currentActions[actionIndex]
393 && !currentActions[actionIndex]->isFinished())
395 currentActions[actionIndex]->commandEvent(e);
401 defaultAction->commandEvent(e);
405 RS_DEBUG->print("RS_EventHandler::commandEvent: OK");
409 * Enables coordinate input in the command line.
411 void RS_EventHandler::enableCoordinateInput()
413 coordinateInputEnabled = true;
417 * Enables coordinate input in the command line.
419 void RS_EventHandler::disableCoordinateInput()
421 coordinateInputEnabled = false;
425 * @return Current action.
427 ActionInterface * RS_EventHandler::getCurrentAction()
429 if (actionIndex >= 0 && currentActions[actionIndex]
430 && !currentActions[actionIndex]->isFinished())
431 return currentActions[actionIndex];
433 return defaultAction;
437 * @return The current default action.
439 ActionInterface * RS_EventHandler::getDefaultAction()
441 return defaultAction;
445 * Sets the default action.
447 void RS_EventHandler::setDefaultAction(ActionInterface * action)
451 defaultAction->finish();
452 delete defaultAction;
453 defaultAction = NULL;
456 defaultAction = action;
460 * Sets the current action.
462 void RS_EventHandler::setCurrentAction(ActionInterface * action)
464 RS_DEBUG->print("RS_EventHandler::setCurrentAction");
469 // Predecessor of the new action or NULL:
470 ActionInterface * predecessor = NULL;
472 // Suspend current action:
473 if (actionIndex >= 0 && currentActions[actionIndex]
474 && !currentActions[actionIndex]->isFinished())
476 predecessor = currentActions[actionIndex];
477 predecessor->suspend();
478 predecessor->hideOptions();
484 predecessor = defaultAction;
485 predecessor->suspend();
486 predecessor->hideOptions();
490 // Forget about the oldest action and make space for the new action:
491 if (actionIndex == RS_MAXACTIONS - 1)
493 // delete oldest action if necessary (usually never happens):
494 if (currentActions[0])
496 currentActions[0]->finish();
497 delete currentActions[0];
498 currentActions[0] = NULL;
501 // Move up actionstack (optimize):
502 for(int i=0; i<RS_MAXACTIONS-1; ++i)
503 currentActions[i] = currentActions[i + 1];
505 else if (actionIndex < RS_MAXACTIONS - 1)
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());
513 // Initialisation of our new action:
514 RS_DEBUG->print("RS_EventHandler::setCurrentAction: init current action");
518 if (action->isFinished() == false)
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);
526 RS_DEBUG->print("RS_EventHandler::setCurrentAction: cleaning up..");
529 RS_DEBUG->print("RS_EventHandler::setCurrentAction: debugging actions");
531 RS_DEBUG->print("GraphicView::setCurrentAction: OK");
535 * Kills all running selection actions. Called when a selection action
536 * is launched to reduce confusion.
538 void RS_EventHandler::killSelectActions()
540 for(int c=0; c<RS_MAXACTIONS; ++c)
542 if (currentActions[c])
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();
555 * Kills all running actions. Called when a window is closed.
557 void RS_EventHandler::killAllActions()
560 for (int c=0; c<RS_MAXACTIONS; ++c) {
561 if (currentActions[c]!=NULL) {
562 currentActions[c]->finish();
570 * @return true if there is at least one action in the action stack.
572 bool RS_EventHandler::hasAction()
574 if (actionIndex != -1 || defaultAction)
581 * Garbage collector for actions.
583 void RS_EventHandler::cleanUp()
585 RS_DEBUG->print("RS_EventHandler::cleanUp");
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
597 // search first used action (o)
598 while (currentActions[o] == NULL && o < RS_MAXACTIONS)
601 // delete action if it is finished
602 if (o < RS_MAXACTIONS && currentActions[o] != NULL
603 && currentActions[o]->isFinished())
605 delete currentActions[o];
606 currentActions[o] = NULL;
610 // move a running action up in the stack
611 if (o < RS_MAXACTIONS && currentActions[o] != NULL)
615 currentActions[n] = currentActions[o];
617 currentActions[o] = NULL;
621 if (o < RS_MAXACTIONS)
627 if (n < RS_MAXACTIONS - 1)
631 while (o < RS_MAXACTIONS);
635 // Resume last used action:
638 if (currentActions[resume] && !currentActions[resume]->isFinished())
640 currentActions[resume]->resume();
641 currentActions[resume]->showOptions();
647 defaultAction->resume();
648 defaultAction->showOptions();
653 RS_DEBUG->print("RS_EventHandler::cleanUp: OK");
657 * Sets the snap mode for all currently active actions.
659 void RS_EventHandler::setSnapMode(RS2::SnapMode sm)
662 for(int c=0; c<RS_MAXACTIONS; ++c)
663 if (currentActions[c])
664 currentActions[c]->setSnapMode(sm);
667 defaultAction->setSnapMode(sm);
669 #warning "!!! Not sure if this is going to work correctly..."
671 graphicView->snapper.setSnapMode(sm);
676 * Sets the snap restriction for all currently active actions.
678 void RS_EventHandler::setSnapRestriction(RS2::SnapRestriction sr)
681 for(int c=0; c<RS_MAXACTIONS; ++c)
682 if (currentActions[c])
683 currentActions[c]->setSnapRestriction(sr);
686 defaultAction->setSnapRestriction(sr);
688 #warning "!!! Not sure if this is going to work correctly..."
690 graphicView->snapper.setSnapRestriction(sr);
694 void RS_EventHandler::debugActions()
696 RS_DEBUG->print("---");
698 for(int c=0; c<RS_MAXACTIONS; ++c)
700 if (c == actionIndex)
701 RS_DEBUG->print("Current");
703 if (currentActions[c])
704 RS_DEBUG->print("Action %03d: %s [%s]",
705 c, currentActions[c]->getName().toLatin1().data(),
706 currentActions[c]->isFinished() ? "finished" : "active");
708 RS_DEBUG->print("Action %03d: NULL", c);