Logo Search packages:      
Sourcecode: qcad version File versions  Download package

rs_eventhandler.cpp

/****************************************************************************
** $Id: rs_eventhandler.cpp,v 1.29 2004/07/13 23:25:58 andrew Exp $
**
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
** This file is part of the qcadlib Library project.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** Licensees holding valid qcadlib Professional Edition licenses may use 
** this file in accordance with the qcadlib Commercial License
** Agreement provided with the Software.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.ribbonsoft.com for further details.
**
** Contact info@ribbonsoft.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/


#include "rs_eventhandler.h"

#include "rs_actioninterface.h"
#include "rs_coordinateevent.h"
#include "rs_regexp.h"

/**
 * Constructor.
 */
00037 RS_EventHandler::RS_EventHandler(RS_GraphicView* graphicView) {
    this->graphicView = graphicView;
    actionIndex=-1;
    for (int i=0; i<RS_MAXACTIONS; ++i) {
        currentActions[i] = NULL;
    }
    coordinateInputEnabled = true;
    defaultAction = NULL;
}



/**
 * Destructor.
 */
00052 RS_EventHandler::~RS_EventHandler() {
    RS_DEBUG->print("RS_EventHandler::~RS_EventHandler");
    if (defaultAction!=NULL) {
            defaultAction->finish();
        delete defaultAction;
            defaultAction = NULL;
    }

    killAllActions();

    RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: Deleting all actions..");
    for (int i=0; i<RS_MAXACTIONS; ++i) {
        if (currentActions[i]!=NULL) {
                  currentActions[i]->setFinished();
            //delete currentActions[i];
            //currentActions[i] = NULL;
        }
    }
      cleanUp();
    RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: Deleting all actions..: OK");

    RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: OK");
}


/**
 * Go back in current action.
 */
00080 void RS_EventHandler::back() {
    RS_MouseEvent e(QEvent::MouseButtonRelease, QPoint(0,0),
                    Qt::RightButton, Qt::RightButton);
    mouseReleaseEvent(&e);
}



/**
 * Go enter pressed event for current action.
 */
00091 void RS_EventHandler::enter() {
    RS_KeyEvent e(QEvent::KeyPress, Qt::Key_Enter, '\n', 0);
    keyPressEvent(&e);
}


/**
 * Called by RS_GraphicView 
 */
00100 void RS_EventHandler::mousePressEvent(RS_MouseEvent* e) {
    if (actionIndex>=0 && currentActions[actionIndex]!=NULL) {
        currentActions[actionIndex]->mousePressEvent(e);
#if QT_VERSION>=0x030000
        e->accept();
#endif
    } else {
        if (defaultAction!=NULL) {
            defaultAction->mousePressEvent(e);
#if QT_VERSION>=0x030000
            e->accept();
#endif
        } else {
            RS_DEBUG->print("currently no action defined");
#if QT_VERSION>=0x030000
            e->ignore();
#endif
        }
    }
}



/**
 * Called by RS_GraphicView 
 */
00126 void RS_EventHandler::mouseReleaseEvent(RS_MouseEvent* e) {

    if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
            !currentActions[actionIndex]->isFinished()) {
        RS_DEBUG->print("call action %s",
                        currentActions[actionIndex]->getName().latin1());

        currentActions[actionIndex]->mouseReleaseEvent(e);

        // Clean up actions - one might be finished now
        cleanUp();
#if QT_VERSION>=0x030000
        e->accept();
#endif
    } else {
        if (defaultAction!=NULL) {
            defaultAction->mouseReleaseEvent(e);
        } else {
#if QT_VERSION>=0x030000            
            e->ignore();
#endif                  
        }
    }
}



/**
 * Called by RS_GraphicView 
 */
00156 void RS_EventHandler::mouseMoveEvent(RS_MouseEvent* e) {
    if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
            !currentActions[actionIndex]->isFinished()) {
        currentActions[actionIndex]->mouseMoveEvent(e);
#if QT_VERSION>=0x030000
        e->accept();
#endif
    } else {
        if (defaultAction!=NULL) {
            defaultAction->mouseMoveEvent(e);
#if QT_VERSION>=0x030000
            e->accept();
#endif
        } else {
#if QT_VERSION>=0x030000
            e->ignore();
#endif
        }
        //RS_DEBUG->print("currently no action defined");
    }
}



