]> Shamusworld >> Repos - architektonas/blob - src/base/rs_graphicview.cpp
29ab3f4c5632d184c85835a766a3123a1cdd5002
[architektonas] / src / base / rs_graphicview.cpp
1 // rs_graphicview.cpp
2 //
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
7 //
8 // JLH = James L. Hammons <jlhamm@acm.org>
9 //
10 // Who  When        What
11 // ---  ----------  -----------------------------------------------------------
12 // JLH  05/21/2010  Added this text. :-)
13 //
14
15 #include "rs_graphicview.h"
16
17 #include <stdio.h>
18 #include "rs_actioninterface.h"
19 #include "rs_application.h"
20 #include "rs_block.h"
21 #include "rs_eventhandler.h"
22 #include "rs_graphic.h"
23 #include "rs_grid.h"
24 #include "rs_insert.h"
25 #include "rs_layer.h"
26 #include "rs_line.h"
27 #include "rs_solid.h"
28 #include "rs_text.h"
29 #include "rs_units.h"
30 #include "paintintf.h"
31 #include "settings.h"
32
33 /**
34  * Constructor.
35  */
36 RS_GraphicView::RS_GraphicView(): background(), foreground(), previewMode(false),
37         previewOffset(Vector(0, 0)), snapperDraw(false)
38 {
39         drawingMode = RS2::ModeFull;
40         printing = false;
41         deleteMode = false;
42         factor = Vector(1.0, 1.0);
43         offsetX = 0;
44         offsetY = 0;
45         previousFactor = Vector(1.0, 1.0);
46         previousOffsetX = 0;
47         previousOffsetY = 0;
48         container = NULL;
49         eventHandler = new RS_EventHandler(this);
50         gridColor = Qt::gray;
51         metaGridColor = RS_Color(64, 64, 64);
52         grid = new RS_Grid(this);
53         updateEnabled = 0;
54         zoomFrozen = false;
55         //gridVisible = true;
56         draftMode = false;
57         painter = NULL;
58         //drawRecursion = 0;
59
60         borderLeft = 0;
61         borderTop = 0;
62         borderRight = 0;
63         borderBottom = 0;
64
65         relativeZero = Vector(false);
66         relativeZeroLocked = false;
67
68         mx = my = 0;
69
70         defaultSnapMode = RS2::SnapFree;
71         defaultSnapRes = RS2::RestrictNothing;
72
73         /*
74                 background = RS_Color(0,0,0);
75                 foreground = RS_Color(255,255,255);
76                 gridColor = RS_Color("gray");
77         metaGridColor = RS_Color("#404040");
78                 selectedColor = RS_Color("#a54747");
79                 highlightedColor = RS_Color("#739373");
80         */
81
82         settings.beginGroup("Appearance");
83         setBackground(QColor(settings.value("BackgroundColor", "#000000").toString()));
84         setGridColor(QColor(settings.value("GridColor", "#7F7F7F").toString()));
85         setMetaGridColor(QColor(settings.value("MetaGridColor", "#3F3F3F").toString()));
86         setSelectedColor(QColor(settings.value("SelectedColor", "#A54747").toString()));
87         setHighlightedColor(QColor(settings.value("HighlightedColor", "#739373").toString()));
88         settings.endGroup();
89
90         printPreview = false;
91
92         simulationSpeed = 100;
93         simulationSmooth = false;
94         simulationRapid = false;
95         simulationRunning = false;
96
97         //currentInsert = NULL;
98 }
99
100 /**
101  * Destructor.
102  */
103 RS_GraphicView::~RS_GraphicView()
104 {
105         //delete eventHandler;
106         if (painter != NULL)
107                 delete painter;
108
109         delete grid;
110 }
111
112 /**
113  * Must be called by any derrived class in the destructor.
114  */
115 void RS_GraphicView::cleanUp()
116 {
117         delete eventHandler;
118 }
119
120 /**
121  * @return Pointer to the graphic entity if the entity container
122  * connected to this view is a graphic and valid.
123  * NULL otherwise.
124  */
125 RS_Graphic * RS_GraphicView::getGraphic()
126 {
127         if (container != NULL && container->rtti() == RS2::EntityGraphic)
128                 return (RS_Graphic*)container;
129         else
130                 return NULL;
131 }
132
133 /**
134  * Sets the drawing mode.
135  */
136 void RS_GraphicView::setDrawingMode(RS2::DrawingMode m)
137 {
138         drawingMode = m;
139 }
140
141 /**
142  * @return Current drawing mode.
143  */
144 RS2::DrawingMode RS_GraphicView::getDrawingMode()
145 {
146         return drawingMode;
147 }
148
149 /**
150  * Activates or deactivates the delete mode.
151  */
152 void RS_GraphicView::setDeleteMode(bool m)
153 {
154         deleteMode = m;
155 }
156
157 /**
158  * @reval true Deleting instead of drawing.
159  *        false Normal drawing mode.
160  */
161 bool RS_GraphicView::getDeleteMode()
162 {
163         return deleteMode;
164 }
165
166 /** This virtual method must be overwritten and is then
167         called whenever the view changed */
168 void RS_GraphicView::adjustOffsetControls()
169 {
170 }
171
172 /** This virtual method must be overwritten and is then
173         called whenever the view changed */
174 void RS_GraphicView::adjustZoomControls()
175 {
176 }
177
178 /**
179  * Sets an external painter device.
180  */
181 //void RS_GraphicView::setPainter(RS_Painter * p)
182 void RS_GraphicView::setPainter(PaintInterface * p)
183 {
184         painter = p;
185 }
186
187 /**
188  * Sets the background color. Note that applying the background
189  * color for the widget is up to the implementing class.
190  */
191 void RS_GraphicView::setBackground(const RS_Color & bg)
192 {
193         background = bg;
194
195         // bright background:
196         if (bg.red() + bg.green() + bg.blue() > 380)
197 //              foreground = Qt::black;
198                 foreground = RS_Color(0, 0, 0);
199         else
200 //              foreground = Qt::white;
201                 foreground = RS_Color(255, 255, 255);
202 }
203
204 /**
205  * @return Current background color.
206  */
207 RS_Color RS_GraphicView::getBackground()
208 {
209         return background;
210 }
211
212 /**
213  * @return Current foreground color.
214  */
215 RS_Color RS_GraphicView::getForeground()
216 {
217         return foreground;
218 }
219
220 /**
221  * Sets the grid color.
222  */
223 void RS_GraphicView::setGridColor(const RS_Color & c)
224 {
225         gridColor = c;
226 }
227
228 /**
229  * Sets the meta grid color.
230  */
231 void RS_GraphicView::setMetaGridColor(const RS_Color & c)
232 {
233         metaGridColor = c;
234 }
235
236 /**
237  * Sets the selection color.
238  */
239 void RS_GraphicView::setSelectedColor(const RS_Color & c)
240 {
241         selectedColor = c;
242 }
243
244 /**
245  * Sets the highlight color.
246  */
247 void RS_GraphicView::setHighlightedColor(const RS_Color & c)
248 {
249         highlightedColor = c;
250 }
251
252 /**
253  * This virtual method can be overwritten to set the mouse
254  * cursor to the given type.
255  */
256 void RS_GraphicView::setMouseCursor(RS2::CursorType /*c*/)
257 {
258 }
259
260 RS_EntityContainer * RS_GraphicView::getContainer()
261 {
262         return container;
263 }
264
265 void RS_GraphicView::setFactor(double f)
266 {
267         setFactorX(f);
268         setFactorY(f);
269 }
270
271 Vector RS_GraphicView::getFactor()
272 {
273         return factor;
274 }
275
276 /**
277  * Sets the offset of the graphic.
278  */
279 void RS_GraphicView::setOffset(int ox, int oy)
280 {
281         setOffsetX(ox);
282         setOffsetY(oy);
283 }
284
285 void RS_GraphicView::setOffsetX(int ox)
286 {
287         offsetX = ox;
288 }
289
290 void RS_GraphicView::setOffsetY(int oy)
291 {
292         offsetY = oy;
293 }
294
295 int RS_GraphicView::getOffsetX()
296 {
297         return offsetX;
298 }
299
300 int RS_GraphicView::getOffsetY()
301 {
302         return offsetY;
303 }
304
305 /**
306  * Sets a fixed border in pixel around the graphic. This border
307  * specifies how far the user can scroll outside the graphic
308  * area.
309  */
310 void RS_GraphicView::setBorders(int left, int top, int right, int bottom)
311 {
312         borderLeft = left;
313         borderTop = top;
314         borderRight = right;
315         borderBottom = bottom;
316 }
317
318 int RS_GraphicView::getBorderLeft()
319 {
320         return borderLeft;
321 }
322
323 int RS_GraphicView::getBorderTop()
324 {
325         return borderTop;
326 }
327
328 int RS_GraphicView::getBorderRight()
329 {
330         return borderRight;
331 }
332
333 int RS_GraphicView::getBorderBottom()
334 {
335         return borderBottom;
336 }
337
338 void RS_GraphicView::disableUpdate()
339 {
340         updateEnabled--;
341 }
342
343 void RS_GraphicView::enableUpdate()
344 {
345         updateEnabled++;
346 }
347
348 bool RS_GraphicView::isUpdateEnabled()
349 {
350         return (updateEnabled == 0);
351 }
352
353 void RS_GraphicView::freezeZoom(bool freeze)
354 {
355         zoomFrozen = freeze;
356 }
357
358 bool RS_GraphicView::isZoomFrozen()
359 {
360         return zoomFrozen;
361 }
362
363 /**
364  * Sets the pointer to the graphic which contains the entities
365  * which are visualized by this widget.
366  */
367 void RS_GraphicView::setContainer(RS_EntityContainer * container)
368 {
369         this->container = container;
370         //adjustOffsetControls();
371 }
372
373 /**
374  * Sets the zoom factor in X for this visualization of the graphic.
375  */
376 void RS_GraphicView::setFactorX(double f)
377 {
378         if (!zoomFrozen)
379                 factor.x = fabs(f);
380 }
381
382 /**
383  * Sets the zoom factor in Y for this visualization of the graphic.
384  */
385 void RS_GraphicView::setFactorY(double f)
386 {
387         if (!zoomFrozen)
388                 factor.y = fabs(f);
389 }
390
391 /**
392  * @return true if the grid is switched on.
393  */
394 bool RS_GraphicView::isGridOn()
395 {
396         if (container != NULL)
397         {
398                 RS_Graphic * g = container->getGraphic();
399
400                 if (g != NULL)
401                         return g->isGridOn();
402         }
403
404         return true;
405 }
406
407 /**
408  * Centers the drawing in x-direction.
409  */
410 void RS_GraphicView::centerOffsetX()
411 {
412         if (container != NULL && !zoomFrozen)
413                 offsetX = (int)(((getWidth() - borderLeft - borderRight)
414                         - (container->getSize().x * factor.x)) / 2.0
415                         - (container->getMin().x * factor.x)) + borderLeft;
416 }
417
418 /**
419  * Centers the drawing in y-direction.
420  */
421 void RS_GraphicView::centerOffsetY()
422 {
423         if (container != NULL && !zoomFrozen)
424                 offsetY = (int)((getHeight() - borderTop - borderBottom
425                         - (container->getSize().y * factor.y)) / 2.0
426                         - (container->getMin().y * factor.y)) + borderBottom;
427 }
428
429 /**
430  * Centers the given coordinate in the view in x-direction.
431  */
432 void RS_GraphicView::centerX(double v)
433 {
434         if (!zoomFrozen)
435                 offsetX = (int)((v * factor.x) - (double)(getWidth() - borderLeft - borderRight) / 2.0);
436 }
437
438 /**
439  * Centers the given coordinate in the view in y-direction.
440  */
441 void RS_GraphicView::centerY(double v)
442 {
443     if (!zoomFrozen)
444         offsetY = (int)((v * factor.y) - (double)(getHeight() - borderTop - borderBottom) / 2.0);
445 }
446
447 void RS_GraphicView::updateView()
448 {
449         static int running = 0;
450         running++;
451
452         if (running < 100)
453         {
454                 adjustZoomControls();
455                 adjustOffsetControls();
456         }
457
458         running--;
459
460         if (running == 0)
461                 redraw();
462 }
463
464 /**
465  * @return Current action or NULL.
466  */
467 RS_ActionInterface * RS_GraphicView::getDefaultAction()
468 {
469         if (eventHandler != NULL)
470                 return eventHandler->getDefaultAction();
471         else
472                 return NULL;
473 }
474
475 /**
476  * Sets the default action of the event handler.
477  */
478 void RS_GraphicView::setDefaultAction(RS_ActionInterface * action)
479 {
480     if (eventHandler != NULL)
481         eventHandler->setDefaultAction(action);
482 }
483
484 /**
485  * @return Current action or NULL.
486  */
487 RS_ActionInterface * RS_GraphicView::getCurrentAction()
488 {
489         if (eventHandler != NULL)
490                 return eventHandler->getCurrentAction();
491         else
492                 return NULL;
493 }
494
495 /**
496  * Sets the current action of the event handler.
497  */
498 void RS_GraphicView::setCurrentAction(RS_ActionInterface * action)
499 {
500         RS_DEBUG->print("RS_GraphicView::setCurrentAction");
501
502         if (eventHandler != NULL)
503                 eventHandler->setCurrentAction(action);
504
505         RS_DEBUG->print("RS_GraphicView::setCurrentAction: OK");
506 }
507
508 /**
509  * Kills all running selection actions. Called when a selection action
510  * is launched to reduce confusion.
511  */
512 void RS_GraphicView::killSelectActions()
513 {
514         if (eventHandler != NULL)
515                 eventHandler->killSelectActions();
516 }
517
518 /**
519  * Kills all running actions.
520  */
521 void RS_GraphicView::killAllActions()
522 {
523         if (eventHandler != NULL)
524                 eventHandler->killAllActions();
525 }
526
527 /**
528  * Go back in menu or current action.
529  */
530 void RS_GraphicView::back()
531 {
532         if (eventHandler != NULL && eventHandler->hasAction())
533                 eventHandler->back();
534         else
535                 if (RS_DIALOGFACTORY != NULL)
536                         RS_DIALOGFACTORY->requestPreviousMenu();
537 }
538
539 /**
540  * Go forward with the current action.
541  */
542 void RS_GraphicView::enter()
543 {
544         if (eventHandler != NULL && eventHandler->hasAction())
545                 eventHandler->enter();
546 }
547
548 /**
549  * Called by the actual GUI class which implements the RS_GraphicView
550  * interface to notify qcadlib about mouse events.
551  */
552 void RS_GraphicView::mousePressEvent(QMouseEvent * e)
553 {
554         if (eventHandler != NULL)
555                 eventHandler->mousePressEvent(e);
556 }
557
558 /**
559  * Called by the actual GUI class which implements the RS_GraphicView
560  * interface to notify qcadlib about mouse events.
561  */
562 void RS_GraphicView::mouseReleaseEvent(QMouseEvent * e)
563 {
564         RS_DEBUG->print("RS_GraphicView::mouseReleaseEvent");
565
566         if (eventHandler != NULL)
567         {
568                 if (RS2::qtToRsButtonState(e->button()) != RS2::RightButton
569                         || eventHandler->hasAction())
570                 {
571                         eventHandler->mouseReleaseEvent(e);
572                         //e->accept();
573                 }
574                 else
575                 {
576                         back();
577 //#if QT_VERSION>=0x030000
578                         e->accept();
579 //#endif
580
581                 }
582         }
583
584         RS_DEBUG->print("RS_GraphicView::mouseReleaseEvent: OK");
585 }
586
587 /**
588  * Called by the actual GUI class which implements the RS_GraphicView
589  * interface to notify qcadlib about mouse events.
590  */
591 void RS_GraphicView::mouseMoveEvent(QMouseEvent * e)
592 {
593         RS_DEBUG->print("RS_GraphicView::mouseMoveEvent begin");
594
595         RS_Graphic * graphic = NULL;
596
597         if (container->rtti() == RS2::EntityGraphic)
598                 graphic = (RS_Graphic *)container;
599
600         RS_DEBUG->print("RS_GraphicView::mouseMoveEvent 001");
601
602         if (e != NULL)
603         {
604                 mx = e->x();
605                 my = e->y();
606         }
607
608         RS_DEBUG->print("RS_GraphicView::mouseMoveEvent 002");
609
610         if (eventHandler != NULL)
611                 eventHandler->mouseMoveEvent(e);
612
613         RS_DEBUG->print("RS_GraphicView::mouseMoveEvent 003");
614
615         if (eventHandler == NULL || !eventHandler->hasAction() && graphic != NULL)
616         {
617                 Vector mouse = toGraph(Vector(mx, my));
618                 Vector relMouse = mouse - getRelativeZero();
619
620                 if (RS_DIALOGFACTORY != NULL)
621                         RS_DIALOGFACTORY->updateCoordinateWidget(mouse, relMouse);
622         }
623
624         RS_DEBUG->print("RS_GraphicView::mouseMoveEvent end");
625 }
626
627 /**
628  * Called by the actual GUI class which implements the RS_GraphicView
629  * interface to notify qcadlib about mouse events.
630  */
631 void RS_GraphicView::mouseLeaveEvent()
632 {
633         if (eventHandler != NULL)
634                 eventHandler->mouseLeaveEvent();
635 }
636
637 /**
638  * Called by the actual GUI class which implements the RS_GraphicView
639  * interface to notify qcadlib about mouse events.
640  */
641 void RS_GraphicView::mouseEnterEvent()
642 {
643         if (eventHandler != NULL)
644                 eventHandler->mouseEnterEvent();
645 }
646
647 /**
648  * Called by the actual GUI class which implements the RS_GraphicView
649  * interface to notify qcadlib about key events.
650  */
651 void RS_GraphicView::keyPressEvent(QKeyEvent * e)
652 {
653         if (eventHandler != NULL)
654                 eventHandler->keyPressEvent(e);
655 }
656
657 /**
658  * Called by the actual GUI class which implements the RS_GraphicView
659  * interface to notify qcadlib about key events.
660  */
661 void RS_GraphicView::keyReleaseEvent(QKeyEvent * e)
662 {
663         if (eventHandler != NULL)
664                 eventHandler->keyReleaseEvent(e);
665 }
666
667 /**
668  * Called by the actual GUI class which implements a command line.
669  */
670 void RS_GraphicView::commandEvent(RS_CommandEvent * e)
671 {
672         if (eventHandler != NULL)
673                 eventHandler->commandEvent(e);
674 }
675
676 /**
677  * Enables coordinate input in the command line.
678  */
679 void RS_GraphicView::enableCoordinateInput()
680 {
681         if (eventHandler != NULL)
682                 eventHandler->enableCoordinateInput();
683 }
684
685 /**
686  * Disables coordinate input in the command line.
687  */
688 void RS_GraphicView::disableCoordinateInput()
689 {
690         if (eventHandler != NULL)
691                 eventHandler->disableCoordinateInput();
692 }
693
694 /**
695  * zooms in by factor f
696  */
697 void RS_GraphicView::zoomIn(double f, const Vector & center)
698 {
699         if (f < 1.0e-6)
700         {
701                 RS_DEBUG->print(RS_Debug::D_WARNING, "RS_GraphicView::zoomIn: invalid factor");
702                 return;
703         }
704
705         if (simulationRunning)
706                 return;
707
708         Vector c = center;
709         if (c.valid == false)
710                 c = toGraph(Vector(getWidth() / 2, getHeight() / 2));
711
712         zoomWindow(
713                 toGraph(Vector(0, 0)).scale(c, Vector(1.0 / f, 1.0 / f)),
714                 toGraph(Vector(getWidth(), getHeight())).scale(c, Vector(1.0 / f, 1.0 / f)));
715
716         //adjustOffsetControls();
717         //adjustZoomControls();
718         //updateGrid();
719         //redraw();
720 }
721
722 /**
723  * zooms in by factor f in x
724  */
725 void RS_GraphicView::zoomInX(double f)
726 {
727         if (simulationRunning)
728                 return;
729
730         factor.x *= f;
731         offsetX = (int)((offsetX - getWidth() / 2) * f) + getWidth() / 2;
732         adjustOffsetControls();
733         adjustZoomControls();
734         updateGrid();
735         redraw();
736 }
737
738 /**
739  * zooms in by factor f in y
740  */
741 void RS_GraphicView::zoomInY(double f)
742 {
743         if (simulationRunning)
744                 return;
745
746         factor.y *= f;
747         offsetY = (int)((offsetY - getHeight() / 2) * f)+getHeight() / 2;
748         adjustOffsetControls();
749         adjustZoomControls();
750         updateGrid();
751         redraw();
752 }
753
754 /**
755  * zooms out by factor f
756  */
757 void RS_GraphicView::zoomOut(double f, const Vector & center)
758 {
759         if (f < 1.0e-6)
760         {
761                 RS_DEBUG->print(RS_Debug::D_WARNING,
762                         "RS_GraphicView::zoomOut: invalid factor");
763                 return;
764         }
765
766         if (simulationRunning)
767                 return;
768
769         zoomIn(1/f, center);
770 }
771
772 /**
773  * zooms out by factor f in x
774  */
775 void RS_GraphicView::zoomOutX(double f)
776 {
777         if (f < 1.0e-6)
778         {
779                 RS_DEBUG->print(RS_Debug::D_WARNING,
780                         "RS_GraphicView::zoomOutX: invalid factor");
781                 return;
782         }
783
784         if (simulationRunning)
785                 return;
786
787         factor.x /= f;
788         offsetX = (int)(offsetX / f);
789         adjustOffsetControls();
790         adjustZoomControls();
791         updateGrid();
792         redraw();
793 }
794
795 /**
796  * zooms out by factor f y
797  */
798 void RS_GraphicView::zoomOutY(double f)
799 {
800         if (f < 1.0e-6)
801         {
802                 RS_DEBUG->print(RS_Debug::D_WARNING,
803                         "RS_GraphicView::zoomOutY: invalid factor");
804                 return;
805         }
806
807         if (simulationRunning)
808                 return;
809
810         factor.y /= f;
811         offsetY = (int)(offsetY / f);
812         adjustOffsetControls();
813         adjustZoomControls();
814         updateGrid();
815         redraw();
816 }
817
818 /**
819  * performs autozoom
820  *
821  * @param axis include axis in zoom
822  * @param keepAspectRatio true: keep aspect ratio 1:1
823  *                        false: factors in x and y are stretched to the max
824  */
825 void RS_GraphicView::zoomAuto(bool axis, bool keepAspectRatio)
826 {
827         RS_DEBUG->print("RS_GraphicView::zoomAuto");
828
829         if (simulationRunning)
830                 return;
831
832         saveView();
833
834         if (container != NULL)
835         {
836                 container->calculateBorders();
837
838                 double sx, sy;
839                 if (axis)
840                 {
841                         sx = std::max(container->getMax().x, 0.0) - std::min(container->getMin().x, 0.0);
842                         sy = std::max(container->getMax().y, 0.0) - std::min(container->getMin().y, 0.0);
843                 }
844                 else
845                 {
846                         sx = container->getSize().x;
847                         sy = container->getSize().y;
848                 }
849
850                 double fx, fy;
851
852                 if (sx > RS_TOLERANCE)
853                         fx = (getWidth() - borderLeft - borderRight) / sx;
854                 else
855                         fx = 1.0;
856
857                 if (sy > RS_TOLERANCE)
858                         fy = (getHeight() - borderTop - borderBottom) / sy;
859                 else
860                         fy = 1.0;
861
862                 RS_DEBUG->print("f: %f/%f", fx, fy);
863
864                 if (keepAspectRatio)
865                         fx = fy = std::min(fx, fy);
866
867                 RS_DEBUG->print("f: %f/%f", fx, fy);
868
869                 if (fx < RS_TOLERANCE)
870                         fx = fy = 1.0;
871
872                 setFactorX(fx);
873                 setFactorY(fy);
874
875                 RS_DEBUG->print("f: %f/%f", fx, fy);
876
877                 RS_DEBUG->print("adjustOffsetControls");
878                 adjustOffsetControls();
879                 RS_DEBUG->print("adjustZoomControls");
880                 adjustZoomControls();
881                 RS_DEBUG->print("centerOffsetX");
882                 centerOffsetX();
883                 RS_DEBUG->print("centerOffsetY");
884                 centerOffsetY();
885                 RS_DEBUG->print("updateGrid");
886                 updateGrid();
887                 redraw();
888         }
889
890         RS_DEBUG->print("RS_GraphicView::zoomAuto OK");
891 }
892
893 /**
894  * Shows previous view.
895  */
896 void RS_GraphicView::zoomPrevious()
897 {
898         RS_DEBUG->print("RS_GraphicView::zoomPrevious");
899
900         if (simulationRunning)
901                 return;
902
903         if (container != NULL)
904                 restoreView();
905 }
906
907 /**
908  * Saves the current view as previous view to which we can
909  * switch back later with @see restoreView().
910  */
911 void RS_GraphicView::saveView()
912 {
913         previousOffsetX = offsetX;
914         previousOffsetY = offsetY;
915         previousFactor = factor;
916 }
917
918 /**
919  * Restores the view previously saved with
920  * @see saveView().
921  */
922 void RS_GraphicView::restoreView()
923 {
924         int pox = previousOffsetX;
925         int poy = previousOffsetY;
926         Vector pf = previousFactor;
927
928         saveView();
929
930         offsetX = pox;
931         offsetY = poy;
932         factor = pf;
933
934         adjustOffsetControls();
935         adjustZoomControls();
936         updateGrid();
937         redraw();
938 }
939
940 /**
941  * performs autozoom in y only
942  *
943  * @param axis include axis in zoom
944  */
945 void RS_GraphicView::zoomAutoY(bool axis)
946 {
947         if (simulationRunning)
948                 return;
949
950         if (container != NULL)
951         {
952                 double visibleHeight = 0.0;
953                 double minY = RS_MAXDOUBLE;
954                 double maxY = RS_MINDOUBLE;
955                 bool noChange = false;
956
957                 for(RS_Entity * e=container->firstEntity(RS2::ResolveNone);
958                         e!=NULL; e = container->nextEntity(RS2::ResolveNone))
959                 {
960                         if (e->rtti() == RS2::EntityLine)
961                         {
962                                 RS_Line * l = (RS_Line *)e;
963                                 double x1, x2;
964                                 x1 = toGuiX(l->getStartpoint().x);
965                                 x2 = toGuiX(l->getEndpoint().x);
966
967                                 if (x1 > 0.0 && x1 < (double)getWidth() || x2 > 0.0 && x2 < (double)getWidth())
968                                 {
969                                         minY = std::min(minY, l->getStartpoint().y);
970                                         minY = std::min(minY, l->getEndpoint().y);
971                                         maxY = std::max(maxY, l->getStartpoint().y);
972                                         maxY = std::max(maxY, l->getEndpoint().y);
973                                 }
974                         }
975                 }
976
977                 if (axis)
978                         visibleHeight = std::max(maxY, 0.0) - std::min(minY, 0.0);
979                 else
980                         visibleHeight = maxY - minY;
981
982                 if (visibleHeight < 1.0)
983                         noChange = true;
984
985                 double fy = 1.0;
986
987                 if (visibleHeight > 1.0e-6)
988                 {
989                         fy = (getHeight() - borderTop - borderBottom) / visibleHeight;
990
991                         if (factor.y < 0.000001)
992                                 noChange = true;
993                 }
994
995                 if (noChange == false)
996                 {
997                         setFactorY(fy);
998                         //centerOffsetY();
999                         offsetY = (int)((getHeight() - borderTop - borderBottom - (visibleHeight * factor.y)) / 2.0
1000                                 - (minY * factor.y)) + borderBottom;
1001                         adjustOffsetControls();
1002                         adjustZoomControls();
1003                         updateGrid();
1004                 }
1005
1006                 RS_DEBUG->print("Auto zoom y ok");
1007         }
1008 }
1009
1010 /**
1011  * Zooms the area given by v1 and v2.
1012  *
1013  * @param keepAspectRatio true: keeps the aspect ratio 1:1
1014  *                        false: zooms exactly the selected range to the
1015  *                               current graphic view
1016  */
1017 void RS_GraphicView::zoomWindow(Vector v1, Vector v2, bool keepAspectRatio)
1018 {
1019         if (simulationRunning)
1020                 return;
1021
1022         saveView();
1023
1024         double zoomX = 480.0;    // Zoom for X-Axis
1025         double zoomY = 640.0;    // Zoom for Y-Axis   (Set smaller one)
1026         double dum;            // Dummy for switching values
1027         int zoomBorder = 0;
1028
1029         // Switch left/right and top/bottom is necessary:
1030         if (v1.x > v2.x)
1031         {
1032                 dum = v1.x;
1033                 v1.x = v2.x;
1034                 v2.x = dum;
1035         }
1036
1037         if (v1.y > v2.y)
1038         {
1039                 dum = v1.y;
1040                 v1.y = v2.y;
1041                 v2.y = dum;
1042         }
1043
1044         // Get zoom in X and zoom in Y:
1045         if (v2.x - v1.x > 1.0e-6)
1046                 zoomX = getWidth() / (v2.x - v1.x);
1047
1048         if (v2.y - v1.y > 1.0e-6)
1049                 zoomY = getHeight() / (v2.y - v1.y);
1050
1051         // Take smaller zoom:
1052         if (keepAspectRatio)
1053         {
1054                 if (zoomX < zoomY)
1055                 {
1056                         if (getWidth() != 0)
1057                         {
1058                                 zoomX = zoomY = ((double)(getWidth() - 2 * zoomBorder)) /
1059                                                                 (double)getWidth() * zoomX;
1060                         }
1061                 }
1062                 else
1063                 {
1064                         if (getHeight() != 0)
1065                         {
1066                                 zoomX = zoomY = ((double)(getHeight() - 2 * zoomBorder)) /
1067                                                                 (double)getHeight() * zoomY;
1068                         }
1069                 }
1070         }
1071
1072         if (zoomX < 0.0)
1073                 zoomX *= -1;
1074
1075         if (zoomY < 0.0)
1076                 zoomY *= -1;
1077
1078         // Borders in pixel after zoom
1079         int pixLeft   = (int)(v1.x * zoomX);
1080         int pixTop    = (int)(v2.y * zoomY);
1081         int pixRight  = (int)(v2.x * zoomX);
1082         int pixBottom = (int)(v1.y * zoomY);
1083
1084         // Set new offset for zero point:
1085         offsetX = - pixLeft + (getWidth() - pixRight + pixLeft) / 2;
1086         offsetY = - pixTop + (getHeight() - pixBottom + pixTop) / 2;
1087         factor.x = zoomX;
1088         factor.y = zoomY;
1089
1090         adjustOffsetControls();
1091         adjustZoomControls();
1092         updateGrid();
1093         redraw();
1094 }
1095
1096 /**
1097  * Centers the point v1.
1098  */
1099 void RS_GraphicView::zoomPan(int dx, int dy)
1100 {
1101         //offsetX+=(int)toGuiDX(v1.x);
1102         //offsetY+=(int)toGuiDY(v1.y);
1103         if (simulationRunning)
1104                 return;
1105
1106         offsetX += dx;
1107         offsetY -= dy;
1108
1109         disableUpdate();
1110         adjustOffsetControls();
1111         //adjustZoomControls();
1112         updateGrid();
1113         enableUpdate();
1114         redraw();
1115 }
1116
1117 /**
1118  * Scrolls in the given direction.
1119  */
1120 void RS_GraphicView::zoomScroll(RS2::Direction direction)
1121 {
1122         if (simulationRunning)
1123                 return;
1124
1125         switch (direction)
1126         {
1127         case RS2::Up:
1128                 offsetY -= 50;
1129                 break;
1130         case RS2::Down:
1131                 offsetY += 50;
1132                 break;
1133         case RS2::Right:
1134                 offsetX += 50;
1135                 break;
1136         case RS2::Left:
1137                 offsetX -= 50;
1138                 break;
1139         }
1140
1141         adjustOffsetControls();
1142         adjustZoomControls();
1143         updateGrid();
1144         redraw();
1145 }
1146
1147 /**
1148  * Zooms to page extends.
1149  */
1150 void RS_GraphicView::zoomPage()
1151 {
1152         RS_DEBUG->print("RS_GraphicView::zoomPage");
1153
1154         if (container == NULL)
1155                 return;
1156
1157         if (simulationRunning)
1158                 return;
1159
1160         RS_Graphic * graphic = container->getGraphic();
1161
1162         if (graphic == NULL)
1163                 return;
1164
1165         Vector s = graphic->getPaperSize();
1166         Vector pinsbase = graphic->getPaperInsertionBase();
1167
1168         double fx, fy;
1169
1170         if (s.x > RS_TOLERANCE)
1171                 fx = (getWidth() - borderLeft - borderRight) / s.x;
1172         else
1173                 fx = 1.0;
1174
1175         if (s.y > RS_TOLERANCE)
1176                 fy = (getHeight() - borderTop - borderBottom) / s.y;
1177         else
1178                 fy = 1.0;
1179
1180         RS_DEBUG->print("f: %f/%f", fx, fy);
1181
1182         fx = fy = std::min(fx, fy);
1183
1184         RS_DEBUG->print("f: %f/%f", fx, fy);
1185
1186         if (fx < RS_TOLERANCE)
1187                 fx = fy = 1.0;
1188
1189         setFactorX(fx);
1190         setFactorY(fy);
1191
1192         RS_DEBUG->print("f: %f/%f", fx, fy);
1193
1194         centerOffsetX();
1195         centerOffsetY();
1196         adjustOffsetControls();
1197         adjustZoomControls();
1198         updateGrid();
1199         redraw();
1200 }
1201
1202 /**
1203  * Draws the entities within the given range.
1204  */
1205 void RS_GraphicView::drawWindow(Vector v1, Vector v2)
1206 {
1207         RS_DEBUG->print("RS_GraphicView::drawWindow() begin");
1208
1209         if (simulationRunning)
1210                 return;
1211
1212         if (container != NULL)
1213         {
1214                 for (RS_Entity * se=container->firstEntity(RS2::ResolveNone);
1215                         se!=NULL; se = container->nextEntity(RS2::ResolveNone))
1216                 {
1217                         if (se->isInWindow(v1, v2))
1218                                 drawEntity(se);
1219                 }
1220         }
1221
1222         RS_DEBUG->print("RS_GraphicView::drawWindow() end");
1223 }
1224
1225 /**
1226  * Draws the entities. If painter is NULL a new painter will
1227  * be created and destroyed.
1228  */
1229 void RS_GraphicView::drawIt()
1230 {
1231         if (!isUpdateEnabled())
1232 //{
1233 //printf("RS_GraphicView::drawIt(): isUpdateEnabled() == false!\n");
1234                 return;
1235 //}
1236
1237         if (simulationRunning)
1238 //{
1239 //printf("RS_GraphicView::drawIt(): simulationRunning == true!\n");
1240                 return;
1241 //}
1242
1243 //      bool painterCreated = false;
1244
1245         settings.beginGroup("Appearance");
1246         draftMode = settings.value("DraftMode", false).toBool();
1247         settings.endGroup();
1248
1249         //RS_DEBUG->print("RS_GraphicView::drawIt() begin");
1250         //RS_DEBUG->print("  factors: %f/%f", factor.x, factor.y);
1251         //RS_DEBUG->timestamp();
1252
1253         if (painter == NULL)
1254         {
1255 printf("RS_GraphicView::drawIt(): painter == NULL!\n");
1256                 return;
1257 //              createPainter();
1258 //              painterCreated = true;
1259         }
1260         else
1261                 painter->erase();
1262
1263         // drawing paper border:
1264         if (isPrintPreview())
1265                 drawPaper();
1266         // drawing meta grid:
1267         else
1268                 drawMetaGrid();
1269
1270         //if (draftMode) {
1271         //    painter->setPen(RS_Pen(foreground, RS2::Width00, RS2::SolidLine));
1272         //}
1273
1274         // drawing entities:
1275 //#warning "!!! This looks like a bug, no match for 'drawEntity(RS_Entity *, bool) !!!"
1276 // and indeed it *is* a bug... true is converted to 1.0 here. Dumb, dumb, dumb.
1277         drawEntity(container, true);
1278
1279         //RS_DEBUG->timestamp();
1280         //RS_DEBUG->print(" draw zero..");
1281
1282         // drawing zero points:
1283         if (!isPrintPreview())
1284         {
1285                 drawAbsoluteZero();
1286                 drawRelativeZero();
1287         }
1288
1289         //RS_DEBUG->timestamp();
1290         //RS_DEBUG->print(" draw grid..");
1291
1292         // drawing grid:
1293         if (!isPrintPreview())
1294                 drawGrid();
1295
1296         //RS_DEBUG->timestamp();
1297         //RS_DEBUG->print("RS_GraphicView::drawIt() end");
1298 //      if (painterCreated == true)
1299 //              destroyPainter();
1300 }
1301
1302 /**
1303  * Sets the pen of the painter object to the suitable pen for the given
1304  * entity.
1305  */
1306 void RS_GraphicView::setPenForEntity(RS_Entity * e)
1307 {
1308         if (drawingMode == RS2::ModePreview /*|| draftMode==true*/)
1309                 return;
1310
1311         // set color of entity
1312         if (painter != NULL && !painter->isPreviewMode())
1313         {
1314                 // Getting pen from entity (or layer)
1315                 RS_Pen pen = e->getPen(true);
1316
1317                 int w = pen.getWidth();
1318
1319                 if (w < 0)
1320                         w = 0;
1321
1322                 // scale pen width:
1323                 if (!draftMode)
1324                 {
1325                         double uf = 1.0;  // unit factor
1326                         double wf = 1.0;  // width factor
1327                         RS_Graphic * graphic = container->getGraphic();
1328
1329                         if (graphic != NULL)
1330                         {
1331                                 uf = RS_Units::convert(1.0, RS2::Millimeter, graphic->getUnit());
1332
1333                                 if ((isPrinting() || isPrintPreview()) && graphic->getPaperScale() > 1.0e-6)
1334                                         wf = 1.0 / graphic->getPaperScale();
1335                         }
1336
1337                         pen.setScreenWidth(toGuiDX(w / 100.0 * uf * wf));
1338                 }
1339                 else
1340                 {
1341                         //pen.setWidth(RS2::Width00);
1342                         pen.setScreenWidth(0);
1343                 }
1344
1345                 // prevent drawing with 1-width which is slow:
1346                 if (RS_Math::round(pen.getScreenWidth()) == 1)
1347                         pen.setScreenWidth(0.0);
1348
1349                 // prevent background color on background drawing:
1350                 if (pen.getColor().stripFlags() == background.stripFlags())
1351                         pen.setColor(foreground);
1352
1353                 // this entity is selected:
1354                 if (e->isSelected())
1355                 {
1356                         pen.setLineType(RS2::DotLine);
1357                         //pen.setColor(RS_Color(0xa5,0x47,0x47));
1358                         pen.setColor(selectedColor);
1359                 }
1360
1361                 // this entity is highlighted:
1362                 if (e->isHighlighted())
1363                 {
1364                         //pen.setColor(RS_Color(0x73, 0x93, 0x73));
1365                         pen.setColor(highlightedColor);
1366                 }
1367
1368                 // deleting not drawing:
1369                 if (getDeleteMode())
1370                         pen.setColor(background);
1371
1372                 painter->setPen(pen);
1373         }
1374 }
1375
1376 /**
1377  * Draws an entity. Might be recusively called e.g. for polylines.
1378  * If the class wide painter is NULL a new painter will be created
1379  * and destroyed afterwards.
1380  *
1381  * @param patternOffset Offset of line pattern (used for connected
1382  *        lines e.g. in splines).
1383  * @param db Double buffering on (recommended) / off
1384  */
1385 void RS_GraphicView::drawEntity(RS_Entity * e, double patternOffset, bool db)
1386 {
1387         //RS_DEBUG->print("RS_GraphicView::drawEntity() begin");
1388
1389         // update is diabled:
1390         if (!isUpdateEnabled())
1391                 return;
1392
1393         // given entity is NULL:
1394         if (e == NULL)
1395                 return;
1396
1397         // entity is not visible:
1398         if (!e->isVisible())
1399                 return;
1400
1401         // test if the entity is in the viewport
1402         if (!e->isContainer() && !isPrinting()
1403                 && (painter == NULL || !painter->isPreviewMode())
1404                 && (toGuiX(e->getMax().x) < 0 || toGuiX(e->getMin().x) > getWidth()
1405                 || toGuiY(e->getMin().y) < 0 || toGuiY(e->getMax().y) > getHeight()))
1406 //{
1407 //printf("RS_GraphicView::drawEntity(): Bailing out of big test!!!\n");
1408                 return;
1409 //}
1410
1411         //drawRecursion++;
1412         //RS_DEBUG->print("recursion 1: %d", drawRecursion);
1413
1414         // set pen (color):
1415         setPenForEntity(e);
1416
1417         //RS_DEBUG->print("draw plain");
1418         if (draftMode)
1419         {
1420                 // large texts as rectangles:
1421                 if (e->rtti() == RS2::EntityText)
1422                 {
1423                         if (toGuiDX(((RS_Text *)e)->getHeight()) < 4 || e->countDeep() > 100)
1424                                 painter->drawRect(toGui(e->getMin()), toGui(e->getMax()));
1425                         else
1426                                 drawEntityPlain(e, patternOffset);
1427                 }
1428                 // all images as rectangles:
1429                 else if (e->rtti() == RS2::EntityImage)
1430                         painter->drawRect(toGui(e->getMin()), toGui(e->getMax()));
1431                 // hide hatches:
1432                 else if (e->rtti() == RS2::EntityHatch)
1433                 {
1434                         // nothing
1435                 }
1436                 else
1437                         drawEntityPlain(e, patternOffset);
1438         }
1439         else
1440                 drawEntityPlain(e, patternOffset);
1441
1442         // draw reference points:
1443         if (e->isSelected())
1444         {
1445                 if (!e->isParentSelected())
1446                 {
1447                         VectorSolutions s = e->getRefPoints();
1448
1449                         for(int i=0; i<s.getNumber(); ++i)
1450                         {
1451                                 int sz = -1;
1452                                 RS_Color col = RS_Color(0, 0, 255);
1453
1454                                 if (e->rtti() == RS2::EntityPolyline)
1455                                 {
1456                                         if (i == 0 || i == s.getNumber() - 1)
1457                                         {
1458                                                 if (i == 0)
1459                                                 {
1460                                                         sz = 4;
1461 //                                                      col = QColor(0, 64, 255);
1462                                                         col = RS_Color(0, 64, 255);
1463                                                 }
1464                                                 else
1465                                                 {
1466                                                         sz = 3;
1467 //                                                      col = QColor(0, 0, 128);
1468                                                         col = RS_Color(0, 0, 128);
1469                                                 }
1470                                         }
1471                                 }
1472
1473                                 if (getDeleteMode())
1474                                         painter->drawHandle(toGui(s.get(i)), background, sz);
1475                                 else
1476                                         painter->drawHandle(toGui(s.get(i)), col, sz);
1477                         }
1478                 }
1479         }
1480
1481         //RS_DEBUG->print("draw plain OK");
1482         //RS_DEBUG->print("RS_GraphicView::drawEntity() end");
1483 }
1484
1485 /**
1486  * Deletes an entity with the background color.
1487  * Might be recusively called e.g. for polylines.
1488  */
1489 void RS_GraphicView::deleteEntity(RS_Entity * e)
1490 {
1491         setDeleteMode(true);
1492         drawEntity(e);
1493         setDeleteMode(false);
1494 }
1495
1496 /**
1497  * Draws an entity.
1498  * The painter must be initialized and all the attributes (pen) must be set.
1499  */
1500 void RS_GraphicView::drawEntityPlain(RS_Entity * e, double patternOffset)
1501 {
1502         if (e == NULL)
1503 //{
1504 //printf("RS_GraphicView::drawEntityPlain(): Entity passed in is NULL!\n");
1505                 return;
1506 //}
1507
1508 //printf("RS_GraphicView::drawEntityPlain(): Passing in painter=%08X, view=%08X\n", painter, this);
1509         e->draw(painter, this, patternOffset);
1510 }
1511
1512 /**
1513  * Simulates this drawing in slow motion.
1514  */
1515 void RS_GraphicView::simulateIt()
1516 {
1517         if (simulationRunning)
1518                 return;
1519
1520         simulationRunning = true;
1521         simulationLast = Vector(0.0, 0.0);
1522
1523         destroyPainter();
1524
1525         createDirectPainter();
1526         painter->erase();
1527
1528         // drawing paper border:
1529         if (isPrintPreview())
1530                 drawPaper();
1531
1532         // drawing meta grid:
1533         if (!isPrintPreview())
1534                 drawMetaGrid();
1535
1536         // drawing grid:
1537         if (!isPrintPreview())
1538                 drawGrid();
1539
1540         //if (draftMode) {
1541         //painter->setPen(RS_Pen(foreground,
1542         //      RS2::Width00, RS2::SolidLine));
1543         //}
1544
1545         // drawing entities:
1546         RS_Pen pen(foreground, RS2::Width00, RS2::SolidLine);
1547         simulateEntity(container, pen);
1548
1549         //RS_DEBUG->timestamp();
1550         //RS_DEBUG->print(" draw zero..");
1551
1552         // drawing zero points:
1553         if (!isPrintPreview())
1554         {
1555                 drawAbsoluteZero();
1556                 drawRelativeZero();
1557         }
1558
1559         //RS_DEBUG->timestamp();
1560         //RS_DEBUG->print(" draw grid..");
1561
1562         //RS_DEBUG->timestamp();
1563         //RS_DEBUG->print("RS_GraphicView::drawIt() end");
1564         //if (painterCreated==true) {
1565         destroyPainter();
1566         //}
1567         simulationRunning = false;
1568 }
1569
1570 /**
1571  * Simulates the given entity.
1572  *
1573  * @param smooth If true, the entity will be drawn slowly (pixel by pixel).
1574  */
1575 void RS_GraphicView::simulateEntity(RS_Entity * e, const RS_Pen & pen)
1576 {
1577         if (painter == NULL || e == NULL)
1578                 return;
1579
1580         if (e->isContainer())
1581         {
1582                 RS_EntityContainer * ec = (RS_EntityContainer *)e;
1583
1584                 for(RS_Entity* en=ec->firstEntity(RS2::ResolveNone);
1585                                 en!=NULL; en = ec->nextEntity(RS2::ResolveNone))
1586                 {
1587                         if (en->isVisible() && en->isUndone() == false)
1588                         {
1589                                 // draw rapid move:
1590                                 if (en->isAtomic() && simulationRapid)
1591                                 {
1592                                         Vector sp = ((RS_AtomicEntity *)en)->getStartpoint();
1593
1594                                         if (sp.distanceTo(simulationLast) > 1.0e-4)
1595                                         {
1596                                                 createDirectPainter();
1597                                                 RS_Pen rpen(RS_Color(0, 0, 255), RS2::Width00, RS2::SolidLine);
1598                                                 //painter->setPen(pen);
1599                                                 RS_Line rapidLine(NULL, RS_LineData(simulationLast, sp));
1600                                                 simulateEntity(&rapidLine, rpen);
1601                                         }
1602                                 }
1603
1604                                 if (en->isHighlighted())
1605                                 {
1606                                         RS_Pen hpen(highlightedColor, RS2::Width00, RS2::SolidLine);
1607                                         simulateEntity(en, hpen);
1608                                 }
1609                                 else
1610                                         simulateEntity(en, pen);
1611
1612                                 if (en->isAtomic())
1613                                         simulationLast = ((RS_AtomicEntity *)en)->getEndpoint();
1614
1615                                 if (!simulationSmooth)
1616                                         simulationDelay(true);
1617                         }
1618                 }
1619         }
1620         else
1621         {
1622                 if (simulationSmooth)
1623                 {
1624                         switch (e->rtti())
1625                         {
1626                         case RS2::EntityLine:
1627                         {
1628                                 RS_Line * line = (RS_Line *)e;
1629                                 drawLineSmooth(toGui(line->getStartpoint()), toGui(line->getEndpoint()), pen);
1630                                         //simulationSpeed);
1631                         }
1632                                 break;
1633
1634                         case RS2::EntityArc:
1635                         {
1636                                 RS_Arc * arc = (RS_Arc *)e;
1637                                 drawArcSmooth(toGui(arc->getCenter()), toGuiDX(arc->getRadius()),
1638                                         arc->getAngle1(), arc->getAngle2(), arc->isReversed(), pen);
1639                         }
1640                                 break;
1641
1642                         case RS2::EntityCircle:
1643                         {
1644                                 RS_Circle * circle = (RS_Circle *)e;
1645                                 drawArcSmooth(toGui(circle->getCenter()), toGuiDX(circle->getRadius()),
1646                                         0.0, 2.0 * M_PI, false, pen);
1647                         }
1648                                 break;
1649
1650                         default:
1651                                 break;
1652                         }
1653                 }
1654                 else
1655                 {
1656                         createDirectPainter();
1657                         //RS_Pen pen(foreground, RS2::Width00, RS2::SolidLine);
1658                         painter->setPen(pen);
1659                         drawEntityPlain(e);
1660                 }
1661         }
1662 }
1663
1664 /**
1665  * Delay for slow motion simulation.
1666  *
1667  * @param step true: stepping mode (entity by entity simulation). adds a delay.
1668  */
1669 void RS_GraphicView::simulationDelay(bool step)
1670 {
1671         int delay;
1672         settings.beginGroup("CAM");
1673         double fact = settings.value("SimulationFactor", 12000.0).toDouble();
1674         settings.endGroup();
1675
1676         // simulationSpeed: 0..100
1677
1678 #ifdef __APPLE__
1679         delay = (int)(((1.0 / (simulationSpeed + 1.0)) * fact) - (fact / 100.0));
1680         if (step)
1681                 delay *= 16;
1682
1683         //usleep(delay);
1684         static int call = 0;
1685
1686         if (call >= (fact - delay) / 1000)
1687         {
1688                 call = 0;
1689                 for(int i=0; i<delay; ++i)
1690                         RS_APP->processEvents(10);
1691         }
1692         else
1693                 call++;
1694 #else
1695         delay = (int)(((1.0 / (simulationSpeed + 1.0)) * fact) - (fact / 100.0));
1696
1697         if (step)
1698         {
1699                 delay *= 16;
1700         }
1701
1702         for(int i=0; i<delay; ++i)
1703         {
1704 #warning "Qt3->4 conversion: commented out problem line... !!! FIX !!!"
1705 //        RS_APP->processEvents(10);
1706         }
1707 #endif
1708 }
1709
1710 /**
1711  * Draws a line slowly from (x1, y1) to (x2, y2). This is used for simulation only.
1712  */
1713 void RS_GraphicView::drawLineSmooth(const Vector & p1, const Vector & p2, const RS_Pen & pen)
1714 {
1715         double alpha = p1.angleTo(p2);
1716         double xStep, yStep;
1717         bool  xIsOne;
1718
1719         if (RS_Math::cmpDouble(alpha, 0.0) || RS_Math::cmpDouble(alpha, 2 * M_PI))
1720         {
1721                 xStep = 1.0;
1722                 yStep = 0.0;
1723                 xIsOne = true;
1724         }
1725         else if (RS_Math::cmpDouble(alpha, M_PI / 2.0))
1726         {
1727                 xStep = 0.0;
1728                 yStep = 1.0;
1729                 xIsOne = false;
1730         }
1731         else if (RS_Math::cmpDouble(alpha, M_PI))
1732         {
1733                 xStep = -1.0;
1734                 yStep = 0.0;
1735                 xIsOne = true;
1736         }
1737         else if (RS_Math::cmpDouble(alpha, M_PI / 2.0 * 3.0))
1738         {
1739                 xStep = 0.0;
1740                 yStep = -1.0;
1741                 xIsOne = false;
1742         }
1743         else if (fabs(p2.x - p1.x) > fabs(p2.y - p1.y))
1744         {
1745                 if (p2.x > p1.x)
1746                         xStep = 1.0;
1747                 else
1748                         xStep = -1.0;
1749
1750                 yStep = tan(alpha) * xStep;
1751                 xIsOne = true;
1752         }
1753         else
1754         {
1755                 if (p2.y > p1.y)
1756                         yStep = 1.0;
1757                 else
1758                         yStep = -1.0;
1759
1760                 xStep = yStep / tan(alpha);
1761                 xIsOne = false;
1762         }
1763
1764         double lx = p1.x;
1765         double ly = p1.y;
1766         //RS_Pen pen(foreground, RS2::Width00, RS2::SolidLine);
1767
1768         do
1769         {
1770                 if (lx >= 0.0 && lx <= (double)getWidth() && ly >= 0.0 && ly <= (double)getHeight())
1771                 {
1772                         //if (painter==NULL) {
1773                         createDirectPainter();
1774                         //}
1775                         painter->setPen(pen);
1776                         painter->drawGridPoint(Vector(lx, ly));
1777
1778                         simulationDelay();
1779                 }
1780
1781                 lx += xStep;
1782                 ly += yStep;
1783
1784         }
1785         while ((xIsOne && ((lx >= p1.x && lx <= p2.x) || (lx >= p2.x && lx <= p1.x)))
1786                 || (!xIsOne && ((ly >= p1.y && ly <= p2.y) || (ly >= p2.y && ly <= p1.y))));
1787 }
1788
1789 void RS_GraphicView::drawArcSmooth(const Vector & center, double radius, double a1, double a2, bool rev,
1790         const RS_Pen & pen)
1791 {
1792         //int icx = graphic->realToScreenX(cx);
1793         //int icy = graphic->realToScreenY(cy);
1794         //RS_Pen pen(foreground, RS2::Width00, RS2::SolidLine);
1795
1796         if (radius <= 1.4)
1797         {
1798                 createDirectPainter();
1799                 painter->setPen(pen);
1800                 painter->drawGridPoint(center);
1801         }
1802         else
1803         {
1804                 int ix1 = RS_Math::round(center.x + cos(a1) * radius);
1805                 int iy1 = RS_Math::round(center.y - sin(a1) * radius);
1806                 int ix2 = RS_Math::round(center.x + cos(a2) * radius);
1807                 int iy2 = RS_Math::round(center.y - sin(a2) * radius);
1808                 int k2x = 0;            // Next point on circle
1809                 int k2y = 0;            //
1810                 int k1x = ix1;          // Prev point on circle
1811                 int k1y = iy1;          //
1812                 double aStep;          // Angle Step (rad)
1813                 double a;              // Actual Angle (rad)
1814                 double a2cp = a2;      // Copy of a2
1815
1816                 if (1.0 / (radius * factor.x) <= 1.0)
1817                         aStep = asin(1.0 / (radius * factor.x));
1818                 else
1819                         aStep = 0.01;
1820
1821                 if (aStep < 0.01)
1822                         aStep = 0.01;
1823
1824                 if (!rev)
1825                 {
1826                         // Arc Counterclockwise:
1827                         //
1828                         if (a1 > a2cp - 0.01)
1829                                 a2cp += 2 * M_PI;
1830
1831                         //if (painter==NULL) {
1832                         //painter->setPen(pen);
1833                         //createDirectPainter();
1834                         //}
1835                         //painter->moveTo(ix1, iy1);
1836
1837                         for(a=a1+aStep; a<=a2cp; a+=aStep)
1838                         {
1839                                 k2x = RS_Math::round(center.x+cos(a)*radius);
1840                                 k2y = RS_Math::round(center.y-sin(a)*radius);
1841                                 //if(graphic->isPointOnScreen(k2x, k2y) ||
1842                                 //   graphic->isPointOnScreen(k1x, k1y)    ) {
1843                                 createDirectPainter();
1844                                 painter->setPen(pen);
1845                                 if ((k2x >= 0 && k2x <= painter->getWidth()
1846                                         && k2y >= 0 && k2y <= painter->getHeight())
1847                                         || (k1x >= 0 && k1x <= painter->getWidth()
1848                                         && k1y >= 0 && k1y <= painter->getHeight()))
1849                                 {
1850                                         //painter->lineTo(k2x, k2y);
1851                                         painter->drawLine(Vector(k1x, k1y), Vector(k2x, k2y));
1852                                         simulationDelay();
1853                                         //graphic->simulationDelay();
1854                                 }
1855                                 //createDirectPainter();
1856                                 //painter->setPen(pen);
1857                                 //painter->moveTo(k2x, k2y);
1858
1859                                 k1x = k2x;
1860                                 k1y = k2y;
1861                         }
1862
1863                         createDirectPainter();
1864                         painter->setPen(pen);
1865                         painter->drawLine(Vector(k2x, k2y), Vector(ix2, iy2));
1866                         //painter->lineTo(ix2, iy2);
1867                 }
1868                 else
1869                 {
1870                         // Arc Clockwise:
1871                         //
1872                         if (a1 < a2cp + 0.01)
1873                                 a2cp -= 2 * M_PI;
1874
1875                         //createDirectPainter();
1876                         //painter->setPen(pen);
1877                         //painter->moveTo(ix1, iy1);
1878                         for(a=a1-aStep; a>=a2cp; a-=aStep)
1879                         {
1880                                 k2x = RS_Math::round(center.x + cos(a) * radius);
1881                                 k2y = RS_Math::round(center.y - sin(a) * radius);
1882                                 //if(graphic->isPointOnScreen(k2x, k2y) ||
1883                                 //        graphic->isPointOnScreen(k1x, k1y)    ) {
1884                                 createDirectPainter();
1885                                 painter->setPen(pen);
1886                                 if ((k2x >=0 && k2x <= painter->getWidth()
1887                                         && k2y >= 0 && k2y <= painter->getHeight())
1888                                         || (k1x >= 0 && k1x <= painter->getWidth()
1889                                         && k1y >= 0 && k1y <= painter->getHeight()))
1890                                 {
1891                                         //painter->lineTo(k2x, k2y);
1892                                         painter->drawLine(Vector(k1x, k1y), Vector(k2x, k2y));
1893                                         simulationDelay();
1894                                 }
1895                                 //createDirectPainter();
1896                                 //painter->setPen(pen);
1897                                 //painter->moveTo(k2x, k2y);
1898                                 k1x = k2x;
1899                                 k1y = k2y;
1900                         }
1901
1902                         createDirectPainter();
1903                         painter->setPen(pen);
1904                         //painter->lineTo(ix2, iy2);
1905                         painter->drawLine(Vector(k2x, k2y), Vector(ix2, iy2));
1906                 }
1907         }
1908 }
1909
1910 /**
1911  * @return Pointer to the static pattern struct that belongs to the
1912  * given pattern type or NULL.
1913  */
1914 RS_LineTypePattern * RS_GraphicView::getPattern(RS2::LineType t)
1915 {
1916         switch (t)
1917         {
1918         case RS2::SolidLine:
1919                 return &patternSolidLine;
1920                 break;
1921
1922         case RS2::DotLine:
1923                 return &patternDotLine;
1924                 break;
1925         case RS2::DotLine2:
1926                 return &patternDotLine2;
1927                 break;
1928         case RS2::DotLineX2:
1929                 return &patternDotLineX2;
1930                 break;
1931
1932         case RS2::DashLine:
1933                 return &patternDashLine;
1934                 break;
1935         case RS2::DashLine2:
1936                 return &patternDashLine2;
1937                 break;
1938         case RS2::DashLineX2:
1939                 return &patternDashLineX2;
1940                 break;
1941
1942         case RS2::DashDotLine:
1943                 return &patternDashDotLine;
1944                 break;
1945         case RS2::DashDotLine2:
1946                 return &patternDashDotLine2;
1947                 break;
1948         case RS2::DashDotLineX2:
1949                 return &patternDashDotLineX2;
1950                 break;
1951
1952         case RS2::DivideLine:
1953                 return &patternDivideLine;
1954                 break;
1955         case RS2::DivideLine2:
1956                 return &patternDivideLine2;
1957                 break;
1958         case RS2::DivideLineX2:
1959                 return &patternDivideLineX2;
1960                 break;
1961
1962         case RS2::CenterLine:
1963                 return &patternCenterLine;
1964                 break;
1965         case RS2::CenterLine2:
1966                 return &patternCenterLine2;
1967                 break;
1968         case RS2::CenterLineX2:
1969                 return &patternCenterLineX2;
1970                 break;
1971
1972         case RS2::BorderLine:
1973                 return &patternBorderLine;
1974                 break;
1975         case RS2::BorderLine2:
1976                 return &patternBorderLine2;
1977                 break;
1978         case RS2::BorderLineX2:
1979                 return &patternBorderLineX2;
1980                 break;
1981
1982         case RS2::LineByLayer:
1983                 return &patternBlockLine;
1984                 break;
1985         case RS2::LineByBlock:
1986                 return &patternBlockLine;
1987                 break;
1988         default:
1989                 break;
1990         }
1991
1992         return NULL;
1993 }
1994
1995 /**
1996  * This virtual method can be overwritten to draw the absolute
1997  * zero. It's called from within drawIt(). The default implemetation
1998  * draws a simple red round zero point.
1999  *
2000  * @see drawIt()
2001  */
2002 void RS_GraphicView::drawAbsoluteZero()
2003 {
2004 //RS_DEBUG->print(RS_Debug::D_CRITICAL, "RS_GraphicView::drawAbsoluteZero (painter=%08X)", painter);
2005 //      bool painterCreated = false;
2006
2007         // create a temporary painter device
2008         if (painter == NULL)
2009         {
2010                 return;
2011 //Hrm.          createDirectPainter();
2012 //              createPainter();
2013 //              painterCreated = true;
2014         }
2015
2016         int zr = 20;
2017
2018 //      RS_Pen pen(metaGridColor, RS2::Width00, RS2::SolidLine);
2019 //      painter->setPen(pen);
2020 //      RS_Pen p(Qt::red, RS2::Width00, RS2::SolidLine);
2021 //Using Qt::red doesn't seem to work here...
2022 //It's because Qt colors and RS_Color are not 100% compatible...
2023         RS_Pen p(RS_Color(255, 0, 0), RS2::Width00, RS2::SolidLine);
2024 //      p.setScreenWidth(0);
2025         painter->setPen(p);
2026         //painter->setBrush(Qt::NoBrush);
2027
2028         painter->drawLine(Vector(toGuiX(0.0) - zr, toGuiY(0.0)),
2029                 Vector(toGuiX(0.0) + zr, toGuiY(0.0)));
2030
2031         painter->drawLine(Vector(toGuiX(0.0), toGuiY(0.0) - zr),
2032                 Vector(toGuiX(0.0), toGuiY(0.0) + zr));
2033
2034 //      if (painterCreated)
2035 //              destroyPainter();
2036 }
2037
2038 /**
2039  * This virtual method can be overwritten to draw the relative
2040  * zero point. It's called from within drawIt(). The default implemetation
2041  * draws a simple red round zero point.
2042  *
2043  * @see drawIt()
2044  */
2045 void RS_GraphicView::drawRelativeZero()
2046 {
2047 //#warning "!!! drawRelativeZero() not working AT ALL !!!"
2048 #if 1
2049 //      bool painterCreated = false;
2050
2051         if (relativeZero.valid == false)
2052                 return;
2053
2054         // create a temporary painter device
2055         if (painter == NULL)
2056         {
2057                 return;
2058 //hrm.          createDirectPainter();
2059 //              createPainter();
2060 //              painterCreated = true;
2061         }
2062
2063 //      RS_Pen p(Qt::red, RS2::Width00, RS2::SolidLine);
2064 //      p.setScreenWidth(0);
2065 //Using Qt::red doesn't seem to work here...
2066         RS_Pen p(RS_Color(255, 0, 0), RS2::Width00, RS2::SolidLine);
2067         painter->setPen(p);
2068         painter->setXORMode();
2069
2070         int zr = 5;
2071
2072         painter->drawLine(Vector(toGuiX(relativeZero.x) - zr, toGuiY(relativeZero.y)),
2073                 Vector(toGuiX(relativeZero.x) + zr, toGuiY(relativeZero.y)));
2074
2075         painter->drawLine(Vector(toGuiX(relativeZero.x), toGuiY(relativeZero.y) - zr),
2076                 Vector(toGuiX(relativeZero.x), toGuiY(relativeZero.y) + zr));
2077
2078         painter->drawCircle(toGui(relativeZero), zr);
2079
2080         painter->setNormalMode();
2081
2082 //      if (painterCreated)
2083 //              destroyPainter();
2084 #endif
2085 }
2086
2087 /**
2088  * Draws the paper border (for print previews).
2089  *
2090  * @see drawIt()
2091  */
2092 void RS_GraphicView::drawPaper()
2093 {
2094         bool painterCreated = false;
2095
2096         if (container == NULL)
2097                 return;
2098
2099         RS_Graphic * graphic = container->getGraphic();
2100
2101         if (graphic == NULL)
2102                 return;
2103
2104         if (graphic->getPaperScale() < 1.0e-6)
2105                 return;
2106
2107         // create a temporary painter device
2108         if (painter == NULL)
2109         {
2110                 createDirectPainter();
2111                 painterCreated = true;
2112         }
2113
2114         // draw paper:
2115         painter->setPen(RS_Pen(Qt::gray));
2116
2117         Vector pinsbase = graphic->getPaperInsertionBase();
2118         Vector size = graphic->getPaperSize();
2119         double scale = graphic->getPaperScale();
2120
2121         Vector v1 = toGui((Vector(0, 0) - pinsbase) / scale);
2122         Vector v2 = toGui((size - pinsbase) / scale);
2123
2124         // gray background:
2125         painter->fillRect(0,0, getWidth(), getHeight(), RS_Color(200, 200, 200));
2126
2127         // shadow
2128         painter->fillRect((int)(v1.x) + 6, (int)(v1.y) + 6,
2129                 (int)((v2.x - v1.x)), (int)((v2.y - v1.y)),
2130                 RS_Color(64, 64, 64));
2131
2132         // border:
2133         painter->fillRect((int)(v1.x), (int)(v1.y),
2134                 (int)((v2.x - v1.x)), (int)((v2.y - v1.y)),
2135                 RS_Color(64, 64, 64));
2136
2137         // paper
2138         painter->fillRect((int)(v1.x) + 1, (int)(v1.y) - 1,
2139                 (int)((v2.x - v1.x)) - 2, (int)((v2.y - v1.y)) + 2,
2140                 RS_Color(255, 255, 255));
2141
2142         if (painterCreated)
2143                 destroyPainter();
2144 }
2145
2146 /**
2147  * Draws the grid.
2148  *
2149  * @see drawIt()
2150  */
2151 void RS_GraphicView::drawGrid()
2152 {
2153         if (grid == NULL || isGridOn() == false)
2154 //      {
2155 //              printf("RS_GraphicView::drawGrid(): Aborting: grid=%08X, isGridOn=%s\n", grid, (isGridOn() ? "true" : "false"));
2156                 return;
2157 //      }
2158
2159         // draw grid:
2160         //painter->setPen(Qt::gray);
2161         painter->setPen(gridColor);
2162 //      painter->setPen(RS_Pen(RS_Color(128, 128, 128), RS2::Width00, RS2::SolidLine));
2163
2164 //Problem here: pts is NULL!
2165         Vector * pts = grid->getPoints();
2166
2167         if (pts != NULL)
2168         {
2169                 for(int i=0; i<grid->count(); ++i)
2170                         painter->drawGridPoint(toGui(pts[i]));
2171         }
2172 //      else
2173 //              printf("RS_GraphicView::drawGrid(): pts == NULL!\n");
2174
2175         // draw grid info:
2176         //painter->setPen(Qt::white);
2177         QString info = grid->getInfo();
2178         //info = QString("%1 / %2")
2179         //       .arg(grid->getSpacing())
2180         //       .arg(grid->getMetaSpacing());
2181
2182         updateGridStatusWidget(info);
2183 }
2184
2185 /**
2186  * Draws the meta grid.
2187  *
2188  * @see drawIt()
2189  */
2190 void RS_GraphicView::drawMetaGrid()
2191 {
2192         if (grid == NULL || isGridOn() == false /*|| grid->getMetaSpacing()<0.0*/)
2193                 return;
2194
2195         bool painterCreated = false;
2196
2197         // create a temporary painter device
2198         if (painter == NULL)
2199         {
2200 //hrm           createDirectPainter();
2201                 createPainter();
2202                 painterCreated = true;
2203         }
2204
2205         RS_Pen pen(metaGridColor, RS2::Width00, RS2::DotLine);
2206         painter->setPen(pen);
2207
2208         // draw meta grid:
2209         double * mx = grid->getMetaX();
2210
2211         if (mx != NULL)
2212         {
2213                 for(int i=0; i<grid->countMetaX(); ++i)
2214                         painter->drawLine(Vector(toGuiX(mx[i]), 0), Vector(toGuiX(mx[i]), getHeight()));
2215         }
2216
2217         double * my = grid->getMetaY();
2218
2219         if (my != NULL)
2220         {
2221                 for(int i=0; i<grid->countMetaY(); ++i)
2222                         painter->drawLine(Vector(0, toGuiY(my[i])), Vector(getWidth(), toGuiY(my[i])));
2223         }
2224
2225         if (painterCreated)
2226                 destroyPainter();
2227 }
2228
2229 /**
2230  * Updates the grid if there is one.
2231  */
2232 void RS_GraphicView::updateGrid()
2233 {
2234         if (grid != NULL)
2235                 grid->update();
2236 }
2237
2238 RS_Grid * RS_GraphicView::getGrid()
2239 {
2240         return grid;
2241 }
2242
2243 void RS_GraphicView::updateGridStatusWidget(const QString & /*text*/)
2244 {
2245 }
2246
2247 RS2::SnapMode RS_GraphicView::getDefaultSnapMode()
2248 {
2249         return defaultSnapMode;
2250 }
2251
2252 RS2::SnapRestriction RS_GraphicView::getSnapRestriction()
2253 {
2254         return defaultSnapRes;
2255 }
2256
2257 /**
2258  * Sets the default snap mode used by newly created actions.
2259  */
2260 void RS_GraphicView::setDefaultSnapMode(RS2::SnapMode sm)
2261 {
2262         defaultSnapMode = sm;
2263
2264         if (eventHandler != NULL)
2265                 eventHandler->setSnapMode(sm);
2266 }
2267
2268 /**
2269  * Sets a snap restriction (e.g. orthogonal).
2270  */
2271 void RS_GraphicView::setSnapRestriction(RS2::SnapRestriction sr)
2272 {
2273         defaultSnapRes = sr;
2274
2275         if (eventHandler != NULL)
2276                 eventHandler->setSnapRestriction(sr);
2277 }
2278
2279 /**
2280  * Translates a vector in real coordinates to a vector in screen coordinates.
2281  */
2282 Vector RS_GraphicView::toGui(Vector v)
2283 {
2284         return Vector(toGuiX(v.x), toGuiY(v.y), 0.0);
2285 }
2286
2287 /**
2288  * Translates a real coordinate in X to a screen coordinate X.
2289  * @param visible Pointer to a boolean which will contain true
2290  * after the call if the coordinate is within the visible range.
2291  */
2292 double RS_GraphicView::toGuiX(double x, bool * visible)
2293 {
2294         if (visible != NULL)
2295         {
2296                 double res = x * factor.x + offsetX;
2297
2298                 if (res > 0.0 && res < getWidth())
2299                         *visible = true;
2300                 else
2301                         *visible = false;
2302         }
2303
2304         return x * factor.x + offsetX;
2305 }
2306
2307 /**
2308  * Translates a real coordinate in Y to a screen coordinate Y.
2309  */
2310 double RS_GraphicView::toGuiY(double y)
2311 {
2312         return -y * factor.y + getHeight() - offsetY;
2313 }
2314
2315 /**
2316  * Translates a real coordinate distance to a screen coordinate distance.
2317  */
2318 double RS_GraphicView::toGuiDX(double d)
2319 {
2320         return d * factor.x;
2321 }
2322
2323 /**
2324  * Translates a real coordinate distance to a screen coordinate distance.
2325  */
2326 double RS_GraphicView::toGuiDY(double d)
2327 {
2328         return d * factor.y;
2329 }
2330
2331 /**
2332  * Translates a vector in screen coordinates to a vector in real coordinates.
2333  */
2334 Vector RS_GraphicView::toGraph(Vector v)
2335 {
2336         return Vector(toGraphX(RS_Math::round(v.x)), toGraphY(RS_Math::round(v.y)), 0.0);
2337 }
2338
2339 /**
2340  * Translates two screen coordinates to a vector in real coordinates.
2341  */
2342 Vector RS_GraphicView::toGraph(int x, int y)
2343 {
2344         return Vector(toGraphX(x), toGraphY(y), 0.0);
2345 }
2346
2347 /**
2348  * Translates a screen coordinate in X to a real coordinate X.
2349  */
2350 double RS_GraphicView::toGraphX(int x)
2351 {
2352         return (x - offsetX) / factor.x;
2353 }
2354
2355 /**
2356  * Translates a screen coordinate in Y to a real coordinate Y.
2357  */
2358 double RS_GraphicView::toGraphY(int y)
2359 {
2360         return -(y - getHeight() + offsetY) / factor.y;
2361 }
2362
2363 /**
2364  * Translates a screen coordinate distance to a real coordinate distance.
2365  */
2366 double RS_GraphicView::toGraphDX(int d)
2367 {
2368         return d / factor.x;
2369 }
2370
2371 /**
2372  * Translates a screen coordinate distance to a real coordinate distance.
2373  */
2374 double RS_GraphicView::toGraphDY(int d)
2375 {
2376         return d / factor.y;
2377 }
2378
2379 /**
2380  * (Un-)Locks the position of the relative zero.
2381  *
2382  * @param lock true: lock, false: unlock
2383  */
2384 void RS_GraphicView::lockRelativeZero(bool lock)
2385 {
2386         relativeZeroLocked=lock;
2387 }
2388
2389 /**
2390  * @return true if the position of the realtive zero point is
2391  * locked.
2392  */
2393 bool RS_GraphicView::isRelativeZeroLocked()
2394 {
2395         return relativeZeroLocked;
2396 }
2397
2398 /**
2399  * @return Relative zero coordinate.
2400  */
2401 Vector RS_GraphicView::getRelativeZero()
2402 {
2403         return relativeZero;
2404 }
2405
2406 /**
2407  * Sets the relative zero coordinate (if not locked)
2408  * without deleting / drawing the point.
2409  */
2410 void RS_GraphicView::setRelativeZero(const Vector & pos)
2411 {
2412         if (!relativeZeroLocked)
2413                 relativeZero = pos;
2414 }
2415
2416 /**
2417  * Sets the relative zero coordinate, deletes the old position
2418  * on the screen and draws the new one.
2419  */
2420 void RS_GraphicView::moveRelativeZero(const Vector & pos)
2421 {
2422 //      bool painterCreated = false;
2423
2424         if (painter == NULL)
2425         {
2426                 return;
2427 //hrm           painter = createDirectPainter();
2428 //              painter = createPainter();
2429 //              painterCreated = true;
2430         }
2431
2432         //painter->setXORMode();
2433         drawRelativeZero();
2434
2435         setRelativeZero(pos);
2436
2437         drawRelativeZero();
2438
2439 //      if (painterCreated)
2440 //              destroyPainter();
2441 }
2442
2443 RS_EventHandler * RS_GraphicView::getEventHandler()
2444 {
2445         return eventHandler;
2446 }
2447
2448 /**
2449  * Enables or disables print preview.
2450  */
2451 void RS_GraphicView::setPrintPreview(bool pv)
2452 {
2453         printPreview = pv;
2454 }
2455
2456 /**
2457  * @retval true This is a print preview graphic view.
2458  * @retval false Otherwise.
2459  */
2460 bool RS_GraphicView::isPrintPreview()
2461 {
2462         return printPreview;
2463 }
2464
2465 /**
2466  * Enables or disables printing.
2467  */
2468 void RS_GraphicView::setPrinting(bool p)
2469 {
2470         printing = p;
2471 }
2472
2473 /**
2474  * @retval true This is a a graphic view for printing.
2475  * @retval false Otherwise.
2476  */
2477 bool RS_GraphicView::isPrinting()
2478 {
2479         return printing;
2480 }
2481
2482 /**
2483  * @retval true Draft mode is on for this view (all lines with 1 pixel / no style scaling).
2484  * @retval false Otherwise.
2485  */
2486 bool RS_GraphicView::isDraftMode()
2487 {
2488         return draftMode;
2489 }
2490
2491 /**
2492  * Sets the simulation speed in percentage.
2493  */
2494 void RS_GraphicView::setSimulationSpeed(int s)
2495 {
2496         simulationSpeed = s;
2497 }
2498
2499 /**
2500  * @return the simulation speed in percentage.
2501  */
2502 int RS_GraphicView::getSimulationSpeed()
2503 {
2504         return simulationSpeed;
2505 }
2506
2507 /**
2508  * Sets the simulation smooth mode.
2509  */
2510 void RS_GraphicView::setSimulationSmooth(bool s)
2511 {
2512         simulationSmooth = s;
2513 }
2514 /**
2515  * Sets the simulation rapid mode.
2516  */
2517 void RS_GraphicView::setSimulationRapid(bool r)
2518 {
2519         simulationRapid = r;
2520 }
2521
2522 /**
2523  * @return the simulation rapid mode.
2524  */
2525 bool RS_GraphicView::getSimulationRapid()
2526 {
2527         return simulationRapid;
2528 }
2529
2530 // These functions are here because of the focacta way that this
2531 // program set up its rendering...
2532 void RS_GraphicView::SetPreviewMode(bool mode/*= true*/)
2533 {
2534         previewMode = mode;
2535 }
2536
2537 void RS_GraphicView::SetPreviewEntity(RS_Preview * p)
2538 {
2539         previewEntity = p;
2540 }
2541
2542 void RS_GraphicView::SetPreviewOffset(Vector o)
2543 {
2544         previewOffset = o;
2545 }
2546
2547 void RS_GraphicView::SetSnapperDraw(bool mode)
2548 {
2549         snapperDraw = mode;
2550 }
2551
2552 void RS_GraphicView::SetSnapperVars(Vector snapSpot, Vector snapCoord, bool showCrosshairs)
2553 {
2554         snapSpot1 = snapSpot;
2555         snapCoord1 = snapCoord;
2556         showCrosshairs1 = showCrosshairs;
2557 }