This commit is contained in:
Chenwenxuan
2024-03-06 14:54:30 +08:00
commit edac2715f0
1525 changed files with 809982 additions and 0 deletions

73
lib/gui/rs_commandevent.h Normal file
View File

@@ -0,0 +1,73 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_COMMANDEVENT_H
#define RS_COMMANDEVENT_H
/**
* Command Events.
*/
class RS_CommandEvent {
public:
/**
* Creates a new command event that is not yet accepted.
*
* @param cmd the command that was triggered.
*/
RS_CommandEvent(const QString& cmd) {
this->cmd = cmd;
accepted = false;
}
/**
* @return the command that was triggered, usually by
* the user.
*/
QString getCommand() {
return cmd;
}
/**
* Sets the event state to accepted.
*/
void accept() {
accepted = true;
}
/**
* @return Whether the event was already accepted or not.
*/
bool isAccepted() {
return accepted;
}
protected:
QString cmd;
bool accepted;
};
#endif

View File

@@ -0,0 +1,54 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_COORDINATEEVENT_H
#define RS_COORDINATEEVENT_H
/**
* Coordinate Events.
*/
class RS_CoordinateEvent {
public:
/**
* @param pos coordinate
* @param abs true: absolute coordinate, false: relative coordinate
*/
RS_CoordinateEvent(const RS_Vector& pos): pos(pos) {}
/**
* @return the position of the event in real graphic measures.
*/
RS_Vector getCoordinate() {
return pos;
}
protected:
RS_Vector pos;
};
#endif

View File

@@ -0,0 +1,81 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include "rs_dialogfactory.h"
#include "rs_debug.h"
/**
* Private constructor.
*/
RS_DialogFactory::RS_DialogFactory():
factoryObject{nullptr}
{
RS_DEBUG->print("RS_DialogFacgory::RS_DialogFactory");
RS_DEBUG->print("RS_DialogFacgory::RS_DialogFactory: OK");
}
/**
* @return Instance to the unique font list.
*/
RS_DialogFactory* RS_DialogFactory::instance()
{
static RS_DialogFactory* uniqueInstance = new RS_DialogFactory{};
return uniqueInstance;
}
/**
* Sets the real factory object that can create and show dialogs.
*/
void RS_DialogFactory::setFactoryObject(RS_DialogFactoryInterface* fo) {
RS_DEBUG->print("RS_DialogFactory::setFactoryObject");
factoryObject = fo;
RS_DEBUG->print("RS_DialogFactory::setFactoryObject: OK");
}
/**
* @return Factory object. This is never nullptr. If no factory
* object was set, the default adapter will be returned.
*/
RS_DialogFactoryInterface* RS_DialogFactory::getFactoryObject()
{
return factoryObject ? factoryObject : &factoryAdapter;
}
void RS_DialogFactory::commandMessage(const QString& m) {
RS_DEBUG->print("RS_DialogFactory::commandMessage");
if (factoryObject)
factoryObject->commandMessage(m);
}

View File

@@ -0,0 +1,61 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_DIALOGFACTORY_H
#define RS_DIALOGFACTORY_H
#include "rs_dialogfactoryadapter.h"
class RS_DialogFactoryInterface;
#define RS_DIALOGFACTORY RS_DialogFactory::instance()->getFactoryObject()
/**
* Interface for objects that can create and show dialogs.
*/
class RS_DialogFactory {
private:
RS_DialogFactory();
public:
virtual ~RS_DialogFactory() = default;
static RS_DialogFactory* instance();
void setFactoryObject(RS_DialogFactoryInterface* fo);
RS_DialogFactoryInterface* getFactoryObject();
void commandMessage(const QString& m);
private:
RS_DialogFactoryInterface* factoryObject;
RS_DialogFactoryAdapter factoryAdapter;
};
#endif

View File

@@ -0,0 +1,85 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_DIALOGFACTORYADAPTER_H
#define RS_DIALOGFACTORYADAPTER_H
#include "rs_dialogfactoryinterface.h"
#include "rs_block.h"
class RS_BlockList;
/**
* Adapter for dialog factory interface.
* Used when no factory object was set.
*/
class RS_DialogFactoryAdapter : public RS_DialogFactoryInterface {
public:
void requestWarningDialog(const QString&) override {}
RS_GraphicView* requestNewDocument(const QString&, RS_Document*) {return nullptr;}
RS_Layer* requestNewLayerDialog(RS_LayerList*) override{return nullptr;}
RS_Layer* requestLayerRemovalDialog(RS_LayerList*) override{return nullptr;}
QStringList requestSelectedLayersRemovalDialog(RS_LayerList*) override{return {};}
RS_Layer* requestEditLayerDialog(RS_LayerList*) override{return nullptr;}
RS_BlockData requestNewBlockDialog(RS_BlockList*) override {return {};}
RS_Block* requestBlockRemovalDialog(RS_BlockList*) override {return nullptr;}
QList<RS_Block*> requestSelectedBlocksRemovalDialog(RS_BlockList*) override{return {};}
RS_BlockData requestBlockAttributesDialog(RS_BlockList*) override{return {};}
void requestEditBlockWindow(RS_BlockList*) override{}
void closeEditBlockWindow(RS_Block*) override {}
QString requestImageOpenDialog() override {return {};}
void requestOptions(RS_ActionInterface*, bool, bool) override{}
void requestSnapDistOptions(double& , bool) override {}
void requestSnapMiddleOptions(int& , bool) override {}
void requestModifyOffsetOptions(double& , bool) override {}
bool requestAttributesDialog(RS_AttributesData&, RS_LayerList&) override{return false;}
bool requestMoveDialog(RS_MoveData&) override {return false;}
bool requestRotateDialog(RS_RotateData&) override {return false;}
bool requestScaleDialog(RS_ScaleData&) override {return false;}
bool requestMirrorDialog(RS_MirrorData&) override {return false;}
bool requestMoveRotateDialog(RS_MoveRotateData&) override {return false;}
bool requestRotate2Dialog(RS_Rotate2Data&) override {return false;}
bool requestModifyEntityDialog(RS_Entity*) override {return false;}
bool requestMTextDialog(RS_MText*) override {return false;}
bool requestTextDialog(RS_Text*) override {return false;}
bool requestHatchDialog(RS_Hatch*) override {return false;}
void requestOptionsGeneralDialog() override {}
void requestOptionsDrawingDialog(RS_Graphic&) override {}
bool requestOptionsMakerCamDialog() override {return false;}
QString requestFileSaveAsDialog(const QString&, const QString&, const QString&, QString*) override {return {};}
void updateCoordinateWidget(const RS_Vector& , const RS_Vector& , bool =false) override {}
void updateMouseWidget(const QString&, const QString&) override{}
void updateSelectionWidget(int, double) override {}
void updateArcTangentialOptions(const double& , bool) override{}
void commandMessage(const QString&) override {}
void setMouseWidget(QG_MouseWidget*) override {}
void setCoordinateWidget(QG_CoordinateWidget* ) override {}
void setSelectionWidget(QG_SelectionWidget* ) override {}
void setCommandWidget(QG_CommandWidget* ) override {}
};
#endif

View File

@@ -0,0 +1,446 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_DIALOGFACTORYINTERFACE_H
#define RS_DIALOGFACTORYINTERFACE_H
#include "rs.h"
#include <QString>
class RS_ActionInterface;
struct RS_ArcData;
class RS_AttributesData;
class RS_BevelData;
class RS_Block;
struct RS_BlockData;
class RS_BlockList;
struct RS_CircleData;
struct RS_DimLinearData;
struct RS_DimensionData;
class RS_Document;
class RS_Entity;
class RS_EventHandler;
class RS_Graphic;
class RS_GraphicView;
class RS_Grid;
class RS_Hatch;
class RS_Insert;
class RS_Layer;
class RS_LayerList;
class RS_MirrorData;
class RS_MoveData;
class RS_MoveRotateData;
class RS_MText;
class RS_Painter;
class RS_Rotate2Data;
class RS_RotateData;
class RS_RoundData;
class RS_ScaleData;
class RS_Solid;
class RS_Text;
class RS_Vector;
class QG_MouseWidget;
class QG_CoordinateWidget;
class QG_SelectionWidget;
class QG_CommandWidget;
/**
* Interface for objects that can create and show dialogs.
*/
class RS_DialogFactoryInterface {
public:
virtual ~RS_DialogFactoryInterface() = default;
/**
* This virtual method must be overwritten and must provide
* a message dialog.
*/
virtual void requestWarningDialog(const QString& warning) = 0;
/**
* This virtual method must be overwritten and must create a new
* window for the given document or for a new document isf no document
* is given.
*/
// virtual RS_GraphicView* requestNewDocument(const QString& fileName = QString(),
// RS_Document* doc=NULL) = 0;
/**
* This virtual method must be overwritten and must provide
* a dialog for choosing the properties of a new layer to be
* created. The method must create the new layer but not add
* it to the layer list. The latter is up to the caller.
*
* @return The implementation is expected to return a pointer
* to the newly created layer or NULL if the user
* cancels the dialog.
*/
virtual RS_Layer* requestNewLayerDialog(
RS_LayerList* layerList = NULL) = 0;
/**
* This virtual method must be overwritten and must provide
* a dialog that asks for permission for removing the selected
* layer from the layer list. The method must not actually
* remove the layer. This is up to the caller.
*
* @return The implementation is expected to return a pointer
* to the layer which can ne removed or NULL if the user
* cancels the dialog.
*/
virtual RS_Layer* requestLayerRemovalDialog(
RS_LayerList* layerList = NULL) = 0;
/**
* This virtual method must be overwritten and must provide
* a dialog that asks for permission for removing the selected
* layers from the layer list. The method must not actually
* remove those layers. This is up to the caller.
*
* @return The implementation is expected to return a list
* of selected layers names to be removed, or empty
* list if the user cancels the dialog.
*/
virtual QStringList requestSelectedLayersRemovalDialog(
RS_LayerList* layerList = NULL) = 0;
/**
* This virtual method must be overwritten and must provide
* a dialog to edit the layers attributes. The method must
* not actually edit the layer. This is up to the caller.
*
* @return The implementation is expected to return a pointer
* to the modified layer or NULL if the user
* cancels the dialog.
*/
virtual RS_Layer* requestEditLayerDialog(
RS_LayerList* layerList = NULL) = 0;
/**
* This virtual method must be overwritten and must provide
* a dialog for choosing the properties of a new block to be
* created. The method must create the new block but not add
* it to the block list. The latter is up to the caller.
*
* @param block Pointer to the newly created block with default
* attributes.
*
* @return The implementation is expected to return a pointer
* to the newly created block or NULL if the user
* cancels the dialog.
*/
virtual RS_BlockData requestNewBlockDialog(RS_BlockList* blockList) = 0;
/**
* This virtual method must be overwritten and must provide
* a dialog that asks for permission for removing the selected
* block from the block list. The method must not actually
* remove the block. This is up to the caller.
*
* @return The implementation is expected to return a pointer
* to the block which can be removed or NULL if the user
* cancels the dialog.
*/
virtual RS_Block* requestBlockRemovalDialog(
RS_BlockList* blockList) = 0;
/**
* This virtual method must be overwritten and must provide
* a dialog that asks for permission for removing the selected
* blocks from the block list. The method must not actually
* remove those blocks. This is up to the caller.
*
* @return The implementation is expected to return a list
* of selected blocks to be removed, or empty
* list if the user cancels the dialog.
*/
virtual QList<RS_Block*> requestSelectedBlocksRemovalDialog(
RS_BlockList* blockList = NULL) = 0;
/**
* This virtual method must be overwritten and must provide
* a dialog that allows to change blocks attributes of the
* currently active block.
*
* @return The implementation is expected to return a pointer
* to the block which was changed or NULL if the user
* cancels the dialog.
*/
virtual RS_BlockData requestBlockAttributesDialog(
RS_BlockList* blockList) = 0;
/**
* This virtual method must be overwritten and should provide
* a way to edit a block.
*/
virtual void requestEditBlockWindow(
RS_BlockList* blockList) = 0;
virtual void closeEditBlockWindow(RS_Block* block) = 0;
/**
* This virtual method must be overwritten and must provide
* a dialog to get a filename for saving a file. The method must
* not actually save the file. This is up to the caller.
*
* @return The implementation is expected to return a string
* which contains the file name or an empty string if
* the user cancels the dialog.
*/
//virtual QString requestFileSaveAsDialog() = 0;
/**
* This virtual method must be overwritten and must provide
* a dialog to get a filename for opening a file. The method must
* not actually open the file. This is up to the caller.
*
* @return The implementation is expected to return a string
* which contains the file name or an empty string if
* the user cancels the dialog.
*/
//virtual QString requestFileOpenDialog() = 0;
/**
* This virtual method must be overwritten and must provide
* a dialog to get a filename for opening an image file. The method must
* not actually open the file. This is up to the caller.
*
* @return The implementation is expected to return a string
* which contains the file name or an empty string if
* the user cancels the dialog.
*/
virtual QString requestImageOpenDialog() = 0;
/**
* This virtual method must be overwritten and must present
* a widget for options for the given action.
*
* @param action Pointer to the action which needs the options.
* @param on true: switch widget on, false: off
* @param update true: widget gets data from the action, false:
* widget gets data from config file.
*/
virtual void requestOptions(RS_ActionInterface* action,
bool on, bool update = false) = 0;
/**
* This virtual method must be overwritten and must present
* a widget for snap point with distance options.
*
* @param dist Distance which can be directly changed
* by the presented widget.
* @param on true: switch widget on, false: off
*/
virtual void requestSnapDistOptions(double& dist, bool on) = 0;
virtual void requestSnapMiddleOptions(int& middlePoints, bool on) = 0;
/**
*This virtual method must overwritten and must present
* a widget for actionmodifyoffset distance
* @dist, distance of offset
* @on, to create the widget if true, and to delete the widget if false
*/
virtual void requestModifyOffsetOptions(double& dist, bool on) = 0;
/**
* This virtual method must be overwritten and must present
* a widget for entity attributes.
*
* @param data Attribute data which can be directly changed
* by the presented widget.
*/
virtual bool requestAttributesDialog(RS_AttributesData& data,
RS_LayerList& layerList) = 0;
/**
* This virtual method must be overwritten and must present
* a widget for move options (number of copies).
*
* @param data Move data which can be directly changed
* by the presented widget.
*/
virtual bool requestMoveDialog(RS_MoveData& data) = 0;
/**
* This virtual method must be overwritten and must present
* a widget for rotate options (number of copies, angle).
*
* @param data Rotation data which can be directly changed
* by the presented widget.
*/
virtual bool requestRotateDialog(RS_RotateData& data) = 0;
/**
* This virtual method must be overwritten and must present
* a widget for rotate options (number of copies, angle).
*
* @param data Scaling data which can be directly changed
* by the presented widget.
*/
virtual bool requestScaleDialog(RS_ScaleData& data) = 0;
/**
* This virtual method must be overwritten and must present
* a widget for mirror options (number of copies).
*
* @param data Mirror data which can be directly changed
* by the presented widget.
*/
virtual bool requestMirrorDialog(RS_MirrorData& data) = 0;
/**
* This virtual method must be overwritten and must present
* a widget for move/rotate options (number of copies, angle).
*
* @param data Move/rotate data which can be directly changed
* by the presented widget.
*/
virtual bool requestMoveRotateDialog(RS_MoveRotateData& data) = 0;
/**
* This virtual method must be overwritten and must present
* a widget for rotate around two centers options (number of
* copies, angles).
*
* @param data Rotate data which can be directly changed
* by the presented widget.
*/
virtual bool requestRotate2Dialog(RS_Rotate2Data& data) = 0;
/**
* This virtual method must be overwritten and must present
* a dialog to edit the given entity.
*
* @param entity Pointer to the entity.
*/
virtual bool requestModifyEntityDialog(RS_Entity* entity) = 0;
/**
* This virtual method must be overwritten and must present
* a dialog to edit multi-line text entity attributes.
*
* @param entity Pointer to the mtext entity.
*/
virtual bool requestMTextDialog(RS_MText* text) = 0;
/**
* This virtual method must be overwritten and must present
* a dialog to edit text entity attributes.
*
* @param entity Pointer to the text entity.
*/
virtual bool requestTextDialog(RS_Text* text) = 0;
/**
* This virtual method must be overwritten and must present
* a dialog to select pattern attributes.
*
* @param entity Pointer to the hatch entity.
*/
virtual bool requestHatchDialog(RS_Hatch* hatch) = 0;
/**
* This virtual method must be overwritten and must present
* a dialog for general application options.
*/
virtual void requestOptionsGeneralDialog() = 0;
/**
* This virtual method must be overwritten and must present
* a dialog for drawing options.
*
* @param graphic Graphic document.
*/
virtual void requestOptionsDrawingDialog(RS_Graphic& graphic) = 0;
/**
* This virtual method must be overwritten and must present
* a dialog for options how to export as MakeCAM SVG.
*/
virtual bool requestOptionsMakerCamDialog() = 0;
/**
* This virtual method must be overwritten and must present
* a dialog for saving a file.
*/
virtual QString requestFileSaveAsDialog(const QString& caption = QString(),
const QString& dir = QString(),
const QString& filter = QString(),
QString* selectedFilter = 0) = 0;
/**
* This virtual method must be overwritten if the graphic view has
* a component that is interested in the current mouse position.
* The implementation will be called every time the mouse position
* changes.
*
* @param abs Absolute coordinate of the mouse cursor or the
* point it snaps to.
* @param rel Relative coordinate.
*/
virtual void updateCoordinateWidget(const RS_Vector& abs, const RS_Vector& rel, bool updateFormat=false) = 0;
/**
* This virtual method must be overwritten if the graphic view has
* a component that is interested in the current mouse button hints.
* The implementation will be called typically by actions to inform
* the user about the current functionality of the mouse buttons.
*
* @param left Help text for the left mouse button.
* @param right Help text for the right mouse button.
*/
virtual void updateMouseWidget(const QString& = QString(),
const QString& = QString())=0;
virtual void updateArcTangentialOptions(const double& d, bool byRadius)=0;
/**
* This virtual method must be overwritten if the graphic view has
* a component that is interested in the current number of selected
* entities.
* The implementation will be called every time the selection
* changes.
*
* @param num Number of selected entities
*/
virtual void updateSelectionWidget(int num, double length) = 0;
/**
* This virtual method must be overwritten if the graphic view has
* a component that is interested in command messages (such as a
* command line history).
* The implementation will be called typically by actions to inform
* the user about current events and errors.
*
* @param message The message for the user.
*/
virtual void commandMessage(const QString& message) = 0;
virtual void setMouseWidget(QG_MouseWidget*) = 0;
virtual void setCoordinateWidget(QG_CoordinateWidget* ) = 0;
virtual void setSelectionWidget(QG_SelectionWidget* ) = 0;
virtual void setCommandWidget(QG_CommandWidget* ) = 0;
};
#endif