/**
 * Called by RS_GraphicView 
 */
00183 void RS_EventHandler::mouseLeaveEvent() {
    if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
            !currentActions[actionIndex]->isFinished()) {
        currentActions[actionIndex]->suspend();
    } else {
        if (defaultAction!=NULL) {
            defaultAction->suspend();
        }
        //RS_DEBUG->print("currently no action defined");
    }
}



/**
 * Called by RS_GraphicView 
 */
00200 void RS_EventHandler::mouseEnterEvent() {
    if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
            !currentActions[actionIndex]->isFinished()) {
        currentActions[actionIndex]->resume();
    } else {
        if (defaultAction!=NULL) {
                  //std::cout << "resume default action\n";
            defaultAction->resume();
        }
        //RS_DEBUG->print("currently no action defined");
    }
}



/**
 * Called by RS_GraphicView 
 */
00218 void RS_EventHandler::keyPressEvent(RS_KeyEvent* e) {
      //std::cout << "RS_EventHandler::keyPressEvent\n";
    if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
            !currentActions[actionIndex]->isFinished()) {
        currentActions[actionIndex]->keyPressEvent(e);
    } else {
        if (defaultAction!=NULL) {
            defaultAction->keyPressEvent(e);
        }
            else {
#if QT_VERSION>=0x030000            
                  e->ignore();
#endif                  
            }
            
        //RS_DEBUG->print("currently no action defined");
    }
}



/**
 * Called by RS_GraphicView 
 */
00242 void RS_EventHandler::keyReleaseEvent(RS_KeyEvent* e) {
    if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
            !currentActions[actionIndex]->isFinished()) {
        currentActions[actionIndex]->keyReleaseEvent(e);
    } else {
        if (defaultAction!=NULL) {
            defaultAction->keyReleaseEvent(e);
        }
            else {
#if QT_VERSION>=0x030000            
                  e->ignore();
#endif                  
            }
        //RS_DEBUG->print("currently no action defined");
    }
}



/**
 * Handles command line events.
 */
00264 void RS_EventHandler::commandEvent(RS_CommandEvent* e) {
      RS_DEBUG->print("RS_EventHandler::commandEvent");

    //RS_RegExp rex;
    RS_String cmd = e->getCommand();

    if (coordinateInputEnabled) {
#if QT_VERSION>=0x030000      
        if (!e->isAccepted()) {
#endif            
            // handle absolute cartesian coordinate input:
            if (cmd.contains(',') && cmd.at(0)!='@') {
                if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
                        !currentActions[actionIndex]->isFinished()) {
                    int commaPos = cmd.find(',');
                    bool ok1, ok2;
                    double x = RS_Math::eval(cmd.left(commaPos), &ok1);
                    double y = RS_Math::eval(cmd.mid(commaPos+1), &ok2);

                    if (ok1 && ok2) {
                        RS_CoordinateEvent ce(RS_Vector(x,y));
                        currentActions[actionIndex]->coordinateEvent(&ce);
                    } else {
                        if (RS_DIALOGFACTORY!=NULL) {
                            RS_DIALOGFACTORY->commandMessage(
                                "Expression Syntax Error");
                        }
                    }
#if QT_VERSION>=0x030000                              
                    e->accept();
#endif                              
                }
            }
#if QT_VERSION>=0x030000                  
        }
#endif            

        // handle relative cartesian coordinate input:
#if QT_VERSION>=0x030000            
        if (!e->isAccepted()) {
#endif            
            if (cmd.contains(',') && cmd.at(0)=='@') {
                if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
                        !currentActions[actionIndex]->isFinished()) {
                    int commaPos = cmd.find(',');
                    bool ok1, ok2;
                    double x = RS_Math::eval(cmd.mid(1, commaPos-1), &ok1);
                    double y = RS_Math::eval(cmd.mid(commaPos+1), &ok2);

                    if (ok1 && ok2) {
                        RS_CoordinateEvent ce(RS_Vector(x,y) +
                                              graphicView->getRelativeZero());
                        currentActions[actionIndex]->coordinateEvent(&ce);
                    } else {
                        if (RS_DIALOGFACTORY!=NULL) {
                            RS_DIALOGFACTORY->commandMessage(
                                "Expression Syntax Error");
                        }
                    }
#if QT_VERSION>=0x030000                              
                    e->accept();
#endif                              
                }
            }
#if QT_VERSION>=0x030000                  
        }
