1 /****************************************************************************
2 ** $Id: rs_insert.cpp 2371 2005-04-29 11:44:39Z andrew $
4 ** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
6 ** This file is part of the qcadlib Library project.
8 ** This file may be distributed and/or modified under the terms of the
9 ** GNU General Public License version 2 as published by the Free Software
10 ** Foundation and appearing in the file LICENSE.GPL included in the
11 ** packaging of this file.
13 ** Licensees holding valid qcadlib Professional Edition licenses may use
14 ** this file in accordance with the qcadlib Commercial License
15 ** Agreement provided with the Software.
17 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 ** See http://www.ribbonsoft.com for further details.
22 ** Contact info@ribbonsoft.com if any conditions of this licensing are
25 **********************************************************************/
27 #include "rs_insert.h"
30 #include "rs_graphic.h"
33 * @param parent The graphic this block belongs to.
35 RS_Insert::RS_Insert(RS_EntityContainer * parent, const RS_InsertData & d):
36 RS_EntityContainer(parent), data(d)
40 if (data.updateMode != RS2::NoUpdate)
50 RS_Insert::~RS_Insert()
54 /*virtual*/ RS_Entity * RS_Insert::clone()
56 RS_Insert * i = new RS_Insert(*this);
57 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
58 // i->entities.setAutoDelete(entities.autoDelete());
64 /** @return RS2::EntityInsert */
65 /*virtual*/ RS2::EntityType RS_Insert::rtti() const
67 return RS2::EntityInsert;
70 /** @return Copy of data that defines the insert. **/
71 RS_InsertData RS_Insert::getData() const
77 * Reimplementation of reparent. Invalidates block cache pointer.
79 /*virtual*/ void RS_Insert::reparent(RS_EntityContainer * parent)
81 RS_Entity::reparent(parent);
86 * @return Pointer to the block associated with this Insert or
87 * NULL if the block couldn't be found. Blocks are requested
88 * from the blockSource if one was supplied and otherwise from
89 * the closest parent graphic.
91 RS_Block * RS_Insert::getBlockForInsert()
96 RS_BlockList * blkList;
98 if (data.blockSource == NULL)
100 if (getGraphic() != NULL)
102 blkList = getGraphic()->getBlockList();
111 blkList = data.blockSource;
114 RS_Block * blk = NULL;
118 blk = blkList->find(data.name);
131 * Updates the entity buffer of this insert entity. This method
132 * needs to be called whenever the block this insert is based on changes.
134 void RS_Insert::update()
136 RS_DEBUG->print("RS_Insert::update");
137 RS_DEBUG->print("RS_Insert::update: name: %s", data.name.toLatin1().data());
138 RS_DEBUG->print("RS_Insert::update: insertionPoint: %f/%f",
139 data.insertionPoint.x, data.insertionPoint.y);
141 if (updateEnabled == false)
146 RS_Block * blk = getBlockForInsert();
151 RS_DEBUG->print("RS_Insert::update: Block is NULL");
157 RS_DEBUG->print("RS_Insert::update: Insert is in undo list");
161 if (fabs(data.scaleFactor.x) < 1.0e-6 || fabs(data.scaleFactor.y) < 1.0e-6)
163 RS_DEBUG->print("RS_Insert::update: scale factor is 0");
169 /*Q3PtrListIterator<RS_Entity> it = createIterator();
171 while ( (e = it.current()) != NULL ) {
174 RS_DEBUG->print("RS_Insert::update: cols: %d, rows: %d", data.cols, data.rows);
175 RS_DEBUG->print("RS_Insert::update: block has %d entities", blk->count());
177 for(RS_Entity * e=blk->firstEntity(); e!=NULL; e=blk->nextEntity())
179 for(int c=0; c<data.cols; ++c)
181 RS_DEBUG->print("RS_Insert::update: col %d", c);
183 for(int r=0; r<data.rows; ++r)
185 RS_DEBUG->print("RS_Insert::update: row %d", r);
187 if (e->rtti() == RS2::EntityInsert && data.updateMode != RS2::PreviewUpdate)
189 RS_DEBUG->print("RS_Insert::update: updating sub-insert");
190 ((RS_Insert *)e)->update();
193 RS_DEBUG->print("RS_Insert::update: cloning entity");
195 RS_Entity * ne = e->clone();
197 ne->setUpdateEnabled(false);
199 ne->setVisible(getFlag(RS2::FlagVisible));
201 RS_DEBUG->print("RS_Insert::update: transforming entity");
204 RS_DEBUG->print("RS_Insert::update: move 1");
205 if (fabs(data.scaleFactor.x) > 1.0e-6 && fabs(data.scaleFactor.y) > 1.0e-6)
207 ne->move(data.insertionPoint + Vector(data.spacing.x / data.scaleFactor.x * c,
208 data.spacing.y / data.scaleFactor.y * r));
212 ne->move(data.insertionPoint);
215 // Move because of block base point:
216 RS_DEBUG->print("RS_Insert::update: move 2");
217 ne->move(blk->getBasePoint() * -1);
219 RS_DEBUG->print("RS_Insert::update: scale");
220 ne->scale(data.insertionPoint, data.scaleFactor);
222 RS_DEBUG->print("RS_Insert::update: rotate");
223 ne->rotate(data.insertionPoint, data.angle);
225 ne->setSelected(isSelected());
227 // individual entities can be on indiv. layers
228 tmpPen = ne->getPen(false);
230 // color from block (free floating):
231 if (tmpPen.getColor() == RS_Color(RS2::FlagByBlock))
232 tmpPen.setColor(getPen().getColor());
234 // line width from block (free floating):
235 if (tmpPen.getWidth() == RS2::WidthByBlock)
236 tmpPen.setWidth(getPen().getWidth());
238 // line type from block (free floating):
239 if (tmpPen.getLineType() == RS2::LineByBlock)
240 tmpPen.setLineType(getPen().getLineType());
242 // now that we've evaluated all flags, let's strip them:
243 // TODO: strip all flags (width, line type)
244 //tmpPen.setColor(tmpPen.getColor().stripFlags());
248 ne->setUpdateEnabled(true);
250 if (data.updateMode != RS2::PreviewUpdate)
252 RS_DEBUG->print("RS_Insert::update: updating new entity");
256 RS_DEBUG->print("RS_Insert::update: adding new entity");
264 RS_DEBUG->print("RS_Insert::update: OK");
267 QString RS_Insert::getName() const
272 void RS_Insert::setName(const QString & newName)
278 Vector RS_Insert::getInsertionPoint() const
280 return data.insertionPoint;
283 void RS_Insert::setInsertionPoint(const Vector & i)
285 data.insertionPoint = i;
288 Vector RS_Insert::getScale() const
290 return data.scaleFactor;
293 void RS_Insert::setScale(const Vector & s)
295 data.scaleFactor = s;
298 double RS_Insert::getAngle() const
303 void RS_Insert::setAngle(double a)
308 int RS_Insert::getCols() const
313 void RS_Insert::setCols(int c)
318 int RS_Insert::getRows() const
323 void RS_Insert::setRows(int r)
328 Vector RS_Insert::getSpacing() const
333 void RS_Insert::setSpacing(const Vector & s)
339 * Is this insert visible? (re-implementation from RS_Entity)
341 * @return true Only if the entity and the block and the layer it is on
343 * The Layer might also be NULL. In that case the layer visiblity
345 * The Block might also be NULL. In that case the block visiblity
348 bool RS_Insert::isVisible()
350 RS_Block * blk = getBlockForInsert();
360 return RS_Entity::isVisible();
363 VectorSolutions RS_Insert::getRefPoints()
365 VectorSolutions ret(data.insertionPoint);
369 Vector RS_Insert::getNearestRef(const Vector & coord, double * dist)
371 return getRefPoints().getClosest(coord, dist);
374 void RS_Insert::move(Vector offset)
376 RS_DEBUG->print("RS_Insert::move: offset: %f/%f",
378 RS_DEBUG->print("RS_Insert::move1: insertionPoint: %f/%f",
379 data.insertionPoint.x, data.insertionPoint.y);
380 data.insertionPoint.move(offset);
381 RS_DEBUG->print("RS_Insert::move2: insertionPoint: %f/%f",
382 data.insertionPoint.x, data.insertionPoint.y);
388 void RS_Insert::rotate(Vector center, double angle) {
389 RS_DEBUG->print("RS_Insert::rotate1: insertionPoint: %f/%f "
391 data.insertionPoint.x, data.insertionPoint.y,
393 data.insertionPoint.rotate(center, angle);
394 data.angle = RS_Math::correctAngle(data.angle+angle);
395 RS_DEBUG->print("RS_Insert::rotate2: insertionPoint: %f/%f",
396 data.insertionPoint.x, data.insertionPoint.y);
402 void RS_Insert::scale(Vector center, Vector factor) {
403 RS_DEBUG->print("RS_Insert::scale1: insertionPoint: %f/%f",
404 data.insertionPoint.x, data.insertionPoint.y);
405 data.insertionPoint.scale(center, factor);
406 data.scaleFactor.scale(Vector(0.0, 0.0), factor);
407 data.spacing.scale(Vector(0.0, 0.0), factor);
408 RS_DEBUG->print("RS_Insert::scale2: insertionPoint: %f/%f",
409 data.insertionPoint.x, data.insertionPoint.y);
415 void RS_Insert::mirror(Vector axisPoint1, Vector axisPoint2) {
416 data.insertionPoint.mirror(axisPoint1, axisPoint2);
419 vec.setPolar(1.0, data.angle);
420 vec.mirror(Vector(0.0,0.0), axisPoint2-axisPoint1);
421 data.angle = vec.angle();
423 data.scaleFactor.y*=-1;
429 std::ostream& operator << (std::ostream& os, const RS_Insert& i) {
430 os << " Insert: " << i.getData() << std::endl;