~librecad-dev/librecad/librecad

« back to all changes in this revision

Viewing changes to librecad/src/lib/gui/rs_eventhandler.cpp

  • Committer: Scott Howard
  • Date: 2014-02-21 19:07:55 UTC
  • Revision ID: showard@debian.org-20140221190755-csjax9wb146hgdq4
first commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** This file is part of the LibreCAD project, a 2D CAD program
 
4
**
 
5
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
 
6
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
 
7
**
 
8
**
 
9
** This file may be distributed and/or modified under the terms of the
 
10
** GNU General Public License version 2 as published by the Free Software
 
11
** Foundation and appearing in the file gpl-2.0.txt included in the
 
12
** packaging of this file.
 
13
**
 
14
** This program is distributed in the hope that it will be useful,
 
15
** but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
** GNU General Public License for more details.
 
18
**
 
19
** You should have received a copy of the GNU General Public License
 
20
** along with this program; if not, write to the Free Software
 
21
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
22
**
 
23
** This copyright notice MUST APPEAR in all copies of the script!
 
24
**
 
25
**********************************************************************/
 
26
 
 
27
 
 
28
#include "rs_eventhandler.h"
 
29
 
 
30
#include "rs_actioninterface.h"
 
31
#include "rs_dialogfactory.h"
 
32
#include "rs_commandevent.h"
 
33
 
 
34
/**
 
35
 * Constructor.
 
36
 */
 
37
RS_EventHandler::RS_EventHandler(RS_GraphicView* graphicView) {
 
38
    this->graphicView = graphicView;
 
39
//    actionIndex=-1;
 
40
    currentActions.clear();
 
41
    //    for (int i=0; i<RS_MAXACTIONS; ++i) {
 
42
    //        currentActions[i] = NULL;
 
43
    //    }
 
44
    coordinateInputEnabled = true;
 
45
    defaultAction = NULL;
 
46
}
 
47
 
 
48
 
 
49
 
 
50
/**
 
51
 * Destructor.
 
52
 */
 
53
RS_EventHandler::~RS_EventHandler() {
 
54
    RS_DEBUG->print("RS_EventHandler::~RS_EventHandler");
 
55
    if (defaultAction!=NULL) {
 
56
        defaultAction->finish();
 
57
        delete defaultAction;
 
58
        defaultAction = NULL;
 
59
    }
 
60
 
 
61
    RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: Deleting all actions..");
 
62
    for(int i=0; i< currentActions.size();i++){
 
63
        //        currentActions[i]->finish(false);
 
64
        delete currentActions[i];
 
65
    }
 
66
    //    for (int i=0; i<RS_MAXACTIONS; ++i) {
 
67
    //        if (currentActions[i]!=NULL) {
 
68
    //            currentActions[i]->setFinished();
 
69
    //        }
 
70
    //    }
 
71
    //cleanUp();
 
72
    RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: Deleting all actions..: OK");
 
73
    RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: OK");
 
74
}
 
75
 
 
76
 
 
77
/**
 
78
 * Go back in current action.
 
79
 */
 
80
void RS_EventHandler::back() {
 
81
    QMouseEvent e(QEvent::MouseButtonRelease, QPoint(0,0),
 
82
                  Qt::RightButton, Qt::RightButton,Qt::NoModifier);
 
83
    mouseReleaseEvent(&e);
 
84
}
 
85
 
 
86
 
 
87
 
 
88
/**
 
89
 * Go enter pressed event for current action.
 
90
 */
 
91
void RS_EventHandler::enter() {
 
92
    QKeyEvent e(QEvent::KeyPress, Qt::Key_Enter, 0);
 
93
    keyPressEvent(&e);
 
94
}
 
95
 
 
96
 
 
97
/**
 
98
 * Called by RS_GraphicView
 
99
 */
 
100
void RS_EventHandler::mousePressEvent(QMouseEvent* e) {
 
101
    if(hasAction()){
 
102
        currentActions.last()->mousePressEvent(e);
 
103
        e->accept();
 
104
    } else {
 
105
        if (defaultAction!=NULL) {
 
106
            defaultAction->mousePressEvent(e);
 
107
            e->accept();
 
108
        } else {
 
109
            RS_DEBUG->print("currently no action defined");
 
110
            e->ignore();
 
111
        }
 
112
    }
 
113
}
 