#endif            

        // handle absolute polar coordinate input:
#if QT_VERSION>=0x030000            
        if (!e->isAccepted()) {
#endif            
            if (cmd.contains('<') && cmd.at(0)!='@') {
                if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
                        !currentActions[actionIndex]->isFinished()) {
                    int commaPos = cmd.find('<');
                    bool ok1, ok2;
                    double r = RS_Math::eval(cmd.left(commaPos), &ok1);
                    double a = RS_Math::eval(cmd.mid(commaPos+1), &ok2);

                    if (ok1 && ok2) {
                        RS_Vector pos;
                        pos.setPolar(r,RS_Math::deg2rad(a));
                        RS_CoordinateEvent ce(pos);
                        currentActions[actionIndex]->coordinateEvent(&ce);
                    } else {
                        if (RS_DIALOGFACTORY!=NULL) {
                            RS_DIALOGFACTORY->commandMessage(
                                "Expression Syntax Error");
                        }
                    }
#if QT_VERSION>=0x030000                              
                    e->accept();
#endif                              
                }
            }
#if QT_VERSION>=0x030000                  
        }
#endif            

        // handle relative polar coordinate input:
#if QT_VERSION>=0x030000            
        if (!e->isAccepted()) {
#endif            
            if (cmd.contains('<') && cmd.at(0)=='@') {
                if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
                        !currentActions[actionIndex]->isFinished()) {
                    int commaPos = cmd.find('<');
                    bool ok1, ok2;
                    double r = RS_Math::eval(cmd.mid(1, commaPos-1), &ok1);
                    double a = RS_Math::eval(cmd.mid(commaPos+1), &ok2);

                    if (ok1 && ok2) {
                        RS_Vector pos;
                        pos.setPolar(r,RS_Math::deg2rad(a));
                        RS_CoordinateEvent ce(pos +
                                              graphicView->getRelativeZero());
                        currentActions[actionIndex]->coordinateEvent(&ce);
                    } else {
                        if (RS_DIALOGFACTORY!=NULL) {
                            RS_DIALOGFACTORY->commandMessage(
                                "Expression Syntax Error");
                        }
                    }
#if QT_VERSION>=0x030000                              
                    e->accept();
#endif                              
                }
            }
#if QT_VERSION>=0x030000                  
        }
#endif            
    }

    // send command event directly to current action:
#if QT_VERSION>=0x030000      
    if (!e->isAccepted()) {
#endif      
        if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
                !currentActions[actionIndex]->isFinished()) {
            currentActions[actionIndex]->commandEvent(e);
#if QT_VERSION>=0x030000                  
            e->accept();
#endif                  
        } else {
            if (defaultAction!=NULL) {
                defaultAction->commandEvent(e);
#if QT_VERSION>=0x030000                        
                //e->accept();
#endif                        
            }
        }
#if QT_VERSION>=0x030000            
    }
#endif      

      RS_DEBUG->print("RS_EventHandler::commandEvent: OK");
}



/**
 * Enables coordinate input in the command line.
 */
00428 void RS_EventHandler::enableCoordinateInput() {
    coordinateInputEnabled = true;
}



/**
 * Enables coordinate input in the command line.
 */
00437 void RS_EventHandler::disableCoordinateInput() {
    coordinateInputEnabled = false;
}



/**
 * @return Current action.
 */
00446 RS_ActionInterface* RS_EventHandler::getCurrentAction() {
    if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
            !currentActions[actionIndex]->isFinished()) {

        return currentActions[actionIndex];
    } else {
        return defaultAction;
    }
}



/**
 * @return The current default action.
 */
