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 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
10 // JLH = James L. Hammons <jlhamm@acm.org>
13 // --- ---------- -----------------------------------------------------------
14 // JLH 06/01/2010 Added this text. :-)
23 * @param parent The graphic this block belongs to.
25 Insert::Insert(EntityContainer * parent, const InsertData & d):
26 EntityContainer(parent), data(d)
30 if (data.updateMode != RS2::NoUpdate)
44 /*virtual*/ Entity * Insert::clone()
46 Insert * i = new Insert(*this);
47 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
48 // i->entities.setAutoDelete(entities.autoDelete());
54 /** @return RS2::EntityInsert */
55 /*virtual*/ RS2::EntityType Insert::rtti() const
57 return RS2::EntityInsert;
60 /** @return Copy of data that defines the insert. **/
61 InsertData Insert::getData() const
67 * Reimplementation of reparent. Invalidates block cache pointer.
69 /*virtual*/ void Insert::reparent(EntityContainer * parent)
71 Entity::reparent(parent);
76 * @return Pointer to the block associated with this Insert or
77 * NULL if the block couldn't be found. Blocks are requested
78 * from the blockSource if one was supplied and otherwise from
79 * the closest parent graphic.
81 Block * Insert::getBlockForInsert()
88 if (!data.blockSource)
90 blkList = (getGraphic() ? getGraphic()->getBlockList() : NULL);
94 blkList = data.blockSource;
100 blk = blkList->find(data.name);
114 * Updates the entity buffer of this insert entity. This method
115 * needs to be called whenever the block this insert is based on changes.
117 void Insert::update()
119 DEBUG->print("Insert::update");
120 DEBUG->print("Insert::update: name: %s", data.name.toLatin1().data());
121 DEBUG->print("Insert::update: insertionPoint: %f/%f",
122 data.insertionPoint.x, data.insertionPoint.y);
128 Block * blk = getBlockForInsert();
132 DEBUG->print("Insert::update: Block is NULL");
138 DEBUG->print("Insert::update: Insert is in undo list");
142 if (fabs(data.scaleFactor.x) < 1.0e-6 || fabs(data.scaleFactor.y) < 1.0e-6)
144 DEBUG->print("Insert::update: scale factor is 0");
150 /*Q3PtrListIterator<Entity> it = createIterator();
152 while ( (e = it.current()) != NULL ) {
155 DEBUG->print("Insert::update: cols: %d, rows: %d", data.cols, data.rows);
156 DEBUG->print("Insert::update: block has %d entities", blk->count());
158 for(Entity * e=blk->firstEntity(); e!=NULL; e=blk->nextEntity())
160 for(int c=0; c<data.cols; ++c)
162 DEBUG->print("Insert::update: col %d", c);
164 for(int r=0; r<data.rows; ++r)
166 DEBUG->print("Insert::update: row %d", r);
168 if (e->rtti() == RS2::EntityInsert && data.updateMode != RS2::PreviewUpdate)
170 DEBUG->print("Insert::update: updating sub-insert");
171 ((Insert *)e)->update();
174 DEBUG->print("Insert::update: cloning entity");
176 Entity * ne = e->clone();
178 ne->setUpdateEnabled(false);
180 ne->setVisible(getFlag(RS2::FlagVisible));
182 DEBUG->print("Insert::update: transforming entity");
185 DEBUG->print("Insert::update: move 1");
186 if (fabs(data.scaleFactor.x) > 1.0e-6 && fabs(data.scaleFactor.y) > 1.0e-6)
188 ne->move(data.insertionPoint + Vector(data.spacing.x / data.scaleFactor.x * c, data.spacing.y / data.scaleFactor.y * r));
192 ne->move(data.insertionPoint);
195 // Move because of block base point:
196 DEBUG->print("Insert::update: move 2");
197 ne->move(blk->getBasePoint() * -1);
199 DEBUG->print("Insert::update: scale");
200 ne->scale(data.insertionPoint, data.scaleFactor);
202 DEBUG->print("Insert::update: rotate");
203 ne->rotate(data.insertionPoint, data.angle);
205 ne->setSelected(isSelected());
207 // individual entities can be on indiv. layers
208 tmpPen = ne->getPen(false);
210 // color from block (free floating):
211 if (tmpPen.getColor() == Color(RS2::FlagByBlock))
212 tmpPen.setColor(getPen().getColor());
214 // line width from block (free floating):
215 if (tmpPen.getWidth() == RS2::WidthByBlock)
216 tmpPen.setWidth(getPen().getWidth());
218 // line type from block (free floating):
219 if (tmpPen.getLineType() == RS2::LineByBlock)
220 tmpPen.setLineType(getPen().getLineType());
222 // now that we've evaluated all flags, let's strip them:
223 // TODO: strip all flags (width, line type)
224 //tmpPen.setColor(tmpPen.getColor().stripFlags());
228 ne->setUpdateEnabled(true);
230 if (data.updateMode != RS2::PreviewUpdate)
232 DEBUG->print("Insert::update: updating new entity");
236 DEBUG->print("Insert::update: adding new entity");
244 DEBUG->print("Insert::update: OK");
247 QString Insert::getName() const
252 void Insert::setName(const QString & newName)
258 Vector Insert::getInsertionPoint() const
260 return data.insertionPoint;
263 void Insert::setInsertionPoint(const Vector & i)
265 data.insertionPoint = i;
268 Vector Insert::getScale() const
270 return data.scaleFactor;
273 void Insert::setScale(const Vector & s)
275 data.scaleFactor = s;
278 double Insert::getAngle() const
283 void Insert::setAngle(double a)
288 int Insert::getCols() const
293 void Insert::setCols(int c)
298 int Insert::getRows() const
303 void Insert::setRows(int r)
308 Vector Insert::getSpacing() const
313 void Insert::setSpacing(const Vector & s)
319 * Is this insert visible? (re-implementation from Entity)
321 * @return true Only if the entity and the block and the layer it is on
323 * The Layer might also be NULL. In that case the layer visiblity
325 * The Block might also be NULL. In that case the block visiblity
328 bool Insert::isVisible()
330 Block * blk = getBlockForInsert();
340 return Entity::isVisible();
343 VectorSolutions Insert::getRefPoints()
345 VectorSolutions ret(data.insertionPoint);
349 Vector Insert::getNearestRef(const Vector & coord, double * dist)
351 return getRefPoints().getClosest(coord, dist);
354 void Insert::move(Vector offset)
356 DEBUG->print("Insert::move: offset: %f/%f",
358 DEBUG->print("Insert::move1: insertionPoint: %f/%f",
359 data.insertionPoint.x, data.insertionPoint.y);
360 data.insertionPoint.move(offset);
361 DEBUG->print("Insert::move2: insertionPoint: %f/%f",
362 data.insertionPoint.x, data.insertionPoint.y);
366 void Insert::rotate(Vector center, double angle)
368 DEBUG->print("Insert::rotate1: insertionPoint: %f/%f "
370 data.insertionPoint.x, data.insertionPoint.y,
372 data.insertionPoint.rotate(center, angle);
373 data.angle = Math::correctAngle(data.angle + angle);
374 DEBUG->print("Insert::rotate2: insertionPoint: %f/%f",
375 data.insertionPoint.x, data.insertionPoint.y);
379 void Insert::scale(Vector center, Vector factor)
381 DEBUG->print("Insert::scale1: insertionPoint: %f/%f",
382 data.insertionPoint.x, data.insertionPoint.y);
383 data.insertionPoint.scale(center, factor);
384 data.scaleFactor.scale(Vector(0.0, 0.0), factor);
385 data.spacing.scale(Vector(0.0, 0.0), factor);
386 DEBUG->print("Insert::scale2: insertionPoint: %f/%f",
387 data.insertionPoint.x, data.insertionPoint.y);
391 void Insert::mirror(Vector axisPoint1, Vector axisPoint2)
393 data.insertionPoint.mirror(axisPoint1, axisPoint2);
396 vec.setPolar(1.0, data.angle);
397 vec.mirror(Vector(0.0, 0.0), axisPoint2 - axisPoint1);
398 data.angle = vec.angle();
400 data.scaleFactor.y *= -1;
405 std::ostream & operator<<(std::ostream & os, const Insert & i)
407 os << " Insert: " << i.getData() << std::endl;