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);
40 previousFactor = Vector(1.0, 1.0);
44 eventHandler = new EventHandler(this);
46 metaGridColor = Color(64, 64, 64);
47 grid = new Grid(this);
58 relativeZero = Vector(false);
59 relativeZeroLocked = false;
63 defaultSnapMode = RS2::SnapFree;
64 defaultSnapRes = RS2::RestrictNothing;
66 settings.beginGroup("Appearance");
67 setBackground(QColor(settings.value("BackgroundColor", "#000000").toString()));
68 setGridColor(QColor(settings.value("GridColor", "#7F7F7F").toString()));
69 setMetaGridColor(QColor(settings.value("MetaGridColor", "#3F3F3F").toString()));
70 setSelectedColor(QColor(settings.value("SelectedColor", "#A54747").toString()));
71 setHighlightedColor(QColor(settings.value("HighlightedColor", "#739373").toString()));
76 simulationSpeed = 100;
77 simulationSmooth = false;
78 simulationRapid = false;
79 simulationRunning = false;
81 // Snapper settings...
83 snapSpot = Vector(false);
84 snapCoord = Vector(false);
85 snapperVisible = false;
88 settings.beginGroup("Snap");
89 snapRange = settings.value("Range", 20).toInt();
91 settings.beginGroup("Appearance");
92 showCrosshairs = settings.value("ShowCrosshairs", true).toBool();
95 // Sanity check for snapRange
103 GraphicView::~GraphicView()
109 * Must be called by any derrived class in the destructor.
111 void GraphicView::cleanUp()
117 * @return Pointer to the graphic entity if the entity container
118 * connected to this view is a graphic and valid.
121 Drawing * GraphicView::getGraphic()
123 if (container && container->rtti() == RS2::EntityGraphic)
124 return (Drawing *)container;
130 * Sets the drawing mode.
132 void GraphicView::setDrawingMode(RS2::DrawingMode m)
138 * @return Current drawing mode.
140 RS2::DrawingMode GraphicView::getDrawingMode()
146 * Activates or deactivates the delete mode.
148 void GraphicView::setDeleteMode(bool m)
154 * @reval true Deleting instead of drawing.
155 * false Normal drawing mode.
157 bool GraphicView::getDeleteMode()
162 /** This virtual method must be overwritten and is then
163 called whenever the view changed */
164 void GraphicView::adjustOffsetControls()
168 /** This virtual method must be overwritten and is then
169 called whenever the view changed */
170 void GraphicView::adjustZoomControls()
175 * Sets the background color. Note that applying the background
176 * color for the widget is up to the implementing class.
178 void GraphicView::setBackground(const Color & bg)
182 // bright background:
183 if (bg.red() + bg.green() + bg.blue() > 380)
184 // foreground = Qt::black;
185 foreground = Color(0, 0, 0);
187 // foreground = Qt::white;
188 foreground = Color(255, 255, 255);
192 * @return Current background color.
194 Color GraphicView::getBackground()
200 * @return Current foreground color.
202 Color GraphicView::getForeground()
208 * Sets the grid color.
210 void GraphicView::setGridColor(const Color & c)
216 * Sets the meta grid color.
218 void GraphicView::setMetaGridColor(const Color & c)
224 * Sets the selection color.
226 void GraphicView::setSelectedColor(const Color & c)
232 * Sets the highlight color.
234 void GraphicView::setHighlightedColor(const Color & c)
236 highlightedColor = c;
240 * This virtual method can be overwritten to set the mouse
241 * cursor to the given type.
243 void GraphicView::setMouseCursor(RS2::CursorType /*c*/)
247 EntityContainer * GraphicView::getContainer()
252 void GraphicView::setFactor(double f)
258 Vector GraphicView::getFactor()
264 * Sets the offset of the graphic.
266 void GraphicView::setOffset(int ox, int oy)
272 void GraphicView::setOffsetX(int ox)
277 void GraphicView::setOffsetY(int oy)
282 int GraphicView::getOffsetX()
287 int GraphicView::getOffsetY()
293 * Sets a fixed border in pixel around the graphic. This border
294 * specifies how far the user can scroll outside the graphic
297 void GraphicView::setBorders(int left, int top, int right, int bottom)
302 borderBottom = bottom;
305 int GraphicView::getBorderLeft()
310 int GraphicView::getBorderTop()
315 int GraphicView::getBorderRight()
320 int GraphicView::getBorderBottom()
325 void GraphicView::disableUpdate()
330 void GraphicView::enableUpdate()
335 bool GraphicView::isUpdateEnabled()
337 return (updateEnabled == 0);
340 void GraphicView::freezeZoom(bool freeze)
345 bool GraphicView::isZoomFrozen()
351 * Sets the pointer to the graphic which contains the entities
352 * which are visualized by this widget.
354 void GraphicView::setContainer(EntityContainer * container)
356 this->container = container;
360 * Sets the zoom factor in X for this visualization of the graphic.
362 void GraphicView::setFactorX(double f)
369 * Sets the zoom factor in Y for this visualization of the graphic.
371 void GraphicView::setFactorY(double f)
378 * @return true if the grid is switched on.
380 bool GraphicView::isGridOn()
384 Drawing * d = container->getGraphic();
387 return d->isGridOn();
394 * Centers the drawing in x-direction.
396 void GraphicView::centerOffsetX()
398 if (container != NULL && !zoomFrozen)
399 offsetX = (int)(((getWidth() - borderLeft - borderRight)
400 - (container->getSize().x * factor.x)) / 2.0
401 - (container->getMin().x * factor.x)) + borderLeft;
405 * Centers the drawing in y-direction.
407 void GraphicView::centerOffsetY()
409 if (container != NULL && !zoomFrozen)
410 offsetY = (int)((getHeight() - borderTop - borderBottom
411 - (container->getSize().y * factor.y)) / 2.0
412 - (container->getMin().y * factor.y)) + borderBottom;
416 * Centers the given coordinate in the view in x-direction.
418 void GraphicView::centerX(double v)
421 offsetX = (int)((v * factor.x) - (double)(getWidth() - borderLeft - borderRight) / 2.0);
425 * Centers the given coordinate in the view in y-direction.
427 void GraphicView::centerY(double v)
430 offsetY = (int)((v * factor.y) - (double)(getHeight() - borderTop - borderBottom) / 2.0);
433 void GraphicView::updateView()
435 static int running = 0;
440 adjustZoomControls();
441 adjustOffsetControls();
451 * @return Current action or NULL.
453 ActionInterface * GraphicView::getDefaultAction()
455 if (eventHandler != NULL)
456 return eventHandler->getDefaultAction();
462 * Sets the default action of the event handler.
464 void GraphicView::setDefaultAction(ActionInterface * action)
467 eventHandler->setDefaultAction(action);
471 * @return Current action or NULL.
473 ActionInterface * GraphicView::getCurrentAction()
476 return eventHandler->getCurrentAction();
482 * Sets the current action of the event handler.
484 void GraphicView::setCurrentAction(ActionInterface * action)
486 DEBUG->print("GraphicView::setCurrentAction");
489 eventHandler->setCurrentAction(action);
491 DEBUG->print("GraphicView::setCurrentAction: OK");
495 * Kills all running selection actions. Called when a selection action
496 * is launched to reduce confusion.
498 void GraphicView::killSelectActions()
501 eventHandler->killSelectActions();
505 * Kills all running actions.
507 void GraphicView::killAllActions()
510 eventHandler->killAllActions();
514 * Go back in menu or current action.
516 void GraphicView::back()
518 if (eventHandler && eventHandler->hasAction())
519 eventHandler->back();
520 else if (DIALOGFACTORY)
521 DIALOGFACTORY->requestPreviousMenu();
525 * Go forward with the current action.
527 void GraphicView::enter()
529 if (eventHandler && eventHandler->hasAction())
530 eventHandler->enter();
534 * Called by the actual GUI class which implements the GraphicView
535 * interface to notify qcadlib about mouse events.
537 void GraphicView::mousePressEvent(QMouseEvent * e)
540 eventHandler->mousePressEvent(e);
544 * Called by the actual GUI class which implements the GraphicView
545 * interface to notify qcadlib about mouse events.
547 void GraphicView::mouseReleaseEvent(QMouseEvent * e)
549 DEBUG->print("GraphicView::mouseReleaseEvent");
554 if (e->button() != Qt::RightButton || eventHandler->hasAction())
556 eventHandler->mouseReleaseEvent(e);
564 DEBUG->print("GraphicView::mouseReleaseEvent: OK");
568 * Called by the actual GUI class which implements the GraphicView
569 * interface to notify qcadlib about mouse events.
571 void GraphicView::mouseMoveEvent(QMouseEvent * e)
573 DEBUG->print("GraphicView::mouseMoveEvent begin");
575 Drawing * graphic = NULL;
577 if (container->rtti() == RS2::EntityGraphic)
578 graphic = (Drawing *)container;
580 DEBUG->print("GraphicView::mouseMoveEvent 001");
588 DEBUG->print("GraphicView::mouseMoveEvent 002");
591 eventHandler->mouseMoveEvent(e);
593 DEBUG->print("GraphicView::mouseMoveEvent 003");
595 if (!eventHandler || !eventHandler->hasAction() && graphic)
597 Vector mouse = toGraph(Vector(mx, my));
598 Vector relMouse = mouse - getRelativeZero();
601 DIALOGFACTORY->updateCoordinateWidget(mouse, relMouse);
604 DEBUG->print("GraphicView::mouseMoveEvent end");
608 * Called by the actual GUI class which implements the GraphicView
609 * interface to notify qcadlib about mouse events.
611 void GraphicView::mouseLeaveEvent()
614 eventHandler->mouseLeaveEvent();
618 * Called by the actual GUI class which implements the GraphicView
619 * interface to notify qcadlib about mouse events.
621 void GraphicView::mouseEnterEvent()
624 eventHandler->mouseEnterEvent();
628 * Called by the actual GUI class which implements the GraphicView
629 * interface to notify qcadlib about key events.
631 void GraphicView::keyPressEvent(QKeyEvent * e)
634 eventHandler->keyPressEvent(e);
638 * Called by the actual GUI class which implements the GraphicView
639 * interface to notify qcadlib about key events.
641 void GraphicView::keyReleaseEvent(QKeyEvent * e)
644 eventHandler->keyReleaseEvent(e);
648 * Called by the actual GUI class which implements a command line.
650 void GraphicView::commandEvent(CommandEvent * e)
653 eventHandler->commandEvent(e);
657 * Enables coordinate input in the command line.
659 void GraphicView::enableCoordinateInput()
662 eventHandler->enableCoordinateInput();
666 * Disables coordinate input in the command line.
668 void GraphicView::disableCoordinateInput()
671 eventHandler->disableCoordinateInput();
675 * zooms in by factor f
677 void GraphicView::zoomIn(double f, const Vector & center)
681 DEBUG->print(Debug::D_WARNING, "GraphicView::zoomIn: invalid factor");
685 if (simulationRunning)
689 if (c.valid == false)
690 c = toGraph(Vector(getWidth() / 2, getHeight() / 2));
692 zoomWindow(toGraph(Vector(0, 0)).scale(c, Vector(1.0 / f, 1.0 / f)),
693 toGraph(Vector(getWidth(), getHeight())).scale(c, Vector(1.0 / f, 1.0 / f)));
697 * zooms in by factor f in x
699 void GraphicView::zoomInX(double f)
701 if (simulationRunning)
705 offsetX = (int)((offsetX - getWidth() / 2) * f) + getWidth() / 2;
706 adjustOffsetControls();
707 adjustZoomControls();
713 * zooms in by factor f in y
715 void GraphicView::zoomInY(double f)
717 if (simulationRunning)
721 offsetY = (int)((offsetY - getHeight() / 2) * f)+getHeight() / 2;
722 adjustOffsetControls();
723 adjustZoomControls();
729 * zooms out by factor f
731 void GraphicView::zoomOut(double f, const Vector & center)
735 DEBUG->print(Debug::D_WARNING,
736 "GraphicView::zoomOut: invalid factor");
740 if (simulationRunning)
747 * zooms out by factor f in x
749 void GraphicView::zoomOutX(double f)
753 DEBUG->print(Debug::D_WARNING,
754 "GraphicView::zoomOutX: invalid factor");
758 if (simulationRunning)
762 offsetX = (int)(offsetX / f);
763 adjustOffsetControls();
764 adjustZoomControls();
770 * zooms out by factor of y
772 void GraphicView::zoomOutY(double f)
776 DEBUG->print(Debug::D_WARNING, "GraphicView::zoomOutY: invalid factor");
780 if (simulationRunning)
784 offsetY = (int)(offsetY / f);
785 adjustOffsetControls();
786 adjustZoomControls();
794 * @param axis include axis in zoom
795 * @param keepAspectRatio true: keep aspect ratio 1:1
796 * false: factors in x and y are stretched to the max
798 void GraphicView::zoomAuto(bool axis, bool keepAspectRatio)
800 DEBUG->print("GraphicView::zoomAuto");
802 if (simulationRunning)
807 if (container != NULL)
809 container->calculateBorders();
814 sx = std::max(container->getMax().x, 0.0) - std::min(container->getMin().x, 0.0);
815 sy = std::max(container->getMax().y, 0.0) - std::min(container->getMin().y, 0.0);
819 sx = container->getSize().x;
820 sy = container->getSize().y;
825 if (sx > RS_TOLERANCE)
826 fx = (getWidth() - borderLeft - borderRight) / sx;
830 if (sy > RS_TOLERANCE)
831 fy = (getHeight() - borderTop - borderBottom) / sy;
835 DEBUG->print("f: %f/%f", fx, fy);
838 fx = fy = std::min(fx, fy);
840 DEBUG->print("f: %f/%f", fx, fy);
842 if (fx < RS_TOLERANCE)
848 DEBUG->print("f: %f/%f", fx, fy);
850 DEBUG->print("adjustOffsetControls");
851 adjustOffsetControls();
852 DEBUG->print("adjustZoomControls");
853 adjustZoomControls();
854 DEBUG->print("centerOffsetX");
856 DEBUG->print("centerOffsetY");
858 DEBUG->print("updateGrid");
863 DEBUG->print("GraphicView::zoomAuto OK");
867 * Shows previous view.
869 void GraphicView::zoomPrevious()
871 DEBUG->print("GraphicView::zoomPrevious");
873 if (simulationRunning)
881 * Saves the current view as previous view to which we can
882 * switch back later with @see restoreView().
884 void GraphicView::saveView()
886 previousOffsetX = offsetX;
887 previousOffsetY = offsetY;
888 previousFactor = factor;
892 * Restores the view previously saved with
895 void GraphicView::restoreView()
897 int pox = previousOffsetX;
898 int poy = previousOffsetY;
899 Vector pf = previousFactor;
907 adjustOffsetControls();
908 adjustZoomControls();
914 * performs autozoom in y only
916 * @param axis include axis in zoom
918 void GraphicView::zoomAutoY(bool axis)
920 if (simulationRunning)
923 if (container != NULL)
925 double visibleHeight = 0.0;
926 double minY = RS_MAXDOUBLE;
927 double maxY = RS_MINDOUBLE;
928 bool noChange = false;
930 for(Entity * e=container->firstEntity(RS2::ResolveNone);
931 e!=NULL; e = container->nextEntity(RS2::ResolveNone))
933 if (e->rtti() == RS2::EntityLine)
935 Line * l = (Line *)e;
937 x1 = toGuiX(l->getStartpoint().x);
938 x2 = toGuiX(l->getEndpoint().x);
940 if ((x1 > 0.0 && x1 < (double)getWidth())
941 || (x2 > 0.0 && x2 < (double)getWidth()))
943 minY = std::min(minY, l->getStartpoint().y);
944 minY = std::min(minY, l->getEndpoint().y);
945 maxY = std::max(maxY, l->getStartpoint().y);
946 maxY = std::max(maxY, l->getEndpoint().y);
952 visibleHeight = std::max(maxY, 0.0) - std::min(minY, 0.0);
954 visibleHeight = maxY - minY;
956 if (visibleHeight < 1.0)
961 if (visibleHeight > 1.0e-6)
963 fy = (getHeight() - borderTop - borderBottom) / visibleHeight;
965 if (factor.y < 0.000001)
969 if (noChange == false)
973 offsetY = (int)((getHeight() - borderTop - borderBottom - (visibleHeight * factor.y)) / 2.0
974 - (minY * factor.y)) + borderBottom;
975 adjustOffsetControls();
976 adjustZoomControls();
980 DEBUG->print("Auto zoom y ok");
985 * Zooms the area given by v1 and v2.
987 * @param keepAspectRatio true: keeps the aspect ratio 1:1
988 * false: zooms exactly the selected range to the
989 * current graphic view
991 void GraphicView::zoomWindow(Vector v1, Vector v2, bool keepAspectRatio)
993 if (simulationRunning)
998 double zoomX = 480.0; // Zoom for X-Axis
999 double zoomY = 640.0; // Zoom for Y-Axis (Set smaller one)
1000 double dum; // Dummy for switching values
1003 // Switch left/right and top/bottom is necessary:
1018 // Get zoom in X and zoom in Y:
1019 if (v2.x - v1.x > 1.0e-6)
1020 zoomX = getWidth() / (v2.x - v1.x);
1022 if (v2.y - v1.y > 1.0e-6)
1023 zoomY = getHeight() / (v2.y - v1.y);
1025 // Take smaller zoom:
1026 if (keepAspectRatio)
1030 if (getWidth() != 0)
1032 zoomX = zoomY = ((double)(getWidth() - 2 * zoomBorder)) /
1033 (double)getWidth() * zoomX;
1038 if (getHeight() != 0)
1040 zoomX = zoomY = ((double)(getHeight() - 2 * zoomBorder)) /
1041 (double)getHeight() * zoomY;
1052 // Borders in pixel after zoom
1053 int pixLeft = (int)(v1.x * zoomX);
1054 int pixTop = (int)(v2.y * zoomY);
1055 int pixRight = (int)(v2.x * zoomX);
1056 int pixBottom = (int)(v1.y * zoomY);
1058 // Set new offset for zero point:
1059 offsetX = - pixLeft + (getWidth() - pixRight + pixLeft) / 2;
1060 offsetY = - pixTop + (getHeight() - pixBottom + pixTop) / 2;
1064 adjustOffsetControls();
1065 adjustZoomControls();
1071 * Centers the point v1.
1073 void GraphicView::zoomPan(int dx, int dy)
1075 if (simulationRunning)
1082 adjustOffsetControls();
1089 * Scrolls in the given direction.
1091 void GraphicView::zoomScroll(RS2::Direction direction)
1093 if (simulationRunning)
1112 adjustOffsetControls();
1113 adjustZoomControls();
1119 * Zooms to page extends.
1121 void GraphicView::zoomPage()
1123 DEBUG->print("GraphicView::zoomPage");
1125 if (container == NULL)
1128 if (simulationRunning)
1131 Drawing * graphic = container->getGraphic();
1133 if (graphic == NULL)
1136 Vector s = graphic->getPaperSize();
1137 Vector pinsbase = graphic->getPaperInsertionBase();
1141 if (s.x > RS_TOLERANCE)
1142 fx = (getWidth() - borderLeft - borderRight) / s.x;
1146 if (s.y > RS_TOLERANCE)
1147 fy = (getHeight() - borderTop - borderBottom) / s.y;
1151 DEBUG->print("f: %f/%f", fx, fy);
1153 fx = fy = std::min(fx, fy);
1155 DEBUG->print("f: %f/%f", fx, fy);
1157 if (fx < RS_TOLERANCE)
1163 DEBUG->print("f: %f/%f", fx, fy);
1167 adjustOffsetControls();
1168 adjustZoomControls();
1174 * Draws the entities within the given range.
1176 void GraphicView::drawWindow(Vector v1, Vector v2)
1178 DEBUG->print("GraphicView::drawWindow() begin");
1180 if (simulationRunning)
1185 for(Entity * se=container->firstEntity(RS2::ResolveNone); se!=NULL;
1186 se=container->nextEntity(RS2::ResolveNone))
1188 if (se->isInWindow(v1, v2))
1193 DEBUG->print("GraphicView::drawWindow() end");
1197 * Draws the entities. If painter is NULL a new painter will
1198 * be created and destroyed. [NB: Not any more, we don't let the programmer try
1199 * to outsmart the toolkit anymore. :-P
1201 void GraphicView::drawIt()
1203 if (!isUpdateEnabled())
1205 //printf("GraphicView::drawIt(): isUpdateEnabled() == false!\n");
1209 if (simulationRunning)
1211 //printf("GraphicView::drawIt(): simulationRunning == true!\n");
1215 settings.beginGroup("Appearance");
1216 draftMode = settings.value("DraftMode", false).toBool();
1217 settings.endGroup();
1221 //printf("GraphicView::drawIt(): painter == NULL!\n");
1227 // drawing paper border:
1228 if (isPrintPreview())
1230 // drawing meta grid:
1234 // drawing entities:
1235 //#warning "!!! This looks like a bug, no match for 'drawEntity(Entity *, bool) !!!"
1236 // and indeed it *is* a bug... true is converted to 1.0 here. Dumb, dumb, dumb.
1237 drawEntity(container);//, true);
1239 // drawing zero points:
1240 if (!isPrintPreview())
1247 if (!isPrintPreview())
1252 * Sets the pen of the painter object to the suitable pen for the given
1255 void GraphicView::setPenForEntity(Entity * e)
1257 if (drawingMode == RS2::ModePreview /*|| draftMode==true*/)
1260 if (!painter || painter->isPreviewMode())
1263 // set color of entity
1264 // Getting pen from entity (or layer)
1265 Pen pen = e->getPen(true);
1267 int w = pen.getWidth();
1275 double uf = 1.0; // unit factor
1276 double wf = 1.0; // width factor
1277 Drawing * graphic = container->getGraphic();
1281 uf = Units::convert(1.0, RS2::Millimeter, graphic->getUnit());
1283 if ((isPrinting() || isPrintPreview()) && graphic->getPaperScale() > 1.0e-6)
1284 wf = 1.0 / graphic->getPaperScale();
1287 pen.setScreenWidth(toGuiDX(w / 100.0 * uf * wf));
1291 //pen.setWidth(RS2::Width00);
1292 pen.setScreenWidth(0);
1295 // prevent drawing with 1-width which is slow:
1296 if (Math::round(pen.getScreenWidth()) == 1)
1297 pen.setScreenWidth(0.0);
1299 // prevent background color on background drawing:
1300 if (pen.getColor().stripFlags() == background.stripFlags())
1301 pen.setColor(foreground);
1303 // this entity is selected:
1304 if (e->isSelected())
1306 pen.setLineType(RS2::DotLine);
1307 //pen.setColor(Color(0xa5,0x47,0x47));
1308 pen.setColor(selectedColor);
1311 // this entity is highlighted:
1312 if (e->isHighlighted())
1314 //pen.setColor(Color(0x73, 0x93, 0x73));
1315 pen.setColor(highlightedColor);
1318 // deleting not drawing:
1319 if (getDeleteMode())
1320 pen.setColor(background);
1322 painter->setPen(pen);
1326 * Draws an entity. Might be recusively called e.g. for polylines.
1327 * If the class wide painter is NULL a new painter will be created
1328 * and destroyed afterwards.
1330 * @param patternOffset Offset of line pattern (used for connected
1331 * lines e.g. in splines).
1332 * @param db Double buffering on (recommended) / off
1334 void GraphicView::drawEntity(Entity * e, double patternOffset, bool db)
1336 //DEBUG->print("GraphicView::drawEntity() begin");
1338 // update is diabled:
1339 if (!isUpdateEnabled())
1342 // given entity is NULL:
1346 // entity is not visible:
1347 if (!e->isVisible())
1350 // test if the entity is in the viewport
1351 if (!e->isContainer() && !isPrinting()
1352 && (!painter || !painter->isPreviewMode())
1353 && (toGuiX(e->getMax().x) < 0 || toGuiX(e->getMin().x) > getWidth()
1354 || toGuiY(e->getMin().y) < 0 || toGuiY(e->getMax().y) > getHeight()))
1356 //printf("GraphicView::drawEntity(): Bailing out of big test!!!\n");
1361 //DEBUG->print("recursion 1: %d", drawRecursion);
1366 //DEBUG->print("draw plain");
1369 // large texts as rectangles:
1370 if (e->rtti() == RS2::EntityText)
1372 if (toGuiDX(((Text *)e)->getHeight()) < 4 || e->countDeep() > 100)
1373 painter->drawRect(toGui(e->getMin()), toGui(e->getMax()));
1375 drawEntityPlain(e, patternOffset);
1377 // all images as rectangles:
1378 else if (e->rtti() == RS2::EntityImage)
1379 painter->drawRect(toGui(e->getMin()), toGui(e->getMax()));
1381 else if (e->rtti() == RS2::EntityHatch)
1386 drawEntityPlain(e, patternOffset);
1389 drawEntityPlain(e, patternOffset);
1391 // draw reference points:
1392 if (e->isSelected())
1394 if (!e->isParentSelected())
1396 VectorSolutions s = e->getRefPoints();
1398 for(int i=0; i<s.getNumber(); ++i)
1401 Color col = Color(0, 0, 255);
1403 if (e->rtti() == RS2::EntityPolyline)
1405 if (i == 0 || i == s.getNumber() - 1)
1410 // col = QColor(0, 64, 255);
1411 col = Color(0, 64, 255);
1416 // col = QColor(0, 0, 128);
1417 col = Color(0, 0, 128);
1422 if (getDeleteMode())
1423 painter->drawHandle(toGui(s.get(i)), background, sz);
1425 painter->drawHandle(toGui(s.get(i)), col, sz);
1430 //DEBUG->print("draw plain OK");
1431 //DEBUG->print("GraphicView::drawEntity() end");
1436 * The painter must be initialized and all the attributes (pen) must be set.
1438 void GraphicView::drawEntityPlain(Entity * e, double patternOffset/*= 0.0*/)
1440 //Problems can still occur here when passing in a deleted object... It won't be
1441 //NULL, but it will cause a segfault here...
1444 //printf("GraphicView::drawEntityPlain(): Entity passed in is NULL!\n");
1448 //printf("GraphicView::drawEntityPlain(): Passing in painter=%08X, view=%08X\n", painter, this);
1449 e->draw(painter, this, patternOffset);
1453 * Simulates this drawing in slow motion.
1455 void GraphicView::simulateIt()
1457 if (simulationRunning)
1460 simulationRunning = true;
1461 simulationLast = Vector(0.0, 0.0);
1465 // drawing paper border:
1466 if (isPrintPreview())
1469 // drawing meta grid:
1470 if (!isPrintPreview())
1474 if (!isPrintPreview())
1477 // drawing entities:
1478 Pen pen(foreground, RS2::Width00, RS2::SolidLine);
1479 simulateEntity(container, pen);
1481 // drawing zero points:
1482 if (!isPrintPreview())
1488 simulationRunning = false;
1492 * Simulates the given entity.
1494 * @param smooth If true, the entity will be drawn slowly (pixel by pixel).
1496 void GraphicView::simulateEntity(Entity * e, const Pen & pen)
1501 if (e->isContainer())
1503 EntityContainer * ec = (EntityContainer *)e;
1505 for(Entity * en=ec->firstEntity(RS2::ResolveNone);
1506 en!=NULL; en=ec->nextEntity(RS2::ResolveNone))
1508 if (en->isVisible() && en->isUndone() == false)
1511 if (en->isAtomic() && simulationRapid)
1513 Vector sp = ((AtomicEntity *)en)->getStartpoint();
1515 if (sp.distanceTo(simulationLast) > 1.0e-4)
1517 Pen rpen(Color(0, 0, 255), RS2::Width00, RS2::SolidLine);
1518 Line rapidLine(NULL, LineData(simulationLast, sp));
1519 simulateEntity(&rapidLine, rpen);
1523 if (en->isHighlighted())
1525 Pen hpen(highlightedColor, RS2::Width00, RS2::SolidLine);
1526 simulateEntity(en, hpen);
1529 simulateEntity(en, pen);
1532 simulationLast = ((AtomicEntity *)en)->getEndpoint();
1534 if (!simulationSmooth)
1535 simulationDelay(true);
1541 if (simulationSmooth)
1545 case RS2::EntityLine:
1547 Line * line = (Line *)e;
1548 drawLineSmooth(toGui(line->getStartpoint()), toGui(line->getEndpoint()), pen);
1553 case RS2::EntityArc:
1555 Arc * arc = (Arc *)e;
1556 drawArcSmooth(toGui(arc->getCenter()), toGuiDX(arc->getRadius()),
1557 arc->getAngle1(), arc->getAngle2(), arc->isReversed(), pen);
1561 case RS2::EntityCircle:
1563 Circle * circle = (Circle *)e;
1564 drawArcSmooth(toGui(circle->getCenter()), toGuiDX(circle->getRadius()),
1565 0.0, 2.0 * M_PI, false, pen);
1575 painter->setPen(pen);
1582 * Delay for slow motion simulation.
1584 * @param step true: stepping mode (entity by entity simulation). adds a delay.
1586 void GraphicView::simulationDelay(bool step)
1589 settings.beginGroup("CAM");
1590 double fact = settings.value("SimulationFactor", 12000.0).toDouble();
1591 settings.endGroup();
1593 // simulationSpeed: 0..100
1596 delay = (int)(((1.0 / (simulationSpeed + 1.0)) * fact) - (fact / 100.0));
1601 static int call = 0;
1603 if (call >= (fact - delay) / 1000)
1606 for(int i=0; i<delay; ++i)
1607 RS_APP->processEvents(10);
1612 delay = (int)(((1.0 / (simulationSpeed + 1.0)) * fact) - (fact / 100.0));
1619 for(int i=0; i<delay; ++i)
1621 #warning "Qt3->4 conversion: commented out problem line... !!! FIX !!!"
1622 // RS_APP->processEvents(10);
1628 * Draws a line slowly from (x1, y1) to (x2, y2). This is used for simulation only.
1630 void GraphicView::drawLineSmooth(const Vector & p1, const Vector & p2, const Pen & pen)
1632 double alpha = p1.angleTo(p2);
1633 double xStep, yStep;
1636 if (Math::cmpDouble(alpha, 0.0) || Math::cmpDouble(alpha, 2 * M_PI))
1642 else if (Math::cmpDouble(alpha, M_PI / 2.0))
1648 else if (Math::cmpDouble(alpha, M_PI))
1654 else if (Math::cmpDouble(alpha, M_PI / 2.0 * 3.0))
1660 else if (fabs(p2.x - p1.x) > fabs(p2.y - p1.y))
1667 yStep = tan(alpha) * xStep;
1677 xStep = yStep / tan(alpha);
1686 if (lx >= 0.0 && lx <= (double)getWidth() && ly >= 0.0 && ly <= (double)getHeight())
1688 painter->setPen(pen);
1689 painter->drawGridPoint(Vector(lx, ly));
1698 while ((xIsOne && ((lx >= p1.x && lx <= p2.x) || (lx >= p2.x && lx <= p1.x)))
1699 || (!xIsOne && ((ly >= p1.y && ly <= p2.y) || (ly >= p2.y && ly <= p1.y))));
1702 void GraphicView::drawArcSmooth(const Vector & center, double radius, double a1, double a2, bool rev,
1707 painter->setPen(pen);
1708 painter->drawGridPoint(center);
1712 int ix1 = Math::round(center.x + cos(a1) * radius);
1713 int iy1 = Math::round(center.y - sin(a1) * radius);
1714 int ix2 = Math::round(center.x + cos(a2) * radius);
1715 int iy2 = Math::round(center.y - sin(a2) * radius);
1716 int k2x = 0; // Next point on circle
1718 int k1x = ix1; // Prev point on circle
1720 double aStep; // Angle Step (rad)
1721 double a; // Actual Angle (rad)
1722 double a2cp = a2; // Copy of a2
1724 if (1.0 / (radius * factor.x) <= 1.0)
1725 aStep = asin(1.0 / (radius * factor.x));
1734 // Arc Counterclockwise:
1736 if (a1 > a2cp - 0.01)
1739 for(a=a1+aStep; a<=a2cp; a+=aStep)
1741 k2x = Math::round(center.x+cos(a)*radius);
1742 k2y = Math::round(center.y-sin(a)*radius);
1743 painter->setPen(pen);
1745 if ((k2x >= 0 && k2x <= painter->getWidth()
1746 && k2y >= 0 && k2y <= painter->getHeight())
1747 || (k1x >= 0 && k1x <= painter->getWidth()
1748 && k1y >= 0 && k1y <= painter->getHeight()))
1750 painter->drawLine(Vector(k1x, k1y), Vector(k2x, k2y));
1758 painter->setPen(pen);
1759 painter->drawLine(Vector(k2x, k2y), Vector(ix2, iy2));
1765 if (a1 < a2cp + 0.01)
1768 for(a=a1-aStep; a>=a2cp; a-=aStep)
1770 k2x = Math::round(center.x + cos(a) * radius);
1771 k2y = Math::round(center.y - sin(a) * radius);
1772 painter->setPen(pen);
1774 if ((k2x >=0 && k2x <= painter->getWidth()
1775 && k2y >= 0 && k2y <= painter->getHeight())
1776 || (k1x >= 0 && k1x <= painter->getWidth()
1777 && k1y >= 0 && k1y <= painter->getHeight()))
1779 painter->drawLine(Vector(k1x, k1y), Vector(k2x, k2y));
1787 painter->setPen(pen);
1788 painter->drawLine(Vector(k2x, k2y), Vector(ix2, iy2));
1794 * @return Pointer to the static pattern struct that belongs to the
1795 * given pattern type or NULL.
1797 LineTypePattern * GraphicView::getPattern(RS2::LineType t)
1801 case RS2::SolidLine:
1802 return &patternSolidLine;
1806 return &patternDotLine;
1809 return &patternDotLine2;
1811 case RS2::DotLineX2:
1812 return &patternDotLineX2;
1816 return &patternDashLine;
1818 case RS2::DashLine2:
1819 return &patternDashLine2;
1821 case RS2::DashLineX2:
1822 return &patternDashLineX2;
1825 case RS2::DashDotLine:
1826 return &patternDashDotLine;
1828 case RS2::DashDotLine2:
1829 return &patternDashDotLine2;
1831 case RS2::DashDotLineX2:
1832 return &patternDashDotLineX2;
1835 case RS2::DivideLine:
1836 return &patternDivideLine;
1838 case RS2::DivideLine2:
1839 return &patternDivideLine2;
1841 case RS2::DivideLineX2:
1842 return &patternDivideLineX2;
1845 case RS2::CenterLine:
1846 return &patternCenterLine;
1848 case RS2::CenterLine2:
1849 return &patternCenterLine2;
1851 case RS2::CenterLineX2:
1852 return &patternCenterLineX2;
1855 case RS2::BorderLine:
1856 return &patternBorderLine;
1858 case RS2::BorderLine2:
1859 return &patternBorderLine2;
1861 case RS2::BorderLineX2:
1862 return &patternBorderLineX2;
1865 case RS2::LineByLayer:
1866 return &patternBlockLine;
1868 case RS2::LineByBlock:
1869 return &patternBlockLine;
1879 * This virtual method can be overwritten to draw the absolute
1880 * zero. It's called from within drawIt(). The default implemetation
1881 * draws a simple red round zero point.
1883 * Actually, we have to rework the rendering code because the way that QCad did
1884 * it was wrong on so many levels... Part of that is making sure the rendering
1885 * path is 100% clear!
1889 void GraphicView::drawAbsoluteZero()
1896 // Pen p(Qt::red, RS2::Width00, RS2::SolidLine);
1897 //Using Qt::red doesn't seem to work here...
1898 //It's because Qt colors and Color are not 100% compatible...
1899 Pen p(Color(255, 0, 0), RS2::Width00, RS2::SolidLine);
1902 painter->drawLine(Vector(toGuiX(0.0) - zr, toGuiY(0.0)),
1903 Vector(toGuiX(0.0) + zr, toGuiY(0.0)));
1905 painter->drawLine(Vector(toGuiX(0.0), toGuiY(0.0) - zr),
1906 Vector(toGuiX(0.0), toGuiY(0.0) + zr));
1910 * This virtual method can be overwritten to draw the relative
1911 * zero point. It's called from within drawIt(). The default implemetation
1912 * draws a simple red round zero point.
1916 void GraphicView::drawRelativeZero()
1918 if (!relativeZero.valid || !painter)
1923 if (!relativeZero.valid)
1924 printf("GraphicView::drawRelativeZero(): relativeZero is NOT valid!!!\n");
1927 printf("GraphicView::drawRelativeZero(): painter is NOT valid!!!\n");
1933 //Using Qt::red doesn't seem to work here...
1934 Pen p(Color(255, 0, 0), RS2::Width00, RS2::SolidLine);
1936 //This doesn't work--this is NOT a QPainter!
1937 // painter->setBrush(Qt::NoBrush);
1938 // painter->setBackgroundMode(Qt::TransparentMode); // will that do it???
1939 painter->disableBrush();
1940 // painter->setXORMode();
1944 painter->drawLine(Vector(toGuiX(relativeZero.x) - zr, toGuiY(relativeZero.y)),
1945 Vector(toGuiX(relativeZero.x) + zr, toGuiY(relativeZero.y)));
1946 painter->drawLine(Vector(toGuiX(relativeZero.x), toGuiY(relativeZero.y) - zr),
1947 Vector(toGuiX(relativeZero.x), toGuiY(relativeZero.y) + zr));
1948 painter->drawCircle(toGui(relativeZero), zr);
1949 // painter->setNormalMode();
1953 * Draws the paper border (for print previews).
1957 void GraphicView::drawPaper()
1962 Drawing * graphic = container->getGraphic();
1967 if (graphic->getPaperScale() < 1.0e-6)
1974 painter->setPen(Pen(Qt::gray));
1976 Vector pinsbase = graphic->getPaperInsertionBase();
1977 Vector size = graphic->getPaperSize();
1978 double scale = graphic->getPaperScale();
1980 Vector v1 = toGui((Vector(0, 0) - pinsbase) / scale);
1981 Vector v2 = toGui((size - pinsbase) / scale);
1984 painter->fillRect(0,0, getWidth(), getHeight(), Color(200, 200, 200));
1987 painter->fillRect((int)(v1.x) + 6, (int)(v1.y) + 6,
1988 (int)((v2.x - v1.x)), (int)((v2.y - v1.y)), Color(64, 64, 64));
1991 painter->fillRect((int)(v1.x), (int)(v1.y),
1992 (int)((v2.x - v1.x)), (int)((v2.y - v1.y)), Color(64, 64, 64));
1995 painter->fillRect((int)(v1.x) + 1, (int)(v1.y) - 1,
1996 (int)((v2.x - v1.x)) - 2, (int)((v2.y - v1.y)) + 2, Color(255, 255, 255));
2004 void GraphicView::drawGrid()
2006 if (!grid || isGridOn() == false)
2008 // printf("GraphicView::drawGrid(): Aborting: grid=%08X, isGridOn=%s\n", grid, (isGridOn() ? "true" : "false"));
2013 painter->setPen(gridColor);
2015 //Problem here: pts is NULL!
2016 Vector * pts = grid->getPoints();
2020 for(int i=0; i<grid->count(); ++i)
2021 painter->drawGridPoint(toGui(pts[i]));
2024 // printf("GraphicView::drawGrid(): pts == NULL!\n");
2027 QString info = grid->getInfo();
2028 updateGridStatusWidget(info);
2032 * Draws the meta grid.
2036 void GraphicView::drawMetaGrid()
2038 if (!grid || isGridOn() == false)
2044 Pen pen(metaGridColor, RS2::Width00, RS2::DotLine);
2045 painter->setPen(pen);
2048 double * mx = grid->getMetaX();
2049 double * my = grid->getMetaY();
2053 for(int i=0; i<grid->countMetaX(); ++i)
2054 painter->drawLine(Vector(toGuiX(mx[i]), 0), Vector(toGuiX(mx[i]), getHeight()));
2059 for(int i=0; i<grid->countMetaY(); ++i)
2060 painter->drawLine(Vector(0, toGuiY(my[i])), Vector(getWidth(), toGuiY(my[i])));
2065 * Updates the grid if there is one.
2067 void GraphicView::updateGrid()
2073 Grid * GraphicView::getGrid()
2078 void GraphicView::updateGridStatusWidget(const QString & /*text*/)
2082 RS2::SnapMode GraphicView::getDefaultSnapMode()
2084 return defaultSnapMode;
2087 RS2::SnapRestriction GraphicView::getSnapRestriction()
2089 return defaultSnapRes;
2093 * Sets the default snap mode used by newly created actions.
2095 void GraphicView::setDefaultSnapMode(RS2::SnapMode sm)
2097 defaultSnapMode = sm;
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);
2110 * Sets a snap restriction (e.g. orthogonal).
2112 void GraphicView::setSnapRestriction(RS2::SnapRestriction sr)
2114 defaultSnapRes = sr;
2116 if (eventHandler != NULL)
2117 eventHandler->setSnapRestriction(sr);
2121 * Translates a vector in real coordinates to a vector in screen coordinates.
2123 Vector GraphicView::toGui(Vector v)
2125 return Vector(toGuiX(v.x), toGuiY(v.y), 0.0);
2129 * Translates a real coordinate in X to a screen coordinate X.
2130 * @param visible Pointer to a boolean which will contain true
2131 * after the call if the coordinate is within the visible range.
2133 double GraphicView::toGuiX(double x, bool * visible/*= NULL*/)
2135 if (visible != NULL)
2137 double res = x * factor.x + offsetX;
2139 if (res > 0.0 && res < getWidth())
2145 return x * factor.x + offsetX;
2149 * Translates a real coordinate in Y to a screen coordinate Y.
2151 double GraphicView::toGuiY(double y)
2153 return -y * factor.y + getHeight() - offsetY;
2157 * Translates a real coordinate distance to a screen coordinate distance.
2159 double GraphicView::toGuiDX(double d)
2161 return d * factor.x;
2165 * Translates a real coordinate distance to a screen coordinate distance.
2167 double GraphicView::toGuiDY(double d)
2169 return d * factor.y;
2173 * Translates a vector in screen coordinates to a vector in real coordinates.
2175 Vector GraphicView::toGraph(Vector v)
2177 return Vector(toGraphX(Math::round(v.x)), toGraphY(Math::round(v.y)), 0.0);
2181 * Translates two screen coordinates to a vector in real coordinates.
2183 Vector GraphicView::toGraph(int x, int y)
2185 return Vector(toGraphX(x), toGraphY(y), 0.0);
2189 * Translates a screen coordinate in X to a real coordinate X.
2191 double GraphicView::toGraphX(int x)
2193 return (x - offsetX) / factor.x;
2197 * Translates a screen coordinate in Y to a real coordinate Y.
2199 double GraphicView::toGraphY(int y)
2201 return -(y - getHeight() + offsetY) / factor.y;
2205 * Translates a screen coordinate distance to a real coordinate distance.
2207 double GraphicView::toGraphDX(int d)
2209 return d / factor.x;
2213 * Translates a screen coordinate distance to a real coordinate distance.
2215 double GraphicView::toGraphDY(int d)
2217 return d / factor.y;
2221 * (Un-)Locks the position of the relative zero.
2223 * @param lock true: lock, false: unlock
2225 void GraphicView::lockRelativeZero(bool lock)
2227 relativeZeroLocked = lock;
2231 * @return true if the position of the realtive zero point is
2234 bool GraphicView::isRelativeZeroLocked()
2236 return relativeZeroLocked;
2240 * @return Relative zero coordinate.
2242 Vector GraphicView::getRelativeZero()
2244 return relativeZero;
2248 * Sets the relative zero coordinate (if not locked)
2249 * without deleting / drawing the point.
2251 void GraphicView::setRelativeZero(const Vector & pos)
2253 if (!relativeZeroLocked)
2258 * Sets the relative zero coordinate, deletes the old position
2259 * on the screen and draws the new one.
2261 void GraphicView::moveRelativeZero(const Vector & pos)
2263 setRelativeZero(pos);
2266 EventHandler * GraphicView::getEventHandler()
2268 return eventHandler;
2272 * Enables or disables print preview.
2274 void GraphicView::setPrintPreview(bool pv)
2280 * @retval true This is a print preview graphic view.
2281 * @retval false Otherwise.
2283 bool GraphicView::isPrintPreview()
2285 return printPreview;
2289 * Enables or disables printing.
2291 void GraphicView::setPrinting(bool p)
2297 * @retval true This is a a graphic view for printing.
2298 * @retval false Otherwise.
2300 bool GraphicView::isPrinting()
2306 * @retval true Draft mode is on for this view (all lines with 1 pixel / no style scaling).
2307 * @retval false Otherwise.
2309 bool GraphicView::isDraftMode()
2315 * Sets the simulation speed in percentage.
2317 void GraphicView::setSimulationSpeed(int s)
2319 simulationSpeed = s;
2323 * @return the simulation speed in percentage.
2325 int GraphicView::getSimulationSpeed()
2327 return simulationSpeed;
2331 * Sets the simulation smooth mode.
2333 void GraphicView::setSimulationSmooth(bool s)
2335 simulationSmooth = s;
2338 * Sets the simulation rapid mode.
2340 void GraphicView::setSimulationRapid(bool r)
2342 simulationRapid = r;
2346 * @return the simulation rapid mode.
2348 bool GraphicView::getSimulationRapid()
2350 return simulationRapid;
2354 * Catches an entity which is close to the given position 'pos'.
2356 * @param pos A graphic coordinate.
2357 * @param level The level of resolving for iterating through the entity
2359 * @return Pointer to the entity or NULL.
2361 Entity * GraphicView::CatchEntity(const Vector & pos, RS2::ResolveLevel level)
2363 DEBUG->print("GraphicView::CatchEntity");
2365 // Set default distance for points inside solids
2366 double dist = toGraphDX(snapRange) * 0.9;
2367 Entity * entity = container->getNearestEntity(pos, &dist, level);
2372 if (entity && entity->getParent())
2373 idx = entity->getParent()->findEntity(entity);
2374 // END DEBUGGING INFO
2376 if (entity && dist <= toGraphDX(snapRange))
2379 DEBUG->print("GraphicView::CatchEntity: found: idx=%d", idx);
2383 DEBUG->print("GraphicView::CatchEntity: not found");
2388 * Catches an entity which is close to the mouse cursor.
2390 * @param e A mouse event.
2391 * @param level The level of resolving for iterating through the entity
2393 * @return Pointer to the entity or NULL.
2395 Entity * GraphicView::CatchEntity(QMouseEvent * e, RS2::ResolveLevel level)
2397 return CatchEntity(Vector(toGraphX(e->x()), toGraphY(e->y())), level);
2401 * Snap to a coordinate in the drawing using the current snap mode.
2403 * @param e A mouse event.
2404 * @return The coordinates of the point or an invalid vector.
2406 Vector GraphicView::SnapPoint(QMouseEvent * e)
2408 DEBUG->print("GraphicView::SnapPoint");
2409 /*Vector*/ snapSpot = Vector(false);
2413 DEBUG->print(Debug::D_WARNING, "GraphicView::SnapPoint: QMouseEvent is NULL");
2417 Vector mouseCoord = toGraph(e->x(), e->y());
2419 // switch (snapMode)
2420 switch (defaultSnapMode)
2423 // snapSpot = snapFree(mouseCoord);
2425 snapSpot = mouseCoord;
2428 case RS2::SnapEndpoint:
2429 // snapSpot = snapEndpoint(mouseCoord);
2430 snapSpot = container->getNearestEndpoint(mouseCoord, NULL);
2434 snapSpot = SnapGrid(mouseCoord);
2437 case RS2::SnapOnEntity:
2438 // snapSpot = snapOnEntity(mouseCoord);
2439 snapSpot = container->getNearestPointOnEntity(mouseCoord, true, NULL, &snapEntity);
2442 case RS2::SnapCenter:
2443 // snapSpot = snapCenter(mouseCoord);
2444 snapSpot = container->getNearestCenter(mouseCoord, NULL);
2447 case RS2::SnapMiddle:
2448 // snapSpot = snapMiddle(mouseCoord);
2449 snapSpot = container->getNearestMiddle(mouseCoord, NULL);
2453 // snapSpot = snapDist(mouseCoord);
2454 snapSpot = container->getNearestDist(snapDistance, mouseCoord, NULL);
2457 case RS2::SnapIntersection:
2458 // snapSpot = snapIntersection(mouseCoord);
2459 snapSpot = container->getNearestIntersection(mouseCoord, NULL);
2466 // This is declared here because I really, really hate extraneous braces in
2467 // my switch statements. :-P
2468 Vector relZero = getRelativeZero();
2469 Vector restrictX = Vector(relZero.x, snapSpot.y);
2470 Vector restrictY = Vector(snapSpot.x, relZero.y);
2471 // Vector snapCoord;
2472 // Handle snap restrictions that can be activated in addition to the ones above:
2474 switch (defaultSnapRes)
2476 case RS2::RestrictOrthogonal:
2477 //// snapCoord = restrictOrthogonal(snapSpot);
2478 // rz = graphicView->getRelativeZero();
2479 // retx = Vector(rz.x, snapSpot.y);
2480 // rety = Vector(snapSpot.x, rz.y);
2481 snapCoord = (restrictX.distanceTo(snapSpot) < restrictY.distanceTo(snapSpot) ?
2482 restrictX : restrictY);
2484 case RS2::RestrictHorizontal:
2485 //// snapCoord = restrictHorizontal(snapSpot);
2486 // rz = graphicView->getRelativeZero();
2487 // snapCoord = Vector(snapSpot.x, rz.y);
2488 snapCoord = restrictY;
2490 case RS2::RestrictVertical:
2491 //// snapCoord = restrictVertical(snapSpot);
2492 // rz = graphicView->getRelativeZero();
2493 // snapCoord = Vector(rz.x, snapSpot.y);
2494 snapCoord = restrictX;
2497 case RS2::RestrictNothing:
2498 snapCoord = snapSpot;
2503 DIALOGFACTORY->updateCoordinateWidget(snapCoord, snapCoord - relZero);
2505 DEBUG->print("GraphicView::SnapPoint: OK");
2511 * Snaps to a grid point.
2513 * @param coord The mouse coordinate.
2514 * @return The coordinates of the point or an invalid vector.
2516 Vector GraphicView::SnapGrid(Vector coord)
2518 DEBUG->print("GraphicView::snapGrid begin");
2523 DEBUG->print("GraphicView::snapGrid 001");
2527 DEBUG->print("GraphicView::snapGrid 002");
2528 Vector * pts = grid->getPoints();
2529 DEBUG->print("GraphicView::snapGrid 003");
2532 DEBUG->print("GraphicView::snapGrid 004");
2534 for(int i=0; i<grid->count(); ++i)
2536 double d = pts[i].distanceTo(coord);
2545 DEBUG->print("GraphicView::snapGrid 005");
2550 DEBUG->print("GraphicView::snapGrid 006");
2555 DEBUG->print("GraphicView::snapGrid end");
2560 void GraphicView::DrawSnapper(PaintInterface * painter)
2562 //Is "finished" used at all? Seems it's used only in ActionInterface, and it's commented out
2563 // if (finished || !snapSpot.valid || !snapCoord.valid)
2564 if (!snapSpot.valid || !snapCoord.valid)
2567 printf("DrawSnapper: snapSpot=%s, snapCoord=%s...\n", (snapSpot.valid ? "valid" : "INVALID"), (snapCoord.valid ? "valid" : "INVALID"));
2574 // Snap point (need to make sure the brush is NULL!)
2575 // painter->setPen(Pen(Color(0, 127, 255), RS2::Width00, RS2::DashLine));
2576 painter->setPen(Pen(Color(255, 127, 0), RS2::Width00, RS2::DashLine));
2577 painter->drawCircle(toGui(snapCoord), 4);
2582 painter->setPen(Pen(Color(0, 255, 255), RS2::Width00, RS2::DashLine));
2583 painter->drawLine(Vector(0, toGuiY(snapCoord.y)),
2584 Vector(getWidth(), toGuiY(snapCoord.y)));
2585 painter->drawLine(Vector(toGuiX(snapCoord.x), 0),
2586 Vector(toGuiX(snapCoord.x), getHeight()));
2590 if (snapCoord != snapSpot)
2592 painter->drawLine(toGui(snapSpot) + Vector(-5, 0), toGui(snapSpot) + Vector(-1, 4));
2593 painter->drawLine(toGui(snapSpot) + Vector(0, 5), toGui(snapSpot) + Vector(4, 1));
2594 painter->drawLine(toGui(snapSpot) + Vector(5, 0), toGui(snapSpot) + Vector(1, -4));
2595 painter->drawLine(toGui(snapSpot) + Vector(0, -5), toGui(snapSpot) + Vector(-4, -1));
2599 void GraphicView::SetSnapperVisible(bool visibility/*= true*/)
2601 snapperVisible = visibility;
2604 bool GraphicView::SnapperVisible(void)
2606 return snapperVisible;
2611 only place this is called is in ActionInterface. And its only function is to
2612 have it not drawn anymore. But, the GraphicView seems to draw it anyway... So
2613 some other approach is needed...
2615 void Snapper::finish()
2621 * @return Pointer to the entity which was the key entity for the last
2622 * successful snapping action. If the snap mode is "end point" the key entity
2623 * is the entity whose end point was caught. If the snap mode didn't require an
2624 * entity (e.g. free, grid) this method will return NULL.
2626 Entity * Snapper::getKeyEntity()
2631 /** Sets a new snap mode. */
2632 void Snapper::setSnapMode(RS2::SnapMode snapMode)
2634 this->snapMode = snapMode;
2637 /** Sets a new snap restriction. */
2638 void Snapper::setSnapRestriction(RS2::SnapRestriction snapRes)
2640 this->snapRes = snapRes;
2643 RS2::SnapMode Snapper::getSnapMode(void)
2648 RS2::SnapRestriction Snapper::getSnapRestriction(void)
2654 * Sets the snap range in pixels for catchEntity().
2656 * @see catchEntity()
2658 void Snapper::setSnapRange(int r)
2664 I think that these suspend() & resume() functions are not used anymore...
2667 * Suspends this snapper while another action takes place.
2669 /*virtual*/ void Snapper::suspend()
2671 #warning "!!! This may need to have SetVisibility() called !!!"
2673 snapSpot = snapCoord = Vector(false);
2677 * Resumes this snapper after it has been suspended.
2679 /*virtual*/ void Snapper::resume()
2681 #warning "!!! This may need to have SetVisibility() called !!!"
2686 * Hides the snapper options.
2688 /*virtual*/ void Snapper::hideOptions()
2690 if (snapMode == RS2::SnapDist && DIALOGFACTORY)
2691 DIALOGFACTORY->requestSnapDistOptions(distance, false);
2695 * Shows the snapper options.
2697 /*virtual*/ void Snapper::showOptions()
2699 if (snapMode == RS2::SnapDist && DIALOGFACTORY)
2700 DIALOGFACTORY->requestSnapDistOptions(distance, true);