00461 RS_ActionInterface* RS_EventHandler::getDefaultAction() {
    return defaultAction;
}



/**
 * Sets the default action.
 */
00470 void RS_EventHandler::setDefaultAction(RS_ActionInterface* action) {
    if (defaultAction!=NULL) {
            defaultAction->finish();
        delete defaultAction;
        defaultAction = NULL;
    }

    defaultAction = action;
}



/**
 * Sets the current action.
 */
00485 void RS_EventHandler::setCurrentAction(RS_ActionInterface* action) {
      RS_DEBUG->print("RS_EventHandler::setCurrentAction");
    if (action==NULL) {
        return;
    }

    // Predecessor of the new action or NULL:
    RS_ActionInterface* predecessor = NULL;

    // Suspend current action:
    if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
            !currentActions[actionIndex]->isFinished()) {
        predecessor = currentActions[actionIndex];
        predecessor->suspend();
        predecessor->hideOptions();
    }
      else {
            if (defaultAction!=NULL) {
            predecessor = defaultAction;
            predecessor->suspend();
            predecessor->hideOptions();
            }
      }

    // Forget about the oldest action and make space for the new action:
    if (actionIndex==RS_MAXACTIONS-1) {
        // delete oldest action if necessary (usually never happens):
        if (currentActions[0]!=NULL) {
                  currentActions[0]->finish();
            delete currentActions[0];
                  currentActions[0] = NULL;
        }
        // Move up actionstack (optimize):
        for (int i=0; i<RS_MAXACTIONS-1; ++i) {
            currentActions[i] = currentActions[i+1];
        }
    } else if (actionIndex<RS_MAXACTIONS-1) {
        actionIndex++;
    }

    // Set current action:
    currentActions[actionIndex] = action;
    RS_DEBUG->print("RS_EventHandler::setCurrentAction: current action is: %s",
                    currentActions[actionIndex]->getName().latin1());

    // Initialisation of our new action:
    RS_DEBUG->print("RS_EventHandler::setCurrentAction: init current action");
    action->init();
    // ## new:
      if (action->isFinished()==false) {
      RS_DEBUG->print("RS_EventHandler::setCurrentAction: show options");
      currentActions[actionIndex]->showOptions();
      RS_DEBUG->print("RS_EventHandler::setCurrentAction: set predecessor");
      action->setPredecessor(predecessor);
      }

    RS_DEBUG->print("RS_EventHandler::setCurrentAction: cleaning up..");
    cleanUp();

    RS_DEBUG->print("RS_EventHandler::setCurrentAction: debugging actions");
    debugActions();
      RS_DEBUG->print("RS_GraphicView::setCurrentAction: OK");
}



/**
 * Kills all running selection actions. Called when a selection action
 * is launched to reduce confusion.
 */
00555 void RS_EventHandler::killSelectActions() {
    for (int c=0; c<RS_MAXACTIONS; ++c) {
        if (currentActions[c]!=NULL) {
            if (currentActions[c]->rtti()==RS2::ActionSelectSingle ||
                    currentActions[c]->rtti()==RS2::ActionSelectContour ||
                    currentActions[c]->rtti()==RS2::ActionSelectWindow ||
                    currentActions[c]->rtti()==RS2::ActionSelectIntersected ||
                    currentActions[c]->rtti()==RS2::ActionSelectLayer) {

                currentActions[c]->finish();
            }
        }
    }
}



/**
 * Kills all running actions. Called when a window is closed.
 */
00575 void RS_EventHandler::killAllActions() {
      /*
      std::cout << "  Killing all actions\n";
    for (int c=0; c<RS_MAXACTIONS; ++c) {
        if (currentActions[c]!=NULL) {
            currentActions[c]->finish();
        }
    }
      std::cout << "  Killing all actions: OK\n";
    cleanUp();
      */
}



/**
 * @return true if there is at least one action in the action stack.
 */
00593 bool RS_EventHandler::hasAction() {
    if (actionIndex!=-1 || defaultAction!=NULL) {
        return true;
    } else {
        return false;
    }
}



/**
 * Garbage collector for actions.
 */