114
 
 
115
 
 
116
 
 
117
/**
 
118
 * Called by RS_GraphicView
 
119
 */
 
120
void RS_EventHandler::mouseReleaseEvent(QMouseEvent* e) {
 
121
    if(hasAction()){
 
122
        //    if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
 
123
        //            !currentActions[actionIndex]->isFinished()) {
 
124
        RS_DEBUG->print("call action %s",
 
125
                        currentActions.last()->getName().toLatin1().data());
 
126
 
 
127
        currentActions.last()->mouseReleaseEvent(e);
 
128
 
 
129
        // Clean up actions - one might be finished now
 
130
        cleanUp();
 
131
        e->accept();
 
132
    } else {
 
133
        if (defaultAction!=NULL) {
 
134
            defaultAction->mouseReleaseEvent(e);
 
135
        } else {
 
136
            e->ignore();
 
137
        }
 
138
    }
 
139
}
 
140
 
 
141
 
 
142
 
 
143
/**
 
144
 * Called by RS_GraphicView
 
145
 */
 
146
void RS_EventHandler::mouseMoveEvent(QMouseEvent* e) {
 
147
    if(hasAction()){
 
148
        currentActions.last()->mouseMoveEvent(e);
 
149
        e->accept();
 
150
    } else {
 
151
        if (defaultAction!=NULL) {
 
152
            defaultAction->mouseMoveEvent(e);
 
153
            e->accept();
 
154
        } else {
 
155
            e->ignore();
 
156
        }
 
157
        //RS_DEBUG->print("currently no action defined");
 
158
    }
 
159
}
 
160
 
 
161
 
 
162
 
 
163
/**
 
164
 * Called by RS_GraphicView
 
165
 */
 
166
void RS_EventHandler::mouseLeaveEvent() {
 
167
 
 
168
    if(hasAction()){
 
169
        currentActions.last()->suspend();
 
170
    } else {
 
171
        if (defaultAction!=NULL) {
 
172
            defaultAction->suspend();
 
173
        }
 
174
        //RS_DEBUG->print("currently no action defined");
 
175
    }
 
176
}
 
177
 
 
178
 
 
179
 
 
180
/**
 
181
 * Called by RS_GraphicView
 
182
 */
 
183
void RS_EventHandler::mouseEnterEvent() {
 
184
 
 
185
    if(hasAction()){
 
186
        currentActions.last()->resume();
 
187
    } else {
 
188
        if (defaultAction!=NULL) {
 
189
            defaultAction->resume();
 
190
        }
 
191
    }
 
192
}
 
193
 
 
194
 
 
195
 
 
196
/**
 
197
 * Called by RS_GraphicView
 
198
 */
 
199
void RS_EventHandler::keyPressEvent(QKeyEvent* e) {
 
200
 
 
201
    if(hasAction()){
 
202
        currentActions.last()->keyPressEvent(e);
 
203
    } else {
 
204
        if (defaultAction!=NULL) {
 
205
            defaultAction->keyPressEvent(e);
 
206
        }
 
207
        else {
 
208
            e->ignore();
 
209
        }
 
210
 
 
211
        //RS_DEBUG->print("currently no action defined");
 
212
    }
 
213
}
 
214
 
 
215
 
 
216
 
 
217
/**
 
218
 * Called by RS_GraphicView
 
219
 */
 
220
void RS_EventHandler::keyReleaseEvent(QKeyEvent* e) {
 
221
 
 
222
    if(hasAction()){
 
223
        currentActions.last()->keyReleaseEvent(e);
 
224
    } else {
 
225
        if (defaultAction!=NULL) {
 
226
            defaultAction->keyReleaseEvent(e);
 
227
        }
 
228
        else {
 
229
            e->ignore();
 
230
        }
 
231
        //RS_DEBUG->print("currently no action defined");
 
232
    }
 
233
}
 
