1
/****************************************************************************
3
** This file is part of the LibreCAD project, a 2D CAD program
5
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
6
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
9
** This file may be distributed and/or modified under the terms of the
10
** GNU General Public License version 2 as published by the Free Software
11
** Foundation and appearing in the file gpl-2.0.txt included in the
12
** packaging of this file.
14
** This program is distributed in the hope that it will be useful,
15
** but WITHOUT ANY WARRANTY; without even the implied warranty of
16
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
** GNU General Public License for more details.
19
** You should have received a copy of the GNU General Public License
20
** along with this program; if not, write to the Free Software
21
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
** This copyright notice MUST APPEAR in all copies of the script!
25
**********************************************************************/
29
#include "qc_applicationwindow.h"
30
#include "rs_graphicview.h"
32
#include "rs_linetypepattern.h"
33
#include "rs_eventhandler.h"
34
#include "rs_graphic.h"
36
#include "rs_painter.h"
39
#include "rs_settings.h"
40
#include "rs_dialogfactory.h"
50
RS_GraphicView::RS_GraphicView()
51
: background(), foreground(),
52
savedViews(16), savedViewIndex(0),savedViewCount(0),previousViewTime(QDateTime::currentDateTime())
55
drawingMode = RS2::ModeFull;
58
factor = RS_Vector(1.0,1.0);
62
eventHandler = new RS_EventHandler(this);
64
metaGridColor = RS_Color(64,64,64);
65
grid = new RS_Grid(this);
75
relativeZero = RS_Vector(false);
76
relativeZeroLocked=false;
80
RS_SETTINGS->beginGroup("/Appearance");
81
setBackground(QColor(RS_SETTINGS->readEntry("/BackgroundColor", "#000000")));
82
setGridColor(QColor(RS_SETTINGS->readEntry("/GridColor", "#7F7F7F")));
83
setMetaGridColor(QColor(RS_SETTINGS->readEntry("/MetaGridColor", "#3F3F3F")));
84
setSelectedColor(QColor(RS_SETTINGS->readEntry("/SelectedColor", "#A54747")));
85
setHighlightedColor(QColor(RS_SETTINGS->readEntry("/HighlightedColor", "#739373")));
86
setStartHandleColor(QColor(RS_SETTINGS->readEntry("/StartHandleColor", "#00FFFF")));
87
setHandleColor(QColor(RS_SETTINGS->readEntry("/HandleColor", "#0000FF")));
88
setEndHandleColor(QColor(RS_SETTINGS->readEntry("/EndHandleColor", "#0000FF")));
90
RS_SETTINGS->endGroup();
94
QC_ApplicationWindow::getAppWindow()->setPreviousZoomEnable(false);
95
//currentInsert = NULL;
103
RS_GraphicView::~RS_GraphicView() {
105
//@write default snap mode from prefrences.
106
defaultSnapMode.restriction=defaultSnapRes;
107
unsigned int snapFlags=RS_Snapper::snapModeToInt(defaultSnapMode);
108
RS_SETTINGS->beginGroup("/Snap");
109
RS_SETTINGS->writeEntry("/SnapMode",QString::number(snapFlags));
110
RS_SETTINGS->endGroup();
111
// no need to delete child widgets, Qt does it all for us
119
* Must be called by any derrived class in the destructor.
121
void RS_GraphicView::cleanUp() {
123
//delete eventHandler;
128
* Sets the pointer to the graphic which contains the entities
129
* which are visualized by this widget.
131
void RS_GraphicView::setContainer(RS_EntityContainer* container) {
132
this->container = container;
133
//adjustOffsetControls();
139
* Sets the zoom factor in X for this visualization of the graphic.
141
void RS_GraphicView::setFactorX(double f) {
150
* Sets the zoom factor in Y for this visualization of the graphic.
152
void RS_GraphicView::setFactorY(double f) {
158
void RS_GraphicView::setOffset(int ox, int oy) {
160
// RS_DEBUG->print(/*RS_Debug::D_WARNING, */"set offset from (%d, %d) to (%d, %d)", getOffsetX(), getOffsetY(), ox, oy);
166
* @return true if the grid is switched on.
168
bool RS_GraphicView::isGridOn() {
169
if (container!=NULL) {
170
RS_Graphic* g = container->getGraphic();
172
return g->isGridOn();
179
* @return true if the grid is isometric
183
bool RS_GraphicView::isGridIsometric() {
184
return grid->isIsometric();
188
void RS_GraphicView::setCrosshairType(RS2::CrosshairType chType){
189
grid->setCrosshairType(chType);
192
RS2::CrosshairType RS_GraphicView::getCrosshairType(){
193
return grid->getCrosshairType();
198
* Centers the drawing in x-direction.
200
void RS_GraphicView::centerOffsetX() {
201
if (container!=NULL && !zoomFrozen) {
202
offsetX = (int)(((getWidth()-borderLeft-borderRight)
203
- (container->getSize().x*factor.x))/2.0
204
- (container->getMin().x*factor.x)) + borderLeft;
211
* Centers the drawing in y-direction.
213
void RS_GraphicView::centerOffsetY() {
214
if (container!=NULL && !zoomFrozen) {
215
offsetY = (int)((getHeight()-borderTop-borderBottom
216
- (container->getSize().y*factor.y))/2.0
217
- (container->getMin().y*factor.y)) + borderBottom;
224
* Centers the given coordinate in the view in x-direction.
226
void RS_GraphicView::centerX(double v) {
228
offsetX = (int)((v*factor.x)
229
- (double)(getWidth()-borderLeft-borderRight)/2.0);
236
* Centers the given coordinate in the view in y-direction.
238
void RS_GraphicView::centerY(double v) {
240
offsetY = (int)((v*factor.y)
241
- (double)(getHeight()-borderTop-borderBottom)/2.0);
246
* @return Current action or NULL.
248
RS_ActionInterface* RS_GraphicView::getDefaultAction() {
249
if (eventHandler!=NULL) {
250
return eventHandler->getDefaultAction();
259
* Sets the default action of the event handler.
261
void RS_GraphicView::setDefaultAction(RS_ActionInterface* action) {
262
if (eventHandler!=NULL) {
263
eventHandler->setDefaultAction(action);
270
* @return Current action or NULL.
272
RS_ActionInterface* RS_GraphicView::getCurrentAction() {
273
if (eventHandler!=NULL) {
274
return eventHandler->getCurrentAction();
283
* Sets the current action of the event handler.
285
void RS_GraphicView::setCurrentAction(RS_ActionInterface* action) {
286
RS_DEBUG->print("RS_GraphicView::setCurrentAction");
287
if (eventHandler!=NULL) {
288
eventHandler->setCurrentAction(action);
290
RS_DEBUG->print("RS_GraphicView::setCurrentAction: OK");
295
* Kills all running selection actions. Called when a selection action
296
* is launched to reduce confusion.
298
void RS_GraphicView::killSelectActions() {
299
if (eventHandler!=NULL) {
300
eventHandler->killSelectActions();
307
* Kills all running actions.
309
void RS_GraphicView::killAllActions() {
310
if (eventHandler!=NULL) {
311
eventHandler->killAllActions();
318
* Go back in menu or current action.
320
void RS_GraphicView::back() {
321
if (eventHandler!=NULL && eventHandler->hasAction()) {
322
eventHandler->back();
324
if (RS_DIALOGFACTORY!=NULL) {
325
RS_DIALOGFACTORY->requestPreviousMenu();
333
* Go forward with the current action.
335
void RS_GraphicView::enter() {
336
if (eventHandler!=NULL && eventHandler->hasAction()) {
337
eventHandler->enter();
344
* Called by the actual GUI class which implements the RS_GraphicView
345
* interface to notify LibreCAD about mouse events.
347
void RS_GraphicView::mousePressEvent(QMouseEvent* e) {
348
if (eventHandler!=NULL) {
349
eventHandler->mousePressEvent(e);
356
* Called by the actual GUI class which implements the RS_GraphicView
357
* interface to notify LibreCAD about mouse events.
359
void RS_GraphicView::mouseReleaseEvent(QMouseEvent* e) {
360
RS_DEBUG->print("RS_GraphicView::mouseReleaseEvent");
361
if (eventHandler!=NULL) {
362
if (e->button()!=Qt::RightButton ||
363
eventHandler->hasAction()) {
365
eventHandler->mouseReleaseEvent(e);
374
RS_DEBUG->print("RS_GraphicView::mouseReleaseEvent: OK");
381
* Description: - Called by the actual GUI class which implements the
382
* RS_GraphicView interface to notify LibreCAD about
385
* Author(s): ..., Claude Sylvain
387
* Last modified: 23 July 2011
389
* Parameters: QMouseEvent* e:
395
void RS_GraphicView::mouseMoveEvent(QMouseEvent* e) {
396
RS_DEBUG->print("RS_GraphicView::mouseMoveEvent begin");
398
RS_Graphic* graphic = NULL;
400
if (container->rtti()==RS2::EntityGraphic) {
401
graphic = (RS_Graphic*)container;
404
RS_DEBUG->print("RS_GraphicView::mouseMoveEvent 001");
411
RS_DEBUG->print("RS_GraphicView::mouseMoveEvent 002");
413
if (eventHandler!=NULL) {
414
eventHandler->mouseMoveEvent(e);
417
RS_DEBUG->print("RS_GraphicView::mouseMoveEvent 003");
419
if ( ((eventHandler == NULL) || !eventHandler->hasAction()) &&
422
RS_Vector mouse = toGraph(RS_Vector(mx, my));
423
RS_Vector relMouse = mouse - getRelativeZero();
425
if (RS_DIALOGFACTORY!=NULL)
426
RS_DIALOGFACTORY->updateCoordinateWidget(mouse, relMouse);
429
RS_DEBUG->print("RS_GraphicView::mouseMoveEvent end");
435
* Called by the actual GUI class which implements the RS_GraphicView
436
* interface to notify LibreCAD about mouse events.
438
void RS_GraphicView::mouseLeaveEvent() {
439
if (eventHandler!=NULL) {
440
eventHandler->mouseLeaveEvent();
447
* Called by the actual GUI class which implements the RS_GraphicView
448
* interface to notify LibreCAD about mouse events.
450
void RS_GraphicView::mouseEnterEvent() {
451
if (eventHandler!=NULL) {
452
eventHandler->mouseEnterEvent();
459
* Called by the actual GUI class which implements the RS_GraphicView
460
* interface to notify LibreCAD about key events.
462
void RS_GraphicView::keyPressEvent(QKeyEvent* e) {
463
if (eventHandler!=NULL) {
464
eventHandler->keyPressEvent(e);
471
* Called by the actual GUI class which implements the RS_GraphicView
472
* interface to notify LibreCAD about key events.
474
void RS_GraphicView::keyReleaseEvent(QKeyEvent* e) {
475
if (eventHandler!=NULL) {
476
eventHandler->keyReleaseEvent(e);
483
* Called by the actual GUI class which implements a command line.
485
void RS_GraphicView::commandEvent(RS_CommandEvent* e) {
486
if (eventHandler!=NULL) {
487
eventHandler->commandEvent(e);
494
* Enables coordinate input in the command line.
496
void RS_GraphicView::enableCoordinateInput() {
497
if (eventHandler!=NULL) {
498
eventHandler->enableCoordinateInput();
505
* Disables coordinate input in the command line.
507
void RS_GraphicView::disableCoordinateInput() {
508
if (eventHandler!=NULL) {
509
eventHandler->disableCoordinateInput();
516
* zooms in by factor f
518
void RS_GraphicView::zoomIn(double f, const RS_Vector& center) {
521
RS_DEBUG->print(RS_Debug::D_WARNING,
522
"RS_GraphicView::zoomIn: invalid factor");
527
RS_Vector c = center;
528
if (c.valid==false) {
529
c = toGraph(RS_Vector(getWidth()/2, getHeight()/2));
533
toGraph(RS_Vector(0,0))
534
.scale(c, RS_Vector(1.0/f,1.0/f)),
535
toGraph(RS_Vector(getWidth(),getHeight()))
536
.scale(c, RS_Vector(1.0/f,1.0/f)));
538
//adjustOffsetControls();
539
//adjustZoomControls();
547
* zooms in by factor f in x
549
void RS_GraphicView::zoomInX(double f) {
551
offsetX=(int)((offsetX-getWidth()/2)*f)+getWidth()/2;
552
adjustOffsetControls();
553
adjustZoomControls();
561
* zooms in by factor f in y
563
void RS_GraphicView::zoomInY(double f) {
565
offsetY=(int)((offsetY-getHeight()/2)*f)+getHeight()/2;
566
adjustOffsetControls();
567
adjustZoomControls();
575
* zooms out by factor f
577
void RS_GraphicView::zoomOut(double f, const RS_Vector& center) {
579
RS_DEBUG->print(RS_Debug::D_WARNING,
580
"RS_GraphicView::zoomOut: invalid factor");
589
* zooms out by factor f in x
591
void RS_GraphicView::zoomOutX(double f) {
593
RS_DEBUG->print(RS_Debug::D_WARNING,
594
"RS_GraphicView::zoomOutX: invalid factor");
598
offsetX=(int)(offsetX/f);
599
adjustOffsetControls();
600
adjustZoomControls();
608
* zooms out by factor f y
610
void RS_GraphicView::zoomOutY(double f) {
612
RS_DEBUG->print(RS_Debug::D_WARNING,
613
"RS_GraphicView::zoomOutY: invalid factor");
617
offsetY=(int)(offsetY/f);
618
adjustOffsetControls();
619
adjustZoomControls();
627
* @param axis include axis in zoom
628
* @param keepAspectRatio true: keep aspect ratio 1:1
629
* false: factors in x and y are stretched to the max
631
void RS_GraphicView::zoomAuto(bool axis, bool keepAspectRatio) {
633
RS_DEBUG->print("RS_GraphicView::zoomAuto");
636
if (container!=NULL) {
637
container->calculateBorders();
641
sx = std::max(container->getMax().x, 0.0)
642
- std::min(container->getMin().x, 0.0);
643
sy = std::max(container->getMax().y, 0.0)
644
- std::min(container->getMin().y, 0.0);
646
sx = container->getSize().x;
647
sy = container->getSize().y;
649
// std::cout<<" RS_GraphicView::zoomAuto("<<axis<<","<<keepAspectRatio<<")"<<std::endl;
652
unsigned short fFlags=0;
654
if (sx>RS_TOLERANCE) {
655
fx = (getWidth()-borderLeft-borderRight) / sx;
657
fFlags += 1; //invalid x factor
660
if (sy>RS_TOLERANCE) {
661
fy = (getHeight()-borderTop-borderBottom) / sy;
663
fFlags += 2; //invalid y factor
665
// std::cout<<"0: fx= "<<fx<<"\tfy="<<fy<<std::endl;
667
RS_DEBUG->print("f: %f/%f", fx, fy);
677
return; //do not do anything, invalid factors
679
if (keepAspectRatio) {
680
fx = fy = std::min(fx, fy);
684
// std::cout<<"1: fx= "<<fx<<"\tfy="<<fy<<std::endl;
686
RS_DEBUG->print("f: %f/%f", fx, fy);
687
//exclude invalid factors
689
if (fx<RS_TOLERANCE||fx>RS_MAXDOUBLE) {
693
if (fy<RS_TOLERANCE||fy>RS_MAXDOUBLE) {
697
if(fFlags == 3 ) return;
699
// std::cout<<"2: fx= "<<fx<<"\tfy="<<fy<<std::endl;
703
RS_DEBUG->print("f: %f/%f", fx, fy);
706
// RS_DEBUG->print("adjustZoomControls");
707
adjustZoomControls();
708
// RS_DEBUG->print("centerOffsetX");
710
// RS_DEBUG->print("centerOffsetY");
712
// RS_DEBUG->print("adjustOffsetControls");
713
adjustOffsetControls();
714
// RS_DEBUG->print("updateGrid");
719
RS_DEBUG->print("RS_GraphicView::zoomAuto OK");
725
* Shows previous view.
727
void RS_GraphicView::zoomPrevious() {
729
RS_DEBUG->print("RS_GraphicView::zoomPrevious");
731
if (container!=NULL) {
739
* Saves the current view as previous view to which we can
740
* switch back later with @see restoreView().
742
void RS_GraphicView::saveView() {
743
QDateTime noUpdateWindow=QDateTime::currentDateTime().addMSecs(-500);
744
//do not update view within 500 milliseconds
745
if(previousViewTime > noUpdateWindow) return;
746
previousViewTime = QDateTime::currentDateTime();
747
savedViews[savedViewIndex]=std::make_tuple(offsetX,offsetY,factor);
748
savedViewIndex = (savedViewIndex+1)%savedViews.size();
749
if(savedViewCount<savedViews.size()) savedViewCount++;
751
if(savedViewCount==1){
752
QC_ApplicationWindow::getAppWindow()->setPreviousZoomEnable(true);
759
* Restores the view previously saved with
762
void RS_GraphicView::restoreView() {
763
if(savedViewCount == 0) return;
765
if(savedViewCount==0){
766
QC_ApplicationWindow::getAppWindow()->setPreviousZoomEnable(false);
768
savedViewIndex = (savedViewIndex + savedViews.size() - 1)%savedViews.size();
770
offsetX = std::get<0>(savedViews[savedViewIndex]);
771
offsetY = std::get<1>(savedViews[savedViewIndex]);
772
factor = std::get<2>(savedViews[savedViewIndex]);
774
adjustOffsetControls();
775
adjustZoomControls();
784
* Description: Performs autozoom in Y axis only.
785
* Author(s): ..., Claude Sylvain
787
* Last modified: 23 July 2011
789
* Parameters: bool axis:
795
void RS_GraphicView::zoomAutoY(bool axis) {
796
if (container!=NULL) {
797
double visibleHeight = 0.0;
798
double minY = RS_MAXDOUBLE;
799
double maxY = RS_MINDOUBLE;
800
bool noChange = false;
802
for (RS_Entity* e=container->firstEntity(RS2::ResolveNone);
804
e = container->nextEntity(RS2::ResolveNone)) {
806
if (e->rtti()==RS2::EntityLine) {
807
RS_Line* l = (RS_Line*)e;
809
x1 = toGuiX(l->getStartpoint().x);
810
x2 = toGuiX(l->getEndpoint().x);
812
if ( ((x1 > 0.0) && (x1 < (double) getWidth())) ||
813
((x2 > 0.0) && (x2 < (double) getWidth())))
815
minY = std::min(minY, l->getStartpoint().y);
816
minY = std::min(minY, l->getEndpoint().y);
817
maxY = std::max(maxY, l->getStartpoint().y);
818
maxY = std::max(maxY, l->getEndpoint().y);
824
visibleHeight = std::max(maxY, 0.0) - std::min(minY, 0.0);
826
visibleHeight = maxY-minY;
829
if (visibleHeight<1.0) {
834
if (visibleHeight>1.0e-6) {
835
fy = (getHeight()-borderTop-borderBottom)
837
if (factor.y<0.000001) {
842
if (noChange==false) {
845
offsetY = (int)((getHeight()-borderTop-borderBottom
846
- (visibleHeight*factor.y))/2.0
847
- (minY*factor.y)) + borderBottom;
848
adjustOffsetControls();
849
adjustZoomControls();
853
RS_DEBUG->print("Auto zoom y ok");
860
* Zooms the area given by v1 and v2.
862
* @param keepAspectRatio true: keeps the aspect ratio 1:1
863
* false: zooms exactly the selected range to the
864
* current graphic view
866
void RS_GraphicView::zoomWindow(RS_Vector v1, RS_Vector v2,
867
bool keepAspectRatio) {
871
double zoomX=480.0; // Zoom for X-Axis
872
double zoomY=640.0; // Zoom for Y-Axis (Set smaller one)
875
// Switch left/right and top/bottom is necessary:
877
std::swap(v1.x,v2.x);
880
std::swap(v1.y,v2.y);
883
// Get zoom in X and zoom in Y:
884
if(v2.x-v1.x>1.0e-6) {
885
zoomX = getWidth() / (v2.x-v1.x);
887
if(v2.y-v1.y>1.0e-6) {
888
zoomY = getHeight() / (v2.y-v1.y);
891
// Take smaller zoom:
892
if (keepAspectRatio) {
895
zoomX = zoomY = ((double)(getWidth()-2*zoomBorder)) /
896
(double)getWidth()*zoomX;
900
zoomX = zoomY = ((double)(getHeight()-2*zoomBorder)) /
901
(double)getHeight()*zoomY;
909
// Borders in pixel after zoom
910
int pixLeft =(int)(v1.x*zoomX);
911
int pixTop =(int)(v2.y*zoomY);
912
int pixRight =(int)(v2.x*zoomX);
913
int pixBottom=(int)(v1.y*zoomY);
914
if( pixLeft == INT_MIN || pixLeft== INT_MAX ||
915
pixRight == INT_MIN || pixRight== INT_MAX ||
916
pixTop == INT_MIN || pixTop== INT_MAX ||
917
pixBottom == INT_MIN || pixBottom== INT_MAX ) {
918
RS_DIALOGFACTORY->commandMessage("Requested zooming factor out of range. Zooming not changed");
923
// Set new offset for zero point:
924
offsetX = - pixLeft + (getWidth() -pixRight +pixLeft)/2;
925
offsetY = - pixTop + (getHeight() -pixBottom +pixTop)/2;
929
adjustOffsetControls();
930
adjustZoomControls();
939
* Centers the point v1.
941
void RS_GraphicView::zoomPan(int dx, int dy) {
942
//offsetX+=(int)toGuiDX(v1.x);
943
//offsetY+=(int)toGuiDY(v1.y);
948
adjustOffsetControls();
949
//adjustZoomControls();
958
* Scrolls in the given direction.
960
void RS_GraphicView::zoomScroll(RS2::Direction direction) {
975
adjustOffsetControls();
976
adjustZoomControls();
985
* Zooms to page extends.
987
void RS_GraphicView::zoomPage() {
989
RS_DEBUG->print("RS_GraphicView::zoomPage");
990
if (container==NULL) {
994
RS_Graphic* graphic = container->getGraphic();
999
RS_Vector s = graphic->getPaperSize()/graphic->getPaperScale();
1003
if (s.x>RS_TOLERANCE) {
1004
fx = (getWidth()-borderLeft-borderRight) / s.x;
1009
if (s.y>RS_TOLERANCE) {
1010
fy = (getHeight()-borderTop-borderBottom) / s.y;
1015
RS_DEBUG->print("f: %f/%f", fx, fy);
1017
fx = fy = std::min(fx, fy);
1019
RS_DEBUG->print("f: %f/%f", fx, fy);
1021
if (fx<RS_TOLERANCE) {
1028
RS_DEBUG->print("f: %f/%f", fx, fy);
1032
adjustOffsetControls();
1033
adjustZoomControls();
1042
* Draws the entities within the given range.
1044
void RS_GraphicView::drawWindow_DEPRECATED(RS_Vector v1, RS_Vector v2) {
1045
RS_DEBUG->print("RS_GraphicView::drawWindow() begin");
1046
if (container!=NULL) {
1047
for (RS_Entity* se=container->firstEntity(RS2::ResolveNone);
1049
se = container->nextEntity(RS2::ResolveNone)) {
1050
if (se->isInWindow(v1, v2)) {
1051
drawEntity(NULL, se);
1055
RS_DEBUG->print("RS_GraphicView::drawWindow() end");
1059
* Draws the entities.
1060
* This function can only be called from within the paint event
1063
void RS_GraphicView::drawLayer1(RS_Painter *painter) {
1065
// drawing paper border:
1066
if (isPrintPreview()) {
1070
// drawing meta grid:
1071
if (!isPrintPreview()) {
1073
//only drawGrid updates the grid layout (updatePointArray())
1074
drawMetaGrid(painter);
1075
//draw grid after metaGrid to avoid overwriting grid points by metaGrid lines
1086
* Description: Do the drawing, step 2/3.
1087
* Author(s): ..., Claude Sylvain
1089
* Last modified: 23 July 2011
1091
* Parameters: RS_Painter *painter:
1097
void RS_GraphicView::drawLayer2(RS_Painter *painter)
1099
drawEntity(painter, container); // Draw all entities.
1101
// If not in print preview, draw the absolute zero reference.
1102
// ----------------------------------------------------------
1103
if (!isPrintPreview())
1104
drawAbsoluteZero(painter);
1108
void RS_GraphicView::drawLayer3(RS_Painter *painter) {
1109
// drawing zero points:
1110
if (!isPrintPreview()) {
1111
drawRelativeZero(painter);
1112
drawOverlay(painter);
1120
* Description: - Sets the pen of the painter object to the suitable pen
1121
* for the given entity.
1123
* Author(s): ..., Claude Sylvain
1125
* Last modified: 17 November 2011
1127
* Parameters: RS_Painter *painter:
1136
void RS_GraphicView::setPenForEntity(RS_Painter *painter,RS_Entity *e)
1139
painter->setPen(RS_Pen(foreground,
1140
RS2::Width00, RS2::SolidLine));
1143
// Getting pen from entity (or layer)
1144
RS_Pen pen = e->getPen(true);
1146
int w = pen.getWidth();
1152
// - Scale pen width.
1153
// - Notes: pen width is not scaled on print and print preview.
1154
// This is the standard (AutoCAD like) behaviour.
1156
// ------------------------------------------------------------
1159
double uf = 1.0; // Unit factor.
1160
double wf = 1.0; // Width factor.
1162
RS_Graphic* graphic = container->getGraphic();
1164
if (graphic != NULL)
1166
uf = RS_Units::convert(1.0, RS2::Millimeter, graphic->getUnit());
1168
if ( (isPrinting() || isPrintPreview()) &&
1169
graphic->getPaperScale() > RS_TOLERANCE )
1171
wf = 1.0 / graphic->getPaperScale();
1175
pen.setScreenWidth(toGuiDX(w / 100.0 * uf * wf));
1179
// pen.setWidth(RS2::Width00);
1180
pen.setScreenWidth(0);
1185
// - Scale pen width.
1186
// - Notes: pen width is scaled on print and print preview.
1187
// This is not the standard (AutoCAD like) behaviour.
1188
// --------------------------------------------------------
1191
double uf = 1.0; // Unit factor.
1193
RS_Graphic* graphic = container->getGraphic();
1195
if (graphic != NULL)
1196
uf = RS_Units::convert(1.0, RS2::Millimeter, graphic->getUnit());
1198
pen.setScreenWidth(toGuiDX(w / 100.0 * uf));
1201
pen.setScreenWidth(0);
1204
// prevent drawing with 1-width which is slow:
1205
if (RS_Math::round(pen.getScreenWidth())==1) {
1206
pen.setScreenWidth(0.0);
1209
// prevent background color on background drawing:
1210
if (pen.getColor().stripFlags()==background.stripFlags()) {
1211
pen.setColor(foreground);
1214
// this entity is selected:
1215
if (e->isSelected()) {
1216
pen.setLineType(RS2::DotLine);
1217
pen.setColor(selectedColor);
1220
// this entity is highlighted:
1221
if (e->isHighlighted()) {
1222
pen.setColor(highlightedColor);
1225
// deleting not drawing:
1226
if (getDeleteMode()) {
1227
pen.setColor(background);
1230
painter->setPen(pen);
1235
* Draws an entity. Might be recusively called e.g. for polylines.
1236
* If the class wide painter is NULL a new painter will be created
1237
* and destroyed afterwards.
1239
* @param patternOffset Offset of line pattern (used for connected
1240
* lines e.g. in splines).
1241
* @param db Double buffering on (recommended) / off
1243
void RS_GraphicView::drawEntity(RS_Entity* /*e*/, double& /*patternOffset*/) {
1244
RS_DEBUG->print("RS_GraphicView::drawEntity(RS_Entity*,patternOffset) not supported anymore");
1245
// RVT_PORT this needs to be optimized
1246
// ONe way to do is to send a RS2::RedrawSelected, then teh draw routine will onyl draw all selected entities
1247
// Dis-advantage is that we still need to iterate over all entities, but
1248
// this might be very fast
1249
// For now we just redraw the drawing untill we are going to optmize drawing
1250
redraw(RS2::RedrawDrawing);
1252
void RS_GraphicView::drawEntity(RS_Entity* /*e*/ /*patternOffset*/) {
1253
RS_DEBUG->print("RS_GraphicView::drawEntity(RS_Entity*,patternOffset) not supported anymore");
1254
// RVT_PORT this needs to be optimized
1255
// ONe way to do is to send a RS2::RedrawSelected, then teh draw routine will onyl draw all selected entities
1256
// Dis-advantage is that we still need to iterate over all entities, but
1257
// this might be very fast
1258
// For now we just redraw the drawing untill we are going to optmize drawing
1259
redraw(RS2::RedrawDrawing);
1261
void RS_GraphicView::drawEntity(RS_Painter *painter, RS_Entity* e) {
1263
drawEntity(painter,e,offset);
1265
void RS_GraphicView::drawEntity(RS_Painter *painter, RS_Entity* e, double& patternOffset) {
1267
// update is diabled:
1268
// given entity is NULL:
1273
// entity is not visible:
1274
if (!e->isVisible()) {
1277
if( isPrintPreview() || isPrinting() ) {
1278
//do not draw help layer on print preview or print
1279
if(e->isHelpLayer()) return;
1282
// test if the entity is in the viewport
1283
/* temporary disabled so rs_overlaylien can be drawn
1284
if (!e->isContainer() && !isPrinting() &&
1285
(painter==NULL || !painter->isPreviewMode()) &&
1286
(toGuiX(e->getMax().x)<0 || toGuiX(e->getMin().x)>getWidth() ||
1287
toGuiY(e->getMin().y)<0 || toGuiY(e->getMax().y)>getHeight())) {
1292
setPenForEntity(painter, e );
1294
//RS_DEBUG->print("draw plain");
1295
if (isDraftMode()) {
1296
// large mtexts as rectangles:
1297
if (e->rtti()==RS2::EntityMText) {
1298
if (toGuiDX(((RS_MText*)e)->getHeight())<4 || e->countDeep()>100) {
1299
painter->drawRect(toGui(e->getMin()), toGui(e->getMax()));
1301
drawEntityPlain(painter, e, patternOffset);
1304
// large texts as rectangles:
1305
else if (e->rtti()==RS2::EntityText) {
1306
if (toGuiDX(((RS_Text*)e)->getHeight())<4 || e->countDeep()>100) {
1307
painter->drawRect(toGui(e->getMin()), toGui(e->getMax()));
1309
drawEntityPlain(painter, e, patternOffset);
1313
// all images as rectangles:
1314
else if (e->rtti()==RS2::EntityImage) {
1315
painter->drawRect(toGui(e->getMin()), toGui(e->getMax()));
1319
else if (e->rtti()==RS2::EntityHatch) {
1324
drawEntityPlain(painter, e, patternOffset);
1327
drawEntityPlain(painter, e, patternOffset);
1330
// draw reference points:
1331
if (e->isSelected()) {
1332
if (!e->isParentSelected()) {
1333
RS_VectorSolutions s = e->getRefPoints();
1335
for (int i=0; i<s.getNumber(); ++i) {
1337
RS_Color col = handleColor;
1339
col = startHandleColor;
1341
else if (i == s.getNumber() - 1) {
1342
col = endHandleColor;
1344
if (getDeleteMode()) {
1345
painter->drawHandle(toGui(s.get(i)), background, sz);
1347
painter->drawHandle(toGui(s.get(i)), col, sz);
1353
//RS_DEBUG->print("draw plain OK");
1356
//RS_DEBUG->print("RS_GraphicView::drawEntity() end");
1362
* The painter must be initialized and all the attributes (pen) must be set.
1364
void RS_GraphicView::drawEntityPlain(RS_Painter *painter, RS_Entity* e, double& patternOffset) {
1369
if (!e->isContainer() && (e->isSelected()!=painter->shouldDrawSelected())) {
1373
e->draw(painter, this, patternOffset);
1376
void RS_GraphicView::drawEntityPlain(RS_Painter *painter, RS_Entity* e) {
1381
if (!e->isContainer() && (e->isSelected()!=painter->shouldDrawSelected())) {
1384
double patternOffset(0.);
1385
e->draw(painter, this, patternOffset);
1389
* Deletes an entity with the background color.
1390
* Might be recusively called e.g. for polylines.
1392
void RS_GraphicView::deleteEntity(RS_Entity* e) {
1394
// RVT_PORT When we delete a single entoty, we can do this but we need to remove this then also from containerEntities
1395
RS_DEBUG->print("RS_GraphicView::deleteEntity will for now redraw the whole screen instead of just deleting the entity");
1396
setDeleteMode(true);
1398
setDeleteMode(false);
1399
redraw(RS2::RedrawDrawing);
1406
* @return Pointer to the static pattern struct that belongs to the
1407
* given pattern type or NULL.
1409
RS_LineTypePattern* RS_GraphicView::getPattern(RS2::LineType t) {
1411
case RS2::SolidLine:
1412
return &patternSolidLine;
1416
return &patternDotLine;
1419
return &patternDotLine2;
1421
case RS2::DotLineX2:
1422
return &patternDotLineX2;
1426
return &patternDashLine;
1428
case RS2::DashLine2:
1429
return &patternDashLine2;
1431
case RS2::DashLineX2:
1432
return &patternDashLineX2;
1435
case RS2::DashDotLine:
1436
return &patternDashDotLine;
1438
case RS2::DashDotLine2:
1439
return &patternDashDotLine2;
1441
case RS2::DashDotLineX2:
1442
return &patternDashDotLineX2;
1445
case RS2::DivideLine:
1446
return &patternDivideLine;
1448
case RS2::DivideLine2:
1449
return &patternDivideLine2;
1451
case RS2::DivideLineX2:
1452
return &patternDivideLineX2;
1455
case RS2::CenterLine:
1456
return &patternCenterLine;
1458
case RS2::CenterLine2:
1459
return &patternCenterLine2;
1461
case RS2::CenterLineX2:
1462
return &patternCenterLineX2;
1465
case RS2::BorderLine:
1466
return &patternBorderLine;
1468
case RS2::BorderLine2:
1469
return &patternBorderLine2;
1471
case RS2::BorderLineX2:
1472
return &patternBorderLineX2;
1475
case RS2::LineByLayer:
1476
return &patternBlockLine;
1478
case RS2::LineByBlock:
1479
return &patternBlockLine;
1490
* This virtual method can be overwritten to draw the absolute
1491
* zero. It's called from within drawIt(). The default implemetation
1492
* draws a simple red cross on the zero of thge sheet
1493
* THis function can ONLY be called from within a paintEvent because it will
1498
void RS_GraphicView::drawAbsoluteZero(RS_Painter *painter) {
1502
RS_Pen p(QColor(255,0,0), RS2::Width00, RS2::SolidLine);
1503
p.setScreenWidth(0);
1505
//painter->setBrush(Qt::NoBrush);
1507
painter->drawLine(RS_Vector(toGuiX(0.0)-zr,
1509
RS_Vector(toGuiX(0.0)+zr,
1512
painter->drawLine(RS_Vector(toGuiX(0.0),
1514
RS_Vector(toGuiX(0.0),
1522
* This virtual method can be overwritten to draw the relative
1523
* zero point. It's called from within drawIt(). The default implemetation
1524
* draws a simple red round zero point. This is the point that was last created by the user, end of a line for example
1525
* THis function can ONLY be called from within a paintEvent because it will
1530
void RS_GraphicView::drawRelativeZero(RS_Painter *painter) {
1532
if (relativeZero.valid==false) {
1536
RS_Pen p(RS_Color(255, 0, 0), RS2::Width00, RS2::SolidLine);
1537
p.setScreenWidth(0);
1542
painter->drawLine(RS_Vector(toGuiX(relativeZero.x)-zr,
1543
toGuiY(relativeZero.y)),
1544
RS_Vector(toGuiX(relativeZero.x)+zr,
1545
toGuiY(relativeZero.y)));
1547
painter->drawLine(RS_Vector(toGuiX(relativeZero.x),
1548
toGuiY(relativeZero.y)-zr),
1549
RS_Vector(toGuiX(relativeZero.x),
1550
toGuiY(relativeZero.y)+zr));
1552
painter->drawCircle(toGui(relativeZero), 5);
1558
* Draws the paper border (for print previews).
1559
* This function can ONLY be called from within a paintEvent because it will
1564
void RS_GraphicView::drawPaper(RS_Painter *painter) {
1566
if (container==NULL) {
1570
RS_Graphic* graphic = container->getGraphic();
1571
if (graphic->getPaperScale()<1.0e-6) {
1576
// RVT_PORT rewritten from painter->setPen(Qt::gray);
1577
painter->setPen(QColor(Qt::gray));
1579
RS_Vector pinsbase = graphic->getPaperInsertionBase();
1580
RS_Vector size = graphic->getPaperSize();
1581
double scale = graphic->getPaperScale();
1583
RS_Vector v1 = toGui((RS_Vector(0,0)-pinsbase)/scale);
1584
RS_Vector v2 = toGui((size-pinsbase)/scale);
1587
painter->fillRect(0,0, getWidth(), getHeight(),
1588
RS_Color(200,200,200));
1592
(int)(v1.x)+6, (int)(v1.y)+6,
1593
(int)((v2.x-v1.x)), (int)((v2.y-v1.y)),
1594
RS_Color(64,64,64));
1598
(int)(v1.x), (int)(v1.y),
1599
(int)((v2.x-v1.x)), (int)((v2.y-v1.y)),
1600
RS_Color(64,64,64));
1604
(int)(v1.x)+1, (int)(v1.y)-1,
1605
(int)((v2.x-v1.x))-2, (int)((v2.y-v1.y))+2,
1606
RS_Color(255,255,255));
1616
void RS_GraphicView::drawGrid(RS_Painter *painter) {
1618
if (grid==NULL || isGridOn()==false) {
1624
//painter->setPen(Qt::gray);
1625
painter->setPen(gridColor);
1627
// grid->updatePointArray();
1628
RS_Vector* pts = grid->getPoints();
1630
for (int i=0; i<grid->count(); ++i) {
1631
painter->drawGridPoint(toGui(pts[i]));
1636
//painter->setPen(Qt::white);
1637
QString info = grid->getInfo();
1638
//info = QString("%1 / %2")
1639
// .arg(grid->getSpacing())
1640
// .arg(grid->getMetaSpacing());
1642
updateGridStatusWidget(info);
1650
* Draws the meta grid.
1654
void RS_GraphicView::drawMetaGrid(RS_Painter *painter) {
1656
if (grid==NULL || isGridOn()==false /*|| grid->getMetaSpacing()<0.0*/) {
1660
//draw grid after metaGrid to avoid overwriting grid points by metaGrid lines
1662
grid->updatePointArray();
1663
RS_Pen pen(metaGridColor,
1666
painter->setPen(pen);
1668
RS_Vector dv=grid->getMetaGridWidth().scale(factor);
1669
double dx=fabs(dv.x);
1670
double dy=fabs(dv.y); //potential bug, need to recover metaGrid.width
1672
double* mx = grid->getMetaX();
1674
for (int i=0; i<grid->countMetaX(); ++i) {
1675
painter->drawLine(RS_Vector(toGuiX(mx[i]), 0),
1676
RS_Vector(toGuiX(mx[i]), getHeight()));
1677
if(grid->isIsometric()){
1678
painter->drawLine(RS_Vector(toGuiX(mx[i])+0.5*dx, 0),
1679
RS_Vector(toGuiX(mx[i])+0.5*dx, getHeight()));
1683
double* my = grid->getMetaY();
1684
if(grid->isIsometric()){//isometric metaGrid
1687
if(my==NULL || dx<1||dy<1) return;
1688
RS_Vector baseMeta(toGui(RS_Vector(mx[0],my[0])));
1689
// x-x0=k*dx, x-remainder(x-x0,dx)
1690
RS_Vector vp0(-remainder(-baseMeta.x,dx)-dx,getHeight()-remainder(getHeight()-baseMeta.y,dy)+dy);
1692
RS_Vector vp2(getWidth()-remainder(getWidth()-baseMeta.x,dx)+dx,vp0.y);
1694
int cmx = round((vp2.x - vp0.x)/dx);
1695
int cmy = round((vp0.y +remainder(-baseMeta.y,dy)+dy)/dy);
1696
for(int i=cmx+cmy+2;i>=0;i--){
1711
painter->drawLine(vp0,vp1);
1712
painter->drawLine(vp2,vp3);
1718
for (int i=0; i<grid->countMetaY(); ++i) {
1719
painter->drawLine(RS_Vector(0, toGuiY(my[i])),
1720
RS_Vector(getWidth(), toGuiY(my[i])));
1728
void RS_GraphicView::drawOverlay(RS_Painter *painter) {
1729
QList<int> keys=overlayEntities.keys();
1730
for (int i = 0; i < keys.size(); ++i) {
1731
if (overlayEntities[i] != NULL) {
1732
setPenForEntity(painter, overlayEntities[i] );
1733
drawEntityPlain(painter, overlayEntities[i]);
1739
* Sets the default snap mode used by newly created actions.
1741
void RS_GraphicView::setDefaultSnapMode(RS_SnapMode sm) {
1742
defaultSnapMode = sm;
1743
if (eventHandler!=NULL) {
1744
eventHandler->setSnapMode(sm);
1751
* Sets a snap restriction (e.g. orthogonal).
1753
void RS_GraphicView::setSnapRestriction(RS2::SnapRestriction sr) {
1754
defaultSnapRes = sr;
1756
if (eventHandler!=NULL) {
1757
eventHandler->setSnapRestriction(sr);
1764
* Translates a vector in real coordinates to a vector in screen coordinates.
1766
RS_Vector RS_GraphicView::toGui(RS_Vector v) {
1767
return RS_Vector(toGuiX(v.x), toGuiY(v.y));
1773
* Translates a real coordinate in X to a screen coordinate X.
1774
* @param visible Pointer to a boolean which will contain true
1775
* after the call if the coordinate is within the visible range.
1777
double RS_GraphicView::toGuiX(double x) {
1778
return x*factor.x + offsetX;
1784
* Translates a real coordinate in Y to a screen coordinate Y.
1786
double RS_GraphicView::toGuiY(double y) {
1787
return -y*factor.y + getHeight() - offsetY;
1793
* Translates a real coordinate distance to a screen coordinate distance.
1795
double RS_GraphicView::toGuiDX(double d) {
1802
* Translates a real coordinate distance to a screen coordinate distance.
1804
double RS_GraphicView::toGuiDY(double d) {
1811
* Translates a vector in screen coordinates to a vector in real coordinates.
1813
RS_Vector RS_GraphicView::toGraph(RS_Vector v) {
1814
return RS_Vector(toGraphX(RS_Math::round(v.x)),
1815
toGraphY(RS_Math::round(v.y)));
1821
* Translates two screen coordinates to a vector in real coordinates.
1823
RS_Vector RS_GraphicView::toGraph(int x, int y) {
1824
return RS_Vector(toGraphX(x), toGraphY(y));
1829
* Translates a screen coordinate in X to a real coordinate X.
1831
double RS_GraphicView::toGraphX(int x) {
1832
return (x - offsetX)/factor.x;
1838
* Translates a screen coordinate in Y to a real coordinate Y.
1840
double RS_GraphicView::toGraphY(int y) {
1841
return -(y - getHeight() + offsetY)/factor.y;
1847
* Translates a screen coordinate distance to a real coordinate distance.
1849
double RS_GraphicView::toGraphDX(int d) {
1856
* Translates a screen coordinate distance to a real coordinate distance.
1858
double RS_GraphicView::toGraphDY(int d) {
1864
* Sets the relative zero coordinate (if not locked)
1865
* without deleting / drawing the point.
1867
void RS_GraphicView::setRelativeZero(const RS_Vector& pos) {
1868
if (relativeZeroLocked==false) {
1876
* Sets the relative zero coordinate, deletes the old position
1877
* on the screen and draws the new one.
1879
void RS_GraphicView::moveRelativeZero(const RS_Vector& pos) {
1880
setRelativeZero(pos);
1881
redraw(RS2::RedrawGrid);
1886
* Remove all overlay entities
1888
RS_EntityContainer* RS_GraphicView::getOverlayContainer(RS2::OverlayGraphics position)
1890
if (overlayEntities[position]!=NULL) {
1891
return overlayEntities[position];
1893
overlayEntities[position]=new RS_EntityContainer(NULL);
1895
return overlayEntities[position];