00606 void RS_EventHandler::cleanUp() {
    RS_DEBUG->print("RS_EventHandler::cleanUp");
      
    int o=0;   // old index
    int n=0;   // new index
    int resume=0; // index of action to resume
    bool doResume=false; // do we need to resume an action
    actionIndex = -1;

    //RS_DEBUG->print("RS_EventHandler::cleanUp()", o);
      //std::cout << "RS_EventHandler::cleanUp()\n";
    debugActions();
    do {
        // search first used action (o)
        while (currentActions[o]==NULL && o<RS_MAXACTIONS) {
            o++;
        }

        // delete action if it is finished
        if (o<RS_MAXACTIONS && currentActions[o]!=NULL &&
                currentActions[o]->isFinished()) {
            //RS_DEBUG->print("Deleting action %d '%s'",
            //                o, currentActions[o]->getName().latin1());
                  //std::cout << "Deleting action " << o << "\n";
            //currentActions[o]->hideOptions();
            delete currentActions[o];
            //RS_DEBUG->print("Action %d deleted", o);
            currentActions[o] = NULL;
                  //std::cout << "Deleting action " << o << ": OK\n";

            doResume = true;
        }

        // move a running action up in the stack
        if (o<RS_MAXACTIONS && currentActions[o]!=NULL) {
            if (n!=o) {
                currentActions[n] = currentActions[o];
                resume = n;
                currentActions[o] = NULL;
            } else {
                if (o<RS_MAXACTIONS) {
                    o++;
                }
            }
            actionIndex = n;
            if (n<RS_MAXACTIONS-1) {
                n++;
            }
        }
    } while (o<RS_MAXACTIONS);

    debugActions();

    // Resume last used action:
    //std::cout << "doResume: " << doResume << ": " << resume << "\n";

    if (doResume) {
        if (currentActions[resume]!=NULL &&
                !currentActions[resume]->isFinished()) {

            //std::cout << "resume action: " << resume << "\n";

            ////std::cout << "action name: "
            //    << currentActions[resume]->getName().latin1() << "\n";

            currentActions[resume]->resume();
            //std::cout << "resume action: " << resume << ": OK\n";
                  
            //std::cout << "show options\n";
            currentActions[resume]->showOptions();
            //std::cout << "show options: OK\n";
        } else {
            if (defaultAction!=NULL) {
                  //std::cout << "resume default action\n";
                defaultAction->resume();
                  defaultAction->showOptions();
                  //std::cout << "resume default action: OK\n";
            }
        }
    }
    RS_DEBUG->print("RS_EventHandler::cleanUp: OK");
}



/**
 * Sets the snap mode for all currently active actions.
 */
00694 void RS_EventHandler::setSnapMode(RS2::SnapMode sm) {
    for (int c=0; c<RS_MAXACTIONS; ++c) {
        if (currentActions[c]!=NULL) {
            currentActions[c]->setSnapMode(sm);
        }
    }

    if (defaultAction!=NULL) {
        defaultAction->setSnapMode(sm);
    }
}



/**
 * Sets the snap restriction for all currently active actions.
 */
00711 void RS_EventHandler::setSnapRestriction(RS2::SnapRestriction sr) {
    for (int c=0; c<RS_MAXACTIONS; ++c) {
        if (currentActions[c]!=NULL) {
            currentActions[c]->setSnapRestriction(sr);
        }
    }

    if (defaultAction!=NULL) {
        defaultAction->setSnapRestriction(sr);
    }
}


void RS_EventHandler::debugActions() {
    RS_DEBUG->print("---");
    for (int c=0; c<RS_MAXACTIONS; ++c) {
        if (c==actionIndex) {
            RS_DEBUG->print("Current");
        }
        if (currentActions[c]!=NULL) {
            RS_DEBUG->print("Action %03d: %s [%s]",
                            c, currentActions[c]->getName().latin1(),
                            currentActions[c]->isFinished() ? "finished" : "active");
        } else {
            RS_DEBUG->print("Action %03d: NULL", c);
        }
    }
}

// EOF

Generated by  Doxygen 1.6.0   Back to index