650
lib/gui/rs_eventhandler.cpp Normal file
View File

@@ -0,0 +1,650 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QRegExp>
#include <QAction>
#include <QMouseEvent>
#include "rs_eventhandler.h"
#include "rs_actioninterface.h"
#include "rs_dialogfactory.h"
#include "rs_commandevent.h"
#include "rs_coordinateevent.h"
#include "rs_commands.h"
#include "rs_math.h"
#include "rs_snapper.h"
#include "rs_debug.h"
/**
* Constructor.
*/
RS_EventHandler::RS_EventHandler(QObject* parent) : QObject(parent)
{
connect(parent, SIGNAL(relative_zero_changed(const RS_Vector&)),
this, SLOT(setRelativeZero(const RS_Vector&)));
}
/**
* Destructor.
*/
RS_EventHandler::~RS_EventHandler() {
RS_DEBUG->print("RS_EventHandler::~RS_EventHandler");
delete defaultAction;
defaultAction = nullptr;
RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: Deleting all actions..");
for(auto a: currentActions){
delete a;
}
currentActions.clear();
RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: Deleting all actions..: OK");
RS_DEBUG->print("RS_EventHandler::~RS_EventHandler: OK");
}
/**
* Go back in current action.
*/
void RS_EventHandler::back() {
QMouseEvent e(QEvent::MouseButtonRelease, QPoint(0,0),
Qt::RightButton, Qt::RightButton,Qt::NoModifier);
mouseReleaseEvent(&e);
if (!hasAction() && q_action)
{
q_action->setChecked(false);
q_action = nullptr;
}
}
/**
* Go enter pressed event for current action.
*/
void RS_EventHandler::enter() {
QKeyEvent e(QEvent::KeyPress, Qt::Key_Enter, 0);
keyPressEvent(&e);
}
/**
* Called by QG_GraphicView
*/
void RS_EventHandler::mousePressEvent(QMouseEvent* e) {
if(hasAction()){
currentActions.last()->mousePressEvent(e);
e->accept();
} else {
if (defaultAction) {
defaultAction->mousePressEvent(e);
e->accept();
} else {
RS_DEBUG->print("currently no action defined");
e->ignore();
}
}
}
/**
* Called by QG_GraphicView
*/
void RS_EventHandler::mouseReleaseEvent(QMouseEvent* e) {
if(hasAction()){
// if (actionIndex>=0 && currentActions[actionIndex] &&
// !currentActions[actionIndex]->isFinished()) {
RS_DEBUG->print("call action %s",
currentActions.last()->getName().toLatin1().data());
currentActions.last()->mouseReleaseEvent(e);
// Clean up actions - one might be finished now
cleanUp();
e->accept();
} else {
if (defaultAction) {
defaultAction->mouseReleaseEvent(e);
} else {
e->ignore();
}
}
}
/**
* Called by QG_GraphicView
*/
void RS_EventHandler::mouseMoveEvent(QMouseEvent* e)
{
if(hasAction())
currentActions.last()->mouseMoveEvent(e);
else if (defaultAction)
defaultAction->mouseMoveEvent(e);
}
/**
* Called by QG_GraphicView
*/
void RS_EventHandler::mouseLeaveEvent() {
if(hasAction()){
currentActions.last()->suspend();
} else {
if (defaultAction) {
defaultAction->suspend();
}
//RS_DEBUG->print("currently no action defined");
}
}
/**
* Called by QG_GraphicView
*/
void RS_EventHandler::mouseEnterEvent() {
if(hasAction()){
currentActions.last()->resume();
} else {
if (defaultAction) {
defaultAction->resume();
}
}
}
/**
* Called by QG_GraphicView
*/
void RS_EventHandler::keyPressEvent(QKeyEvent* e) {
if(hasAction()){
currentActions.last()->keyPressEvent(e);
} else {
if (defaultAction) {
defaultAction->keyPressEvent(e);
}
else {
e->ignore();
}
//RS_DEBUG->print("currently no action defined");
}
}
/**
* Called by QG_GraphicView
*/
void RS_EventHandler::keyReleaseEvent(QKeyEvent* e) {
if(hasAction()){
currentActions.last()->keyReleaseEvent(e);
} else {
if (defaultAction) {
defaultAction->keyReleaseEvent(e);
}
else {
e->ignore();
}
//RS_DEBUG->print("currently no action defined");
}
}
/**
* Handles command line events.
*/
void RS_EventHandler::commandEvent(RS_CommandEvent* e) {
RS_DEBUG->print("RS_EventHandler::commandEvent");
QString cmd = e->getCommand();
if (coordinateInputEnabled) {
if (!e->isAccepted()) {
if(hasAction()){
// handle absolute cartesian coordinate input:
if (cmd.contains(',') && cmd.at(0)!='@') {
int commaPos = cmd.indexOf(',');
RS_DEBUG->print("RS_EventHandler::commandEvent: 001");
bool ok1, ok2;
RS_DEBUG->print("RS_EventHandler::commandEvent: 002");
double x = RS_Math::eval(cmd.left(commaPos), &ok1);
RS_DEBUG->print("RS_EventHandler::commandEvent: 003a");
double y = RS_Math::eval(cmd.mid(commaPos+1), &ok2);
RS_DEBUG->print("RS_EventHandler::commandEvent: 004");
if (ok1 && ok2) {
RS_DEBUG->print("RS_EventHandler::commandEvent: 005");
RS_CoordinateEvent ce(RS_Vector(x,y));
RS_DEBUG->print("RS_EventHandler::commandEvent: 006");
currentActions.last()->coordinateEvent(&ce);
} else
RS_DIALOGFACTORY->commandMessage(
"Expression Syntax Error");
e->accept();
}
// handle relative cartesian coordinate input:
if (!e->isAccepted()) {
if (cmd.contains(',') && cmd.at(0)=='@') {
int commaPos = cmd.indexOf(',');
bool ok1, ok2;
double x = RS_Math::eval(cmd.mid(1, commaPos-1), &ok1);
double y = RS_Math::eval(cmd.mid(commaPos+1), &ok2);
if (ok1 && ok2) {
RS_CoordinateEvent ce(RS_Vector(x,y) + relative_zero);
currentActions.last()->coordinateEvent(&ce);
// currentActions[actionIndex]->coordinateEvent(&ce);
} else
RS_DIALOGFACTORY->commandMessage(
"Expression Syntax Error");
e->accept();
}
}
// handle absolute polar coordinate input:
if (!e->isAccepted()) {
if (cmd.contains('<') && cmd.at(0)!='@') {
int commaPos = cmd.indexOf('<');
bool ok1, ok2;
double r = RS_Math::eval(cmd.left(commaPos), &ok1);
double a = RS_Math::eval(cmd.mid(commaPos+1), &ok2);
if (ok1 && ok2) {
RS_Vector pos{
RS_Vector::polar(r,RS_Math::deg2rad(a))};
RS_CoordinateEvent ce(pos);
currentActions.last()->coordinateEvent(&ce);
} else
RS_DIALOGFACTORY->commandMessage(
"Expression Syntax Error");
e->accept();
}
}
// handle relative polar coordinate input:
if (!e->isAccepted()) {
if (cmd.contains('<') && cmd.at(0)=='@') {
int commaPos = cmd.indexOf('<');
bool ok1, ok2;
double r = RS_Math::eval(cmd.mid(1, commaPos-1), &ok1);
double a = RS_Math::eval(cmd.mid(commaPos+1), &ok2);
if (ok1 && ok2) {
RS_Vector pos = RS_Vector::polar(r,RS_Math::deg2rad(a));
RS_CoordinateEvent ce(pos + relative_zero);
currentActions.last()->coordinateEvent(&ce);
} else
RS_DIALOGFACTORY->commandMessage(
"Expression Syntax Error");
e->accept();
}
}
// send command event directly to current action:
if (!e->isAccepted()) {
// std::cout<<"RS_EventHandler::commandEvent(RS_CommandEvent* e): sending cmd("<<qPrintable(e->getCommand()) <<") to action: "<<currentActions.last()->rtti()<<std::endl;
currentActions.last()->commandEvent(e);
}
}else{
//send the command to default action
if (defaultAction) {
defaultAction->commandEvent(e);
}
}
// do not accept command here. Actions themselves should be responsible to accept commands
// e->accept();
}
}
RS_DEBUG->print("RS_EventHandler::commandEvent: OK");
}
/**
* Enables coordinate input in the command line.
*/
void RS_EventHandler::enableCoordinateInput() {
coordinateInputEnabled = true;
}
/**
* Enables coordinate input in the command line.
*/
void RS_EventHandler::disableCoordinateInput() {
coordinateInputEnabled = false;
}
/**
* @return Current action.
*/
RS_ActionInterface* RS_EventHandler::getCurrentAction(){
if(hasAction()){
return currentActions.last();
} else {
return defaultAction;
}
}
/**
* @return The current default action.
*/
RS_ActionInterface* RS_EventHandler::getDefaultAction() const{
return defaultAction;
}
/**
* Sets the default action.
*/
void RS_EventHandler::setDefaultAction(RS_ActionInterface* action) {
if (defaultAction) {
defaultAction->finish();
delete defaultAction;
// defaultAction = NULL;
}
defaultAction = action;
}
/**
* Sets the current action.
*/
void RS_EventHandler::setCurrentAction(RS_ActionInterface* action) {
RS_DEBUG->print("RS_EventHandler::setCurrentAction");
if (action==NULL) {
return;
}
// Predecessor of the new action or NULL:
RS_ActionInterface* predecessor = NULL;
// Suspend current action:
if(hasAction()){
predecessor = currentActions.last();
predecessor->suspend();
predecessor->hideOptions();
}
else {
if (defaultAction) {
predecessor = defaultAction;
predecessor->suspend();
predecessor->hideOptions();
}
}
// // Forget about the oldest action and make space for the new action:
// if (actionIndex==RS_MAXACTIONS-1) {
// // delete oldest action if necessary (usually never happens):
// if (currentActions[0]) {
// currentActions[0]->finish();
// delete currentActions[0];
// currentActions[0] = NULL;
// }
// // Move up actionstack (optimize):
// for (int i=0; i<RS_MAXACTIONS-1; ++i) {
// currentActions[i] = currentActions[i+1];
// }
// } else if (actionIndex<RS_MAXACTIONS-1) {
// actionIndex++;
// }
// Set current action:
currentActions.push_back(action);
RS_DEBUG->print("RS_EventHandler::setCurrentAction: current action is: %s",
currentActions.last()->getName().toLatin1().data());
// Initialisation of our new action:
RS_DEBUG->print("RS_EventHandler::setCurrentAction: init current action");
action->init();
// ## new:
if (action->isFinished()==false) {
RS_DEBUG->print("RS_EventHandler::setCurrentAction: show options");
currentActions.last()->showOptions();
RS_DEBUG->print("RS_EventHandler::setCurrentAction: set predecessor");
action->setPredecessor(predecessor);
}
RS_DEBUG->print("RS_EventHandler::setCurrentAction: cleaning up..");
cleanUp();
RS_DEBUG->print("RS_EventHandler::setCurrentAction: debugging actions");
debugActions();
RS_DEBUG->print("RS_GraphicView::setCurrentAction: OK");
if (q_action)
q_action->setChecked(true);
}
/**
* Kills all running selection actions. Called when a selection action
* is launched to reduce confusion.
*/
void RS_EventHandler::killSelectActions() {
for (auto it=currentActions.begin();it != currentActions.end();){
if ((*it)->rtti()==RS2::ActionSelectSingle ||
(*it)->rtti()==RS2::ActionSelectContour ||
(*it)->rtti()==RS2::ActionSelectWindow ||
(*it)->rtti()==RS2::ActionSelectIntersected ||
(*it)->rtti()==RS2::ActionSelectLayer) {
if( ! (*it)->isFinished()){
(*it)->finish();
}
delete *it;
it= currentActions.erase(it);
}else{
it++;
}
}
}
/**
* Kills all running actions. Called when a window is closed.
*/
void RS_EventHandler::killAllActions()
{
RS_DEBUG->print(__FILE__ ": %s: line %d: begin\n", __func__, __LINE__);
if (q_action)
{
q_action->setChecked(false);
q_action = nullptr;
}
for(auto p: currentActions)
{
if (!p->isFinished())
{
p->finish();
}
}
if (!defaultAction->isFinished())
{
defaultAction->finish();
}
RS_DEBUG->print(__FILE__ ": %s: line %d: begin\n", __func__, __LINE__);
defaultAction->init(0);
}
/**
* @return true if the action is within currentActions
*/
bool RS_EventHandler::isValid(RS_ActionInterface* action) const{
return currentActions.indexOf(action) >= 0;
}
/**
* @return true if there is at least one action in the action stack.
*/
bool RS_EventHandler::hasAction()
{
foreach (RS_ActionInterface* a, currentActions)
{
if(!a->isFinished())
return true;
}
return false;
}
/**
* Garbage collector for actions.
*/
void RS_EventHandler::cleanUp() {
RS_DEBUG->print("RS_EventHandler::cleanUp");
for (auto it=currentActions.begin(); it != currentActions.end();)
{
if( (*it)->isFinished())
{
delete *it;
it= currentActions.erase(it);
}else{
++it;
}
}
if(hasAction()){
currentActions.last()->resume();
currentActions.last()->showOptions();
} else {
if (defaultAction) {
defaultAction->resume();
defaultAction->showOptions();
}
}
RS_DEBUG->print("RS_EventHandler::cleanUp: OK");
}
/**
* Sets the snap mode for all currently active actions.
*/
void RS_EventHandler::setSnapMode(RS_SnapMode sm) {
for(auto a: currentActions){
if( ! a->isFinished()){
a->setSnapMode(sm);
}
}
if (defaultAction) {
defaultAction->setSnapMode(sm);
}
}
/**
* Sets the snap restriction for all currently active actions.
*/
void RS_EventHandler::setSnapRestriction(RS2::SnapRestriction sr) {
for(auto a: currentActions){
if( ! a->isFinished()){
a->setSnapRestriction(sr);
}
}
if (defaultAction) {
defaultAction->setSnapRestriction(sr);
}
}
void RS_EventHandler::debugActions() const{
// std::cout<<"action queue size=:"<<currentActions.size()<<std::endl;
RS_DEBUG->print("---");
for(int i=0;i<currentActions.size();++i){
if (i == currentActions.size() - 1 ) {
RS_DEBUG->print("Current");
}
RS_DEBUG->print("Action %03d: %s [%s]",
i, currentActions.at(i)->getName().toLatin1().data(),
currentActions.at(i)->isFinished() ? "finished" : "active");
}
}
void RS_EventHandler::setQAction(QAction* action)
{
if (q_action)
{
q_action->setChecked(false);
killAllActions();
}
q_action = action;
}
void RS_EventHandler::setRelativeZero(const RS_Vector& point)
{
relative_zero = point;
}
bool RS_EventHandler::inSelectionMode()
{
switch (getCurrentAction()->rtti())
{
case RS2::ActionDefault:
case RS2::ActionSelectSingle:
case RS2::ActionSelectWindow:
case RS2::ActionDeselectWindow:
case RS2::ActionSelectContour:
case RS2::ActionSelectIntersected:
case RS2::ActionDeselectIntersected:
case RS2::ActionSelectLayer:
return true;
default:
return false;
}
}
// EOF

