📄 rs_entitycontainer.cpp
字号:
/****************************************************************************** $Id: rs_entitycontainer.cpp 2363 2005-04-04 14:56:55Z andrew $**** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.**** This file is part of the qcadlib Library project.**** 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 LICENSE.GPL included in the** packaging of this file.**** Licensees holding valid qcadlib Professional Edition licenses may use ** this file in accordance with the qcadlib Commercial License** Agreement provided with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.ribbonsoft.com for further details.**** Contact info@ribbonsoft.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "rs_entitycontainer.h"//#include <values.h>#include "rs_debug.h"#include "rs_dimension.h"#include "rs_math.h"#include "rs_layer.h"#include "rs_line.h"#include "rs_polyline.h"#include "rs_text.h"#include "rs_insert.h"#include "rs_spline.h"#include "rs_information.h"#include "rs_graphicview.h"bool RS_EntityContainer::autoUpdateBorders = true;/** * Default constructor. * * @param owner True if we own and also delete the entities. */RS_EntityContainer::RS_EntityContainer(RS_EntityContainer* parent, bool owner) : RS_Entity(parent) { entities.setAutoDelete(owner); RS_DEBUG->print("RS_EntityContainer::RS_EntityContainer: " "owner: %d", (int)owner); subContainer = NULL; //autoUpdateBorders = true;}/** * Copy constructor. Makes a deep copy of all entities. *//*RS_EntityContainer::RS_EntityContainer(const RS_EntityContainer& ec) : RS_Entity(ec) { }*//** * Destructor. */RS_EntityContainer::~RS_EntityContainer() { clear();}RS_Entity* RS_EntityContainer::clone() { RS_DEBUG->print("RS_EntityContainer::clone: ori autoDel: %d", entities.autoDelete()); RS_EntityContainer* ec = new RS_EntityContainer(*this); ec->entities.setAutoDelete(entities.autoDelete()); RS_DEBUG->print("RS_EntityContainer::clone: clone autoDel: %d", ec->entities.autoDelete()); ec->detach(); ec->initId(); return ec;}/** * Detaches shallow copies and creates deep copies of all subentities. * This is called after cloning entity containers. */void RS_EntityContainer::detach() { RS_PtrList<RS_Entity> tmp; bool autoDel = entities.autoDelete(); RS_DEBUG->print("RS_EntityContainer::detach: autoDel: %d", (int)autoDel); entities.setAutoDelete(false); // make deep copies of all entities: for (RS_Entity* e=firstEntity(); e!=NULL; e=nextEntity()) { if (!e->getFlag(RS2::FlagTemp)) { tmp.append(e->clone()); } } // clear shared pointers: entities.clear(); entities.setAutoDelete(autoDel); // point to new deep copies: for (RS_Entity* e=tmp.first(); e!=NULL; e=tmp.next()) { entities.append(e); e->reparent(this); }}void RS_EntityContainer::reparent(RS_EntityContainer* parent) { RS_Entity::reparent(parent); // All sub-entities: for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) { e->reparent(parent); }}/** * Called when the undo state changed. Forwards the event to all sub-entities. * * @param undone true: entity has become invisible. * false: entity has become visible. */void RS_EntityContainer::undoStateChanged(bool undone) { RS_Entity::undoStateChanged(undone); // ! don't pass on to subentities. undo list handles them // All sub-entities: /*for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) { e->setUndoState(undone);}*/}void RS_EntityContainer::setVisible(bool v) { RS_DEBUG->print("RS_EntityContainer::setVisible: %d", v); RS_Entity::setVisible(v); // All sub-entities: for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) { RS_DEBUG->print("RS_EntityContainer::setVisible: subentity: %d", v); e->setVisible(v); }}/** * @return Total length of all entities in this container. */double RS_EntityContainer::getLength() { double ret = 0.0; for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) { if (e->isVisible()) { double l = e->getLength(); if (l<0.0) { ret = -1.0; break; } else { ret += l; } } } return ret;}/** * Selects this entity. */bool RS_EntityContainer::setSelected(bool select) { // This entity's select: if (RS_Entity::setSelected(select)) { // All sub-entity's select: for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) { if (e->isVisible()) { e->setSelected(select); } } return true; } else { return false; }}/** * Toggles select on this entity. */bool RS_EntityContainer::toggleSelected() { // Toggle this entity's select: if (RS_Entity::toggleSelected()) { // Toggle all sub-entity's select: /*for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) { e->toggleSelected(); }*/ return true; } else { return false; }}/** * Selects all entities within the given area. * * @param select True to select, False to deselect the entities. */void RS_EntityContainer::selectWindow(RS_Vector v1, RS_Vector v2, bool select, bool cross) { bool included; for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) { included = false; if (e->isVisible()) { if (e->isInWindow(v1, v2)) { //e->setSelected(select); included = true; } else if (cross==true) { RS_Line l[] = { RS_Line(NULL, RS_LineData(v1, RS_Vector(v2.x, v1.y))), RS_Line(NULL, RS_LineData(RS_Vector(v2.x, v1.y), v2)), RS_Line(NULL, RS_LineData(v2, RS_Vector(v1.x, v2.y))), RS_Line(NULL, RS_LineData(RS_Vector(v1.x, v2.y), v1)) }; RS_VectorSolutions sol; if (e->isContainer()) { RS_EntityContainer* ec = (RS_EntityContainer*)e; for (RS_Entity* se=ec->firstEntity(RS2::ResolveAll); se!=NULL && included==false; se=ec->nextEntity(RS2::ResolveAll)) { for (int i=0; i<4; ++i) { sol = RS_Information::getIntersection( se, &l[i], true); if (sol.hasValid()) { included = true; break; } } } } else { for (int i=0; i<4; ++i) { sol = RS_Information::getIntersection(e, &l[i], true); if (sol.hasValid()) { included = true; break; } } } } } if (included) { e->setSelected(select); } }}/** * Adds a entity to this container and updates the borders of this * entity-container if autoUpdateBorders is true. */void RS_EntityContainer::addEntity(RS_Entity* entity) { /* if (isDocument()) { RS_LayerList* lst = getDocument()->getLayerList(); if (lst!=NULL) { RS_Layer* l = lst->getActive(); if (l!=NULL && l->isLocked()) { return; } } } */ if (entity==NULL) { return; } if (entity->rtti()==RS2::EntityImage || entity->rtti()==RS2::EntityHatch) { entities.prepend(entity); } else { entities.append(entity); } if (autoUpdateBorders) { adjustBorders(entity); }}/** * Inserts a entity to this container at the given position and updates * the borders of this entity-container if autoUpdateBorders is true. */void RS_EntityContainer::insertEntity(int index, RS_Entity* entity) { if (entity==NULL) { return; } entities.insert(index, entity); if (autoUpdateBorders) { adjustBorders(entity); }}/** * Replaces the entity at the given index with the given entity * and updates the borders of this entity-container if autoUpdateBorders is true. */void RS_EntityContainer::replaceEntity(int index, RS_Entity* entity) { if (entity==NULL) { return; } entities.replace(index, entity); if (autoUpdateBorders) { adjustBorders(entity); }}/** * Removes an entity from this container and updates the borders of * this entity-container if autoUpdateBorders is true. */bool RS_EntityContainer::removeEntity(RS_Entity* entity) { bool ret = entities.remove(entity); if (autoUpdateBorders) { calculateBorders(); } return ret;}/** * Erases all entities in this container and resets the borders.. */void RS_EntityContainer::clear() { entities.clear(); resetBorders();}/** * Counts all entities (branches of the tree). */unsigned long int RS_EntityContainer::count() { return entities.count();}/** * Counts all entities (leaves of the tree). */unsigned long int RS_EntityContainer::countDeep() { unsigned long int c=0; for (RS_Entity* t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone)) { c+=t->countDeep(); } return c;}/** * Counts the selected entities in this container. */unsigned long int RS_EntityContainer::countSelected() { unsigned long int c=0; for (RS_Entity* t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone)) { if (t->isSelected()) { c++; } } return c;}/** * Adjusts the borders of this graphic (max/min values) */void RS_EntityContainer::adjustBorders(RS_Entity* entity) { //RS_DEBUG->print("RS_EntityContainer::adjustBorders"); //resetBorders(); if (entity!=NULL) { // make sure a container is not empty (otherwise the border // would get extended to 0/0): if (!entity->isContainer() || entity->count()>0) { minV = RS_Vector::minimum(entity->getMin(),minV); maxV = RS_Vector::maximum(entity->getMax(),maxV); } // Notify parents. The border for the parent might // also change TODO: Check for efficiency //if(parent!=NULL) { //parent->adjustBorders(this); //} }}/** * Recalculates the borders of this entity container. */void RS_EntityContainer::calculateBorders() { RS_DEBUG->print("RS_EntityContainer::calculateBorders"); resetBorders(); for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) { RS_Layer* layer = e->getLayer(); RS_DEBUG->print("RS_EntityContainer::calculateBorders: " "isVisible: %d", (int)e->isVisible()); if (e->isVisible() && (layer==NULL || !layer->isFrozen())) { e->calculateBorders(); adjustBorders(e); } } RS_DEBUG->print("RS_EntityContainer::calculateBorders: size 1: %f,%f", getSize().x, getSize().y); // needed for correcting corrupt data (PLANS.dxf) if (minV.x>maxV.x || minV.x>RS_MAXDOUBLE || maxV.x>RS_MAXDOUBLE || minV.x<RS_MINDOUBLE || maxV.x<RS_MINDOUBLE) { minV.x = 0.0; maxV.x = 0.0; } if (minV.y>maxV.y || minV.y>RS_MAXDOUBLE || maxV.y>RS_MAXDOUBLE || minV.y<RS_MINDOUBLE || maxV.y<RS_MINDOUBLE) { minV.y = 0.0; maxV.y = 0.0; } RS_DEBUG->print("RS_EntityCotnainer::calculateBorders: size: %f,%f", getSize().x, getSize().y); //RS_DEBUG->print(" borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y); //printf("borders: %lf/%lf %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y); //RS_Entity::calculateBorders();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -