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_commandevent.h"
21 #include "rs_dialogfactory.h"
22 #include "rs_graphicview.h"
28 RS_EventHandler::RS_EventHandler(RS_GraphicView * graphicView)
30 this->graphicView = graphicView;
33 for(int i=0; i<RS_MAXACTIONS; ++i)
34 currentActions[i] = NULL;
36 coordinateInputEnabled = true;
43 RS_EventHandler::~RS_EventHandler()
45 RS_DEBUG->print("RS_EventHandler::~RS_EventHandler");
47 if (defaultAction != NULL)
49 defaultAction->finish();
56 RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: Deleting all actions..");
58 for(int i=0; i<RS_MAXACTIONS; ++i)
60 if (currentActions[i] != NULL)
62 currentActions[i]->setFinished();
63 //delete currentActions[i];
64 //currentActions[i] = NULL;
69 RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: Deleting all actions..: OK");
70 RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: OK");
74 * Go back in current action.
76 void RS_EventHandler::back()
78 QMouseEvent e(QEvent::MouseButtonRelease, QPoint(0, 0), Qt::RightButton, Qt::RightButton,
80 mouseReleaseEvent(&e);
84 * Go enter pressed event for current action.
86 void RS_EventHandler::enter()
88 // QKeyEvent e(QEvent::KeyPress, Qt::Key_Enter, '\n', 0);
89 QKeyEvent e(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier, "\n", false, 0);
94 * Called by RS_GraphicView
96 void RS_EventHandler::mousePressEvent(QMouseEvent * e)
98 if (actionIndex >= 0 && currentActions[actionIndex] != NULL)
100 currentActions[actionIndex]->mousePressEvent(e);
105 if (defaultAction != NULL)
107 defaultAction->mousePressEvent(e);
112 RS_DEBUG->print("currently no action defined");
119 * Called by RS_GraphicView
121 void RS_EventHandler::mouseReleaseEvent(QMouseEvent * e)
123 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
124 && !currentActions[actionIndex]->isFinished())
126 RS_DEBUG->print("call action %s", currentActions[actionIndex]->getName().toLatin1().data());
127 currentActions[actionIndex]->mouseReleaseEvent(e);
129 // Clean up actions - one might be finished now
135 if (defaultAction != NULL)
136 defaultAction->mouseReleaseEvent(e);
143 * Called by RS_GraphicView
145 void RS_EventHandler::mouseMoveEvent(QMouseEvent * e)
147 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
148 && !currentActions[actionIndex]->isFinished())
150 currentActions[actionIndex]->mouseMoveEvent(e);
155 if (defaultAction!=NULL)
157 defaultAction->mouseMoveEvent(e);
162 //RS_DEBUG->print("currently no action defined");
167 * Called by RS_GraphicView
169 void RS_EventHandler::mouseLeaveEvent()
171 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
172 && !currentActions[actionIndex]->isFinished())
174 currentActions[actionIndex]->suspend();
178 if (defaultAction != NULL)
179 defaultAction->suspend();
180 //RS_DEBUG->print("currently no action defined");
185 * Called by RS_GraphicView
187 void RS_EventHandler::mouseEnterEvent()
189 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
190 && !currentActions[actionIndex]->isFinished())
192 currentActions[actionIndex]->resume();
196 if (defaultAction != NULL)
197 defaultAction->resume();
202 * Called by RS_GraphicView
204 void RS_EventHandler::keyPressEvent(QKeyEvent * e)
206 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
207 && !currentActions[actionIndex]->isFinished())
209 currentActions[actionIndex]->keyPressEvent(e);
213 if (defaultAction != NULL)
214 defaultAction->keyPressEvent(e);
218 //RS_DEBUG->print("currently no action defined");
223 * Called by RS_GraphicView
225 void RS_EventHandler::keyReleaseEvent(QKeyEvent * e)
227 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
228 && !currentActions[actionIndex]->isFinished())
230 currentActions[actionIndex]->keyReleaseEvent(e);
234 if (defaultAction != NULL)
235 defaultAction->keyReleaseEvent(e);
239 //RS_DEBUG->print("currently no action defined");
244 * Handles command line events.
246 void RS_EventHandler::commandEvent(RS_CommandEvent * e)
248 RS_DEBUG->print("RS_EventHandler::commandEvent");
249 QString cmd = e->getCommand();
251 if (coordinateInputEnabled)
253 if (!e->isAccepted())
255 // handle absolute cartesian coordinate input:
256 if (cmd.contains(',') && cmd.at(0) != '@')
258 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
259 && !currentActions[actionIndex]->isFinished())
261 int commaPos = cmd.indexOf(',');
262 RS_DEBUG->print("RS_EventHandler::commandEvent: 001");
264 RS_DEBUG->print("RS_EventHandler::commandEvent: 002");
265 double x = RS_Math::eval(cmd.left(commaPos), &ok1);
266 RS_DEBUG->print("RS_EventHandler::commandEvent: 003a");
267 double y = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
268 RS_DEBUG->print("RS_EventHandler::commandEvent: 004");
272 // RS_DEBUG->print("RS_EventHandler::commandEvent: 005");
273 // RS_CoordinateEvent ce(Vector(x, y));
274 RS_DEBUG->print("RS_EventHandler::commandEvent: 006");
275 // currentActions[actionIndex]->coordinateEvent(&ce);
277 currentActions[actionIndex]->coordinateEvent(&ce);
281 if (RS_DIALOGFACTORY != NULL)
282 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
290 // handle relative cartesian coordinate input:
291 if (!e->isAccepted())
293 if (cmd.contains(',') && cmd.at(0) == '@')
295 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
296 && !currentActions[actionIndex]->isFinished())
298 int commaPos = cmd.indexOf(',');
300 double x = RS_Math::eval(cmd.mid(1, commaPos - 1), &ok1);
301 double y = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
305 // RS_CoordinateEvent ce(Vector(x,y) + graphicView->getRelativeZero());
306 // currentActions[actionIndex]->coordinateEvent(&ce);
307 Vector ce(Vector(x,y) + graphicView->getRelativeZero());
308 currentActions[actionIndex]->coordinateEvent(&ce);
312 if (RS_DIALOGFACTORY != NULL)
313 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
321 // handle absolute polar coordinate input:
322 if (!e->isAccepted())
324 if (cmd.contains('<') && cmd.at(0) != '@')
326 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
327 && !currentActions[actionIndex]->isFinished())
329 // int commaPos = cmd.find('<');
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 != NULL)
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] != NULL
393 && !currentActions[actionIndex]->isFinished())
395 currentActions[actionIndex]->commandEvent(e);
400 if (defaultAction != NULL)
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 RS_ActionInterface * RS_EventHandler::getCurrentAction()
429 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
430 && !currentActions[actionIndex]->isFinished())
431 return currentActions[actionIndex];
433 return defaultAction;
437 * @return The current default action.
439 RS_ActionInterface * RS_EventHandler::getDefaultAction()
441 return defaultAction;
445 * Sets the default action.
447 void RS_EventHandler::setDefaultAction(RS_ActionInterface * action)
449 if (defaultAction != NULL)
451 defaultAction->finish();
452 delete defaultAction;
453 defaultAction = NULL;
456 defaultAction = action;
460 * Sets the current action.
462 void RS_EventHandler::setCurrentAction(RS_ActionInterface * action)
464 RS_DEBUG->print("RS_EventHandler::setCurrentAction");
469 // Predecessor of the new action or NULL:
470 RS_ActionInterface * predecessor = NULL;
472 // Suspend current action:
473 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
474 && !currentActions[actionIndex]->isFinished())
476 predecessor = currentActions[actionIndex];
477 predecessor->suspend();
478 predecessor->hideOptions();
482 if (defaultAction != NULL)
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] != NULL)
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("RS_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] != NULL)
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 != NULL)
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] != NULL && !currentActions[resume]->isFinished())
640 currentActions[resume]->resume();
641 currentActions[resume]->showOptions();
645 if (defaultAction != NULL)
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)
661 for(int c=0; c<RS_MAXACTIONS; ++c)
662 if (currentActions[c] != NULL)
663 currentActions[c]->setSnapMode(sm);
665 if (defaultAction!=NULL)
666 defaultAction->setSnapMode(sm);
670 * Sets the snap restriction for all currently active actions.
672 void RS_EventHandler::setSnapRestriction(RS2::SnapRestriction sr)
674 for(int c=0; c<RS_MAXACTIONS; ++c)
675 if (currentActions[c] != NULL)
676 currentActions[c]->setSnapRestriction(sr);
678 if (defaultAction != NULL)
679 defaultAction->setSnapRestriction(sr);
682 void RS_EventHandler::debugActions()
684 RS_DEBUG->print("---");
686 for(int c=0; c<RS_MAXACTIONS; ++c)
688 if (c == actionIndex)
689 RS_DEBUG->print("Current");
691 if (currentActions[c] != NULL)
692 RS_DEBUG->print("Action %03d: %s [%s]",
693 c, currentActions[c]->getName().toLatin1().data(),
694 currentActions[c]->isFinished() ? "finished" : "active");
696 RS_DEBUG->print("Action %03d: NULL", c);