106
lib/gui/rs_eventhandler.h Normal file
View File

@@ -0,0 +1,106 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_EVENTHANDLER_H
#define RS_EVENTHANDLER_H
#include <QObject>
#include "rs_vector.h"
class RS_ActionInterface;
class QAction;
class QMouseEvent;
class QKeyEvent;
class RS_CommandEvent;
class RS_Vector;
struct RS_SnapMode;
/**
* The event handler owns and manages all actions that are currently
* active. All events going from the view to the actions come over
* this class.
*/
class RS_EventHandler : public QObject
{
Q_OBJECT
public:
RS_EventHandler(QObject* parent = 0);
~RS_EventHandler();
void setQAction(QAction* action);
void back();
void enter();
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void mouseLeaveEvent();
void mouseEnterEvent();
void keyPressEvent(QKeyEvent* e);
void keyReleaseEvent(QKeyEvent* e);
void commandEvent(RS_CommandEvent* e);
void enableCoordinateInput();
void disableCoordinateInput();
void setDefaultAction(RS_ActionInterface* action);
RS_ActionInterface* getDefaultAction() const;
void setCurrentAction(RS_ActionInterface* action);
RS_ActionInterface* getCurrentAction();
bool isValid(RS_ActionInterface* action) const;
void killSelectActions();
void killAllActions();
bool hasAction();
void cleanUp();
void debugActions() const;
void setSnapMode(RS_SnapMode sm);
void setSnapRestriction(RS2::SnapRestriction sr);
//! return true if the current action is for selecting
bool inSelectionMode();
private:
QAction* q_action{nullptr};
RS_ActionInterface* defaultAction{nullptr};
QList<RS_ActionInterface*> currentActions;
bool coordinateInputEnabled{true};
RS_Vector relative_zero;
public slots:
void setRelativeZero(const RS_Vector&);
};
#endif

1883
lib/gui/rs_graphicview.cpp Normal file

File diff suppressed because it is too large Load Diff

472
lib/gui/rs_graphicview.h Normal file
View File