234
 
 
235
 
 
236
 
 
237
/**
 
238
 * Handles command line events.
 
239
 */
 
240
void RS_EventHandler::commandEvent(RS_CommandEvent* e) {
 
241
    RS_DEBUG->print("RS_EventHandler::commandEvent");
 
242
 
 
243
    QString cmd = e->getCommand();
 
244
 
 
245
    if (coordinateInputEnabled) {
 
246
        if (!e->isAccepted()) {
 
247
 
 
248
            if(hasAction()){
 
249
                // handle absolute cartesian coordinate input:
 
250
                if (cmd.contains(',') && cmd.at(0)!='@') {
 
251
 
 
252
                    int commaPos = cmd.indexOf(',');
 
253
                    RS_DEBUG->print("RS_EventHandler::commandEvent: 001");
 
254
                    bool ok1, ok2;
 
255
                    RS_DEBUG->print("RS_EventHandler::commandEvent: 002");
 
256
                    double x = RS_Math::eval(cmd.left(commaPos), &ok1);
 
257
                    RS_DEBUG->print("RS_EventHandler::commandEvent: 003a");
 
258
                    double y = RS_Math::eval(cmd.mid(commaPos+1), &ok2);
 
259
                    RS_DEBUG->print("RS_EventHandler::commandEvent: 004");
 
260
 
 
261
                    if (ok1 && ok2) {
 
262
                        RS_DEBUG->print("RS_EventHandler::commandEvent: 005");
 
263
                        RS_CoordinateEvent ce(RS_Vector(x,y));
 
264
                        RS_DEBUG->print("RS_EventHandler::commandEvent: 006");
 
265
                        currentActions.last()->coordinateEvent(&ce);
 
266
                    } else {
 
267
                        if (RS_DIALOGFACTORY!=NULL) {
 
268
                            RS_DIALOGFACTORY->commandMessage(
 
269
                                        "Expression Syntax Error");
 
270
                        }
 
271
                    }
 
272
                    e->accept();
 
273
                }
 
274
 
 
275
                // handle relative cartesian coordinate input:
 
276
                if (!e->isAccepted()) {
 
277
                    if (cmd.contains(',') && cmd.at(0)=='@') {
 
278
                        int commaPos = cmd.indexOf(',');
 
279
                        bool ok1, ok2;
 
280
                        double x = RS_Math::eval(cmd.mid(1, commaPos-1), &ok1);
 
281
                        double y = RS_Math::eval(cmd.mid(commaPos+1), &ok2);
 
282
 
 
283
                        if (ok1 && ok2) {
 
284
                            RS_CoordinateEvent ce(RS_Vector(x,y) +
 
285
                                                  graphicView->getRelativeZero());
 
286
 
 
287
                            currentActions.last()->coordinateEvent(&ce);
 
288
                            //                            currentActions[actionIndex]->coordinateEvent(&ce);
 
289
                        } else {
 
290
                            if (RS_DIALOGFACTORY!=NULL) {
 
291
                                RS_DIALOGFACTORY->commandMessage(
 
292
                                            "Expression Syntax Error");
 
293
                            }
 
294
                        }
 
295
                        e->accept();
 
296
                    }
 
297
                }
 
298
 
 
299
                // handle absolute polar coordinate input:
 
300
                if (!e->isAccepted()) {
 
301
                    if (cmd.contains('<') && cmd.at(0)!='@') {
 
302
                        int commaPos = cmd.indexOf('<');
 
303
                        bool ok1, ok2;
 
304
                        double r = RS_Math::eval(cmd.left(commaPos), &ok1);
 
305
                        double a = RS_Math::eval(cmd.mid(commaPos+1), &ok2);
 
306
 
 
307
                        if (ok1 && ok2) {
 
308
                            RS_Vector pos;
 
309
                            pos.setPolar(r,RS_Math::deg2rad(a));
 
310
                            RS_CoordinateEvent ce(pos);
 
311
                            currentActions.last()->coordinateEvent(&ce);
 
312
                        } else {
 
313
                            if (RS_DIALOGFACTORY!=NULL) {
 
314
                                RS_DIALOGFACTORY->commandMessage(
 
315
                                            "Expression Syntax Error");
 
316
                            }
 
317
                        }
 
318
                        e->accept();
 
319
                    }
 
320
                }
 
321
 
 
322
                // handle relative polar coordinate input:
 
323
                if (!e->isAccepted()) {
 
324
                    if (cmd.contains('<') && cmd.at(0)=='@') {
 
325
                        int commaPos = cmd.indexOf('<');
 
326
                        bool ok1, ok2;
 
327
                        double r = RS_Math::eval(cmd.mid(1, commaPos-1), &ok1);
 
328
                        double a = RS_Math::eval(cmd.mid(commaPos+1), &ok2);
 
329
 
 
330
                        if (ok1 && ok2) {
 
331
                            RS_Vector pos;
 
332
                            pos.setPolar(r,RS_Math::deg2rad(a));
 
333
                            RS_CoordinateEvent ce(pos +
 
334
                                                  graphicView->getRelativeZero());
 
335
                            currentActions.last()->coordinateEvent(&ce);
 
336
                        } else {
 
337
                            if (RS_DIALOGFACTORY!=NULL) {
 
338
                                RS_DIALOGFACTORY->commandMessage(
 
339
                                            "Expression Syntax Error");
 
340
                            }
 
341
                        }
 
342
                        e->accept();
 
343
                    }
 
344
                }
 
345
 
 
346
                // send command event directly to current action:
 
347
                if (!e->isAccepted()) {
 
348
//                    std::cout<<"RS_EventHandler::commandEvent(RS_CommandEvent* e): sending cmd("<<qPrintable(e->getCommand()) <<") to action: "<<currentActions.last()->rtti()<<std::endl;
 
349
                    currentActions.last()->commandEvent(e);
 
350
                }
 
351
            }else{
 
352
            //send the command to default action
 
353
                if (defaultAction!=NULL) {
 
354
                    defaultAction->commandEvent(e);
 
355
                }
 
356
            }
 
357
            // do not accept command here. Actions themselves should be responsible to accept commands
 
358
//            e->accept();
 
359
        }
 
360
    }
 
361
 
 
362
    RS_DEBUG->print("RS_EventHandler::commandEvent: OK");
 
363
}
 
