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 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
10 // JLH = James L. Hammons <jlhamm@acm.org>
13 // --- ---------- -----------------------------------------------------------
14 // JLH 06/16/2010 Created this file. :-)
17 #include "graphicview.h"
19 #include "dialogfactory.h"
21 #include "eventhandler.h"
23 #include "linetypepattern.h"
24 #include "paintinterface.h"
32 GraphicView::GraphicView(): background(), foreground()
34 drawingMode = RS2::ModeFull;
37 factor = Vector(1.0, 1.0);
38 offsetX = offsetY = 0;
39 previousFactor = Vector(1.0, 1.0);
40 previousOffsetX = previousOffsetY = 0;
42 eventHandler = new EventHandler();
44 metaGridColor = Color(64, 64, 64);
45 grid = new Grid(this);
51 borderLeft = borderTop = borderRight = borderBottom = 0;
53 relativeZero = Vector(false);
54 relativeZeroLocked = false;
58 defaultSnapMode = RS2::SnapFree;
59 defaultSnapRes = RS2::RestrictNothing;
61 settings.beginGroup("Appearance");
62 setBackground(QColor(settings.value("BackgroundColor", "#000000").toString()));
63 setGridColor(QColor(settings.value("GridColor", "#7F7F7F").toString()));
64 setMetaGridColor(QColor(settings.value("MetaGridColor", "#3F3F3F").toString()));
65 setSelectedColor(QColor(settings.value("SelectedColor", "#A54747").toString()));
66 setHighlightedColor(QColor(settings.value("HighlightedColor", "#739373").toString()));
71 simulationSpeed = 100;
72 simulationSmooth = false;
73 simulationRapid = false;
74 simulationRunning = false;
76 // Snapper settings...
78 snapSpot = Vector(false);
79 snapCoord = Vector(false);
80 snapperVisible = false;
83 settings.beginGroup("Snap");
84 snapRange = settings.value("Range", 20).toInt();
86 settings.beginGroup("Appearance");
87 showCrosshairs = settings.value("ShowCrosshairs", true).toBool();
90 // Sanity check for snapRange
98 GraphicView::~GraphicView()
104 * Must be called by any derrived class in the destructor.
106 void GraphicView::cleanUp()
112 * @return Pointer to the graphic entity if the entity container
113 * connected to this view is a graphic and valid.
116 Drawing * GraphicView::GetDrawing()
118 if (container && container->rtti() == RS2::EntityDrawing)
119 return (Drawing *)container;
125 * Sets the drawing mode.
127 void GraphicView::setDrawingMode(RS2::DrawingMode m)
133 * @return Current drawing mode.
135 RS2::DrawingMode GraphicView::getDrawingMode()
141 * Activates or deactivates the delete mode.
143 void GraphicView::setDeleteMode(bool m)
149 * @reval true Deleting instead of drawing.
150 * false Normal drawing mode.
152 bool GraphicView::getDeleteMode()
157 /** This virtual method must be overwritten and is then
158 called whenever the view changed */
159 void GraphicView::adjustOffsetControls()
163 /** This virtual method must be overwritten and is then
164 called whenever the view changed */
165 void GraphicView::adjustZoomControls()
170 * Sets the background color. Note that applying the background
171 * color for the widget is up to the implementing class.
173 void GraphicView::setBackground(const Color & bg)
177 // bright background:
178 if (bg.red() + bg.green() + bg.blue() > 380)
179 // foreground = Qt::black;
180 foreground = Color(0, 0, 0);
182 // foreground = Qt::white;
183 foreground = Color(255, 255, 255);
187 * @return Current background color.
189 Color GraphicView::getBackground()
195 * @return Current foreground color.
197 Color GraphicView::getForeground()
203 * Sets the grid color.
205 void GraphicView::setGridColor(const Color & c)
211 * Sets the meta grid color.
213 void GraphicView::setMetaGridColor(const Color & c)
219 * Sets the selection color.
221 void GraphicView::setSelectedColor(const Color & c)
227 * Sets the highlight color.
229 void GraphicView::setHighlightedColor(const Color & c)
231 highlightedColor = c;
235 * This virtual method can be overwritten to set the mouse
236 * cursor to the given type.
238 void GraphicView::setMouseCursor(RS2::CursorType /*c*/)
242 EntityContainer * GraphicView::getContainer()
247 void GraphicView::setFactor(double f)
253 Vector GraphicView::getFactor()
259 * Sets the offset of the graphic.
261 void GraphicView::setOffset(int ox, int oy)
267 void GraphicView::setOffsetX(int ox)
272 void GraphicView::setOffsetY(int oy)
277 int GraphicView::getOffsetX()
282 int GraphicView::getOffsetY()
288 * Sets a fixed border in pixel around the graphic. This border
289 * specifies how far the user can scroll outside the graphic
292 void GraphicView::setBorders(int left, int top, int right, int bottom)
297 borderBottom = bottom;
300 int GraphicView::getBorderLeft()
305 int GraphicView::getBorderTop()
310 int GraphicView::getBorderRight()
315 int GraphicView::getBorderBottom()
320 void GraphicView::disableUpdate()
325 void GraphicView::enableUpdate()
330 bool GraphicView::isUpdateEnabled()
332 return (updateEnabled == 0);
335 void GraphicView::freezeZoom(bool freeze)
340 bool GraphicView::isZoomFrozen()
346 * Sets the pointer to the graphic which contains the entities
347 * which are visualized by this widget.
349 void GraphicView::setContainer(EntityContainer * container)
351 this->container = container;
355 * Sets the zoom factor in X for this visualization of the graphic.
357 void GraphicView::setFactorX(double f)
364 * Sets the zoom factor in Y for this visualization of the graphic.
366 void GraphicView::setFactorY(double f)
373 * @return true if the grid is switched on.
375 bool GraphicView::isGridOn()
379 Drawing * d = container->GetDrawing();
382 return d->isGridOn();
389 * Centers the drawing in x-direction.
391 void GraphicView::centerOffsetX()
393 if (container != NULL && !zoomFrozen)
394 offsetX = (int)(((getWidth() - borderLeft - borderRight)
395 - (container->getSize().x * factor.x)) / 2.0
396 - (container->getMin().x * factor.x)) + borderLeft;
400 * Centers the drawing in y-direction.
402 void GraphicView::centerOffsetY()
404 if (container != NULL && !zoomFrozen)
405 offsetY = (int)((getHeight() - borderTop - borderBottom
406 - (container->getSize().y * factor.y)) / 2.0
407 - (container->getMin().y * factor.y)) + borderBottom;
411 * Centers the given coordinate in the view in x-direction.
413 void GraphicView::centerX(double v)
416 offsetX = (int)((v * factor.x) - (double)(getWidth() - borderLeft - borderRight) / 2.0);
420 * Centers the given coordinate in the view in y-direction.
422 void GraphicView::centerY(double v)
425 offsetY = (int)((v * factor.y) - (double)(getHeight() - borderTop - borderBottom) / 2.0);
428 void GraphicView::updateView()
430 static int running = 0;
435 adjustZoomControls();
436 adjustOffsetControls();
446 * @return Current action or NULL.
448 ActionInterface * GraphicView::getDefaultAction()
451 return eventHandler->GetDefaultAction();
457 * Sets the default action of the event handler.
459 void GraphicView::setDefaultAction(ActionInterface * action)
462 eventHandler->SetDefaultAction(action);
466 * @return Current action or NULL.
468 ActionInterface * GraphicView::getCurrentAction()
471 return eventHandler->GetCurrentAction();
477 * Sets the current action of the event handler.
479 void GraphicView::setCurrentAction(ActionInterface * action)
481 DEBUG->print("GraphicView::setCurrentAction");
484 eventHandler->SetCurrentAction(action);
486 DEBUG->print("GraphicView::setCurrentAction: OK");
490 * Kills all running selection actions. Called when a selection action
491 * is launched to reduce confusion.
493 void GraphicView::killSelectActions()
496 eventHandler->KillSelectActions();
500 * Kills all running actions.
502 void GraphicView::killAllActions()
504 //KillAll does nothing...
506 eventHandler->KillAllActions();
510 * Go back in menu or current action.
512 void GraphicView::back()
514 if (eventHandler && eventHandler->HasAction())
515 eventHandler->Back();
516 else if (DIALOGFACTORY)
517 DIALOGFACTORY->requestPreviousMenu();
521 * Go forward with the current action.
523 void GraphicView::enter()
525 if (eventHandler && eventHandler->HasAction())
526 eventHandler->Enter();
530 * Called by the actual GUI class which implements the GraphicView
531 * interface to notify qcadlib about mouse events.
533 void GraphicView::_mousePressEvent(QMouseEvent * e)
536 eventHandler->MousePressEvent(e);
540 * Called by the actual GUI class which implements the GraphicView
541 * interface to notify qcadlib about mouse events.
543 void GraphicView::_mouseReleaseEvent(QMouseEvent * e)
545 DEBUG->print("GraphicView::mouseReleaseEvent");
550 if (e->button() != Qt::RightButton || eventHandler->HasAction())
552 eventHandler->MouseReleaseEvent(e);
560 DEBUG->print("GraphicView::mouseReleaseEvent: OK");
564 * Called by the actual GUI class which implements the GraphicView
565 * interface to notify qcadlib about mouse events.
567 void GraphicView::_mouseMoveEvent(QMouseEvent * e)
569 DEBUG->print("GraphicView::mouseMoveEvent begin");
571 Drawing * drawing = NULL;
573 if (container->rtti() == RS2::EntityDrawing)
574 drawing = (Drawing *)container;
576 DEBUG->print("GraphicView::mouseMoveEvent 001");
584 DEBUG->print("GraphicView::mouseMoveEvent 002");
587 eventHandler->MouseMoveEvent(e);
589 DEBUG->print("GraphicView::mouseMoveEvent 003");
591 if (!eventHandler || !eventHandler->HasAction() && drawing)
595 Vector mouse = toGraph(Vector(mx, my));
596 Vector relMouse = mouse - getRelativeZero();
597 DIALOGFACTORY->updateCoordinateWidget(mouse, relMouse);
601 DEBUG->print("GraphicView::mouseMoveEvent end");
605 * Called by the actual GUI class which implements the GraphicView
606 * interface to notify qcadlib about mouse events.
608 void GraphicView::_mouseLeaveEvent()
611 eventHandler->MouseLeaveEvent();
615 * Called by the actual GUI class which implements the GraphicView
616 * interface to notify qcadlib about mouse events.
618 void GraphicView::_mouseEnterEvent()
621 eventHandler->MouseEnterEvent();
625 * Called by the actual GUI class which implements the GraphicView
626 * interface to notify qcadlib about key events.
628 void GraphicView::_keyPressEvent(QKeyEvent * e)
631 eventHandler->KeyPressEvent(e);
635 * Called by the actual GUI class which implements the GraphicView
636 * interface to notify qcadlib about key events.
638 void GraphicView::_keyReleaseEvent(QKeyEvent * e)
641 eventHandler->KeyReleaseEvent(e);
645 * Called by the actual GUI class which implements a command line.
647 void GraphicView::commandEvent(CommandEvent * e)
650 eventHandler->HandleCommandEvent(this, e);
654 * Enables coordinate input in the command line.
656 void GraphicView::enableCoordinateInput()
659 eventHandler->EnableCoordinateInput();
663 * Disables coordinate input in the command line.
665 void GraphicView::disableCoordinateInput()
668 eventHandler->DisableCoordinateInput();
672 * zooms in by factor f
674 void GraphicView::zoomIn(double f, const Vector & center)
678 DEBUG->print(Debug::D_WARNING, "GraphicView::zoomIn: invalid factor");
682 if (simulationRunning)
687 if (c.valid == false)
688 c = toGraph(Vector(getWidth() / 2, getHeight() / 2));
690 zoomWindow(toGraph(Vector(0, 0)).scale(c, Vector(1.0 / f, 1.0 / f)),
691 toGraph(Vector(getWidth(), getHeight())).scale(c, Vector(1.0 / f, 1.0 / f)));
695 * zooms in by factor f in x
697 void GraphicView::zoomInX(double f)
699 if (simulationRunning)
703 offsetX = (int)((offsetX - getWidth() / 2) * f) + getWidth() / 2;
704 adjustOffsetControls();
705 adjustZoomControls();
711 * zooms in by factor f in y
713 void GraphicView::zoomInY(double f)
715 if (simulationRunning)
719 offsetY = (int)((offsetY - getHeight() / 2) * f)+getHeight() / 2;
720 adjustOffsetControls();
721 adjustZoomControls();
727 * zooms out by factor f
729 void GraphicView::zoomOut(double f, const Vector & center)
733 DEBUG->print(Debug::D_WARNING,
734 "GraphicView::zoomOut: invalid factor");
738 if (simulationRunning)
745 * zooms out by factor f in x
747 void GraphicView::zoomOutX(double f)
751 DEBUG->print(Debug::D_WARNING,
752 "GraphicView::zoomOutX: invalid factor");
756 if (simulationRunning)
760 offsetX = (int)(offsetX / f);
761 adjustOffsetControls();
762 adjustZoomControls();
768 * zooms out by factor of y
770 void GraphicView::zoomOutY(double f)
774 DEBUG->print(Debug::D_WARNING, "GraphicView::zoomOutY: invalid factor");
778 if (simulationRunning)
782 offsetY = (int)(offsetY / f);
783 adjustOffsetControls();
784 adjustZoomControls();
792 * @param axis include axis in zoom
793 * @param keepAspectRatio true: keep aspect ratio 1:1
794 * false: factors in x and y are stretched to the max
796 void GraphicView::zoomAuto(bool axis, bool keepAspectRatio)
798 DEBUG->print("GraphicView::zoomAuto");
800 if (simulationRunning)
805 if (container != NULL)
807 container->calculateBorders();
812 sx = std::max(container->getMax().x, 0.0) - std::min(container->getMin().x, 0.0);
813 sy = std::max(container->getMax().y, 0.0) - std::min(container->getMin().y, 0.0);
817 sx = container->getSize().x;
818 sy = container->getSize().y;
823 if (sx > RS_TOLERANCE)
824 fx = (getWidth() - borderLeft - borderRight) / sx;
828 if (sy > RS_TOLERANCE)
829 fy = (getHeight() - borderTop - borderBottom) / sy;
833 DEBUG->print("f: %f/%f", fx, fy);
836 fx = fy = std::min(fx, fy);
838 DEBUG->print("f: %f/%f", fx, fy);
840 if (fx < RS_TOLERANCE)
846 DEBUG->print("f: %f/%f", fx, fy);
848 DEBUG->print("adjustOffsetControls");
849 adjustOffsetControls();
850 DEBUG->print("adjustZoomControls");
851 adjustZoomControls();
852 DEBUG->print("centerOffsetX");
854 DEBUG->print("centerOffsetY");
856 DEBUG->print("updateGrid");
861 DEBUG->print("GraphicView::zoomAuto OK");
865 * Shows previous view.
867 void GraphicView::zoomPrevious()
869 DEBUG->print("GraphicView::zoomPrevious");
871 if (simulationRunning)
879 * Saves the current view as previous view to which we can
880 * switch back later with @see restoreView().
882 void GraphicView::saveView()
884 previousOffsetX = offsetX;
885 previousOffsetY = offsetY;
886 previousFactor = factor;
890 * Restores the view previously saved with
893 void GraphicView::restoreView()
895 int pox = previousOffsetX;
896 int poy = previousOffsetY;
897 Vector pf = previousFactor;
905 adjustOffsetControls();
906 adjustZoomControls();
912 * performs autozoom in y only
914 * @param axis include axis in zoom
916 void GraphicView::zoomAutoY(bool axis)
918 if (simulationRunning)
921 if (container != NULL)
923 double visibleHeight = 0.0;
924 double minY = RS_MAXDOUBLE;
925 double maxY = RS_MINDOUBLE;
926 bool noChange = false;
928 for(Entity * e=container->firstEntity(RS2::ResolveNone);
929 e!=NULL; e = container->nextEntity(RS2::ResolveNone))
931 if (e->rtti() == RS2::EntityLine)
933 Line * l = (Line *)e;
935 x1 = toGuiX(l->getStartpoint().x);
936 x2 = toGuiX(l->getEndpoint().x);
938 if ((x1 > 0.0 && x1 < (double)getWidth())
939 || (x2 > 0.0 && x2 < (double)getWidth()))
941 minY = std::min(minY, l->getStartpoint().y);
942 minY = std::min(minY, l->getEndpoint().y);
943 maxY = std::max(maxY, l->getStartpoint().y);
944 maxY = std::max(maxY, l->getEndpoint().y);
950 visibleHeight = std::max(maxY, 0.0) - std::min(minY, 0.0);
952 visibleHeight = maxY - minY;
954 if (visibleHeight < 1.0)
959 if (visibleHeight > 1.0e-6)
961 fy = (getHeight() - borderTop - borderBottom) / visibleHeight;
963 if (factor.y < 0.000001)
967 if (noChange == false)
971 offsetY = (int)((getHeight() - borderTop - borderBottom - (visibleHeight * factor.y)) / 2.0
972 - (minY * factor.y)) + borderBottom;
973 adjustOffsetControls();
974 adjustZoomControls();
978 DEBUG->print("Auto zoom y ok");
983 * Zooms the area given by v1 and v2.
985 * @param keepAspectRatio true: keeps the aspect ratio 1:1
986 * false: zooms exactly the selected range to the
987 * current graphic view
989 void GraphicView::zoomWindow(Vector v1, Vector v2, bool keepAspectRatio)
991 if (simulationRunning)
996 double zoomX = 480.0; // Zoom for X-Axis
997 double zoomY = 640.0; // Zoom for Y-Axis (Set smaller one)
998 double dum; // Dummy for switching values
1001 // Switch left/right and top/bottom is necessary:
1016 // Get zoom in X and zoom in Y:
1017 if (v2.x - v1.x > 1.0e-6)
1018 zoomX = getWidth() / (v2.x - v1.x);
1020 if (v2.y - v1.y > 1.0e-6)
1021 zoomY = getHeight() / (v2.y - v1.y);
1023 // Take smaller zoom:
1024 if (keepAspectRatio)
1028 if (getWidth() != 0)
1030 zoomX = zoomY = ((double)(getWidth() - 2 * zoomBorder)) /
1031 (double)getWidth() * zoomX;
1036 if (getHeight() != 0)
1038 zoomX = zoomY = ((double)(getHeight() - 2 * zoomBorder)) /
1039 (double)getHeight() * zoomY;
1050 // Borders in pixel after zoom
1051 int pixLeft = (int)(v1.x * zoomX);
1052 int pixTop = (int)(v2.y * zoomY);
1053 int pixRight = (int)(v2.x * zoomX);
1054 int pixBottom = (int)(v1.y * zoomY);
1056 // Set new offset for zero point:
1057 offsetX = - pixLeft + (getWidth() - pixRight + pixLeft) / 2;
1058 offsetY = - pixTop + (getHeight() - pixBottom + pixTop) / 2;
1062 adjustOffsetControls();
1063 adjustZoomControls();
1069 * Centers the point v1.
1071 void GraphicView::zoomPan(int dx, int dy)
1073 if (simulationRunning)
1080 adjustOffsetControls();
1087 * Scrolls in the given direction.
1089 void GraphicView::zoomScroll(RS2::Direction direction)
1091 if (simulationRunning)
1110 adjustOffsetControls();
1111 adjustZoomControls();
1117 * Zooms to page extends.
1119 void GraphicView::zoomPage()
1121 DEBUG->print("GraphicView::zoomPage");
1123 if (container == NULL)
1126 if (simulationRunning)
1129 Drawing * drawing = container->GetDrawing();
1131 if (drawing == NULL)
1134 Vector s = drawing->getPaperSize();
1135 Vector pinsbase = drawing->getPaperInsertionBase();
1139 if (s.x > RS_TOLERANCE)
1140 fx = (getWidth() - borderLeft - borderRight) / s.x;
1144 if (s.y > RS_TOLERANCE)
1145 fy = (getHeight() - borderTop - borderBottom) / s.y;
1149 DEBUG->print("f: %f/%f", fx, fy);
1151 fx = fy = std::min(fx, fy);
1153 DEBUG->print("f: %f/%f", fx, fy);
1155 if (fx < RS_TOLERANCE)
1161 DEBUG->print("f: %f/%f", fx, fy);
1165 adjustOffsetControls();
1166 adjustZoomControls();
1172 * Draws the entities within the given range.
1174 void GraphicView::drawWindow(Vector v1, Vector v2)
1176 DEBUG->print("GraphicView::drawWindow() begin");
1178 if (simulationRunning)
1183 for(Entity * se=container->firstEntity(RS2::ResolveNone); se!=NULL;
1184 se=container->nextEntity(RS2::ResolveNone))
1186 if (se->isInWindow(v1, v2))
1191 DEBUG->print("GraphicView::drawWindow() end");
1195 * Draws the entities. If painter is NULL a new painter will
1196 * be created and destroyed. [NB: Not any more, we don't let the programmer try
1197 * to outsmart the toolkit anymore. :-P
1199 void GraphicView::drawIt()
1201 if (!isUpdateEnabled())
1203 //printf("GraphicView::drawIt(): isUpdateEnabled() == false!\n");
1207 if (simulationRunning)
1209 //printf("GraphicView::drawIt(): simulationRunning == true!\n");
1213 settings.beginGroup("Appearance");
1214 draftMode = settings.value("DraftMode", false).toBool();
1215 settings.endGroup();
1219 //printf("GraphicView::drawIt(): painter == NULL!\n");
1225 // drawing paper border:
1226 if (isPrintPreview())
1228 // drawing meta grid:
1232 // drawing entities:
1233 //#warning "!!! This looks like a bug, no match for 'drawEntity(Entity *, bool) !!!"
1234 // and indeed it *is* a bug... true is converted to 1.0 here. Dumb, dumb, dumb.
1235 drawEntity(container);//, true);
1237 // drawing zero points:
1238 if (!isPrintPreview())
1245 if (!isPrintPreview())
1250 * Sets the pen of the painter object to the suitable pen for the given
1253 void GraphicView::setPenForEntity(Entity * e)
1255 if (drawingMode == RS2::ModePreview /*|| draftMode==true*/)
1258 if (!painter || painter->isPreviewMode())
1261 // set color of entity
1262 // Getting pen from entity (or layer)
1263 Pen pen = e->getPen(true);
1265 int w = pen.getWidth();
1273 double uf = 1.0; // unit factor
1274 double wf = 1.0; // width factor
1275 Drawing * drawing = container->GetDrawing();
1279 uf = Units::convert(1.0, RS2::Millimeter, drawing->getUnit());
1281 if ((isPrinting() || isPrintPreview()) && drawing->getPaperScale() > 1.0e-6)
1282 wf = 1.0 / drawing->getPaperScale();
1285 pen.setScreenWidth(toGuiDX(w / 100.0 * uf * wf));
1289 //pen.setWidth(RS2::Width00);
1290 pen.setScreenWidth(0);
1293 // prevent drawing with 1-width which is slow:
1294 if (Math::round(pen.getScreenWidth()) == 1)
1295 pen.setScreenWidth(0.0);
1297 // prevent background color on background drawing:
1298 if (pen.getColor().stripFlags() == background.stripFlags())
1299 pen.setColor(foreground);
1301 // this entity is selected:
1302 if (e->isSelected())
1304 pen.setLineType(RS2::DotLine);
1305 //pen.setColor(Color(0xa5,0x47,0x47));
1306 pen.setColor(selectedColor);
1309 // this entity is highlighted:
1310 if (e->isHighlighted())
1312 //pen.setColor(Color(0x73, 0x93, 0x73));
1313 pen.setColor(highlightedColor);
1316 // deleting not drawing:
1317 if (getDeleteMode())
1318 pen.setColor(background);
1320 painter->setPen(pen);
1324 * Draws an entity. Might be recusively called e.g. for polylines.
1325 * If the class wide painter is NULL a new painter will be created
1326 * and destroyed afterwards.
1328 * @param patternOffset Offset of line pattern (used for connected
1329 * lines e.g. in splines).
1330 * @param db Double buffering on (recommended) / off
1332 void GraphicView::drawEntity(Entity * e, double patternOffset, bool db)
1334 //DEBUG->print("GraphicView::drawEntity() begin");
1336 // update is diabled:
1337 if (!isUpdateEnabled())
1340 // given entity is NULL:
1344 // entity is not visible:
1345 if (!e->isVisible())
1348 // test if the entity is in the viewport
1349 if (!e->isContainer() && !isPrinting()
1350 && (!painter || !painter->isPreviewMode())
1351 && (toGuiX(e->getMax().x) < 0 || toGuiX(e->getMin().x) > getWidth()
1352 || toGuiY(e->getMin().y) < 0 || toGuiY(e->getMax().y) > getHeight()))
1354 //printf("GraphicView::drawEntity(): Bailing out of big test!!!\n");
1359 //DEBUG->print("recursion 1: %d", drawRecursion);
1364 //DEBUG->print("draw plain");
1367 // large texts as rectangles:
1368 if (e->rtti() == RS2::EntityText)
1370 if (toGuiDX(((Text *)e)->getHeight()) < 4 || e->countDeep() > 100)
1371 painter->drawRect(toGui(e->getMin()), toGui(e->getMax()));
1373 drawEntityPlain(e, patternOffset);
1375 // all images as rectangles:
1376 else if (e->rtti() == RS2::EntityImage)
1377 painter->drawRect(toGui(e->getMin()), toGui(e->getMax()));
1379 else if (e->rtti() == RS2::EntityHatch)
1384 drawEntityPlain(e, patternOffset);
1387 drawEntityPlain(e, patternOffset);
1389 // draw reference points:
1390 if (e->isSelected())
1392 if (!e->isParentSelected())
1394 VectorSolutions s = e->getRefPoints();
1396 for(int i=0; i<s.getNumber(); ++i)
1399 Color col = Color(0, 0, 255);
1401 if (e->rtti() == RS2::EntityPolyline)
1403 if (i == 0 || i == s.getNumber() - 1)
1408 // col = QColor(0, 64, 255);
1409 col = Color(0, 64, 255);
1414 // col = QColor(0, 0, 128);
1415 col = Color(0, 0, 128);
1420 if (getDeleteMode())
1421 painter->drawHandle(toGui(s.get(i)), background, sz);
1423 painter->drawHandle(toGui(s.get(i)), col, sz);
1428 //DEBUG->print("draw plain OK");
1429 //DEBUG->print("GraphicView::drawEntity() end");
1434 * The painter must be initialized and all the attributes (pen) must be set.
1436 void GraphicView::drawEntityPlain(Entity * e, double patternOffset/*= 0.0*/)
1438 //Problems can still occur here when passing in a deleted object... It won't be
1439 //NULL, but it will cause a segfault here...
1442 //printf("GraphicView::drawEntityPlain(): Entity passed in is NULL!\n");
1446 //printf("GraphicView::drawEntityPlain(): Passing in painter=%08X, view=%08X\n", painter, this);
1447 e->draw(painter, this, patternOffset);
1451 * Simulates this drawing in slow motion.
1453 void GraphicView::simulateIt()
1455 if (simulationRunning)
1458 simulationRunning = true;
1459 simulationLast = Vector(0.0, 0.0);
1463 // drawing paper border:
1464 if (isPrintPreview())
1467 // drawing meta grid:
1468 if (!isPrintPreview())
1472 if (!isPrintPreview())
1475 // drawing entities:
1476 Pen pen(foreground, RS2::Width00, RS2::SolidLine);
1477 simulateEntity(container, pen);
1479 // drawing zero points:
1480 if (!isPrintPreview())
1486 simulationRunning = false;
1490 * Simulates the given entity.
1492 * @param smooth If true, the entity will be drawn slowly (pixel by pixel).
1494 void GraphicView::simulateEntity(Entity * e, const Pen & pen)
1499 if (e->isContainer())
1501 EntityContainer * ec = (EntityContainer *)e;
1503 for(Entity * en=ec->firstEntity(RS2::ResolveNone);
1504 en!=NULL; en=ec->nextEntity(RS2::ResolveNone))
1506 if (en->isVisible() && en->isUndone() == false)
1509 if (en->isAtomic() && simulationRapid)
1511 Vector sp = ((AtomicEntity *)en)->getStartpoint();
1513 if (sp.distanceTo(simulationLast) > 1.0e-4)
1515 Pen rpen(Color(0, 0, 255), RS2::Width00, RS2::SolidLine);
1516 Line rapidLine(NULL, LineData(simulationLast, sp));
1517 simulateEntity(&rapidLine, rpen);
1521 if (en->isHighlighted())
1523 Pen hpen(highlightedColor, RS2::Width00, RS2::SolidLine);
1524 simulateEntity(en, hpen);
1527 simulateEntity(en, pen);
1530 simulationLast = ((AtomicEntity *)en)->getEndpoint();
1532 if (!simulationSmooth)
1533 simulationDelay(true);
1539 if (simulationSmooth)
1543 case RS2::EntityLine:
1545 Line * line = (Line *)e;
1546 drawLineSmooth(toGui(line->getStartpoint()), toGui(line->getEndpoint()), pen);
1551 case RS2::EntityArc:
1553 Arc * arc = (Arc *)e;
1554 drawArcSmooth(toGui(arc->getCenter()), toGuiDX(arc->getRadius()),
1555 arc->getAngle1(), arc->getAngle2(), arc->isReversed(), pen);
1559 case RS2::EntityCircle:
1561 Circle * circle = (Circle *)e;
1562 drawArcSmooth(toGui(circle->getCenter()), toGuiDX(circle->getRadius()),
1563 0.0, 2.0 * M_PI, false, pen);
1573 painter->setPen(pen);
1580 * Delay for slow motion simulation.
1582 * @param step true: stepping mode (entity by entity simulation). adds a delay.
1584 void GraphicView::simulationDelay(bool step)
1587 settings.beginGroup("CAM");
1588 double fact = settings.value("SimulationFactor", 12000.0).toDouble();
1589 settings.endGroup();
1591 // simulationSpeed: 0..100
1594 delay = (int)(((1.0 / (simulationSpeed + 1.0)) * fact) - (fact / 100.0));
1599 static int call = 0;
1601 if (call >= (fact - delay) / 1000)
1604 for(int i=0; i<delay; ++i)
1605 RS_APP->processEvents(10);
1610 delay = (int)(((1.0 / (simulationSpeed + 1.0)) * fact) - (fact / 100.0));
1617 for(int i=0; i<delay; ++i)
1619 #warning "Qt3->4 conversion: commented out problem line... !!! FIX !!!"
1620 // RS_APP->processEvents(10);
1626 * Draws a line slowly from (x1, y1) to (x2, y2). This is used for simulation only.
1628 void GraphicView::drawLineSmooth(const Vector & p1, const Vector & p2, const Pen & pen)
1630 double alpha = p1.angleTo(p2);
1631 double xStep, yStep;
1634 if (Math::cmpDouble(alpha, 0.0) || Math::cmpDouble(alpha, 2 * M_PI))
1640 else if (Math::cmpDouble(alpha, M_PI / 2.0))
1646 else if (Math::cmpDouble(alpha, M_PI))
1652 else if (Math::cmpDouble(alpha, M_PI / 2.0 * 3.0))
1658 else if (fabs(p2.x - p1.x) > fabs(p2.y - p1.y))
1665 yStep = tan(alpha) * xStep;
1675 xStep = yStep / tan(alpha);
1684 if (lx >= 0.0 && lx <= (double)getWidth() && ly >= 0.0 && ly <= (double)getHeight())
1686 painter->setPen(pen);
1687 painter->drawGridPoint(Vector(lx, ly));
1696 while ((xIsOne && ((lx >= p1.x && lx <= p2.x) || (lx >= p2.x && lx <= p1.x)))
1697 || (!xIsOne && ((ly >= p1.y && ly <= p2.y) || (ly >= p2.y && ly <= p1.y))));
1700 void GraphicView::drawArcSmooth(const Vector & center, double radius, double a1, double a2, bool rev,
1705 painter->setPen(pen);
1706 painter->drawGridPoint(center);
1710 int ix1 = Math::round(center.x + cos(a1) * radius);
1711 int iy1 = Math::round(center.y - sin(a1) * radius);
1712 int ix2 = Math::round(center.x + cos(a2) * radius);
1713 int iy2 = Math::round(center.y - sin(a2) * radius);
1714 int k2x = 0; // Next point on circle
1716 int k1x = ix1; // Prev point on circle
1718 double aStep; // Angle Step (rad)
1719 double a; // Actual Angle (rad)
1720 double a2cp = a2; // Copy of a2
1722 if (1.0 / (radius * factor.x) <= 1.0)
1723 aStep = asin(1.0 / (radius * factor.x));
1732 // Arc Counterclockwise:
1734 if (a1 > a2cp - 0.01)
1737 for(a=a1+aStep; a<=a2cp; a+=aStep)
1739 k2x = Math::round(center.x+cos(a)*radius);
1740 k2y = Math::round(center.y-sin(a)*radius);
1741 painter->setPen(pen);
1743 if ((k2x >= 0 && k2x <= painter->getWidth()
1744 && k2y >= 0 && k2y <= painter->getHeight())
1745 || (k1x >= 0 && k1x <= painter->getWidth()
1746 && k1y >= 0 && k1y <= painter->getHeight()))
1748 painter->drawLine(Vector(k1x, k1y), Vector(k2x, k2y));
1756 painter->setPen(pen);
1757 painter->drawLine(Vector(k2x, k2y), Vector(ix2, iy2));
1763 if (a1 < a2cp + 0.01)
1766 for(a=a1-aStep; a>=a2cp; a-=aStep)
1768 k2x = Math::round(center.x + cos(a) * radius);
1769 k2y = Math::round(center.y - sin(a) * radius);
1770 painter->setPen(pen);
1772 if ((k2x >=0 && k2x <= painter->getWidth()
1773 && k2y >= 0 && k2y <= painter->getHeight())
1774 || (k1x >= 0 && k1x <= painter->getWidth()
1775 && k1y >= 0 && k1y <= painter->getHeight()))
1777 painter->drawLine(Vector(k1x, k1y), Vector(k2x, k2y));
1785 painter->setPen(pen);
1786 painter->drawLine(Vector(k2x, k2y), Vector(ix2, iy2));
1792 * @return Pointer to the static pattern struct that belongs to the
1793 * given pattern type or NULL.
1795 LineTypePattern * GraphicView::getPattern(RS2::LineType t)
1799 case RS2::SolidLine:
1800 return &patternSolidLine;
1804 return &patternDotLine;
1807 return &patternDotLine2;
1809 case RS2::DotLineX2:
1810 return &patternDotLineX2;
1814 return &patternDashLine;
1816 case RS2::DashLine2:
1817 return &patternDashLine2;
1819 case RS2::DashLineX2:
1820 return &patternDashLineX2;
1823 case RS2::DashDotLine:
1824 return &patternDashDotLine;
1826 case RS2::DashDotLine2:
1827 return &patternDashDotLine2;
1829 case RS2::DashDotLineX2:
1830 return &patternDashDotLineX2;
1833 case RS2::DivideLine:
1834 return &patternDivideLine;
1836 case RS2::DivideLine2:
1837 return &patternDivideLine2;
1839 case RS2::DivideLineX2:
1840 return &patternDivideLineX2;
1843 case RS2::CenterLine:
1844 return &patternCenterLine;
1846 case RS2::CenterLine2:
1847 return &patternCenterLine2;
1849 case RS2::CenterLineX2:
1850 return &patternCenterLineX2;
1853 case RS2::BorderLine:
1854 return &patternBorderLine;
1856 case RS2::BorderLine2:
1857 return &patternBorderLine2;
1859 case RS2::BorderLineX2:
1860 return &patternBorderLineX2;
1863 case RS2::LineByLayer:
1864 return &patternBlockLine;
1866 case RS2::LineByBlock:
1867 return &patternBlockLine;
1877 * This virtual method can be overwritten to draw the absolute
1878 * zero. It's called from within drawIt(). The default implemetation
1879 * draws a simple red round zero point.
1881 * Actually, we have to rework the rendering code because the way that QCad did
1882 * it was wrong on so many levels... Part of that is making sure the rendering
1883 * path is 100% clear!
1887 void GraphicView::drawAbsoluteZero()
1894 // Pen p(Qt::red, RS2::Width00, RS2::SolidLine);
1895 //Using Qt::red doesn't seem to work here...
1896 //It's because Qt colors and Color are not 100% compatible...
1897 Pen p(Color(255, 0, 0), RS2::Width00, RS2::SolidLine);
1900 painter->drawLine(Vector(toGuiX(0.0) - zr, toGuiY(0.0)),
1901 Vector(toGuiX(0.0) + zr, toGuiY(0.0)));
1903 painter->drawLine(Vector(toGuiX(0.0), toGuiY(0.0) - zr),
1904 Vector(toGuiX(0.0), toGuiY(0.0) + zr));
1908 * This virtual method can be overwritten to draw the relative
1909 * zero point. It's called from within drawIt(). The default implemetation
1910 * draws a simple red round zero point.
1914 void GraphicView::drawRelativeZero()
1916 if (!relativeZero.valid || !painter)
1921 if (!relativeZero.valid)
1922 printf("GraphicView::drawRelativeZero(): relativeZero is NOT valid!!!\n");
1925 printf("GraphicView::drawRelativeZero(): painter is NOT valid!!!\n");
1931 //Using Qt::red doesn't seem to work here...
1932 Pen p(Color(255, 0, 0), RS2::Width00, RS2::SolidLine);
1934 //This doesn't work--this is NOT a QPainter!
1935 // painter->setBrush(Qt::NoBrush);
1936 // painter->setBackgroundMode(Qt::TransparentMode); // will that do it???
1937 painter->disableBrush();
1938 // painter->setXORMode();
1942 painter->drawLine(Vector(toGuiX(relativeZero.x) - zr, toGuiY(relativeZero.y)),
1943 Vector(toGuiX(relativeZero.x) + zr, toGuiY(relativeZero.y)));
1944 painter->drawLine(Vector(toGuiX(relativeZero.x), toGuiY(relativeZero.y) - zr),
1945 Vector(toGuiX(relativeZero.x), toGuiY(relativeZero.y) + zr));
1946 painter->drawCircle(toGui(relativeZero), zr);
1947 // painter->setNormalMode();
1951 * Draws the paper border (for print previews).
1955 void GraphicView::drawPaper()
1960 Drawing * drawing = container->GetDrawing();
1965 if (drawing->getPaperScale() < 1.0e-6)
1972 painter->setPen(Pen(Qt::gray));
1974 Vector pinsbase = drawing->getPaperInsertionBase();
1975 Vector size = drawing->getPaperSize();
1976 double scale = drawing->getPaperScale();
1978 Vector v1 = toGui((Vector(0, 0) - pinsbase) / scale);
1979 Vector v2 = toGui((size - pinsbase) / scale);
1982 painter->fillRect(0,0, getWidth(), getHeight(), Color(200, 200, 200));
1985 painter->fillRect((int)(v1.x) + 6, (int)(v1.y) + 6,
1986 (int)((v2.x - v1.x)), (int)((v2.y - v1.y)), Color(64, 64, 64));
1989 painter->fillRect((int)(v1.x), (int)(v1.y),
1990 (int)((v2.x - v1.x)), (int)((v2.y - v1.y)), Color(64, 64, 64));
1993 painter->fillRect((int)(v1.x) + 1, (int)(v1.y) - 1,
1994 (int)((v2.x - v1.x)) - 2, (int)((v2.y - v1.y)) + 2, Color(255, 255, 255));
2002 void GraphicView::drawGrid()
2004 if (!grid || isGridOn() == false)
2006 // printf("GraphicView::drawGrid(): Aborting: grid=%08X, isGridOn=%s\n", grid, (isGridOn() ? "true" : "false"));
2011 painter->setPen(gridColor);
2013 //Problem here: pts is NULL!
2014 Vector * pts = grid->getPoints();
2018 for(int i=0; i<grid->count(); ++i)
2019 painter->drawGridPoint(toGui(pts[i]));
2022 // printf("GraphicView::drawGrid(): pts == NULL!\n");
2025 QString info = grid->getInfo();
2026 updateGridStatusWidget(info);
2030 * Draws the meta grid.
2034 void GraphicView::drawMetaGrid()
2036 if (!grid || isGridOn() == false)
2042 Pen pen(metaGridColor, RS2::Width00, RS2::DotLine);
2043 painter->setPen(pen);
2046 double * mx = grid->getMetaX();
2047 double * my = grid->getMetaY();
2051 for(int i=0; i<grid->countMetaX(); ++i)
2052 painter->drawLine(Vector(toGuiX(mx[i]), 0), Vector(toGuiX(mx[i]), getHeight()));
2057 for(int i=0; i<grid->countMetaY(); ++i)
2058 painter->drawLine(Vector(0, toGuiY(my[i])), Vector(getWidth(), toGuiY(my[i])));
2063 * Updates the grid if there is one.
2065 void GraphicView::updateGrid()
2071 Grid * GraphicView::getGrid()
2076 void GraphicView::updateGridStatusWidget(const QString & /*text*/)
2080 RS2::SnapMode GraphicView::getDefaultSnapMode()
2082 return defaultSnapMode;
2085 RS2::SnapRestriction GraphicView::getSnapRestriction()
2087 return defaultSnapRes;
2091 * Sets the default snap mode used by newly created actions.
2093 void GraphicView::setDefaultSnapMode(RS2::SnapMode sm)
2095 defaultSnapMode = sm;
2097 // Don't need this shiaut anymore
2100 eventHandler->setSnapMode(sm);
2102 //OK, the above sets the snap mode in the snapper that's derived from
2103 //the RS_ActionInterface and Snapper. So the following should fix
2104 //us up, hm notwithstanding. [and it does. :-)]
2106 snapper.setSnapMode(sm);
2111 * Sets a snap restriction (e.g. orthogonal).
2113 void GraphicView::setSnapRestriction(RS2::SnapRestriction sr)
2115 defaultSnapRes = sr;
2117 // Don't need this shiaut anymore
2119 if (eventHandler != NULL)
2120 eventHandler->setSnapRestriction(sr);
2125 * Translates a vector in real coordinates to a vector in screen coordinates.
2127 Vector GraphicView::toGui(Vector v)
2129 return Vector(toGuiX(v.x), toGuiY(v.y), 0.0);
2133 * Translates a real coordinate in X to a screen coordinate X.
2134 * @param visible Pointer to a boolean which will contain true
2135 * after the call if the coordinate is within the visible range.
2137 double GraphicView::toGuiX(double x, bool * visible/*= NULL*/)
2139 if (visible != NULL)
2141 double res = x * factor.x + offsetX;
2143 if (res > 0.0 && res < getWidth())
2149 return x * factor.x + offsetX;
2153 * Translates a real coordinate in Y to a screen coordinate Y.
2155 double GraphicView::toGuiY(double y)
2157 return -y * factor.y + getHeight() - offsetY;
2161 * Translates a real coordinate distance to a screen coordinate distance.
2163 double GraphicView::toGuiDX(double d)
2165 return d * factor.x;
2169 * Translates a real coordinate distance to a screen coordinate distance.
2171 double GraphicView::toGuiDY(double d)
2173 return d * factor.y;
2177 * Translates a vector in screen coordinates to a vector in real coordinates.
2179 Vector GraphicView::toGraph(Vector v)
2181 return Vector(toGraphX(Math::round(v.x)), toGraphY(Math::round(v.y)), 0.0);
2185 * Translates two screen coordinates to a vector in real coordinates.
2187 Vector GraphicView::toGraph(int x, int y)
2189 return Vector(toGraphX(x), toGraphY(y), 0.0);
2193 * Translates a screen coordinate in X to a real coordinate X.
2195 double GraphicView::toGraphX(int x)
2197 return (x - offsetX) / factor.x;
2201 * Translates a screen coordinate in Y to a real coordinate Y.
2203 double GraphicView::toGraphY(int y)
2205 return -(y - getHeight() + offsetY) / factor.y;
2209 * Translates a screen coordinate distance to a real coordinate distance.
2211 double GraphicView::toGraphDX(int d)
2213 return d / factor.x;
2217 * Translates a screen coordinate distance to a real coordinate distance.
2219 double GraphicView::toGraphDY(int d)
2221 return d / factor.y;
2225 * (Un-)Locks the position of the relative zero.
2227 * @param lock true: lock, false: unlock
2229 void GraphicView::lockRelativeZero(bool lock)
2231 relativeZeroLocked = lock;
2235 * @return true if the position of the realtive zero point is
2238 bool GraphicView::isRelativeZeroLocked()
2240 return relativeZeroLocked;
2244 * @return Relative zero coordinate.
2246 Vector GraphicView::getRelativeZero()
2248 return relativeZero;
2252 * Sets the relative zero coordinate (if not locked)
2253 * without deleting / drawing the point.
2255 void GraphicView::setRelativeZero(const Vector & pos)
2257 if (!relativeZeroLocked)
2262 * Sets the relative zero coordinate, deletes the old position
2263 * on the screen and draws the new one.
2265 void GraphicView::moveRelativeZero(const Vector & pos)
2267 setRelativeZero(pos);
2270 EventHandler * GraphicView::getEventHandler()
2272 return eventHandler;
2276 * Enables or disables print preview.
2278 void GraphicView::setPrintPreview(bool pv)
2284 * @retval true This is a print preview graphic view.
2285 * @retval false Otherwise.
2287 bool GraphicView::isPrintPreview()
2289 return printPreview;
2293 * Enables or disables printing.
2295 void GraphicView::setPrinting(bool p)
2301 * @retval true This is a a graphic view for printing.
2302 * @retval false Otherwise.
2304 bool GraphicView::isPrinting()
2310 * @retval true Draft mode is on for this view (all lines with 1 pixel / no style scaling).
2311 * @retval false Otherwise.
2313 bool GraphicView::isDraftMode()
2319 * Sets the simulation speed in percentage.
2321 void GraphicView::setSimulationSpeed(int s)
2323 simulationSpeed = s;
2327 * @return the simulation speed in percentage.
2329 int GraphicView::getSimulationSpeed()
2331 return simulationSpeed;
2335 * Sets the simulation smooth mode.
2337 void GraphicView::setSimulationSmooth(bool s)
2339 simulationSmooth = s;
2342 * Sets the simulation rapid mode.
2344 void GraphicView::setSimulationRapid(bool r)
2346 simulationRapid = r;
2350 * @return the simulation rapid mode.
2352 bool GraphicView::getSimulationRapid()
2354 return simulationRapid;
2358 * Catches an entity which is close to the given position 'pos'.
2360 * @param pos A graphic coordinate.
2361 * @param level The level of resolving for iterating through the entity
2363 * @return Pointer to the entity or NULL.
2365 Entity * GraphicView::CatchEntity(const Vector & pos, RS2::ResolveLevel level)
2367 DEBUG->print("GraphicView::CatchEntity");
2369 // Set default distance for points inside solids
2370 double dist = toGraphDX(snapRange) * 0.9;
2371 Entity * entity = container->getNearestEntity(pos, &dist, level);
2376 if (entity && entity->getParent())
2377 idx = entity->getParent()->findEntity(entity);
2378 // END DEBUGGING INFO
2380 if (entity && dist <= toGraphDX(snapRange))
2383 DEBUG->print("GraphicView::CatchEntity: found: idx=%d", idx);
2387 DEBUG->print("GraphicView::CatchEntity: not found");
2392 * Catches an entity which is close to the mouse cursor.
2394 * @param e A mouse event.
2395 * @param level The level of resolving for iterating through the entity
2397 * @return Pointer to the entity or NULL.
2399 Entity * GraphicView::CatchEntity(QMouseEvent * e, RS2::ResolveLevel level)
2401 return CatchEntity(Vector(toGraphX(e->x()), toGraphY(e->y())), level);
2405 * @return Pointer to the entity which was the key entity for the last
2406 * successful snapping action. If the snap mode is "end point" the key entity
2407 * is the entity whose end point was caught. If the snap mode didn't require an
2408 * entity (e.g. free, grid) this method will return NULL.
2410 Entity * GraphicView::GetSnapperEntity()
2416 * Snap to a coordinate in the drawing using the current snap mode.
2418 * @param e A mouse event.
2419 * @return The coordinates of the point or an invalid vector.
2421 Vector GraphicView::SnapPoint(QMouseEvent * e)
2423 DEBUG->print("GraphicView::SnapPoint");
2424 /*Vector*/ snapSpot = Vector(false);
2428 DEBUG->print(Debug::D_WARNING, "GraphicView::SnapPoint: QMouseEvent is NULL");
2432 Vector mouseCoord = toGraph(e->x(), e->y());
2434 // switch (snapMode)
2435 switch (defaultSnapMode)
2438 // snapSpot = snapFree(mouseCoord);
2440 snapSpot = mouseCoord;
2443 case RS2::SnapEndpoint:
2444 // snapSpot = snapEndpoint(mouseCoord);
2445 snapSpot = container->getNearestEndpoint(mouseCoord, NULL);
2449 snapSpot = SnapGrid(mouseCoord);
2452 case RS2::SnapOnEntity:
2453 // snapSpot = snapOnEntity(mouseCoord);
2454 snapSpot = container->getNearestPointOnEntity(mouseCoord, true, NULL, &snapEntity);
2457 case RS2::SnapCenter:
2458 // snapSpot = snapCenter(mouseCoord);
2459 snapSpot = container->getNearestCenter(mouseCoord, NULL);
2462 case RS2::SnapMiddle:
2463 // snapSpot = snapMiddle(mouseCoord);
2464 snapSpot = container->getNearestMiddle(mouseCoord, NULL);
2468 // snapSpot = snapDist(mouseCoord);
2469 snapSpot = container->getNearestDist(snapDistance, mouseCoord, NULL);
2472 case RS2::SnapIntersection:
2473 // snapSpot = snapIntersection(mouseCoord);
2474 snapSpot = container->getNearestIntersection(mouseCoord, NULL);
2481 // This is declared here because I really, really hate extraneous braces in
2482 // my switch statements. :-P
2483 Vector relZero = getRelativeZero();
2484 Vector restrictX = Vector(relZero.x, snapSpot.y);
2485 Vector restrictY = Vector(snapSpot.x, relZero.y);
2486 // Vector snapCoord;
2487 // Handle snap restrictions that can be activated in addition to the ones above:
2489 switch (defaultSnapRes)
2491 case RS2::RestrictOrthogonal:
2492 //// snapCoord = restrictOrthogonal(snapSpot);
2493 // rz = graphicView->getRelativeZero();
2494 // retx = Vector(rz.x, snapSpot.y);
2495 // rety = Vector(snapSpot.x, rz.y);
2496 snapCoord = (restrictX.distanceTo(snapSpot) < restrictY.distanceTo(snapSpot) ?
2497 restrictX : restrictY);
2499 case RS2::RestrictHorizontal:
2500 //// snapCoord = restrictHorizontal(snapSpot);
2501 // rz = graphicView->getRelativeZero();
2502 // snapCoord = Vector(snapSpot.x, rz.y);
2503 snapCoord = restrictY;
2505 case RS2::RestrictVertical:
2506 //// snapCoord = restrictVertical(snapSpot);
2507 // rz = graphicView->getRelativeZero();
2508 // snapCoord = Vector(rz.x, snapSpot.y);
2509 snapCoord = restrictX;
2512 case RS2::RestrictNothing:
2513 snapCoord = snapSpot;
2518 DIALOGFACTORY->updateCoordinateWidget(snapCoord, snapCoord - relZero);
2520 DEBUG->print("GraphicView::SnapPoint: OK");
2526 * Snaps to a grid point.
2528 * @param coord The mouse coordinate.
2529 * @return The coordinates of the point or an invalid vector.
2531 Vector GraphicView::SnapGrid(Vector coord)
2533 DEBUG->print("GraphicView::snapGrid begin");
2538 DEBUG->print("GraphicView::snapGrid 001");
2542 DEBUG->print("GraphicView::snapGrid 002");
2543 Vector * pts = grid->getPoints();
2544 DEBUG->print("GraphicView::snapGrid 003");
2547 DEBUG->print("GraphicView::snapGrid 004");
2549 for(int i=0; i<grid->count(); ++i)
2551 double d = pts[i].distanceTo(coord);
2560 DEBUG->print("GraphicView::snapGrid 005");
2565 DEBUG->print("GraphicView::snapGrid 006");
2570 DEBUG->print("GraphicView::snapGrid end");
2575 void GraphicView::DrawSnapper(PaintInterface * painter)
2577 //Is "finished" used at all? Seems it's used only in ActionInterface, and it's commented out
2578 // if (finished || !snapSpot.valid || !snapCoord.valid)
2579 if (!snapSpot.valid || !snapCoord.valid)
2582 printf("DrawSnapper: snapSpot=%s, snapCoord=%s...\n", (snapSpot.valid ? "valid" : "INVALID"), (snapCoord.valid ? "valid" : "INVALID"));
2589 // Snap point (need to make sure the brush is NULL!)
2590 // painter->setPen(Pen(Color(0, 127, 255), RS2::Width00, RS2::DashLine));
2591 painter->setPen(Pen(Color(255, 127, 0), RS2::Width00, RS2::DashLine));
2592 painter->drawCircle(toGui(snapCoord), 4);
2597 painter->setPen(Pen(Color(0, 255, 255), RS2::Width00, RS2::DashLine));
2598 painter->drawLine(Vector(0, toGuiY(snapCoord.y)),
2599 Vector(getWidth(), toGuiY(snapCoord.y)));
2600 painter->drawLine(Vector(toGuiX(snapCoord.x), 0),
2601 Vector(toGuiX(snapCoord.x), getHeight()));
2605 if (snapCoord != snapSpot)
2607 painter->drawLine(toGui(snapSpot) + Vector(-5, 0), toGui(snapSpot) + Vector(-1, 4));
2608 painter->drawLine(toGui(snapSpot) + Vector(0, 5), toGui(snapSpot) + Vector(4, 1));
2609 painter->drawLine(toGui(snapSpot) + Vector(5, 0), toGui(snapSpot) + Vector(1, -4));
2610 painter->drawLine(toGui(snapSpot) + Vector(0, -5), toGui(snapSpot) + Vector(-4, -1));
2614 void GraphicView::SetSnapperVisible(bool visibility/*= true*/)
2616 snapperVisible = visibility;
2619 bool GraphicView::SnapperVisible(void)
2621 return snapperVisible;
2626 only place this is called is in ActionInterface. And its only function is to
2627 have it not drawn anymore. But, the GraphicView seems to draw it anyway... So
2628 some other approach is needed...
2630 void Snapper::finish()
2635 /** Sets a new snap mode. */
2636 void Snapper::setSnapMode(RS2::SnapMode snapMode)
2638 this->snapMode = snapMode;
2641 /** Sets a new snap restriction. */
2642 void Snapper::setSnapRestriction(RS2::SnapRestriction snapRes)
2644 this->snapRes = snapRes;
2647 RS2::SnapMode Snapper::getSnapMode(void)
2652 RS2::SnapRestriction Snapper::getSnapRestriction(void)
2658 * Sets the snap range in pixels for catchEntity().
2660 * @see catchEntity()
2662 void Snapper::setSnapRange(int r)
2668 I think that these suspend() & resume() functions are not used anymore...
2671 * Suspends this snapper while another action takes place.
2673 /*virtual*/ void Snapper::suspend()
2675 #warning "!!! This may need to have SetVisibility() called !!!"
2677 snapSpot = snapCoord = Vector(false);
2681 * Resumes this snapper after it has been suspended.
2683 /*virtual*/ void Snapper::resume()
2685 #warning "!!! This may need to have SetVisibility() called !!!"
2690 * Hides the snapper options.
2692 /*virtual*/ void Snapper::hideOptions()
2694 if (snapMode == RS2::SnapDist && DIALOGFACTORY)
2695 DIALOGFACTORY->requestSnapDistOptions(distance, false);
2699 * Shows the snapper options.
2701 /*virtual*/ void Snapper::showOptions()
2703 if (snapMode == RS2::SnapDist && DIALOGFACTORY)
2704 DIALOGFACTORY->requestSnapDistOptions(distance, true);