@@ -0,0 +1,472 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_GRAPHICVIEW_H
#define RS_GRAPHICVIEW_H
#include "rs_entitycontainer.h"
#include "rs_snapper.h"
#include "lc_rect.h"
#include <QDateTime>
#include <QMap>
#include <tuple>
#include <memory>
#include <QAction>
class QMouseEvent;
class QKeyEvent;
class RS_ActionInterface;
class RS_EventHandler;
class RS_CommandEvent;
class RS_Grid;
struct RS_LineTypePattern;
/**
* This class is a common GUI interface for the graphic viewer
* widget which has to be implemented by real GUI classes such
* as the Qt graphical view.
*
* Note that this is just an interface used as a slot to
* communicate with the LibreCAD from a GUI level.
*/
class RS_GraphicView : public QWidget
{
Q_OBJECT
public:
RS_GraphicView(QWidget * parent = 0, Qt::WindowFlags f = 0);
virtual ~RS_GraphicView();
void cleanUp();
/**
* @return Pointer to the graphic entity if the entity container
* connected to this view is a graphic and valid.
* NULL otherwise.
*/
RS_Graphic* getGraphic() const;
/**
* \brief setDrawingMode Sets the drawing mode.
*/
void setDrawingMode(RS2::DrawingMode m) {
drawingMode = m;
}
/**
* @return Current drawing mode.
*/
RS2::DrawingMode getDrawingMode() const {
return drawingMode;
}
/**
* Activates or deactivates the delete mode.
*/
void setDeleteMode(bool m) {
deleteMode = m;
}
/**
* @reval true Deleting instead of drawing.
* false Normal drawing mode.
*/
bool getDeleteMode() const{
return deleteMode;
}
/** This virtual method must be overwritten to return
the width of the widget the graphic is shown in */
virtual int getWidth() const= 0;
/** This virtual method must be overwritten to return
the height of the widget the graphic is shown in */
virtual int getHeight() const= 0;
/** This virtual method must be overwritten to redraw
the widget. */
virtual void redraw(RS2::RedrawMethod method=RS2::RedrawAll) = 0;
/** This virtual method must be overwritten and is then
called whenever the view changed */
virtual void adjustOffsetControls() = 0;
/** This virtual method must be overwritten and is then
called whenever the view changed */
virtual void adjustZoomControls() = 0;
/**
* Sets the background color. Note that applying the background
* color for the widget is up to the implementing class.
*/
virtual void setBackground(const RS_Color& bg);
/**
* @return Current background color.
*/
RS_Color getBackground() const{
return background;
}
/**
* @return Current foreground color.
*/
RS_Color getForeground() const{
return foreground;
}
/**
* Sets the grid color.
*/
void setGridColor(const RS_Color& c) {
gridColor = c;
}
/**
* Sets the meta grid color.
*/
void setMetaGridColor(const RS_Color& c) {
metaGridColor = c;
}
/**
* Sets the selection color.
*/
void setSelectedColor(const RS_Color& c) {
selectedColor = c;
}
/**
* Sets the highlight color.
*/
void setHighlightedColor(const RS_Color& c) {
highlightedColor = c;
}
/**
* Sets the color for the first handle (start vertex)
*/
void setStartHandleColor(const RS_Color& c) {
startHandleColor = c;
}
/**
* Sets the color for handles, that are neither start nor end vertices
*/
void setHandleColor(const RS_Color& c) {
handleColor = c;
}
/**
* Sets the color for the last handle (end vertex)
*/
void setEndHandleColor(const RS_Color& c) {
endHandleColor = c;
}
/**
* This virtual method can be overwritten to set the mouse
* cursor to the given type.
*/
virtual void setMouseCursor(RS2::CursorType /*c*/) = 0;
void setContainer(RS_EntityContainer* container);
RS_EntityContainer* getContainer() const;
void setFactor(double f);
void setFactorX(double f);
void setFactorY(double f);
RS_Vector getFactor() const;
/**
* @brief setOffset
* @param ox, offset X
* @param oy, offset Y
*/
virtual void setOffset(int ox, int oy);
void setOffsetX(int ox);
void setOffsetY(int oy);
int getOffsetX() const;
int getOffsetY() const;
void centerOffsetX();
void centerOffsetY();
void centerX(double x);
void centerY(double y);
/**
* Sets a fixed border in pixel around the graphic. This border
* specifies how far the user can scroll outside the graphic
* area.
*/
void setBorders(int left, int top, int right, int bottom);
int getBorderLeft() const;
int getBorderTop() const;
int getBorderRight() const;
int getBorderBottom() const;
void freezeZoom(bool freeze);
bool isZoomFrozen() const;
void setDefaultAction(RS_ActionInterface* action);
RS_ActionInterface* getDefaultAction();
void setCurrentAction(RS_ActionInterface* action);
RS_ActionInterface* getCurrentAction();
void killSelectActions();
void killAllActions();
void back();
void enter();
void commandEvent(RS_CommandEvent* e);
void enableCoordinateInput();
void disableCoordinateInput();
virtual void zoomIn(double f=1.5, const RS_Vector& center=RS_Vector(false));
virtual void zoomInX(double f=1.5);
virtual void zoomInY(double f=1.5);
virtual void zoomOut(double f=1.5, const RS_Vector& center=RS_Vector(false));
virtual void zoomOutX(double f=1.5);
virtual void zoomOutY(double f=1.5);
virtual void zoomAuto(bool axis=true, bool keepAspectRatio=true);
virtual void zoomAutoY(bool axis=true);
virtual void zoomPrevious();
virtual void saveView();
virtual void restoreView();
virtual void zoomWindow(RS_Vector v1, RS_Vector v2,
bool keepAspectRatio=true);
//virtual void zoomPan(RS_Vector v1);
virtual void zoomPan(int dx, int dy);
virtual void zoomScroll(RS2::Direction direction);
virtual void zoomPage();
virtual void drawWindow_DEPRECATED(RS_Vector v1, RS_Vector v2);
virtual void drawLayer1(RS_Painter *painter);
virtual void drawLayer2(RS_Painter *painter);
virtual void drawLayer3(RS_Painter *painter);
virtual void deleteEntity(RS_Entity* e);
virtual void drawEntity(RS_Painter *painter, RS_Entity* e, double& patternOffset);
virtual void drawEntity(RS_Painter *painter, RS_Entity* e);
virtual void drawEntity(RS_Entity* e, double& patternOffset);
virtual void drawEntity(RS_Entity* e);
virtual void drawEntityPlain(RS_Painter *painter, RS_Entity* e);
virtual void drawEntityPlain(RS_Painter *painter, RS_Entity* e, double& patternOffset);
virtual void setPenForEntity(RS_Painter *painter, RS_Entity* e );
virtual RS_Vector getMousePosition() const = 0;
virtual const RS_LineTypePattern* getPattern(RS2::LineType t);
virtual void drawAbsoluteZero(RS_Painter *painter);
virtual void drawRelativeZero(RS_Painter *painter);
virtual void drawPaper(RS_Painter *painter);
virtual void drawGrid(RS_Painter *painter);
virtual void drawMetaGrid(RS_Painter *painter);
virtual void drawOverlay(RS_Painter *painter);
RS_Grid* getGrid() const;
virtual void updateGridStatusWidget(const QString& /*text*/) = 0;
void setDefaultSnapMode(RS_SnapMode sm);
RS_SnapMode getDefaultSnapMode() const;
void setSnapRestriction(RS2::SnapRestriction sr);
RS2::SnapRestriction getSnapRestriction() const;
bool isGridOn() const;
bool isGridIsometric() const;
void setCrosshairType(RS2::CrosshairType chType);
RS2::CrosshairType getCrosshairType() const;
RS_Vector toGui(RS_Vector v) const;
double toGuiX(double x) const;
double toGuiY(double y) const;
double toGuiDX(double d) const;
double toGuiDY(double d) const;
RS_Vector toGraph(RS_Vector v) const;
RS_Vector toGraph(int x, int y) const;
double toGraphX(int x) const;
double toGraphY(int y) const;
double toGraphDX(int d) const;
double toGraphDY(int d) const;
/**
* (Un-)Locks the position of the relative zero.
*
* @param lock true: lock, false: unlock
*/
void lockRelativeZero(bool lock);
/**
* @return true if the position of the relative zero point is
* locked.
*/
bool isRelativeZeroLocked() const;
/**
* @return Relative zero coordinate.
*/
RS_Vector const& getRelativeZero() const;
void setRelativeZero(const RS_Vector& pos);
void moveRelativeZero(const RS_Vector& pos);
RS_EventHandler* getEventHandler() const;
/**
* Enables or disables print preview.
*/
void setPrintPreview(bool pv);
/**
* @retval true This is a print preview graphic view.
* @retval false Otherwise.
*/
bool isPrintPreview() const;
/**
* Enables or disables printing.
*/
void setPrinting(bool p);
/**
* @retval true This is a graphic view for printing.
* @retval false setSnapOtherwise.
*/
bool isPrinting() const;
/**
* @retval true Draft mode is on for this view (all lines with 1 pixel / no style scaling).
* @retval false Otherwise.
*/
bool isDraftMode() const;
void setDraftMode(bool dm);
bool isCleanUp(void) const;
virtual RS_EntityContainer* getOverlayContainer(RS2::OverlayGraphics position);
const LC_Rect& getViewRect() {
return view_rect;
}
bool isPanning() const;
void setPanning(bool state);
void setLineWidthScaling(bool state){
scaleLineWidth = state;
}
bool getLineWidthScaling(){
return scaleLineWidth;
}
protected:
RS_EntityContainer* container{nullptr}; // Holds a pointer to all the enties
RS_EventHandler* eventHandler;
/** background color (any color) */
RS_Color background;
/** foreground color (black or white) */
RS_Color foreground;
/** grid color */
RS_Color gridColor;
/** meta grid color */
RS_Color metaGridColor;
/** selected color */
RS_Color selectedColor;
/** highlighted color */
RS_Color highlightedColor;
/** Start handle color */
RS_Color startHandleColor;
/** Intermediate (not start/end vertex) handle color */
RS_Color handleColor;
/** End handle color */
RS_Color endHandleColor;
/** Grid */
std::unique_ptr<RS_Grid> grid;
/**
* Current default snap mode for this graphic view. Used for new
* actions.
*/
RS_SnapMode defaultSnapMode;
/**
* Current default snap restriction for this graphic view. Used for new
* actions.
*/
RS2::SnapRestriction defaultSnapRes;
RS2::DrawingMode drawingMode;
/**
* Delete mode. If true, all drawing actions will delete in background color
* instead.
*/
bool deleteMode=false;
LC_Rect view_rect;
private:
bool zoomFrozen=false;
bool draftMode=false;
RS_Vector factor=RS_Vector(1.,1.);
int offsetX=0;
int offsetY=0;
//circular buffer for saved views
std::vector<std::tuple<int, int, RS_Vector> > savedViews;
unsigned short savedViewIndex=0;
unsigned short savedViewCount=0;
QDateTime previousViewTime;
int borderLeft=0;
int borderTop=0;
int borderRight=0;
int borderBottom=0;
RS_Vector relativeZero{false};
bool relativeZeroLocked=false;
//! Print preview flag
bool printPreview=false;
//! Active when printing only:
bool printing=false;
// Map that will be used for overlaying additional items on top of the main CAD drawing
QMap<int, RS_EntityContainer *> overlayEntities;
/** if true, graphicView is under cleanup */
bool m_bIsCleanUp=false;
bool panning;
bool scaleLineWidth;
signals:
void relative_zero_changed(const RS_Vector&);
void previous_zoom_state(bool);
};
#endif

535
lib/gui/rs_grid.cpp Normal file
View File

