1 // Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License
5 // as published by the Free Software Foundation; either version 2
6 // of the License, or (at your option) any later version.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 #include "object_factory.h"
20 #include "bogus_imp.h"
21 #include "curve_imp.h"
22 #include "intersection_types.h"
24 #include "object_drawer.h"
25 #include "object_holder.h"
26 #include "other_type.h"
27 #include "point_imp.h"
28 #include "point_type.h"
29 #include "text_type.h"
31 #include "../kig/kig_document.h"
32 #include "../kig/kig_view.h"
33 #include "../misc/calcpaths.h"
34 #include "../misc/coordinate.h"
35 #include "../misc/object_hierarchy.h"
40 ObjectHolder
* ObjectFactory::fixedPoint( const Coordinate
& c
) const
42 ObjectHolder
* o
= new ObjectHolder( fixedPointCalcer( c
) );
46 ObjectTypeCalcer
* ObjectFactory::fixedPointCalcer( const Coordinate
& c
) const
48 std::vector
<ObjectCalcer
*> args
;
49 args
.push_back( new ObjectConstCalcer( new DoubleImp( c
.x
) ) );
50 args
.push_back( new ObjectConstCalcer( new DoubleImp( c
.y
) ) );
51 ObjectTypeCalcer
* oc
= new ObjectTypeCalcer( FixedPointType::instance(), args
);
55 ObjectTypeCalcer
* ObjectFactory::cursorPointCalcer( const Coordinate
& c
) const
57 std::vector
<ObjectCalcer
*> args
;
58 args
.push_back( new ObjectConstCalcer( new DoubleImp( c
.x
) ) );
59 args
.push_back( new ObjectConstCalcer( new DoubleImp( c
.y
) ) );
60 ObjectTypeCalcer
* oc
= new ObjectTypeCalcer( CursorPointType::instance(), args
);
64 const ObjectFactory
* ObjectFactory::instance()
66 static ObjectFactory f
;
70 ObjectTypeCalcer
* ObjectFactory::sensiblePointCalcer(
71 const Coordinate
& c
, const KigDocument
& d
, const KigWidget
& w
) const
73 std::vector
<ObjectHolder
*> os
= d
.whatAmIOn( c
, w
);
76 // we can calc intersection point *olny* between two objects...
77 std::vector
<ObjectCalcer
*> args
;
78 args
.push_back( os
[0]->calcer() );
79 args
.push_back( os
[1]->calcer() );
80 // the simpliest case: two lines...
81 if ( ( os
[0]->imp()->inherits( AbstractLineImp::stype() ) ) &&
82 ( os
[1]->imp()->inherits( AbstractLineImp::stype() ) ) )
83 return new ObjectTypeCalcer( LineLineIntersectionType::instance(), args
);
84 // other cases will follow...
86 for ( std::vector
<ObjectHolder
*>::iterator i
= os
.begin(); i
!= os
.end(); ++i
)
87 if ( (*i
)->imp()->inherits( CurveImp::stype() ) )
88 return constrainedPointCalcer( (*i
)->calcer(), c
, d
);
89 return fixedPointCalcer( c
);
92 ObjectHolder
* ObjectFactory::sensiblePoint(
93 const Coordinate
& c
, const KigDocument
& d
, const KigWidget
& w
) const
95 return new ObjectHolder( sensiblePointCalcer( c
, d
, w
) );
98 ObjectTypeCalcer
* ObjectFactory::relativePointCalcer(
99 ObjectCalcer
* o
, const Coordinate
& loc
) const
101 Coordinate reference
=
102 static_cast<const ObjectImp
*>( o
->imp() )->attachPoint();
103 assert( reference
.valid() );
109 x
= loc
.x
- reference
.x
;
110 y
= loc
.y
- reference
.y
;
112 std::vector
<ObjectCalcer
*> parents
;
113 parents
.push_back( new ObjectConstCalcer( new DoubleImp( x
) ) );
114 parents
.push_back( new ObjectConstCalcer( new DoubleImp( y
) ) );
115 parents
.push_back( o
);
116 return new ObjectTypeCalcer( RelativePointType::instance(), parents
);
119 ObjectTypeCalcer
* ObjectFactory::constrainedPointCalcer(
120 ObjectCalcer
* curve
, double param
) const
122 assert( curve
->imp()->inherits( CurveImp::stype() ) );
123 std::vector
<ObjectCalcer
*> parents
;
124 parents
.push_back( new ObjectConstCalcer( new DoubleImp( param
) ) );
125 parents
.push_back( curve
);
126 return new ObjectTypeCalcer( ConstrainedPointType::instance(), parents
);
129 ObjectHolder
* ObjectFactory::constrainedPoint(
130 ObjectCalcer
* curve
, double param
) const
132 return new ObjectHolder( constrainedPointCalcer( curve
, param
) );
135 ObjectTypeCalcer
* ObjectFactory::constrainedPointCalcer(
136 ObjectCalcer
* curve
, const Coordinate
& c
, const KigDocument
& d
) const
138 assert( curve
->imp()->inherits( CurveImp::stype() ) );
139 double param
= static_cast<const CurveImp
*>( curve
->imp() )->getParam( c
, d
);
140 return constrainedPointCalcer( curve
, param
);
143 ObjectHolder
* ObjectFactory::constrainedPoint(
144 ObjectCalcer
* curve
, const Coordinate
& c
, const KigDocument
& d
) const
146 return new ObjectHolder( constrainedPointCalcer( curve
, c
, d
) );
149 ObjectTypeCalcer
* ObjectFactory::locusCalcer(
150 ObjectCalcer
* a
, ObjectCalcer
* b
) const
152 assert( dynamic_cast<const ObjectTypeCalcer
*>( a
) );
153 ObjectTypeCalcer
* constrained
= static_cast<ObjectTypeCalcer
*>( a
);
154 assert( constrained
->type()->inherits( ObjectType::ID_ConstrainedPointType
) );
155 assert( constrained
->parents().size() == 2 );
156 ObjectCalcer
* curve
= a
->parents().back();
158 const ObjectCalcer
* moving
= b
;
160 std::vector
<ObjectCalcer
*> hierparents
;
161 hierparents
.push_back( constrained
);
162 std::vector
<ObjectCalcer
*> sideOfTree
= sideOfTreePath( hierparents
, moving
);
163 std::copy( sideOfTree
.begin(), sideOfTree
.end(), std::back_inserter( hierparents
) );
165 ObjectHierarchy
hier( hierparents
, moving
);
167 std::vector
<ObjectCalcer
*> realparents( 2 + sideOfTree
.size(), 0 );
168 realparents
[0] = new ObjectConstCalcer( new HierarchyImp( hier
) );
169 realparents
[1] = curve
;
170 copy( sideOfTree
.begin(), sideOfTree
.end(), realparents
.begin() + 2 );
172 return new ObjectTypeCalcer( LocusType::instance(), realparents
);
175 ObjectHolder
* ObjectFactory::locus( ObjectCalcer
* a
, ObjectCalcer
* b
) const
177 return new ObjectHolder( locusCalcer( a
, b
) );
180 ObjectHolder
* ObjectFactory::label(
181 const QString
& s
, const Coordinate
& loc
,
182 bool needframe
, const std::vector
<ObjectCalcer
*>& parents
,
183 const KigDocument
& doc
) const
185 return new ObjectHolder( labelCalcer( s
, loc
, needframe
, parents
, doc
) );
188 ObjectTypeCalcer
* ObjectFactory::labelCalcer(
189 const QString
& s
, const Coordinate
& loc
,
190 bool needframe
, const std::vector
<ObjectCalcer
*>& parents
,
191 const KigDocument
& doc
) const
193 return attachedLabelCalcer( s
, 0, loc
, needframe
, parents
, doc
);
196 ObjectTypeCalcer
* ObjectFactory::attachedLabelCalcer(
197 const QString
& s
, ObjectCalcer
* p
,
198 const Coordinate
& loc
, bool needframe
,
199 const std::vector
<ObjectCalcer
*>& nparents
,
200 const KigDocument
& doc
) const
202 std::vector
<ObjectCalcer
*> parents
;
203 parents
.reserve( nparents
.size() + 3 );
204 parents
.push_back( new ObjectConstCalcer( new IntImp( needframe
? 1 : 0 ) ) );
207 * mp: (changes to add relative-attachment). Now an object is tested
209 * - if attachPoint() returns a valid coordinate, then we use the new method
210 * - if it is a point: 'old-style' treatment (we can change this shortly)
211 * - if it is a curve: 'old-style' treatment (we could use the new approach,
212 * which can be better/worse depending on personal taste, I think)
214 * the first condition that matches determines the behaviour.
215 * the new method works similarly to the curve case, but we generate a new
216 * RelativePointType instead of a ConstrainedPointType; this will in turn make use
217 * of the new attachPoint() method for objects.
219 * changed the preference order 2005/01/21 (now attachPoint has preference over points)
221 * NOTE: changes in the tests performed should be matched also in
222 * modes/popup.cc (addNameLabel) and in label.cc (TextLabelModeBase::mouseMoved)
225 if ( p
&& p
->imp()->attachPoint().valid() )
227 ObjectCalcer
* o
= relativePointCalcer( p
, loc
);
229 parents
.push_back( o
);
231 else if ( p
&& p
->imp()->inherits( PointImp::stype() ) )
233 parents
.push_back( p
);
235 else if ( p
&& p
->imp()->inherits( CurveImp::stype() ) )
239 param
= static_cast<const CurveImp
*>( p
->imp() )->getParam( loc
, doc
);
241 ObjectCalcer
* o
= constrainedPointCalcer( p
, param
);
243 parents
.push_back( o
);
248 parents
.push_back( new ObjectConstCalcer( new PointImp( loc
) ) );
250 parents
.push_back( new ObjectConstCalcer( new PointImp( Coordinate( 0, 0 ) ) ) );
253 parents
.push_back( new ObjectConstCalcer( new StringImp( s
) ) );
254 std::copy( nparents
.begin(), nparents
.end(), std::back_inserter( parents
) );
255 ObjectTypeCalcer
* ret
= new ObjectTypeCalcer( TextType::instance(), parents
);
260 ObjectHolder
* ObjectFactory::attachedLabel(
261 const QString
& s
, ObjectCalcer
* locationparent
,
262 const Coordinate
& loc
, bool needframe
,
263 const std::vector
<ObjectCalcer
*>& parents
,
264 const KigDocument
& doc
) const
266 return new ObjectHolder( attachedLabelCalcer( s
, locationparent
, loc
, needframe
, parents
, doc
) );
269 ObjectPropertyCalcer
* ObjectFactory::propertyObjectCalcer(
270 ObjectCalcer
* o
, const char* p
) const
272 int wp
= o
->imp()->propertiesInternalNames().findIndex( p
);
273 if ( wp
== -1 ) return 0;
274 return new ObjectPropertyCalcer( o
, wp
);
277 ObjectHolder
* ObjectFactory::propertyObject(
278 ObjectCalcer
* o
, const char* p
) const
280 return new ObjectHolder( propertyObjectCalcer( o
, p
) );
283 void ObjectFactory::redefinePoint(
284 ObjectTypeCalcer
* point
, const Coordinate
& c
,
285 KigDocument
& doc
, const KigWidget
& w
) const
287 std::vector
<ObjectHolder
*> hos
= doc
.whatAmIOn( c
, w
);
288 std::vector
<ObjectCalcer
*> os
;
289 ObjectCalcer
* (ObjectHolder::*calcmeth
)() = &ObjectHolder::calcer
;
290 std::transform( hos
.begin(), hos
.end(), std::back_inserter( os
),
291 std::mem_fun( calcmeth
) );
294 // we don't want one of our children as a parent...
295 std::set
<ObjectCalcer
*> children
= getAllChildren( point
);
296 for ( std::vector
<ObjectCalcer
*>::iterator i
= os
.begin();
298 if ( (*i
)->imp()->inherits( CurveImp::stype() ) &&
299 children
.find( *i
) == children
.end() )
307 // we want a constrained point...
308 const CurveImp
* curveimp
= static_cast<const CurveImp
*>( v
->imp() );
309 double newparam
= curveimp
->getParam( c
, doc
);
311 if ( point
->type()->inherits( ObjectType::ID_ConstrainedPointType
) )
313 // point already was constrained -> simply update the param
314 // DataObject and make sure point is on the right curve...
315 ObjectCalcer
* dataobj
= 0;
316 std::vector
<ObjectCalcer
*> parents
= point
->parents();
317 assert( parents
.size() == 2 );
318 assert ( parents
[0]->imp()->inherits( DoubleImp::stype() ) );
319 dataobj
= parents
[0];
322 parents
.push_back( dataobj
);
323 parents
.push_back( v
);
324 point
->setParents( parents
);
326 assert( dynamic_cast<ObjectConstCalcer
*>( dataobj
) );
327 static_cast<ObjectConstCalcer
*>( dataobj
)->setImp(
328 new DoubleImp( newparam
) );
332 // point used to be fixed -> add a new DataObject etc.
333 std::vector
<ObjectCalcer
*> args
;
334 args
.push_back( new ObjectConstCalcer( new DoubleImp( newparam
) ) );
336 point
->setType( ConstrainedPointType::instance() );
337 point
->setParents( args
);
343 if ( point
->type()->inherits( ObjectType::ID_ConstrainedPointType
) )
345 // point used to be constrained..
346 std::vector
<ObjectCalcer
*> a
;
347 a
.push_back( new ObjectConstCalcer( new DoubleImp( c
.x
) ) );
348 a
.push_back( new ObjectConstCalcer( new DoubleImp( c
.y
) ) );
350 point
->setType( FixedPointType::instance() );
351 point
->setParents( a
);
355 // point used to be fixed -> simply update the DataObject's
356 // we can use the point's move function for that..
357 point
->move( c
, doc
);