3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // (C) 2010 Underground Software
8 // JLH = James L. Hammons <jlhamm@acm.org>
11 // --- ---------- -----------------------------------------------------------
12 // JLH 06/01/2010 Added this text. :-)
15 #include "rs_insert.h"
21 * @param parent The graphic this block belongs to.
23 RS_Insert::RS_Insert(RS_EntityContainer * parent, const RS_InsertData & d):
24 RS_EntityContainer(parent), data(d)
28 if (data.updateMode != RS2::NoUpdate)
38 RS_Insert::~RS_Insert()
42 /*virtual*/ RS_Entity * RS_Insert::clone()
44 RS_Insert * i = new RS_Insert(*this);
45 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
46 // i->entities.setAutoDelete(entities.autoDelete());
52 /** @return RS2::EntityInsert */
53 /*virtual*/ RS2::EntityType RS_Insert::rtti() const
55 return RS2::EntityInsert;
58 /** @return Copy of data that defines the insert. **/
59 RS_InsertData RS_Insert::getData() const
65 * Reimplementation of reparent. Invalidates block cache pointer.
67 /*virtual*/ void RS_Insert::reparent(RS_EntityContainer * parent)
69 RS_Entity::reparent(parent);
74 * @return Pointer to the block associated with this Insert or
75 * NULL if the block couldn't be found. Blocks are requested
76 * from the blockSource if one was supplied and otherwise from
77 * the closest parent graphic.
79 RS_Block * RS_Insert::getBlockForInsert()
84 RS_BlockList * blkList;
86 if (data.blockSource == NULL)
88 if (getGraphic() != NULL)
90 blkList = getGraphic()->getBlockList();
99 blkList = data.blockSource;
102 RS_Block * blk = NULL;
106 blk = blkList->find(data.name);
119 * Updates the entity buffer of this insert entity. This method
120 * needs to be called whenever the block this insert is based on changes.
122 void RS_Insert::update()
124 RS_DEBUG->print("RS_Insert::update");
125 RS_DEBUG->print("RS_Insert::update: name: %s", data.name.toLatin1().data());
126 RS_DEBUG->print("RS_Insert::update: insertionPoint: %f/%f",
127 data.insertionPoint.x, data.insertionPoint.y);
129 if (updateEnabled == false)
134 RS_Block * blk = getBlockForInsert();
139 RS_DEBUG->print("RS_Insert::update: Block is NULL");
145 RS_DEBUG->print("RS_Insert::update: Insert is in undo list");
149 if (fabs(data.scaleFactor.x) < 1.0e-6 || fabs(data.scaleFactor.y) < 1.0e-6)
151 RS_DEBUG->print("RS_Insert::update: scale factor is 0");
157 /*Q3PtrListIterator<RS_Entity> it = createIterator();
159 while ( (e = it.current()) != NULL ) {
162 RS_DEBUG->print("RS_Insert::update: cols: %d, rows: %d", data.cols, data.rows);
163 RS_DEBUG->print("RS_Insert::update: block has %d entities", blk->count());
165 for(RS_Entity * e=blk->firstEntity(); e!=NULL; e=blk->nextEntity())
167 for(int c=0; c<data.cols; ++c)
169 RS_DEBUG->print("RS_Insert::update: col %d", c);
171 for(int r=0; r<data.rows; ++r)
173 RS_DEBUG->print("RS_Insert::update: row %d", r);
175 if (e->rtti() == RS2::EntityInsert && data.updateMode != RS2::PreviewUpdate)
177 RS_DEBUG->print("RS_Insert::update: updating sub-insert");
178 ((RS_Insert *)e)->update();
181 RS_DEBUG->print("RS_Insert::update: cloning entity");
183 RS_Entity * ne = e->clone();
185 ne->setUpdateEnabled(false);
187 ne->setVisible(getFlag(RS2::FlagVisible));
189 RS_DEBUG->print("RS_Insert::update: transforming entity");
192 RS_DEBUG->print("RS_Insert::update: move 1");
193 if (fabs(data.scaleFactor.x) > 1.0e-6 && fabs(data.scaleFactor.y) > 1.0e-6)
195 ne->move(data.insertionPoint + Vector(data.spacing.x / data.scaleFactor.x * c,
196 data.spacing.y / data.scaleFactor.y * r));
200 ne->move(data.insertionPoint);
203 // Move because of block base point:
204 RS_DEBUG->print("RS_Insert::update: move 2");
205 ne->move(blk->getBasePoint() * -1);
207 RS_DEBUG->print("RS_Insert::update: scale");
208 ne->scale(data.insertionPoint, data.scaleFactor);
210 RS_DEBUG->print("RS_Insert::update: rotate");
211 ne->rotate(data.insertionPoint, data.angle);
213 ne->setSelected(isSelected());
215 // individual entities can be on indiv. layers
216 tmpPen = ne->getPen(false);
218 // color from block (free floating):
219 if (tmpPen.getColor() == RS_Color(RS2::FlagByBlock))
220 tmpPen.setColor(getPen().getColor());
222 // line width from block (free floating):
223 if (tmpPen.getWidth() == RS2::WidthByBlock)
224 tmpPen.setWidth(getPen().getWidth());
226 // line type from block (free floating):
227 if (tmpPen.getLineType() == RS2::LineByBlock)
228 tmpPen.setLineType(getPen().getLineType());
230 // now that we've evaluated all flags, let's strip them:
231 // TODO: strip all flags (width, line type)
232 //tmpPen.setColor(tmpPen.getColor().stripFlags());
236 ne->setUpdateEnabled(true);
238 if (data.updateMode != RS2::PreviewUpdate)
240 RS_DEBUG->print("RS_Insert::update: updating new entity");
244 RS_DEBUG->print("RS_Insert::update: adding new entity");
252 RS_DEBUG->print("RS_Insert::update: OK");
255 QString RS_Insert::getName() const
260 void RS_Insert::setName(const QString & newName)
266 Vector RS_Insert::getInsertionPoint() const
268 return data.insertionPoint;
271 void RS_Insert::setInsertionPoint(const Vector & i)
273 data.insertionPoint = i;
276 Vector RS_Insert::getScale() const
278 return data.scaleFactor;
281 void RS_Insert::setScale(const Vector & s)
283 data.scaleFactor = s;
286 double RS_Insert::getAngle() const
291 void RS_Insert::setAngle(double a)
296 int RS_Insert::getCols() const
301 void RS_Insert::setCols(int c)
306 int RS_Insert::getRows() const
311 void RS_Insert::setRows(int r)
316 Vector RS_Insert::getSpacing() const
321 void RS_Insert::setSpacing(const Vector & s)
327 * Is this insert visible? (re-implementation from RS_Entity)
329 * @return true Only if the entity and the block and the layer it is on
331 * The Layer might also be NULL. In that case the layer visiblity
333 * The Block might also be NULL. In that case the block visiblity
336 bool RS_Insert::isVisible()
338 RS_Block * blk = getBlockForInsert();
348 return RS_Entity::isVisible();
351 VectorSolutions RS_Insert::getRefPoints()
353 VectorSolutions ret(data.insertionPoint);
357 Vector RS_Insert::getNearestRef(const Vector & coord, double * dist)
359 return getRefPoints().getClosest(coord, dist);
362 void RS_Insert::move(Vector offset)
364 RS_DEBUG->print("RS_Insert::move: offset: %f/%f",
366 RS_DEBUG->print("RS_Insert::move1: insertionPoint: %f/%f",
367 data.insertionPoint.x, data.insertionPoint.y);
368 data.insertionPoint.move(offset);
369 RS_DEBUG->print("RS_Insert::move2: insertionPoint: %f/%f",
370 data.insertionPoint.x, data.insertionPoint.y);
374 void RS_Insert::rotate(Vector center, double angle)
376 RS_DEBUG->print("RS_Insert::rotate1: insertionPoint: %f/%f "
378 data.insertionPoint.x, data.insertionPoint.y,
380 data.insertionPoint.rotate(center, angle);
381 data.angle = RS_Math::correctAngle(data.angle + angle);
382 RS_DEBUG->print("RS_Insert::rotate2: insertionPoint: %f/%f",
383 data.insertionPoint.x, data.insertionPoint.y);
387 void RS_Insert::scale(Vector center, Vector factor)
389 RS_DEBUG->print("RS_Insert::scale1: insertionPoint: %f/%f",
390 data.insertionPoint.x, data.insertionPoint.y);
391 data.insertionPoint.scale(center, factor);
392 data.scaleFactor.scale(Vector(0.0, 0.0), factor);
393 data.spacing.scale(Vector(0.0, 0.0), factor);
394 RS_DEBUG->print("RS_Insert::scale2: insertionPoint: %f/%f",
395 data.insertionPoint.x, data.insertionPoint.y);
399 void RS_Insert::mirror(Vector axisPoint1, Vector axisPoint2)
401 data.insertionPoint.mirror(axisPoint1, axisPoint2);
404 vec.setPolar(1.0, data.angle);
405 vec.mirror(Vector(0.0, 0.0), axisPoint2 - axisPoint1);
406 data.angle = vec.angle();
408 data.scaleFactor.y *= -1;
413 std::ostream & operator<<(std::ostream & os, const RS_Insert & i)
415 os << " Insert: " << i.getData() << std::endl;