@@ -0,0 +1,535 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<cmath>
#include<QString>
#include "rs_grid.h"
#include "rs_graphicview.h"
#include "rs_units.h"
#include "rs_graphic.h"
#include "rs_settings.h"
#include "rs_math.h"
#include "lc_rect.h"
#include "rs_debug.h"
#ifdef EMU_C99
#include "emu_c99.h"
#endif
namespace {
//maximum number grid points to draw, for performance consideration
const int maxGridPoints=1000000;
//minimum grid width to consider
const double minimumGridWidth=1.0e-8;
}
/**
* Constructor.
*/
RS_Grid::RS_Grid(RS_GraphicView* graphicView)
:graphicView(graphicView)
,baseGrid(false)
{}
/**
* find the closest grid point
*@return the closest grid to given point
*@coord: the given point
*/
RS_Vector RS_Grid::snapGrid(const RS_Vector& coord) const {
if( cellV.x<RS_TOLERANCE || cellV.y<RS_TOLERANCE) return coord;
RS_Vector vp(coord-baseGrid);
if(isometric){
//use remainder instead of fmod to locate the left-bottom corner for both positive and negative displacement
RS_Vector vp1( vp-RS_Vector( remainder(vp.x-0.5*cellV.x,cellV.x)+0.5*cellV.x, remainder(vp.y-0.5*cellV.y,cellV.y)+0.5*cellV.y));
RS_VectorSolutions sol({vp1,vp1+cellV,vp1+cellV*0.5, vp1+RS_Vector(cellV.x,0.), vp1+RS_Vector(0.,cellV.y)});
vp1=sol.getClosest(vp);
return baseGrid+vp1;
}else{
return baseGrid+vp-RS_Vector(remainder(vp.x,cellV.x),remainder(vp.y,cellV.y));
}
}
/**
* Updates the grid point array.
*/
void RS_Grid::updatePointArray() {
if (!graphicView->isGridOn()) return;
RS_Graphic* graphic = graphicView->getGraphic();
// auto scale grid?
RS_SETTINGS->beginGroup("/Appearance");
bool scaleGrid = (bool)RS_SETTINGS->readNumEntry("/ScaleGrid", 1);
// get grid setting
RS_Vector userGrid;
if (graphic) {
//$ISOMETRICGRID == $SNAPSTYLE
isometric = static_cast<bool>(graphic->getVariableInt("$SNAPSTYLE",0));
crosshairType=graphic->getCrosshairType();
userGrid = graphic->getVariableVector("$GRIDUNIT",
RS_Vector(-1.0, -1.0));
}else {
isometric = (bool)RS_SETTINGS->readNumEntry("/IsometricGrid", 0);
crosshairType=static_cast<RS2::CrosshairType>(RS_SETTINGS->readNumEntry("/CrosshairType",0));
userGrid.x = RS_SETTINGS->readEntry("/GridSpacingX",QString("-1")).toDouble();
userGrid.y = RS_SETTINGS->readEntry("/GridSpacingY",QString("-1")).toDouble();
}
int minGridSpacing = RS_SETTINGS->readNumEntry("/MinGridSpacing", 10);
RS_SETTINGS->endGroup();
// std::cout<<"Grid userGrid="<<userGrid<<std::endl;
pt.clear();
metaX.clear();
metaY.clear();
// RS_DEBUG->print("RS_Grid::update: 001");
// find out unit:
RS2::Unit unit = RS2::None;
RS2::LinearFormat format = RS2::Decimal;
if (graphic) {
unit = graphic->getUnit();
format = graphic->getLinearFormat();
}
RS_Vector gridWidth;
// RS_Vector metaGridWidth;
// RS_DEBUG->print("RS_Grid::update: 002");
// init grid spacing:
// metric grid:
if (RS_Units::isMetric(unit) || unit==RS2::None ||
format==RS2::Decimal || format==RS2::Engineering) {
//metric grid
gridWidth = getMetricGridWidth(userGrid, scaleGrid, minGridSpacing);
}else {
// imperial grid:
gridWidth = getImperialGridWidth(userGrid, scaleGrid, minGridSpacing);
}
// RS_DEBUG->print("RS_Grid::update: 013");
// for grid info:
spacing = gridWidth.x;
metaSpacing = metaGridWidth.x;
//std::cout<<"Grid spacing="<<spacing<<std::endl;
//std::cout<<"Grid metaSpacing="<<metaSpacing<<std::endl;
if (gridWidth.x>minimumGridWidth && gridWidth.y>minimumGridWidth &&
graphicView->toGuiDX(gridWidth.x)>2 &&
graphicView->toGuiDY(gridWidth.y)>2) {
// find grid boundaries
double left = (int)(graphicView->toGraphX(0) / gridWidth.x)
* gridWidth.x;
double right = (int)(graphicView->toGraphX(graphicView->getWidth()) /
gridWidth.x) * gridWidth.x;
double top = (int)(graphicView->toGraphY(0) /
gridWidth.y) * gridWidth.y;
double bottom =
(int)(graphicView->toGraphY(graphicView->getHeight()) /
gridWidth.y) * gridWidth.y;
left -= gridWidth.x;
right += gridWidth.x;
top += gridWidth.y;
bottom -= gridWidth.y;
//top/bottom is reversed with RectF definition
LC_Rect const rect{{left, bottom}, {right, top}};
// populate grid points and metaGrid line positions: pts, metaX, metaY
if(isometric){
createIsometricGrid(rect, gridWidth);
}else{
createOrthogonalGrid(rect, gridWidth);
}
// RS_DEBUG->print("RS_Grid::update: 015");
}
// RS_DEBUG->print("RS_Grid::update: OK");
}
RS_Vector RS_Grid::getMetricGridWidth(RS_Vector const& userGrid, bool scaleGrid, int minGridSpacing)
{
RS_Vector gridWidth;
if (userGrid.x>0.0) {
gridWidth.x = userGrid.x;
}
else {
gridWidth.x = minimumGridWidth;
}
if (userGrid.y>0.0) {
gridWidth.y = userGrid.y;
}
else {
gridWidth.y = minimumGridWidth;
}
// RS_DEBUG->print("RS_Grid::update: 003");
// auto scale grid
//scale grid by drawing setting as well, bug#3416862
// std::cout<<"RS_Grid::updatePointArray(): userGrid="<<userGrid<<std::endl;
if (scaleGrid|| userGrid.x<=minimumGridWidth || userGrid.y<=minimumGridWidth) {
if(scaleGrid || userGrid.x<=minimumGridWidth) {
while (graphicView->toGuiDX(gridWidth.x)<minGridSpacing) {
gridWidth.x*=10;
}
}
if(scaleGrid || userGrid.y<=minimumGridWidth) {
while (graphicView->toGuiDY(gridWidth.y)<minGridSpacing) {
gridWidth.y*=10;
}
}
}
// std::cout<<"RS_Grid::updatePointArray(): gridWidth="<<gridWidth<<std::endl;
metaGridWidth.x = gridWidth.x*10;
metaGridWidth.y = gridWidth.y*10;
// RS_DEBUG->print("RS_Grid::update: 004");
return gridWidth;
}
RS_Vector RS_Grid::getImperialGridWidth(RS_Vector const& userGrid, bool scaleGrid, int minGridSpacing)
{
RS_Vector gridWidth;
// RS_DEBUG->print("RS_Grid::update: 005");
if (userGrid.x>0.0) {
gridWidth.x = userGrid.x;
}
else {
gridWidth.x = 1.0/1024.0;
}
if (userGrid.y>0.0) {
gridWidth.y = userGrid.y;
}
else {
gridWidth.y = 1.0/1024.0;
}
// RS_DEBUG->print("RS_Grid::update: 006");
RS2::Unit unit = RS2::None;
// RS2::LinearFormat format = RS2::Decimal;
RS_Graphic* graphic = graphicView->getGraphic();
if (graphic) {
unit = graphic->getUnit();
// format = graphic->getLinearFormat();
}
if (unit==RS2::Inch) {
// RS_DEBUG->print("RS_Grid::update: 007");
// auto scale grid
//scale grid by drawing setting as well, bug#3416862
if (scaleGrid|| userGrid.x<=minimumGridWidth || userGrid.y<=minimumGridWidth) {
if(scaleGrid || userGrid.x<=minimumGridWidth) {
while (graphicView->toGuiDX(gridWidth.x)<minGridSpacing) {
if (RS_Math::round(gridWidth.x)>=36) {
gridWidth.x*=2;
} else if (RS_Math::round(gridWidth.x)>=12) {
gridWidth.x*=3;
} else if (RS_Math::round(gridWidth.x)>=4) {
gridWidth.x*=3;
} else if (RS_Math::round(gridWidth.x)>=1) {
gridWidth.x*=2;
} else {
gridWidth.x*=2;
}
}
}
if(scaleGrid || userGrid.y<=minimumGridWidth) {
while (graphicView->toGuiDY(gridWidth.y)<minGridSpacing) {
if (RS_Math::round(gridWidth.y)>=36) {
gridWidth.y*=2;
} else if (RS_Math::round(gridWidth.y)>=12) {
gridWidth.y*=3;
} else if (RS_Math::round(gridWidth.y)>=4) {
gridWidth.y*=3;
} else if (RS_Math::round(gridWidth.y)>=1) {
gridWidth.y*=2;
} else {
gridWidth.y*=2;
}
}
}
}
// RS_DEBUG->print("RS_Grid::update: 008");
// metagrid X shows inches..
metaGridWidth.x = 1.0;
if (graphicView->toGuiDX(metaGridWidth.x)<minGridSpacing*2) {
// .. or feet
metaGridWidth.x = 12.0;
// .. or yards
if (graphicView->toGuiDX(metaGridWidth.x)<minGridSpacing*2) {
metaGridWidth.x = 36.0;
// .. or miles (not really..)
//if (graphicView->toGuiDX(metaGridWidth.x)<20) {
// metaGridWidth.x = 63360.0;
//}
// .. or nothing
if (graphicView->toGuiDX(metaGridWidth.x)<minGridSpacing*2) {
metaGridWidth.x = -1.0;
}
}
}
// RS_DEBUG->print("RS_Grid::update: 009");
// metagrid Y shows inches..
metaGridWidth.y = 1.0;
if (graphicView->toGuiDY(metaGridWidth.y)<minGridSpacing*2) {
// .. or feet
metaGridWidth.y = 12.0;
// .. or yards
if (graphicView->toGuiDY(metaGridWidth.y)<minGridSpacing*2) {
metaGridWidth.y = 36.0;
// .. or miles (not really..)
//if (graphicView->toGuiDY(metaGridWidth.y)<20) {
// metaGridWidth.y = 63360.0;
//}
// .. or nothing
if (graphicView->toGuiDY(metaGridWidth.y)<minGridSpacing*2) {
metaGridWidth.y = -1.0;
}
}
}
// RS_DEBUG->print("RS_Grid::update: 010");
} else {
// RS_DEBUG->print("RS_Grid::update: 011");
if (scaleGrid) {
while (graphicView->toGuiDX(gridWidth.x)<minGridSpacing) {
gridWidth.x*=2;
}
metaGridWidth.x = -1.0;
while (graphicView->toGuiDY(gridWidth.y)<minGridSpacing) {
gridWidth.y*=2;
}
metaGridWidth.y = -1.0;
}
// RS_DEBUG->print("RS_Grid::update: 012");
}
//gridWidth.y = gridWidth.x;
//metaGridWidth.y = metaGridWidth.x;
return gridWidth;
}
void RS_Grid::createOrthogonalGrid(LC_Rect const& rect, RS_Vector const& gridWidth)
{
double const left=rect.minP().x;
double const right=rect.maxP().x;
//top/bottom reversed
double const top=rect.maxP().y;
double const bottom=rect.minP().y;
cellV.set(fabs(gridWidth.x),fabs(gridWidth.y));
int numberX = (RS_Math::round((right-left) / gridWidth.x) + 1);
int numberY = (RS_Math::round((top-bottom) / gridWidth.y) + 1);
int number = numberX*numberY;
//todo, fix baseGrid for orthogonal grid
baseGrid.set(left,bottom);
// create grid array:
if (number<=0 || number>maxGridPoints) return;
pt.resize(number);
int i=0;
RS_Vector bp0(baseGrid);
for (int y=0; y<numberY; ++y) {
RS_Vector bp1(bp0);
for (int x=0; x<numberX; ++x) {
pt[i++] = bp1;
bp1.x += gridWidth.x;
}
bp0.y += gridWidth.y;
}
// find meta grid boundaries
if (metaGridWidth.x>minimumGridWidth && metaGridWidth.y>minimumGridWidth &&
graphicView->toGuiDX(metaGridWidth.x)>2 &&
graphicView->toGuiDY(metaGridWidth.y)>2) {
double mleft = (int)(graphicView->toGraphX(0) /
metaGridWidth.x) * metaGridWidth.x;
double mright = (int)(graphicView->toGraphX(graphicView->getWidth()) /
metaGridWidth.x) * metaGridWidth.x;
double mtop = (int)(graphicView->toGraphY(0) /
metaGridWidth.y) * metaGridWidth.y;
double mbottom = (int)(graphicView->toGraphY(graphicView->getHeight()) /
metaGridWidth.y) * metaGridWidth.y;
mleft -= metaGridWidth.x;
mright += metaGridWidth.x;
mtop += metaGridWidth.y;
mbottom -= metaGridWidth.y;
// calculate number of visible meta grid lines:
int numMetaX = (RS_Math::round((mright-mleft) / metaGridWidth.x) + 1);
int numMetaY = (RS_Math::round((mtop-mbottom) / metaGridWidth.y) + 1);
if (numMetaX<=0 || numMetaY<=0) return;
// create meta grid arrays:
metaX.resize(numMetaX);
metaY.resize(numMetaY);
int i=0;
for (int x=0; x<numMetaX; ++x) {
metaX[i++] = mleft+x*metaGridWidth.x;
}
i=0;
for (int y=0; y<numMetaY; ++y) {
metaY[i++] = mbottom+y*metaGridWidth.y;
}
}
}
void RS_Grid::createIsometricGrid(LC_Rect const& rect, RS_Vector const& gridWidth)
{
double const left=rect.minP().x;
double const right=rect.maxP().x;
//top/bottom reversed
double const top=rect.maxP().y;
double const bottom=rect.minP().y;
int numberY = (RS_Math::round((top-bottom) / gridWidth.y) + 1);
double dx=sqrt(3.)*gridWidth.y;
cellV.set(fabs(dx),fabs(gridWidth.y));
double hdx=0.5*dx;
double hdy=0.5*gridWidth.y;
int numberX = (RS_Math::round((right-left) / dx) + 1);
int number = 2*numberX*numberY;
baseGrid.set(left+remainder(-left,dx),bottom+remainder(-bottom,fabs(gridWidth.y)));
if (number<=0 || number>maxGridPoints) return;
pt.resize(number);
int i=0;
RS_Vector bp0(baseGrid),dbp1(hdx,hdy);
for (int y=0; y<numberY; ++y) {
RS_Vector bp1(bp0);
for (int x=0; x<numberX; ++x) {
pt[i++] = bp1;
pt[i++] = bp1+dbp1;
bp1.x += dx;
}
bp0.y += gridWidth.y;
}
//find metaGrid
if (metaGridWidth.y>minimumGridWidth &&
graphicView->toGuiDY(metaGridWidth.y)>2) {
metaGridWidth.x=(metaGridWidth.x<0.)?-sqrt(3.)*fabs(metaGridWidth.y):sqrt(3.)*fabs(metaGridWidth.y);
RS_Vector baseMetaGrid(left+remainder(-left,metaGridWidth.x)-fabs(metaGridWidth.x),bottom+remainder(-bottom,metaGridWidth.y)-fabs(metaGridWidth.y));
// calculate number of visible meta grid lines:
int numMetaX = (RS_Math::round((right-left) / metaGridWidth.x) + 1);
int numMetaY = (RS_Math::round((top-bottom) / metaGridWidth.y) + 1);
if (numMetaX<=0 || numMetaY<=0) return;
// create meta grid arrays:
metaX.resize(numMetaX);
metaY.resize(numMetaY);
double x0(baseMetaGrid.x);
for (int i=0; i<numMetaX; x0 += metaGridWidth.x) {
metaX[i++] = x0;
}
x0=baseMetaGrid.y;
for (int i=0; i<numMetaY; x0 += metaGridWidth.y) {
metaY[i++] = x0;
}
}
}
QString RS_Grid::getInfo() const{
return QString("%1 / %2").arg(spacing).arg(metaSpacing);
}
std::vector<RS_Vector> const& RS_Grid::getPoints() const{
return pt;
}
std::vector<double> const& RS_Grid::getMetaX() const{
return metaX;
}
std::vector<double> const& RS_Grid::getMetaY() const{
return metaY;
}
bool RS_Grid::isIsometric() const{
return isometric;
}
void RS_Grid::setIsometric(bool b){
isometric=b;
}
RS_Vector RS_Grid::getMetaGridWidth() const {
return metaGridWidth;
}
RS_Vector const& RS_Grid::getCellVector() const
{
return cellV;
}
void RS_Grid::setCrosshairType(RS2::CrosshairType chType){
crosshairType=chType;
}
RS2::CrosshairType RS_Grid::getCrosshairType() const{
return crosshairType;
}
// EOF

132
lib/gui/rs_grid.h Normal file
View File

