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.indexOf('<');
331 double r = RS_Math::eval(cmd.left(commaPos), &ok1);
332 double a = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
337 pos.setPolar(r,RS_Math::deg2rad(a));
338 // RS_CoordinateEvent ce(pos);
339 // currentActions[actionIndex]->coordinateEvent(&ce);
340 currentActions[actionIndex]->coordinateEvent(&pos);
344 if (RS_DIALOGFACTORY != NULL)
345 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
353 // handle relative polar coordinate input:
354 if (!e->isAccepted())
356 if (cmd.contains('<') && cmd.at(0) == '@')
358 if (actionIndex >= 0 && currentActions[actionIndex] !=NULL
359 && !currentActions[actionIndex]->isFinished())
361 // int commaPos = cmd.find('<');
362 int commaPos = cmd.indexOf('<');
364 double r = RS_Math::eval(cmd.mid(1, commaPos - 1), &ok1);
365 double a = RS_Math::eval(cmd.mid(commaPos + 1), &ok2);
370 pos.setPolar(r,RS_Math::deg2rad(a));
371 // RS_CoordinateEvent ce(pos + graphicView->getRelativeZero());
372 // currentActions[actionIndex]->coordinateEvent(&ce);
373 Vector ce(pos + graphicView->getRelativeZero());
374 currentActions[actionIndex]->coordinateEvent(&ce);
378 if (RS_DIALOGFACTORY != NULL)
379 RS_DIALOGFACTORY->commandMessage("Expression Syntax Error");
388 // send command event directly to current action:
389 if (!e->isAccepted())
391 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
392 && !currentActions[actionIndex]->isFinished())
394 currentActions[actionIndex]->commandEvent(e);
399 if (defaultAction != NULL)
400 defaultAction->commandEvent(e);
404 RS_DEBUG->print("RS_EventHandler::commandEvent: OK");
408 * Enables coordinate input in the command line.
410 void RS_EventHandler::enableCoordinateInput()
412 coordinateInputEnabled = true;
416 * Enables coordinate input in the command line.
418 void RS_EventHandler::disableCoordinateInput()
420 coordinateInputEnabled = false;
424 * @return Current action.
426 RS_ActionInterface * RS_EventHandler::getCurrentAction()
428 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
429 && !currentActions[actionIndex]->isFinished())
430 return currentActions[actionIndex];
432 return defaultAction;
436 * @return The current default action.
438 RS_ActionInterface * RS_EventHandler::getDefaultAction()
440 return defaultAction;
444 * Sets the default action.
446 void RS_EventHandler::setDefaultAction(RS_ActionInterface * action)
448 if (defaultAction != NULL)
450 defaultAction->finish();
451 delete defaultAction;
452 defaultAction = NULL;
455 defaultAction = action;
459 * Sets the current action.
461 void RS_EventHandler::setCurrentAction(RS_ActionInterface * action)
463 RS_DEBUG->print("RS_EventHandler::setCurrentAction");
468 // Predecessor of the new action or NULL:
469 RS_ActionInterface * predecessor = NULL;
471 // Suspend current action:
472 if (actionIndex >= 0 && currentActions[actionIndex] != NULL
473 && !currentActions[actionIndex]->isFinished())
475 predecessor = currentActions[actionIndex];
476 predecessor->suspend();
477 predecessor->hideOptions();
481 if (defaultAction != NULL)
483 predecessor = defaultAction;
484 predecessor->suspend();
485 predecessor->hideOptions();
489 // Forget about the oldest action and make space for the new action:
490 if (actionIndex == RS_MAXACTIONS - 1)
492 // delete oldest action if necessary (usually never happens):
493 if (currentActions[0] != NULL)
495 currentActions[0]->finish();
496 delete currentActions[0];
497 currentActions[0] = NULL;
500 // Move up actionstack (optimize):
501 for(int i=0; i<RS_MAXACTIONS-1; ++i)
502 currentActions[i] = currentActions[i + 1];
504 else if (actionIndex < RS_MAXACTIONS - 1)
507 // Set current action:
508 currentActions[actionIndex] = action;
509 RS_DEBUG->print("RS_EventHandler::setCurrentAction: current action is: %s",
510 currentActions[actionIndex]->getName().toLatin1().data());
512 // Initialisation of our new action:
513 RS_DEBUG->print("RS_EventHandler::setCurrentAction: init current action");
517 if (action->isFinished() == false)
519 RS_DEBUG->print("RS_EventHandler::setCurrentAction: show options");
520 currentActions[actionIndex]->showOptions();
521 RS_DEBUG->print("RS_EventHandler::setCurrentAction: set predecessor");
522 action->setPredecessor(predecessor);
525 RS_DEBUG->print("RS_EventHandler::setCurrentAction: cleaning up..");
528 RS_DEBUG->print("RS_EventHandler::setCurrentAction: debugging actions");
530 RS_DEBUG->print("RS_GraphicView::setCurrentAction: OK");
534 * Kills all running selection actions. Called when a selection action
535 * is launched to reduce confusion.
537 void RS_EventHandler::killSelectActions()
539 for(int c=0; c<RS_MAXACTIONS; ++c)
541 if (currentActions[c] != NULL)
543 if (currentActions[c]->rtti() == RS2::ActionSelectSingle
544 || currentActions[c]->rtti() == RS2::ActionSelectContour
545 || currentActions[c]->rtti() == RS2::ActionSelectWindow
546 || currentActions[c]->rtti() == RS2::ActionSelectIntersected
547 || currentActions[c]->rtti() == RS2::ActionSelectLayer)
548 currentActions[c]->finish();
554 * Kills all running actions. Called when a window is closed.
556 void RS_EventHandler::killAllActions()
559 for (int c=0; c<RS_MAXACTIONS; ++c) {
560 if (currentActions[c]!=NULL) {
561 currentActions[c]->finish();
569 * @return true if there is at least one action in the action stack.
571 bool RS_EventHandler::hasAction()
573 if (actionIndex != -1 || defaultAction != NULL)
580 * Garbage collector for actions.
582 void RS_EventHandler::cleanUp()
584 RS_DEBUG->print("RS_EventHandler::cleanUp");
586 int o = 0; // old index
587 int n = 0; // new index
588 int resume = 0; // index of action to resume
589 bool doResume = false; // do we need to resume an action
596 // search first used action (o)
597 while (currentActions[o] == NULL && o < RS_MAXACTIONS)
600 // delete action if it is finished
601 if (o < RS_MAXACTIONS && currentActions[o] != NULL
602 && currentActions[o]->isFinished())
604 delete currentActions[o];
605 currentActions[o] = NULL;
609 // move a running action up in the stack
610 if (o < RS_MAXACTIONS && currentActions[o] != NULL)
614 currentActions[n] = currentActions[o];
616 currentActions[o] = NULL;
620 if (o < RS_MAXACTIONS)
626 if (n < RS_MAXACTIONS - 1)
630 while (o < RS_MAXACTIONS);
634 // Resume last used action:
637 if (currentActions[resume] != NULL && !currentActions[resume]->isFinished())
639 currentActions[resume]->resume();
640 currentActions[resume]->showOptions();
644 if (defaultAction != NULL)
646 defaultAction->resume();
647 defaultAction->showOptions();
652 RS_DEBUG->print("RS_EventHandler::cleanUp: OK");
656 * Sets the snap mode for all currently active actions.
658 void RS_EventHandler::setSnapMode(RS2::SnapMode sm)
660 for(int c=0; c<RS_MAXACTIONS; ++c)
661 if (currentActions[c] != NULL)
662 currentActions[c]->setSnapMode(sm);
664 if (defaultAction!=NULL)
665 defaultAction->setSnapMode(sm);
669 * Sets the snap restriction for all currently active actions.
671 void RS_EventHandler::setSnapRestriction(RS2::SnapRestriction sr)
673 for(int c=0; c<RS_MAXACTIONS; ++c)
674 if (currentActions[c] != NULL)
675 currentActions[c]->setSnapRestriction(sr);
677 if (defaultAction != NULL)
678 defaultAction->setSnapRestriction(sr);
681 void RS_EventHandler::debugActions()
683 RS_DEBUG->print("---");
685 for(int c=0; c<RS_MAXACTIONS; ++c)
687 if (c == actionIndex)
688 RS_DEBUG->print("Current");
690 if (currentActions[c] != NULL)
691 RS_DEBUG->print("Action %03d: %s [%s]",
692 c, currentActions[c]->getName().toLatin1().data(),
693 currentActions[c]->isFinished() ? "finished" : "active");
695 RS_DEBUG->print("Action %03d: NULL", c);