364
 
 
365
 
 
366
 
 
367
/**
 
368
 * Enables coordinate input in the command line.
 
369
 */
 
370
void RS_EventHandler::enableCoordinateInput() {
 
371
    coordinateInputEnabled = true;
 
372
}
 
373
 
 
374
 
 
375
 
 
376
/**
 
377
 * Enables coordinate input in the command line.
 
378
 */
 
379
void RS_EventHandler::disableCoordinateInput() {
 
380
    coordinateInputEnabled = false;
 
381
}
 
382
 
 
383
 
 
384
 
 
385
/**
 
386
 * @return Current action.
 
387
 */
 
388
RS_ActionInterface* RS_EventHandler::getCurrentAction() {
 
389
    if(hasAction()){
 
390
        return currentActions.last();
 
391
    } else {
 
392
        return defaultAction;
 
393
    }
 
394
}
 
395
 
 
396
 
 
397
 
 
398
/**
 
399
 * @return The current default action.
 
400
 */
 
401
RS_ActionInterface* RS_EventHandler::getDefaultAction() {
 
402
    return defaultAction;
 
403
}
 
404
 
 
405
 
 
406
 
 
407
/**
 
408
 * Sets the default action.
 
409
 */
 
410
void RS_EventHandler::setDefaultAction(RS_ActionInterface* action) {
 
411
    if (defaultAction!=NULL) {
 
412
        defaultAction->finish();
 
413
        delete defaultAction;
 
414
        //        defaultAction = NULL;
 
415
    }
 
416
 
 
417
    defaultAction = action;
 
418
}
 
419
 
 
420
 
 
421
 
 
422
/**
 
423
 * Sets the current action.
 
424
 */
 