@@ -0,0 +1,132 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright(C) 2015 Dongxu Li (dongxuli2011@gmail.com)
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_GRID_H
#define RS_GRID_H
#include "rs_vector.h"
class RS_GraphicView;
class QString;
namespace lc {
namespace geo {
class Area;
}
}
using LC_Rect = lc::geo::Area;
/**
* This class represents a grid. Grids can be drawn on graphic
* views and snappers can snap to the grid points.
*
* @author Andrew Mustun
*/
class RS_Grid
{
public:
RS_Grid(RS_GraphicView* graphicView);
void updatePointArray();
/**
* @return Array of all visible grid points.
*/
std::vector<RS_Vector> const& getPoints() const;
/**
* \brief the closest grid point
* \return the closest grid to given point
* \param coord the given point
*/
RS_Vector snapGrid(const RS_Vector& coord) const;
/**
* @return Number of visible grid points.
*/
int count() const;
void setCrosshairType(RS2::CrosshairType chType);
RS2::CrosshairType getCrosshairType() const;
/**
* @return Grid info for status widget.
*/
QString getInfo() const;
/**
* @return a vector of Meta grid positions in X.
*/
std::vector<double> const& getMetaX() const;
/**
* @return a vector of Meta grid positions in Y.
*/
std::vector<double> const& getMetaY() const;
bool isIsometric() const;
void setIsometric(bool b);
RS_Vector getMetaGridWidth() const;
RS_Vector const& getCellVector() const;
private:
//! copy ctor disabled
RS_Grid(RS_Grid const&) = delete;
RS_Grid& operator = (RS_Grid const&) = delete;
//! \{ \brief create grid points
void createOrthogonalGrid(LC_Rect const& rect, RS_Vector const& gridWidth);
void createIsometricGrid(LC_Rect const& rect, RS_Vector const& gridWidth);
//! \}
//! \{ \brief determine grid width
RS_Vector getMetricGridWidth(RS_Vector const& userGrid, bool scaleGrid, int minGridSpacing);
RS_Vector getImperialGridWidth(RS_Vector const& userGrid, bool scaleGrid, int minGridSpacing);
//! \}
//! Graphic view this grid is connected to.
RS_GraphicView* graphicView;
//! Current grid spacing
double spacing;
//! Current meta grid spacing
double metaSpacing;
//! Pointer to array of grid points
std::vector<RS_Vector> pt;
RS_Vector baseGrid; // the left-bottom grid point
RS_Vector cellV;// (dx,dy)
RS_Vector metaGridWidth;
//! Meta grid positions in X
std::vector<double> metaX;
//! Meta grid positions in Y
std::vector<double> metaY;
bool isometric;
RS2::CrosshairType crosshairType;
};
#endif

View File

@@ -0,0 +1,75 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<cmath>
#include "rs_linetypepattern.h"
RS_LineTypePattern::RS_LineTypePattern(std::initializer_list<double> const& pattern):
pattern(pattern)
{
totalLength=0.;
num = pattern.size();
for(double const& l: this->pattern){
totalLength += fabs(l);
}
}
//define all line patterns in pixels
const RS_LineTypePattern RS_LineTypePattern::patternSolidLine={10.0};
const RS_LineTypePattern RS_LineTypePattern::patternDotLineTiny{{0.15, -1.}};
const RS_LineTypePattern RS_LineTypePattern::patternDotLine{{0.2, -6.2}};
const RS_LineTypePattern RS_LineTypePattern::patternDotLine2{{0.2, -3.1}};
const RS_LineTypePattern RS_LineTypePattern::patternDotLineX2{{0.2, -12.4}};
const RS_LineTypePattern RS_LineTypePattern::patternDashLineTiny{{2., -1.}};
const RS_LineTypePattern RS_LineTypePattern::patternDashLine{{12.0, -6.0}};
const RS_LineTypePattern RS_LineTypePattern::patternDashLine2{{6.0, -3.0}};
const RS_LineTypePattern RS_LineTypePattern::patternDashLineX2{{24.0, -12.0}};
const RS_LineTypePattern RS_LineTypePattern::patternDashDotLineTiny{{2., -0.7, 0.15, -2.}};
const RS_LineTypePattern RS_LineTypePattern::patternDashDotLine{{12.0, -5., 0.2, -5.95}};
const RS_LineTypePattern RS_LineTypePattern::patternDashDotLine2{{6.0, -2., 0.2, -2.}};
const RS_LineTypePattern RS_LineTypePattern::patternDashDotLineX2{{24.0, -8., 0.2, -8.}};
const RS_LineTypePattern RS_LineTypePattern::patternDivideLineTiny{{2., -0.7, 0.15, -0.7, 0.15, -0.7}};
const RS_LineTypePattern RS_LineTypePattern::patternDivideLine{{12.0, -4.9, 0.2, -4.9, 0.2, -4.9}};
const RS_LineTypePattern RS_LineTypePattern::patternDivideLine2{{6.0, -1.9, 0.2, -1.9, 0.2, -1.9}};
const RS_LineTypePattern RS_LineTypePattern::patternDivideLineX2{{24.0, -8., 0.2, -8., 0.2, -8.}};
const RS_LineTypePattern RS_LineTypePattern::patternCenterLineTiny{{5., -1., 1., -1.}};
const RS_LineTypePattern RS_LineTypePattern::patternCenterLine{{32.0, -6.0, 6.0, -6.0}};
const RS_LineTypePattern RS_LineTypePattern::patternCenterLine2{{16.0, -3.0, 3.0, -3.0}};
const RS_LineTypePattern RS_LineTypePattern::patternCenterLineX2{{64.0, -12.0, 12.0, -12.0}};
const RS_LineTypePattern RS_LineTypePattern::patternBorderLineTiny{{2., -1., 2., -1., 0.15, -1.}};
const RS_LineTypePattern RS_LineTypePattern::patternBorderLine{{12.0, -4.0, 12.0, -4., 0.2, -4.}};
const RS_LineTypePattern RS_LineTypePattern::patternBorderLine2{{6.0, -3.0, 6.0, -3., 0.2, -3.}};
const RS_LineTypePattern RS_LineTypePattern::patternBorderLineX2{{24.0, -8.0, 24.0, -8., 0.2, -8.}};
const RS_LineTypePattern RS_LineTypePattern::patternBlockLine{{0.5, -0.5}};
const RS_LineTypePattern RS_LineTypePattern::patternSelected{{1.0, -3.0}};

View File

@@ -0,0 +1,83 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_LINETYPEPATTERN_H
#define RS_LINETYPEPATTERN_H
#include <vector>
#include <cstddef>
/**
* Stores a line type pattern.
*/
struct RS_LineTypePattern {
RS_LineTypePattern()=delete;
RS_LineTypePattern(std::initializer_list<double> const& pattern);
~RS_LineTypePattern()=default;
std::vector<double> pattern;
double totalLength;
size_t num;
//define all line patterns in pixels
static const RS_LineTypePattern patternSolidLine;
static const RS_LineTypePattern patternDotLineTiny;
static const RS_LineTypePattern patternDotLine;
static const RS_LineTypePattern patternDotLine2;
static const RS_LineTypePattern patternDotLineX2;
static const RS_LineTypePattern patternDashLineTiny;
static const RS_LineTypePattern patternDashLine;
static const RS_LineTypePattern patternDashLine2;
static const RS_LineTypePattern patternDashLineX2;
static const RS_LineTypePattern patternDashDotLineTiny;
static const RS_LineTypePattern patternDashDotLine;
static const RS_LineTypePattern patternDashDotLine2;
static const RS_LineTypePattern patternDashDotLineX2;
static const RS_LineTypePattern patternDivideLineTiny;
static const RS_LineTypePattern patternDivideLine;
static const RS_LineTypePattern patternDivideLine2;
static const RS_LineTypePattern patternDivideLineX2;
static const RS_LineTypePattern patternCenterLineTiny;
static const RS_LineTypePattern patternCenterLine;
static const RS_LineTypePattern patternCenterLine2;
static const RS_LineTypePattern patternCenterLineX2;
static const RS_LineTypePattern patternBorderLineTiny;
static const RS_LineTypePattern patternBorderLine;
static const RS_LineTypePattern patternBorderLine2;
static const RS_LineTypePattern patternBorderLineX2;
static const RS_LineTypePattern patternBlockLine;
static const RS_LineTypePattern patternSelected;
};
#endif

View File

@@ -0,0 +1,53 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_MAINWINDOWINTERFACE_H
#define RS_MAINWINDOWINTERFACE_H
#include "rs_document.h"
#include "rs_graphicview.h"
/**
* Interface for main application windows.
*/
class RS_MainWindowInterface {
public:
RS_MainWindowInterface() = default;
virtual ~RS_MainWindowInterface() = default;
virtual RS_GraphicView const* getGraphicView() const = 0;
virtual RS_Document const* getDocument() const= 0;
virtual RS_GraphicView* getGraphicView() = 0;
virtual RS_Document* getDocument() = 0;
virtual void createNewDocument(const QString& fileName = QString(), RS_Document* doc=nullptr) = 0;
};
#endif

163
lib/gui/rs_painter.cpp Normal file
View File

@@ -0,0 +1,163 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<cmath>
#include<QPolygon>
#include "rs_pen.h"
#include "rs_color.h"
#include "rs_painter.h"
#include "rs_math.h"
#include "rs_debug.h"
void RS_Painter::createArc(QPolygon& pa,
const RS_Vector& cp, double radius,
double a1, double a2,
bool reversed) {
if (radius<1.0e-6) {
RS_DEBUG->print(RS_Debug::D_WARNING,
"RS_Painter::createArc: invalid radius: %f", radius);
return;
}
double aStep=fabs(2.0/radius); // Angle Step (rad)
if(aStep>=0.5) aStep=0.5;
if(reversed) {
if(a1<=a2+RS_TOLERANCE) a1+=2.*M_PI;
aStep *= -1;
}else{
if(a2<=a1+RS_TOLERANCE) a2+=2.*M_PI;
}
double a; // Current Angle (rad)
// aStep=aStep/2.0;
//if (aStep<0.05) {
// aStep = 0.05;
//}
// less than a pixel long lines:
//if (radius*aStep<1.0) {
// aStep =
//}
//QPointArray pa;
pa.clear();
// pa<<QPoint(toScreenX(cp.x+cos(aStart)*radius), toScreenY(cp.y-sin(aStart)*radius));
double da=fabs(a2-a1);
for(a=a1; fabs(a-a1)<da; a+=aStep) {
pa<<QPoint(toScreenX(cp.x+cos(a)*radius), toScreenY(cp.y-sin(a)*radius));
}
QPoint pt2(toScreenX(cp.x+cos(a2)*radius), toScreenY(cp.y-sin(a2)*radius));
if(pa.size()>0 && pa.last() != pt2) pa<<pt2;
}
void RS_Painter::createEllipse(QPolygon& pa,
const RS_Vector& cp,
double radius1, double radius2,
double angle,
double angle1, double angle2,
bool reversed)
{
const RS_Vector vr(radius1,radius2);
const RS_Vector rvp(radius2,radius1);
const double ab=radius1*radius2;
double ea1=angle1;
double ea2;
double dA=RS_Math::getAngleDifference(angle1, angle2, reversed);
if(dA <= RS_TOLERANCE_ANGLE) {
dA=2.*M_PI;
ea2 =ea1 + dA;
}else
ea2 = ea1 +(reversed?-dA:dA);
const RS_Vector angleVector(-angle);
/*
draw a new line after tangent changes by 0.01 rad
ds^2 = (a^2 sin^2 + b^2 cos^2) da^2
*/
RS_Vector vp(-ea1);
vp.scale(vr);
vp.rotate(angleVector);
vp.move(cp);
// vp.set(cp.x+cos(a1)*radius1,
// cp.y-sin(a1)*radius2);
// vp.rotate(vc, -angle);
pa.clear();
// pa<<QPoint(toScreenX(vp.x),
// toScreenY(vp.y));
// moveTo(toScreenX(vp.x),
// toScreenY(vp.y));
const double minDea=fabs(ea2-ea1)/2048.;
// Arc Counterclockwise:
do {
RS_Vector va(-ea1);
vp=va;
double r2=va.scale(rvp).squared();
if( r2<RS_TOLERANCE15) r2=RS_TOLERANCE15;
double aStep=ab/(r2*sqrt(r2));
if(aStep < minDea) aStep=minDea;
if(aStep > M_PI/4.) aStep=M_PI/4.;
ea1 += reversed?-aStep:aStep;
vp.scale(vr);
vp.rotate(angleVector);
vp.move(cp);
pa<<QPoint(toScreenX(vp.x),
toScreenY(vp.y));
} while(fabs(angle1-ea1)<dA);
vp.set(cos(ea2)*radius1,
-sin(ea2)*radius2);
vp.rotate(angleVector);
vp.move(cp);
pa<<QPoint(toScreenX(vp.x),
toScreenY(vp.y));
}
void RS_Painter::drawRect(const RS_Vector& p1, const RS_Vector& p2) {
drawPolygon(QRect(int(p1.x+0.5), int(p1.y+0.5), int(p2.x - p1.x+0.5), int(p2.y - p1.y+0.5)));
// drawLine(RS_Vector(p1.x, p1.y), RS_Vector(p2.x, p1.y));
// drawLine(RS_Vector(p2.x, p1.y), RS_Vector(p2.x, p2.y));
// drawLine(RS_Vector(p2.x, p2.y), RS_Vector(p1.x, p2.y));
// drawLine(RS_Vector(p1.x, p2.y), RS_Vector(p1.x, p1.y));
}
void RS_Painter::drawHandle(const RS_Vector& p, const RS_Color& c, int size) {
if (size<0) {
size = 2;
}
fillRect((int)(p.x-size), (int)(p.y-size), 2*size, 2*size, c);
}
int RS_Painter::toScreenX(double x) const {
return RS_Math::round(offset.x + x);
}
int RS_Painter::toScreenY(double y) const{
return RS_Math::round(offset.y + y);
}

171
lib/gui/rs_painter.h Normal file
View File

@@ -0,0 +1,171 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_PAINTER_H
#define RS_PAINTER_H
#include "rs_vector.h"
class RS_Color;
class RS_Pen;
class QPainterPath;
class QRectF;
class QPolygon;
class QPolygonF;
class QImage;
class QBrush;
/**
* This class is a common interface for a painter class. Such
* a class will in it's implementation be responsible to paint
* lines, arcs, ... in widgets. All angles in rad.
*
* Note that this is just an interface used as a slot to
* communicate with the LibreCAD from a GUI level. This
* does not contain any Qt or platform specific code.
*/
class RS_Painter {
public:
RS_Painter(): offset{0.0,0.0} {
drawingMode = RS2::ModeFull;
drawSelectedEntities=false;
}
virtual ~RS_Painter() = default;
/**
* Sets the drawing mode.
*/
void setDrawingMode(RS2::DrawingMode m) {
drawingMode = m;
}
// When set to true, only entities that are selected will be drawn
void setDrawSelectedOnly(bool dso) {
drawSelectedEntities=dso;
}
// When true, only selected items will be draw
bool shouldDrawSelected() {
return drawSelectedEntities;
}
/**
* @return Current drawing mode.
*/
RS2::DrawingMode getDrawingMode() {
return drawingMode;
}
virtual void moveTo(int x, int y) = 0;
virtual void lineTo(int x, int y) = 0;
virtual void drawGridPoint(const RS_Vector& p) = 0;
virtual void drawPoint(const RS_Vector& p) = 0;
virtual void drawLine(const RS_Vector& p1, const RS_Vector& p2) = 0;
virtual void drawRect(const RS_Vector& p1, const RS_Vector& p2);
virtual void drawArc(const RS_Vector& cp, double radius,
double a1, double a2,
const RS_Vector& p1, const RS_Vector& p2,
bool reversed) = 0;
virtual void drawArc(const RS_Vector& cp, double radius,
double a1, double a2,
bool reversed) = 0;
void createArc(QPolygon& pa,
const RS_Vector& cp, double radius,
double a1, double a2,
bool reversed);
void createEllipse(QPolygon& pa,
const RS_Vector& cp,
double radius1, double radius2,
double angle,
double angle1, double angle2,
bool reversed);
virtual void drawCircle(const RS_Vector& cp, double radius) = 0;
virtual void drawEllipse(const RS_Vector& cp,
double radius1, double radius2,
double angle,
double angle1, double angle2,
bool reversed) = 0;
virtual void drawImg(QImage& img, const RS_Vector& pos,
double angle, const RS_Vector& factor) = 0;
virtual void drawTextH(int x1, int y1, int x2, int y2,
const QString& text) = 0;
virtual void drawTextV(int x1, int y1, int x2, int y2,
const QString& text) = 0;
virtual void fillRect(int x1, int y1, int w, int h, const RS_Color& col) = 0;
virtual void fillRect ( const QRectF & rectangle, const RS_Color & color ) = 0;
virtual void fillRect ( const QRectF & rectangle, const QBrush & brush ) = 0;
virtual void fillTriangle(const RS_Vector& p1,
const RS_Vector& p2,
const RS_Vector& p3) = 0;
virtual void drawPath ( const QPainterPath & path ) = 0;
virtual void drawHandle(const RS_Vector& p, const RS_Color& c, int size=-1);
virtual RS_Pen getPen() const = 0;
virtual void setPen(const RS_Pen& pen) = 0;
virtual void setPen(const RS_Color& color) = 0;
virtual void setPen(int r, int g, int b) = 0;
virtual void disablePen() = 0;
virtual const QBrush& brush() const = 0;
virtual void setBrush(const RS_Color& color) = 0;
virtual void setBrush(const QBrush& color) = 0;
virtual void drawPolygon(const QPolygon& a, Qt::FillRule rule=Qt::WindingFill) = 0;
virtual void erase() = 0;
virtual int getWidth() const= 0;
virtual int getHeight() const= 0;
virtual double getDpmm() const= 0;
virtual void setOffset(const RS_Vector& o) {
offset = o;
}
virtual void setClipRect(int x, int y, int w, int h) = 0;
virtual void resetClipping() = 0;
int toScreenX(double x) const;
int toScreenY(double y) const;
protected:
/**
* Current drawing mode.
*/
RS2::DrawingMode drawingMode;
/**
* A fixed offset added to all entities drawn (useful for previews).
*/
RS_Vector offset;
// When set to true, only selected entities should be drawn
bool drawSelectedEntities;
};
#endif

630
lib/gui/rs_painterqt.cpp Normal file
View File

@@ -0,0 +1,630 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<cmath>
#include "rs_painterqt.h"
#include "rs_math.h"
#include "rs_debug.h"
namespace {
/**
* Wrapper for Qt
* convert RS2::LineType to Qt::PenStyle
*/
Qt::PenStyle rsToQtLineType(RS2::LineType t) {
switch (t) {
case RS2::NoPen:
return Qt::NoPen;
case RS2::SolidLine:
return Qt::SolidLine;
case RS2::DotLine:
case RS2::DotLineTiny:
case RS2::DotLine2:
case RS2::DotLineX2:
return Qt::DotLine;
case RS2::DashLine:
case RS2::DashLineTiny:
case RS2::DashLine2:
case RS2::DashLineX2:
return Qt::DashLine;
case RS2::DashDotLine:
case RS2::DashDotLineTiny:
case RS2::DashDotLine2:
case RS2::DashDotLineX2:
return Qt::DashDotLine;
case RS2::DivideLine:
case RS2::DivideLineTiny:
case RS2::DivideLine2:
case RS2::DivideLineX2:
return Qt::DashDotDotLine;
case RS2::CenterLine:
case RS2::CenterLineTiny:
case RS2::CenterLine2:
case RS2::CenterLineX2:
return Qt::DashDotLine;
case RS2::BorderLine:
case RS2::BorderLineTiny:
case RS2::BorderLine2:
case RS2::BorderLineX2:
return Qt::DashDotLine;
case RS2::LineByLayer:
case RS2::LineByBlock:
default:
return Qt::SolidLine;
}
return Qt::SolidLine;
}
}
/**
* Constructor.
*/
// RVT_PORT changed from RS_PainterQt::RS_PainterQt( const QPaintDevice* pd)
RS_PainterQt::RS_PainterQt( QPaintDevice* pd)
: QPainter(pd), RS_Painter() {}
void RS_PainterQt::moveTo(int x, int y) {
//RVT_PORT changed from QPainter::moveTo(x,y);
rememberX=x;
rememberY=y;
}
void RS_PainterQt::lineTo(int x, int y) {
// RVT_PORT changed from QPainter::lineTo(x, y);
QPainterPath path;
path.moveTo(rememberX,rememberY);
path.lineTo(x,y);
QPainter::drawPath(path);
rememberX=x;
rememberY=y;
}
/**
* Draws a grid point at (x1, y1).
*/
void RS_PainterQt::drawGridPoint(const RS_Vector& p) {
QPainter::drawPoint(toScreenX(p.x), toScreenY(p.y));
}
/**
* Draws a point at (x1, y1).
*/
void RS_PainterQt::drawPoint(const RS_Vector& p) {
QPainter::drawLine(toScreenX(p.x-1), toScreenY(p.y),
toScreenX(p.x+1), toScreenY(p.y));
QPainter::drawLine(toScreenX(p.x), toScreenY(p.y-1),
toScreenX(p.x), toScreenY(p.y+1));
}
/**
* Draws a line from (x1, y1) to (x2, y2).
*/
void RS_PainterQt::drawLine(const RS_Vector& p1, const RS_Vector& p2)
{
QPainter::drawLine(toScreenX(p1.x), toScreenY(p1.y),
toScreenX(p2.x), toScreenY(p2.y));
}
/**
* Draws a rectangle with corners p1, p2.
*/
/*void RS_PainterQt::drawRect(const RS_Vector& p1, const RS_Vector& p2) {
/ *QPainter::drawRect(toScreenX(p1.x), toScreenY(p1.y),
abs(toScreenX(p2.x) - toScreenX(p1.x)),
abs(toScreenY(p2.y) - toScreenY(p1.y)));* /
QPainter::drawLine(toScreenX(p1.x), toScreenY(p1.y),
toScreenX(p2.x), toScreenY(p1.y));
QPainter::drawLine(toScreenX(p2.x), toScreenY(p1.y),
toScreenX(p2.x), toScreenY(p2.y));
QPainter::drawLine(toScreenX(p2.x), toScreenY(p2.y),
toScreenX(p1.x), toScreenY(p2.y));
QPainter::drawLine(toScreenX(p1.x), toScreenY(p2.y),
toScreenX(p1.x), toScreenY(p1.y));
}*/
/**
* Draws an arc which starts / ends exactly at the given coordinates.
*
* @param cx center in x
* @param cy center in y
* @param radius Radius
* @param a1 Angle 1 in rad
* @param a2 Angle 2 in rad
* @param x1 startpoint x
* @param y1 startpoint y
* @param x2 endpoint x
* @param y2 endpoint y
* @param reversed true: clockwise, false: counterclockwise
*/
void RS_PainterQt::drawArc(const RS_Vector& cp, double radius,
double a1, double a2,
const RS_Vector& p1, const RS_Vector& p2,
bool reversed) {
/*
QPainter::drawArc(cx-radius, cy-radius,
2*radius, 2*radius,
a1*16, (a2-a1)*16);
*/
if(radius<=0.5) {
drawGridPoint(cp);
} else {
int cix; // Next point on circle
int ciy; //
double aStep; // Angle Step (rad)
double a; // Current Angle (rad)
double linStep; // linear step (pixels)
if (drawingMode==RS2::ModePreview) {
linStep = 20.0;
} else {
linStep = 6.0;
}
if (fabs(linStep/radius)<=1.0) {
aStep=asin(linStep/radius);
} else {
aStep=1.0;
}
if (aStep<0.05) {
aStep = 0.05;
}
if(!reversed) {
// Arc Counterclockwise:
if(a1>a2-1.0e-10) {
a2+=2*M_PI;
}
//moveTo(toScreenX(p1.x), toScreenY(p1.y));
QPolygon pa;
int i=0;
pa.resize(i+1);
pa.setPoint(i++, toScreenX(p1.x), toScreenY(p1.y));
for(a=a1+aStep; a<=a2; a+=aStep) {
cix = toScreenX(cp.x+cos(a)*radius);
ciy = toScreenY(cp.y-sin(a)*radius);
//lineTo(cix, ciy);
pa.resize(i+1);
pa.setPoint(i++, cix, ciy);
}
//lineTo(toScreenX(p2.x), toScreenY(p2.y));
pa.resize(i+1);
pa.setPoint(i++, toScreenX(p2.x), toScreenY(p2.y));
drawPolyline(pa);
} else {
// Arc Clockwise:
if(a1<a2+1.0e-10) {
a2-=2*M_PI;
}
QPolygon pa;
int i=0;
pa.resize(i+1);
pa.setPoint(i++, toScreenX(p1.x), toScreenY(p1.y));
//moveTo(toScreenX(p1.x), toScreenY(p1.y));
for(a=a1-aStep; a>=a2; a-=aStep) {
cix = toScreenX(cp.x+cos(a)*radius);
ciy = toScreenY(cp.y-sin(a)*radius);
//lineTo(cix, ciy);
pa.resize(i+1);
pa.setPoint(i++, cix, ciy);
}
//lineTo(toScreenX(p2.x), toScreenY(p2.y));
pa.resize(i+1);
pa.setPoint(i++, toScreenX(p2.x), toScreenY(p2.y));
drawPolyline(pa);
}
}
}
/**
* Draws an arc.
*
* @param cx center in x
* @param cy center in y
* @param radius Radius
* @param a1 Angle 1 in rad
* @param a2 Angle 2 in rad
* @param reversed true: clockwise, false: counterclockwise
*/
void RS_PainterQt::drawArc(const RS_Vector& cp, double radius,
double a1, double a2,
bool reversed) {
if(radius<=0.5) {
drawGridPoint(cp);
} else {
#ifdef __APPL1E__
drawArcMac(cp, radius, a1, a2, reversed);
#else
QPolygon pa;
createArc(pa, cp, radius, a1, a2, reversed);
drawPolyline(pa);
#endif
}
}
/**
* Draws an arc on apple.
*
* @param cx center in x
* @param cy center in y
* @param radius Radius
* @param a1 Angle 1 in rad
* @param a2 Angle 2 in rad
* @param reversed true: clockwise, false: counterclockwise
*/
void RS_PainterQt::drawArcMac(const RS_Vector& cp, double radius,
double a1, double a2,
bool reversed) {
RS_DEBUG->print("RS_PainterQt::drawArcMac");
if(radius<=0.5) {
drawGridPoint(cp);
} else {
//QPointArray pa;
//createArc(pa, cp, radius, a1, a2, reversed);
double cix; // Next point on circle
double ciy; //
double aStep; // Angle Step (rad)
double a; // Current Angle (rad)
double ox;
double oy;
if(2.0/radius<=1.0) {
aStep=asin(2.0/radius);
} else {
aStep=1.0;
}
if (aStep<0.05) {
aStep = 0.05;
}
//QPointArray pa;
//int i=0;
//pa.resize(i+1);
//pa.setPoint(i++, toScreenX(cp.x+cos(a1)*radius),
// toScreenY(cp.y-sin(a1)*radius));
//moveTo(toScreenX(cp.x+cos(a1)*radius),
// toScreenY(cp.y-sin(a1)*radius));
ox = cp.x+cos(a1)*radius;
oy = cp.y-sin(a1)*radius;
if(!reversed) {
// Arc Counterclockwise:
if(a1>a2-1.0e-10) {
a2+=2*M_PI;
}
for(a=a1+aStep; a<=a2; a+=aStep) {
cix = cp.x+cos(a)*radius;
ciy = cp.y-sin(a)*radius;
//lineTo(cix, ciy);
drawLine(RS_Vector(ox, oy), RS_Vector(cix, ciy));
ox = cix;
oy = ciy;
//pa.resize(i+1);
//pa.setPoint(i++, cix, ciy);
}
} else {
// Arc Clockwise:
if(a1<a2+1.0e-10) {
a2-=2*M_PI;
}
for(a=a1-aStep; a>=a2; a-=aStep) {
cix = cp.x+cos(a)*radius;
ciy = cp.y-sin(a)*radius;
drawLine(RS_Vector(ox, oy), RS_Vector(cix, ciy));
ox = cix;
oy = ciy;
//lineTo(cix, ciy);
//pa.resize(i+1);
//pa.setPoint(i++, cix, ciy);
}
}
drawLine(RS_Vector(ox, oy),
RS_Vector(cp.x+cos(a2)*radius,
cp.y-sin(a2)*radius));
//lineTo(toScreenX(cp.x+cos(a2)*radius),
// toScreenY(cp.y-sin(a2)*radius));
//pa.resize(i+1);
//pa.setPoint(i++,
// toScreenX(cp.x+cos(a2)*radius),
// toScreenY(cp.y-sin(a2)*radius));
//drawPolyline(pa);
}
}
/**
* Draws a circle.
* @param cp Center point
* @param radius Radius
*/
void RS_PainterQt::drawCircle(const RS_Vector& cp, double radius)
{
QPainter::drawEllipse(QPointF(cp.x, cp.y), radius, radius);
}
/**
* Draws a rotated ellipse arc.
*/
void RS_PainterQt::drawEllipse(const RS_Vector& cp,
double radius1, double radius2,
double angle,
double a1, double a2,
bool reversed) {
QPolygon pa;
createEllipse(pa, cp, radius1, radius2, angle, a1, a2, reversed);
drawPolyline(pa);
}
/**
* Draws image.
*/
void RS_PainterQt::drawImg(QImage& img, const RS_Vector& pos,
double angle, const RS_Vector& factor) {
save();
// Render smooth only at close zooms
if (factor.x < 1 || factor.y < 1) {
RS_PainterQt::setRenderHint(SmoothPixmapTransform , true);
}
else {
RS_PainterQt::setRenderHint(SmoothPixmapTransform);
}
QMatrix wm;
wm.translate(pos.x, pos.y);
wm.rotate(RS_Math::rad2deg(-angle));
wm.scale(factor.x, factor.y);
setWorldMatrix(wm);
drawImage(0,-img.height(), img);
restore();
}
void RS_PainterQt::drawTextH(int x1, int y1,
int x2, int y2,
const QString& text) {
drawText(x1, y1, x2, y2,
Qt::AlignRight|Qt::AlignVCenter,
text);
}
void RS_PainterQt::drawTextV(int x1, int y1,
int x2, int y2,
const QString& text) {
save();
QMatrix wm = worldMatrix();
wm.rotate(-90.0);
setWorldMatrix(wm);
//rotate(-90.0);
drawText(x1, y1, x2, y2,
Qt::AlignRight|Qt::AlignVCenter,
text);
restore();
}
void RS_PainterQt::fillRect(int x1, int y1, int w, int h,
const RS_Color& col) {
QPainter::fillRect(x1, y1, w, h, col);
}
void RS_PainterQt::fillTriangle(const RS_Vector& p1,
const RS_Vector& p2,
const RS_Vector& p3) {
QPolygon arr(3);
QBrush brushSaved=brush();
arr.putPoints(0, 3,
toScreenX(p1.x),toScreenY(p1.y),
toScreenX(p2.x),toScreenY(p2.y),
toScreenX(p3.x),toScreenY(p3.y));
setBrush(RS_Color(pen().color()));
drawPolygon(arr);
setBrush(brushSaved);
}
void RS_PainterQt::erase() {
QPainter::eraseRect(0,0,getWidth(),getHeight());
}
int RS_PainterQt::getWidth() const{
return device()->width();
}
/** get Density per millimeter on screen/print device
*@return density per millimeter in pixel/mm
*/
double RS_PainterQt::getDpmm() const{
int mm(device()->widthMM());
if(mm==0) mm=400;
return double(device()->width())/mm;
}
int RS_PainterQt::getHeight() const{
return device()->height();
}
const QBrush& RS_PainterQt::brush() const
{
return QPainter::brush();
}
RS_Pen RS_PainterQt::getPen() const{
return lpen;
//RS_Pen p(pen().color(),
// RS2::qw(pen().width()),
// RS2::qw(pen().style()));
//return QPainter::pen();
//return p;
}
void RS_PainterQt::setPen(const RS_Pen& pen) {
lpen = pen;
switch (drawingMode) {
case RS2::ModeBW:
lpen.setColor( RS_Color( Qt::black));
break;
case RS2::ModeWB:
lpen.setColor( RS_Color( Qt::white));
break;
default:
break;
}
QPen p(lpen.getColor(), RS_Math::round(lpen.getScreenWidth()),
rsToQtLineType(lpen.getLineType()));
p.setJoinStyle(Qt::RoundJoin);
p.setCapStyle(Qt::RoundCap);
QPainter::setPen(p);
}
void RS_PainterQt::setPen(const RS_Color& color) {
switch (drawingMode) {
case RS2::ModeBW:
lpen.setColor( RS_Color( Qt::black));
QPainter::setPen( RS_Color( Qt::black));
break;
case RS2::ModeWB:
lpen.setColor( RS_Color( Qt::white));
QPainter::setPen( RS_Color( Qt::white));
break;
default:
lpen.setColor( color);
QPainter::setPen( color);
break;
}
}
void RS_PainterQt::setPen(int r, int g, int b) {
switch (drawingMode) {
case RS2::ModeBW:
setPen( QColor( Qt::black));
break;
case RS2::ModeWB:
setPen( QColor( Qt::white));
break;
default:
setPen( QColor( r, g, b));
break;
}
}
void RS_PainterQt::disablePen() {
lpen = RS_Pen(RS2::FlagInvalid);
QPainter::setPen(Qt::NoPen);
}
void RS_PainterQt::setBrush(const RS_Color& color) {
switch (drawingMode) {
case RS2::ModeBW:
QPainter::setBrush( QColor( Qt::black));
break;
case RS2::ModeWB:
QPainter::setBrush( QColor( Qt::white));
break;
default:
QPainter::setBrush( color);
break;
}
}
void RS_PainterQt::setBrush(const QBrush& color) {
QPainter::setBrush(color);
}
void RS_PainterQt::drawPolygon(const QPolygon& a, Qt::FillRule rule) {
QPainter::drawPolygon(a,rule);
}
void RS_PainterQt::drawPath ( const QPainterPath & path ) {
QPainter::drawPath(path);
}
void RS_PainterQt::setClipRect(int x, int y, int w, int h) {
QPainter::setClipRect(x, y, w, h);
setClipping(true);
}
void RS_PainterQt::resetClipping() {
setClipping(false);
}
void RS_PainterQt::fillRect ( const QRectF & rectangle, const RS_Color & color ) {
double x1=rectangle.left();
double x2=rectangle.right();
double y1=rectangle.top();
double y2=rectangle.bottom();
QPainter::fillRect(toScreenX(x1),toScreenY(y1),toScreenX(x2)-toScreenX(x1),toScreenY(y2)-toScreenX(y1), color);
}
void RS_PainterQt::fillRect ( const QRectF & rectangle, const QBrush & brush ) {
double x1=rectangle.left();
double x2=rectangle.right();
double y1=rectangle.top();
double y2=rectangle.bottom();
QPainter::fillRect(toScreenX(x1),toScreenY(y1),toScreenX(x2),toScreenY(y2), brush);
}