425
void RS_EventHandler::setCurrentAction(RS_ActionInterface* action) {
 
426
    RS_DEBUG->print("RS_EventHandler::setCurrentAction");
 
427
    if (action==NULL) {
 
428
        return;
 
429
    }
 
430
 
 
431
    // Predecessor of the new action or NULL:
 
432
    RS_ActionInterface* predecessor = NULL;
 
433
 
 
434
    // Suspend current action:
 
435
    if(hasAction()){
 
436
        predecessor = currentActions.last();
 
437
        predecessor->suspend();
 
438
        predecessor->hideOptions();
 
439
    }
 
440
    else {
 
441
        if (defaultAction!=NULL) {
 
442
            predecessor = defaultAction;
 
443
            predecessor->suspend();
 
444
            predecessor->hideOptions();
 
445
        }
 
446
    }
 
447
 
 
448
    //    // Forget about the oldest action and make space for the new action:
 
449
    //    if (actionIndex==RS_MAXACTIONS-1) {
 
450
    //        // delete oldest action if necessary (usually never happens):
 
451
    //        if (currentActions[0]!=NULL) {
 
452
    //            currentActions[0]->finish();
 
453
    //            delete currentActions[0];
 
454
    //            currentActions[0] = NULL;
 
455
    //        }
 
456
    //        // Move up actionstack (optimize):
 
457
    //        for (int i=0; i<RS_MAXACTIONS-1; ++i) {
 
458
    //            currentActions[i] = currentActions[i+1];
 
459
    //        }
 
460
    //    } else if (actionIndex<RS_MAXACTIONS-1) {
 
461
    //        actionIndex++;
 
462
    //    }
 
463
 
 
464
    // Set current action:
 
465
    currentActions.push_back(action);
 
466
    RS_DEBUG->print("RS_EventHandler::setCurrentAction: current action is: %s",
 
467
                    currentActions.last()->getName().toLatin1().data());
 
468
 
 
469
    // Initialisation of our new action:
 
470
    RS_DEBUG->print("RS_EventHandler::setCurrentAction: init current action");
 
471
    action->init();
 
472
    // ## new:
 
473
    if (action->isFinished()==false) {
 
474
        RS_DEBUG->print("RS_EventHandler::setCurrentAction: show options");
 
475
        currentActions.last()->showOptions();
 
476
        RS_DEBUG->print("RS_EventHandler::setCurrentAction: set predecessor");
 
477
        action->setPredecessor(predecessor);
 
478
    }
 
479
 
 
480
    RS_DEBUG->print("RS_EventHandler::setCurrentAction: cleaning up..");
 
481
    cleanUp();
 
482
 
 
483
    RS_DEBUG->print("RS_EventHandler::setCurrentAction: debugging actions");
 
484
    debugActions();
 
485
    RS_DEBUG->print("RS_GraphicView::setCurrentAction: OK");
 
486
}
 
487
 
 
488
 
 
489
 
 
490
/**
 
491
 * Kills all running selection actions. Called when a selection action
 
492
 * is launched to reduce confusion.
 
493
 */
 
494
void RS_EventHandler::killSelectActions() {
 
495
 
 
496
    for (auto it=currentActions.begin();it != currentActions.end();){
 
497
        if ((*it)->rtti()==RS2::ActionSelectSingle ||
 
498
                (*it)->rtti()==RS2::ActionSelectContour ||
 
499
                (*it)->rtti()==RS2::ActionSelectWindow ||
 
500
                (*it)->rtti()==RS2::ActionSelectIntersected ||
 
501
                (*it)->rtti()==RS2::ActionSelectLayer) {
 
502
            if( ! (*it)->isFinished()){
 
503
                (*it)->finish();
 
504
            }
 
505
            delete *it;
 
506
            it= currentActions.erase(it);
 
507
        }else{
 
508
            it++;
 
509
        }
 
510
    }
 
511
}
 
512
 
 
513
 
 
514
 
 
515
/**
 
516
 * Kills all running actions. Called when a window is closed.
 
517
 */
 