118
lib/gui/rs_painterqt.h Normal file
View File

@@ -0,0 +1,118 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_PAINTERQT_H
#define RS_PAINTERQT_H
#include <QPainter>
#include <QPainterPath>
#include "rs_painter.h"
#include "rs_pen.h"
/**
* The Qt implementation of a painter. It can draw objects such as
* lines or arcs in a widget. All coordinates are screen coordinates
* and have nothing to do with the graphic view.
*/
class RS_PainterQt: public QPainter, public RS_Painter {
public:
RS_PainterQt( QPaintDevice* pd);
virtual ~RS_PainterQt()=default;
virtual void moveTo(int x, int y);
virtual void lineTo(int x, int y);
virtual void drawGridPoint(const RS_Vector& p);
virtual void drawPoint(const RS_Vector& p);
virtual void drawLine(const RS_Vector& p1, const RS_Vector& p2);
//virtual void drawRect(const RS_Vector& p1, const RS_Vector& p2);
virtual void fillRect ( const QRectF & rectangle, const RS_Color & color );
virtual void fillRect ( const QRectF & rectangle, const QBrush & brush );
virtual void drawArc(const RS_Vector& cp, double radius,
double a1, double a2,
const RS_Vector& p1, const RS_Vector& p2,
bool reversed);
virtual void drawArc(const RS_Vector& cp, double radius,
double a1, double a2,
bool reversed);
virtual void drawArcMac(const RS_Vector& cp, double radius,
double a1, double a2,
bool reversed);
virtual void drawCircle(const RS_Vector&, double radius);
virtual void drawEllipse(const RS_Vector& cp,
double radius1, double radius2,
double angle,
double a1, double a2,
bool reversed);
virtual void drawImg(QImage& img, const RS_Vector& pos,
double angle, const RS_Vector& factor);
virtual void drawTextH(int x1, int y1, int x2, int y2,
const QString& text);
virtual void drawTextV(int x1, int y1, int x2, int y2,
const QString& text);
virtual void fillRect(int x1, int y1, int w, int h,
const RS_Color& col);
virtual void fillTriangle(const RS_Vector& p1,
const RS_Vector& p2,
const RS_Vector& p3);
virtual void drawPolygon(const QPolygon& a,Qt::FillRule rule=Qt::WindingFill);
virtual void drawPath ( const QPainterPath & path );
virtual void erase();
virtual int getWidth() const;
/** get Density per millimeter on screen/print device
*@return density per millimeter in pixel/mm
*/
virtual double getDpmm() const;
virtual int getHeight() const;
virtual RS_Pen getPen() const;
virtual void setPen(const RS_Pen& pen);
virtual void setPen(const RS_Color& color);
virtual void setPen(int r, int g, int b);
virtual void disablePen();
//virtual void setColor(const QColor& color);
virtual const QBrush& brush() const;
virtual void setBrush(const RS_Color& color);
virtual void setBrush(const QBrush& color);
virtual void setClipRect(int x, int y, int w, int h);
virtual void resetClipping();
protected:
RS_Pen lpen;
long rememberX; // Used for the moment because QPainter doesn't support moveTo anymore, thus we need to remember ourselves the moveTo positions
long rememberY;
};
#endif

View File

@@ -0,0 +1,79 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<QSize>
#include "rs_staticgraphicview.h"
#include "rs_graphic.h"
#include "rs_debug.h"
/**
* Constructor.
*
* @param w Width
* @param h Height
*/
RS_StaticGraphicView::RS_StaticGraphicView(int w, int h, RS_Painter* /*p*/,
QSize const* pb):
width(w)
,height(h)
{
setBackground({255,255,255});
QSize b{5, 5};
if (pb) b = *pb;
setBorders(b.width(), b.height(), b.width(), b.height());
}
/**
* @return width of widget.
*/
int RS_StaticGraphicView::getWidth() const{
return width;
}
/**
* @return height of widget.
*/
int RS_StaticGraphicView::getHeight() const{
return height;
}
RS_Vector RS_StaticGraphicView::getMousePosition() const
{
return RS_Vector(false);
}
/**
* Handles paint events by redrawing the graphic in this view.
*/
void RS_StaticGraphicView::paint() {
RS_DEBUG->print("RS_StaticGraphicView::paint begin");
// drawIt();
redraw(RS2::RedrawAll);
RS_DEBUG->print("RS_StaticGraphicView::paint end");
}

View File

@@ -0,0 +1,61 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_STATICGRAPHICVIEW_H
#define RS_STATICGRAPHICVIEW_H
#include "rs_graphicview.h"
//#include "rs_layerlistlistener.h"
/**
* This is an implementation of a graphic viewer with a fixed size
* for drawing onto fixed devices (such as bitmaps).
*/
class RS_StaticGraphicView: public RS_GraphicView {
public:
RS_StaticGraphicView(int w, int h, RS_Painter* p, QSize const* pb = nullptr);
int getWidth() const override;
int getHeight() const override;
void redraw(RS2::RedrawMethod) override{}
void adjustOffsetControls() override{}
void adjustZoomControls() override{}
void setMouseCursor(RS2::CursorType ) override{}
void updateGridStatusWidget(const QString& ) override{}
RS_Vector getMousePosition() const override;
void paint();
private:
//! Width
int width;
//! Height
int height;
};
#endif