518
void RS_EventHandler::killAllActions() {
 
519
 
 
520
    while(currentActions.size()>0){
 
521
        if ( ! currentActions.first()->isFinished() ){
 
522
            currentActions.first()->finish();
 
523
        }
 
524
        //need to check the size again after finish(), bug#3451525, 3451415
 
525
        if(currentActions.size()==0) return;
 
526
        delete currentActions.takeFirst();
 
527
    }
 
528
//    if(defaultAction->rtti() == RS2::ActionDefault){
 
529
 
 
530
//    }
 
531
    //cleanup default action, issue#285
 
532
    defaultAction->init(0);
 
533
}
 
534
 
 
535
 
 
536
 
 
537
/**
 
538
 * @return true if the action is within currentActions
 
539
 */
 
540
bool RS_EventHandler::isValid(RS_ActionInterface* action){
 
541
    return currentActions.indexOf(action) >= 0;
 
542
}
 
543
 
 
544
/**
 
545
 * @return true if there is at least one action in the action stack.
 
546
 */
 
547
bool RS_EventHandler::hasAction() {
 
548
 
 
549
    while(currentActions.size()>0 ) {
 
550
        if(! currentActions.last()->isFinished()){
 
551
            return true;
 
552
        }
 
553
        delete currentActions.last();
 
554
        currentActions.pop_back();
 
555
    }
 
556
    return false;
 
557
}
 
558
 
 
559
 
 
560
 
 
561
/**
 
562
 * Garbage collector for actions.
 
563
 */
 
564
void RS_EventHandler::cleanUp() {
 
565
    RS_DEBUG->print("RS_EventHandler::cleanUp");
 
566
 
 
567
    for (auto it=currentActions.begin();it != currentActions.end();){
 
568
 
 
569
        if( (*it)->isFinished()){
 
570
//            (*it)->finish();
 
571
            delete *it;
 
572
            it= currentActions.erase(it);
 
573
        }else{
 
574
            it++;
 
575
        }
 
576
    }
 
577
    if(hasAction()){
 
578
        currentActions.last()->resume();
 
579
        currentActions.last()->showOptions();
 
580
    } else {
 
581
        if (defaultAction!=NULL) {
 
582
            defaultAction->resume();
 
583
            defaultAction->showOptions();
 
584
        }
 
585
    }
 
586
    RS_DEBUG->print("RS_EventHandler::cleanUp: OK");
 
587
}
 
588
 
 
589
 
 
590
 
 
591
/**
 
592
 * Sets the snap mode for all currently active actions.
 
593
 */
 
594
void RS_EventHandler::setSnapMode(RS_SnapMode sm) {
 
595
    for (auto it=currentActions.begin();it != currentActions.end();it++){
 
596
        if(! (*it)->isFinished()){
 
597
            (*it)->setSnapMode(sm);
 
598
        }
 
599
    }
 
600
 
 
601
    if (defaultAction!=NULL) {
 
602
        defaultAction->setSnapMode(sm);
 
603
    }
 
604
}
 
605
 
 
606
 
 
607
/**
 
608
 * Sets the snap restriction for all currently active actions.
 
609
 */
 
610
void RS_EventHandler::setSnapRestriction(RS2::SnapRestriction sr) {
 
611
    for (auto it=currentActions.begin();it != currentActions.end();it++){
 
612
        if(! (*it)->isFinished()){
 
613
            (*it)->setSnapRestriction(sr);
 
614
        }
 
615
    }
 
616
 
 
617
    if (defaultAction!=NULL) {
 
618
        defaultAction->setSnapRestriction(sr);
 
619
    }
 
620
}
 
621
 
 
622
 
 
623
void RS_EventHandler::debugActions() {
 
624
    //        std::cout<<"action queue size=:"<<currentActions.size()<<std::endl;
 
625
    RS_DEBUG->print("---");
 
626
    for(int i=0;i<currentActions.size();i++){
 
627
 
 
628
        if (i == currentActions.size() - 1 ) {
 
629
            RS_DEBUG->print("Current");
 
630
        }
 
631
        RS_DEBUG->print("Action %03d: %s [%s]",
 
632
                        i, currentActions.at(i)->getName().toLatin1().data(),
 
633
                        currentActions.at(i)->isFinished() ? "finished" : "active");
 
634
    }
 
635
}
 
636
 
 
637
// EOF