From 65a9f54e1051ee8ab936975e78dcb7117b265ef5 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Fri, 11 Dec 2020 21:51:45 +0900 Subject: Renaming of files in preparation for code style tools. Signed-off-by: Michele Calgaro --- kig/misc/CMakeLists.txt | 24 +- kig/misc/Makefile.am | 26 +- kig/misc/boost_intrusive_pointer.h | 256 ++++++ kig/misc/boost_intrusive_pointer.hpp | 256 ------ kig/misc/builtin_stuff.cc | 596 ------------- kig/misc/builtin_stuff.cpp | 596 +++++++++++++ kig/misc/calcpaths.cc | 303 ------- kig/misc/calcpaths.cpp | 303 +++++++ kig/misc/cubic-common.cc | 527 ----------- kig/misc/cubic-common.cpp | 527 +++++++++++ kig/misc/goniometry.cc | 137 --- kig/misc/goniometry.cpp | 137 +++ kig/misc/guiaction.cc | 367 -------- kig/misc/guiaction.cpp | 367 ++++++++ kig/misc/kigfiledialog.cc | 81 -- kig/misc/kigfiledialog.cpp | 81 ++ kig/misc/kiginputdialog.cc | 283 ------ kig/misc/kiginputdialog.cpp | 283 ++++++ kig/misc/lists.cc | 389 -------- kig/misc/lists.cpp | 389 ++++++++ kig/misc/object_constructor.cc | 609 ------------- kig/misc/object_constructor.cpp | 609 +++++++++++++ kig/misc/object_hierarchy.cc | 774 ---------------- kig/misc/object_hierarchy.cpp | 774 ++++++++++++++++ kig/misc/rect.cc | 308 ------- kig/misc/rect.cpp | 308 +++++++ kig/misc/screeninfo.cc | 92 -- kig/misc/screeninfo.cpp | 92 ++ kig/misc/special_constructors.cc | 1628 ---------------------------------- kig/misc/special_constructors.cpp | 1628 ++++++++++++++++++++++++++++++++++ 30 files changed, 6375 insertions(+), 6375 deletions(-) create mode 100644 kig/misc/boost_intrusive_pointer.h delete mode 100644 kig/misc/boost_intrusive_pointer.hpp delete mode 100644 kig/misc/builtin_stuff.cc create mode 100644 kig/misc/builtin_stuff.cpp delete mode 100644 kig/misc/calcpaths.cc create mode 100644 kig/misc/calcpaths.cpp delete mode 100644 kig/misc/cubic-common.cc create mode 100644 kig/misc/cubic-common.cpp delete mode 100644 kig/misc/goniometry.cc create mode 100644 kig/misc/goniometry.cpp delete mode 100644 kig/misc/guiaction.cc create mode 100644 kig/misc/guiaction.cpp delete mode 100644 kig/misc/kigfiledialog.cc create mode 100644 kig/misc/kigfiledialog.cpp delete mode 100644 kig/misc/kiginputdialog.cc create mode 100644 kig/misc/kiginputdialog.cpp delete mode 100644 kig/misc/lists.cc create mode 100644 kig/misc/lists.cpp delete mode 100644 kig/misc/object_constructor.cc create mode 100644 kig/misc/object_constructor.cpp delete mode 100644 kig/misc/object_hierarchy.cc create mode 100644 kig/misc/object_hierarchy.cpp delete mode 100644 kig/misc/rect.cc create mode 100644 kig/misc/rect.cpp delete mode 100644 kig/misc/screeninfo.cc create mode 100644 kig/misc/screeninfo.cpp delete mode 100644 kig/misc/special_constructors.cc create mode 100644 kig/misc/special_constructors.cpp (limited to 'kig/misc') diff --git a/kig/misc/CMakeLists.txt b/kig/misc/CMakeLists.txt index 57449131..3d9b9852 100644 --- a/kig/misc/CMakeLists.txt +++ b/kig/misc/CMakeLists.txt @@ -18,23 +18,23 @@ tde_add_library( kigmisc STATIC_PIC AUTOMOC SOURCES argsparser.cpp - builtin_stuff.cc - calcpaths.cc + builtin_stuff.cpp + calcpaths.cpp common.cpp conic-common.cpp coordinate.cpp coordinate_system.cpp - cubic-common.cc - goniometry.cc - guiaction.cc - kigfiledialog.cc - kiginputdialog.cc + cubic-common.cpp + goniometry.cpp + guiaction.cpp + kigfiledialog.cpp + kiginputdialog.cpp kignumerics.cpp kigpainter.cpp kigtransform.cpp - lists.cc - object_constructor.cc - object_hierarchy.cc - rect.cc screeninfo.cc - special_constructors.cc + lists.cpp + object_constructor.cpp + object_hierarchy.cpp + rect.cpp screeninfo.cpp + special_constructors.cpp ) diff --git a/kig/misc/Makefile.am b/kig/misc/Makefile.am index d97d7989..be1bb571 100644 --- a/kig/misc/Makefile.am +++ b/kig/misc/Makefile.am @@ -25,26 +25,26 @@ noinst_HEADERS = \ libmisc_la_SOURCES = \ argsparser.cpp \ - builtin_stuff.cc \ - calcpaths.cc \ + builtin_stuff.cpp \ + calcpaths.cpp \ common.cpp \ conic-common.cpp \ coordinate.cpp \ coordinate_system.cpp \ - cubic-common.cc \ - goniometry.cc \ - guiaction.cc \ - kigfiledialog.cc \ - kiginputdialog.cc \ + cubic-common.cpp \ + goniometry.cpp \ + guiaction.cpp \ + kigfiledialog.cpp \ + kiginputdialog.cpp \ kignumerics.cpp \ kigpainter.cpp \ kigtransform.cpp \ - lists.cc \ - object_constructor.cc \ - object_hierarchy.cc \ - rect.cc \ - screeninfo.cc \ - special_constructors.cc + lists.cpp \ + object_constructor.cpp \ + object_hierarchy.cpp \ + rect.cpp \ + screeninfo.cpp \ + special_constructors.cpp libmisc_la_LIBADD=-lm METASOURCES=AUTO diff --git a/kig/misc/boost_intrusive_pointer.h b/kig/misc/boost_intrusive_pointer.h new file mode 100644 index 00000000..1dd2dd81 --- /dev/null +++ b/kig/misc/boost_intrusive_pointer.h @@ -0,0 +1,256 @@ +// Copyright (C) 2003 Dominique Devriese + +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + + + +// This code comes from the boost::intrusive_ptr. I adapted it to +// suit my needs ( no dependencies on other boost libs, change the +// namespace to avoid conflicts, + +#ifndef MYBOOST_INTRUSIVE_PTR_H_INCLUDED +#define MYBOOST_INTRUSIVE_PTR_H_INCLUDED + +// +// intrusive_ptr.h +// +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation. +// + +#include // for std::less +#include // for std::basic_ostream + + +namespace myboost +{ + +// +// intrusive_ptr +// +// A smart pointer that uses intrusive reference counting. +// +// Relies on unqualified calls to +// +// void intrusive_ptr_add_ref(T * p); +// void intrusive_ptr_release(T * p); +// +// (p != 0) +// +// The object is responsible for destroying itself. +// + +template class intrusive_ptr +{ +private: + + typedef intrusive_ptr this_type; + +public: + + typedef T element_type; + + intrusive_ptr(): p_(0) + { + } + + intrusive_ptr(T * p, bool add_ref = true): p_(p) + { + if(p_ != 0 && add_ref) intrusive_ptr_add_ref(p_); + } + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) + + template intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.get()) + { + if(p_ != 0) intrusive_ptr_add_ref(p_); + } + +#endif + + intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_) + { + if(p_ != 0) intrusive_ptr_add_ref(p_); + } + + ~intrusive_ptr() + { + if(p_ != 0) intrusive_ptr_release(p_); + } + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) + + template intrusive_ptr & operator=(intrusive_ptr const & rhs) + { + this_type(rhs).swap(*this); + return *this; + } + +#endif + + intrusive_ptr & operator=(intrusive_ptr const & rhs) + { + this_type(rhs).swap(*this); + return *this; + } + + intrusive_ptr & operator=(T * rhs) + { + this_type(rhs).swap(*this); + return *this; + } + + T * get() const + { + return p_; + } + + T & operator*() const + { + return *p_; + } + + T * operator->() const + { + return p_; + } + + typedef T * (intrusive_ptr::*unspecified_bool_type) () const; + + operator unspecified_bool_type () const + { + return p_ == 0? 0: &intrusive_ptr::get; + } + + // operator! is a Borland-specific workaround + bool operator! () const + { + return p_ == 0; + } + + void swap(intrusive_ptr & rhs) + { + T * tmp = p_; + p_ = rhs.p_; + rhs.p_ = tmp; + } + +private: + + T * p_; +}; + +template inline bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator==(intrusive_ptr const & a, T * b) +{ + return a.get() == b; +} + +template inline bool operator!=(intrusive_ptr const & a, T * b) +{ + return a.get() != b; +} + +template inline bool operator==(T * a, intrusive_ptr const & b) +{ + return a == b.get(); +} + +template inline bool operator!=(T * a, intrusive_ptr const & b) +{ + return a != b.get(); +} + +#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 + +// Resolve the ambiguity between our op!= and the one in rel_ops + +template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() != b.get(); +} + +#endif + +template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return std::less()(a.get(), b.get()); +} + +template void swap(intrusive_ptr & lhs, intrusive_ptr & rhs) +{ + lhs.swap(rhs); +} + +// mem_fn support + +template T * get_pointer(intrusive_ptr const & p) +{ + return p.get(); +} + +template intrusive_ptr static_pointer_cast(intrusive_ptr const & p) +{ + return static_cast(p.get()); +} + +template intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & p) +{ + return dynamic_cast(p.get()); +} + +// operator<< + +#if defined(__GNUC__) && (__GNUC__ < 3) + +template std::ostream & operator<< (std::ostream & os, intrusive_ptr const & p) +{ + os << p.get(); + return os; +} + +#else + +template std::basic_ostream & operator<< (std::basic_ostream & os, intrusive_ptr const & p) +{ + os << p.get(); + return os; +} + +#endif + +} // namespace myboost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #ifndef MYBOOST_INTRUSIVE_PTR_H_INCLUDED diff --git a/kig/misc/boost_intrusive_pointer.hpp b/kig/misc/boost_intrusive_pointer.hpp deleted file mode 100644 index a278e736..00000000 --- a/kig/misc/boost_intrusive_pointer.hpp +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright (C) 2003 Dominique Devriese - -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -// 02110-1301, USA. - - - -// This code comes from the boost::intrusive_ptr. I adapted it to -// suit my needs ( no dependencies on other boost libs, change the -// namespace to avoid conflicts, - -#ifndef MYBOOST_INTRUSIVE_PTR_HPP_INCLUDED -#define MYBOOST_INTRUSIVE_PTR_HPP_INCLUDED - -// -// intrusive_ptr.hpp -// -// Copyright (c) 2001, 2002 Peter Dimov -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation. -// - -#include // for std::less -#include // for std::basic_ostream - - -namespace myboost -{ - -// -// intrusive_ptr -// -// A smart pointer that uses intrusive reference counting. -// -// Relies on unqualified calls to -// -// void intrusive_ptr_add_ref(T * p); -// void intrusive_ptr_release(T * p); -// -// (p != 0) -// -// The object is responsible for destroying itself. -// - -template class intrusive_ptr -{ -private: - - typedef intrusive_ptr this_type; - -public: - - typedef T element_type; - - intrusive_ptr(): p_(0) - { - } - - intrusive_ptr(T * p, bool add_ref = true): p_(p) - { - if(p_ != 0 && add_ref) intrusive_ptr_add_ref(p_); - } - -#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) - - template intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.get()) - { - if(p_ != 0) intrusive_ptr_add_ref(p_); - } - -#endif - - intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_) - { - if(p_ != 0) intrusive_ptr_add_ref(p_); - } - - ~intrusive_ptr() - { - if(p_ != 0) intrusive_ptr_release(p_); - } - -#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) - - template intrusive_ptr & operator=(intrusive_ptr const & rhs) - { - this_type(rhs).swap(*this); - return *this; - } - -#endif - - intrusive_ptr & operator=(intrusive_ptr const & rhs) - { - this_type(rhs).swap(*this); - return *this; - } - - intrusive_ptr & operator=(T * rhs) - { - this_type(rhs).swap(*this); - return *this; - } - - T * get() const - { - return p_; - } - - T & operator*() const - { - return *p_; - } - - T * operator->() const - { - return p_; - } - - typedef T * (intrusive_ptr::*unspecified_bool_type) () const; - - operator unspecified_bool_type () const - { - return p_ == 0? 0: &intrusive_ptr::get; - } - - // operator! is a Borland-specific workaround - bool operator! () const - { - return p_ == 0; - } - - void swap(intrusive_ptr & rhs) - { - T * tmp = p_; - p_ = rhs.p_; - rhs.p_ = tmp; - } - -private: - - T * p_; -}; - -template inline bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) -{ - return a.get() == b.get(); -} - -template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) -{ - return a.get() != b.get(); -} - -template inline bool operator==(intrusive_ptr const & a, T * b) -{ - return a.get() == b; -} - -template inline bool operator!=(intrusive_ptr const & a, T * b) -{ - return a.get() != b; -} - -template inline bool operator==(T * a, intrusive_ptr const & b) -{ - return a == b.get(); -} - -template inline bool operator!=(T * a, intrusive_ptr const & b) -{ - return a != b.get(); -} - -#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 - -// Resolve the ambiguity between our op!= and the one in rel_ops - -template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) -{ - return a.get() != b.get(); -} - -#endif - -template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) -{ - return std::less()(a.get(), b.get()); -} - -template void swap(intrusive_ptr & lhs, intrusive_ptr & rhs) -{ - lhs.swap(rhs); -} - -// mem_fn support - -template T * get_pointer(intrusive_ptr const & p) -{ - return p.get(); -} - -template intrusive_ptr static_pointer_cast(intrusive_ptr const & p) -{ - return static_cast(p.get()); -} - -template intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & p) -{ - return dynamic_cast(p.get()); -} - -// operator<< - -#if defined(__GNUC__) && (__GNUC__ < 3) - -template std::ostream & operator<< (std::ostream & os, intrusive_ptr const & p) -{ - os << p.get(); - return os; -} - -#else - -template std::basic_ostream & operator<< (std::basic_ostream & os, intrusive_ptr const & p) -{ - os << p.get(); - return os; -} - -#endif - -} // namespace myboost - -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif - -#endif // #ifndef MYBOOST_INTRUSIVE_PTR_HPP_INCLUDED diff --git a/kig/misc/builtin_stuff.cc b/kig/misc/builtin_stuff.cc deleted file mode 100644 index d42ef8ad..00000000 --- a/kig/misc/builtin_stuff.cc +++ /dev/null @@ -1,596 +0,0 @@ -// Copyright (C) 2003 Dominique Devriese - -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -// 02110-1301, USA. - -#include "builtin_stuff.h" - -#include - -#include "object_constructor.h" -#include "lists.h" -#include "special_constructors.h" -#include "guiaction.h" - -#include "../objects/angle_type.h" -#include "../objects/arc_type.h" -#include "../objects/circle_type.h" -#include "../objects/conic_types.h" -#include "../objects/cubic_type.h" -#include "../objects/intersection_types.h" -#include "../objects/inversion_type.h" -#include "../objects/line_imp.h" -#include "../objects/line_type.h" -#include "../objects/object_imp.h" -#include "../objects/other_imp.h" -#include "../objects/other_type.h" -#include "../objects/point_type.h" -#include "../objects/tests_type.h" -#include "../objects/transform_types.h" -#include "../objects/vector_type.h" -#include "../objects/polygon_type.h" - -#include - -void setupBuiltinStuff() -{ - static bool done = false; - if ( ! done ) - { - ObjectConstructorList* ctors = ObjectConstructorList::instance(); - GUIActionList* actions = GUIActionList::instance(); - ObjectConstructor* c = 0; - - // segment... - c = new SimpleObjectTypeConstructor( - SegmentABType::instance(), I18N_NOOP( "Segment" ), - I18N_NOOP( "A segment constructed from its start and end point" ), - "segment" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_segment", TQt::Key_S ) ); - - // line by two points.. - c = new SimpleObjectTypeConstructor( - LineABType::instance(), I18N_NOOP( "Line by Two Points" ), - I18N_NOOP( "A line constructed through two points"), "line" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_linettp", TQt::Key_L ) ); - - // ray by two points.. - c = new SimpleObjectTypeConstructor( - RayABType::instance(), I18N_NOOP( "Half-Line" ), - I18N_NOOP( "A half-line by its start point, and another point somewhere on it." ), - "ray" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_ray", TQt::Key_R ) ); - - // perpendicular line - c = new SimpleObjectTypeConstructor( - LinePerpendLPType::instance(), I18N_NOOP( "Perpendicular" ), - I18N_NOOP( "A line constructed through a point, perpendicular to another line or segment." ), - "perpendicular" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_lineperpend" ) ); - - // parallel line - c = new SimpleObjectTypeConstructor( - LineParallelLPType::instance(), I18N_NOOP( "Parallel" ), - I18N_NOOP( "A line constructed through a point, and parallel to another line or segment" ), - "parallel" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_lineparallel" ) ); - - // circle - c = new SimpleObjectTypeConstructor( - CircleBCPType::instance(), I18N_NOOP( "Circle by Center && Point" ), - I18N_NOOP( "A circle constructed by its center and a point that pertains to it" ), - "circlebcp" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_circlebcp", TQt::Key_C ) ); - - c = new SimpleObjectTypeConstructor( - CircleBTPType::instance(), I18N_NOOP( "Circle by Three Points" ), - I18N_NOOP( "A circle constructed through three points" ), - "circlebtp" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_circlebtp" ) ); - - // declare this object static to this function, so it gets deleted - // at the end of the program, without us having to wonder about - // deleting it.. We don't want to register this - // object-constructor, because that way, "construct the bisector" - // would appear twice in the angle popup menu: once as the generic - // construct a property stuff, and once because of this ctor.. - // we only register the guiaction, cause it makes sense to have a - // toolbar icon for this.. - static PropertyObjectConstructor anglebisectionctor( - AngleImp::stype(), - I18N_NOOP( "Construct Bisector of This Angle" ), - I18N_NOOP( "Select the angle you want to construct the bisector of..." ), - I18N_NOOP( "Angle Bisector" ), - I18N_NOOP( "The bisector of an angle" ), - "angle_bisector", - "angle-bisector" ); - actions->add( new ConstructibleAction( &anglebisectionctor, "objects_new_angle_bisector" ) ); - - // conic stuff - c = new SimpleObjectTypeConstructor( - ConicB5PType::instance(), I18N_NOOP( "Conic by Five Points" ), - I18N_NOOP( "A conic constructed through five points" ), - "conicb5p" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_conicb5p" ) ); - - c = new SimpleObjectTypeConstructor( - ConicBAAPType::instance(), - I18N_NOOP( "Hyperbola by Asymptotes && Point" ), - I18N_NOOP( "A hyperbola with given asymptotes through a point" ), - "conicbaap" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_conicbaap" ) ); - - c = new SimpleObjectTypeConstructor( - EllipseBFFPType::instance(), - I18N_NOOP( "Ellipse by Focuses && Point" ), // focuses is used in preference to foci - I18N_NOOP( "An ellipse constructed by its focuses and a point that pertains to it" ), - "ellipsebffp" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_ellipsebffp" ) ); - - c = new SimpleObjectTypeConstructor( - HyperbolaBFFPType::instance(), - I18N_NOOP( "Hyperbola by Focuses && Point" ), // focuses is used in preference to foci - I18N_NOOP( "A hyperbola constructed by its focuses and a point that pertains to it" ), - "hyperbolabffp" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_hyperbolabffp" ) ); - - c = new SimpleObjectTypeConstructor( - ConicBDFPType::instance(), - I18N_NOOP( "Conic by Directrix, Focus && Point" ), - I18N_NOOP( "A conic with given directrix and focus, through a point" ), - "conicbdfp" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_conicbdfp" ) ); - - c = new SimpleObjectTypeConstructor( - ParabolaBTPType::instance(), - I18N_NOOP( "Vertical Parabola by Three Points" ), - I18N_NOOP( "A vertical parabola constructed through three points" ), - "parabolabtp" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_parabolabtp" ) ); - - c = new SimpleObjectTypeConstructor( - CubicB9PType::instance(), - I18N_NOOP( "Cubic Curve by Nine Points" ), - I18N_NOOP( "A cubic curve constructed through nine points" ), - "cubicb9p" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_cubicb9p" ) ); - - c = new SimpleObjectTypeConstructor( - ConicPolarPointType::instance(), - I18N_NOOP( "Polar Point of a Line" ), - I18N_NOOP( "The polar point of a line with respect to a conic." ), - "polarpoint" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_pointpolar" ) ); - - c = new SimpleObjectTypeConstructor( - ConicPolarLineType::instance(), - I18N_NOOP( "Polar Line of a Point" ), - I18N_NOOP( "The polar line of a point with respect to a conic." ), - "polarline" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_linepolar" ) ); - - c = new SimpleObjectTypeConstructor( - CubicNodeB6PType::instance(), - I18N_NOOP( "Cubic Curve with Node by Six Points" ), - I18N_NOOP( "A cubic curve with a nodal point at the origin through six points" ), - "cubicnodeb6p" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_cubicnodeb6p" ) ); - - c = new SimpleObjectTypeConstructor( - CubicCuspB4PType::instance(), - I18N_NOOP( "Cubic Curve with Cusp by Four Points" ), - I18N_NOOP( "A cubic curve with a horizontal cusp at the origin through four points" ), - "cubiccuspb4p" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_cubiccuspb4p" ) ); - - c = new SimpleObjectTypeConstructor( - ConicDirectrixType::instance(), - I18N_NOOP( "Directrix of a Conic" ), - I18N_NOOP( "The directrix line of a conic." ), - "directrix" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_linedirectrix" ) ); - - c = new SimpleObjectTypeConstructor( - AngleType::instance(), - I18N_NOOP( "Angle by Three Points" ), - I18N_NOOP( "An angle defined by three points" ), - "angle" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_angle", TQt::Key_A ) ); - - c = new SimpleObjectTypeConstructor( - EquilateralHyperbolaB4PType::instance(), - I18N_NOOP( "Equilateral Hyperbola by Four Points" ), - I18N_NOOP( "An equilateral hyperbola constructed through four points" ), - "equilateralhyperbolab4p" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_equilateralhyperbolab4p" ) ); - - { - // now for the Mid Point action. It does both the mid point of - // a segment, and the mid point of two points. The midpoint of - // two segments just shows the mid point property, and therefore - // doesn't need to be added to the ctors, because there are - // already facilities to construct an object's properties.. - // therefore, we add only an mpotp to the ctors, and add the - // merged constructor only to the actions.. - ctors->add( new MidPointOfTwoPointsConstructor() ); - - ObjectConstructor* mpotp = new MidPointOfTwoPointsConstructor(); - ObjectConstructor* mpos = new PropertyObjectConstructor( - SegmentImp::stype(), I18N_NOOP( "Construct the midpoint of this segment" ), - "", "", "", "", "mid-point" ); - - // make this a static object, so it gets deleted at the end of - // the program. - static MergeObjectConstructor m( - I18N_NOOP( "Mid Point" ), - I18N_NOOP( "The midpoint of a segment or two other points" ), - "bisection" ); - m.merge( mpotp ); - m.merge( mpos ); - actions->add( new ConstructibleAction( &m, "objects_new_midpoint", TQt::Key_M ) ); - }; - - c = new SimpleObjectTypeConstructor( - VectorType::instance(), - I18N_NOOP( "Vector" ), - I18N_NOOP( "Construct a vector from two given points." ), - "vector" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_vector", TQt::Key_V ) ); - - c = new SimpleObjectTypeConstructor( - VectorSumType::instance(), - I18N_NOOP( "Vector Sum" ), - I18N_NOOP( "Construct the vector sum of two vectors." ), - "vectorsum" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_vectorsum", 0 ) ); - - c = new SimpleObjectTypeConstructor( - LineByVectorType::instance(), - I18N_NOOP( "Line by Vector" ), - I18N_NOOP( "Construct the line by a given vector though a given point." ), - "linebyvector" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_linebyvector", 0 ) ); - - c = new SimpleObjectTypeConstructor( - HalflineByVectorType::instance(), - I18N_NOOP( "Half-Line by Vector" ), - I18N_NOOP( "Construct the half-line by a given vector starting at given point." ), - "halflinebyvector" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_halflinebyvector", 0 ) ); - - c = new SimpleObjectTypeConstructor( - ArcBTPType::instance(), - I18N_NOOP( "Arc by Three Points" ), - I18N_NOOP( "Construct an arc through three points." ), - "arc" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_arcbtp" ) ); - - c = new SimpleObjectTypeConstructor( - ArcBCPAType::instance(), - I18N_NOOP( "Arc by Center, Angle && Point" ), - I18N_NOOP( "Construct an arc by its center and a given angle, " - "starting at a given point" ), - "arcbcpa" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_arcbcpa" ) ); - - c = new SimpleObjectTypeConstructor( - ParabolaBDPType::instance(), - I18N_NOOP( "Parabola by Directrix && Focus" ), - I18N_NOOP( "A parabola defined by its directrix and focus" ), - "parabolabdp" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_parabolabdp" ) ); - - // Transformation stuff.. - c = new InversionConstructor(); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_inversion" ) ); - - c = new SimpleObjectTypeConstructor( - TranslatedType::instance(), - I18N_NOOP( "Translate" ), - I18N_NOOP( "The translation of an object by a vector" ), - "translation" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_translation" ) ); - - c = new SimpleObjectTypeConstructor( - PointReflectionType::instance(), - I18N_NOOP( "Reflect in Point" ), - I18N_NOOP( "An object reflected in a point" ), - "centralsymmetry" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_pointreflection" ) ); - - c = new SimpleObjectTypeConstructor( - LineReflectionType::instance(), - I18N_NOOP( "Reflect in Line" ), - I18N_NOOP( "An object reflected in a line" ), - "mirrorpoint" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_linereflection" ) ); - - c = new SimpleObjectTypeConstructor( - RotationType::instance(), - I18N_NOOP( "Rotate" ), - I18N_NOOP( "An object rotated by an angle around a point" ), - "rotation" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_rotation" ) ); - - c = new SimpleObjectTypeConstructor( - ScalingOverCenterType::instance(), - I18N_NOOP( "Scale" ), - I18N_NOOP( "Scale an object over a point, by the ratio given by the length of a segment" ), - "scale" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_scalingovercenter" ) ); - - c = new SimpleObjectTypeConstructor( - ScalingOverLineType::instance(), - I18N_NOOP( "Scale over Line" ), - I18N_NOOP( "An object scaled over a line, by the ratio given by the length of a segment" ), - "stretch" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_scalingoverline" ) ); - - c = new SimpleObjectTypeConstructor( - ScalingOverCenter2Type::instance(), - I18N_NOOP( "Scale (ratio given by two segments)" ), - I18N_NOOP( "Scale an object over a point, by the ratio given by the length of two segments" ), - "scale" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_scalingovercenter2" ) ); - - c = new SimpleObjectTypeConstructor( - ScalingOverLine2Type::instance(), - I18N_NOOP( "Scale over Line (ratio given by two segments)" ), - I18N_NOOP( "An object scaled over a line, by the ratio given by the length of two segments" ), - "stretch" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_scalingoverline2" ) ); - - c = new SimpleObjectTypeConstructor( - SimilitudeType::instance(), - I18N_NOOP( "Apply Similitude" ), - I18N_NOOP( "Apply a similitude to an object ( the sequence of a scaling and rotation around a center )" ), - "similitude" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_similitude" ) ); - - c = new SimpleObjectTypeConstructor( - HarmonicHomologyType::instance(), - I18N_NOOP( "Harmonic Homology" ), - I18N_NOOP( "The harmonic homology with a given center and a given axis (this is a projective transformation)" ), - "harmonichomology" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_harmonichomology" ) ); - - c = new GenericAffinityConstructor(); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_genericaffinity" ) ); - - c = new GenericProjectivityConstructor(); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_genericprojectivity" ) ); - - c = new SimpleObjectTypeConstructor( - CastShadowType::instance(), - I18N_NOOP( "Draw Projective Shadow" ), - I18N_NOOP( "The shadow of an object with a given light source and projection plane (indicated by a line)" ), - "castshadow" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_castshadow" ) ); - -// c = new SimpleObjectTypeConstructor( -// ProjectiveRotationType::instance(), -// I18N_NOOP( "Rotate Projectively" ), -// I18N_NOOP( "An object projectively rotated by an angle and a half-line" ), -// "projectiverotation" ); -// ctors->add( c ); -// actions->add( new ConstructibleAction( c, "objects_new_projectiverotation" ) ); - - c = new MultiObjectTypeConstructor( - ConicAsymptoteType::instance(), - I18N_NOOP( "Asymptotes of a Hyperbola" ), - I18N_NOOP( "The two asymptotes of a hyperbola." ), - "conicasymptotes", -1, 1 ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_lineconicasymptotes" ) ); - - c = new ConicRadicalConstructor(); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_lineconicradical") ); - - /* ----------- start polygons --------- */ - - c = new SimpleObjectTypeConstructor( - TriangleB3PType::instance(), - I18N_NOOP( "Triangle by Its Vertices" ), - I18N_NOOP( "Construct a triangle given its three vertices." ), - "triangle" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_trianglebtp" ) ); - - c = new PolygonBNPTypeConstructor(); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_polygonbnp" )); - - c = new PolygonBCVConstructor(); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_polygonbcv" ) ); - - c = new PolygonVertexTypeConstructor(); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_polygonvertices" )); - - c = new PolygonSideTypeConstructor(); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_polygonsides" )); - - c = new SimpleObjectTypeConstructor( - ConvexHullType::instance(), I18N_NOOP( "Convex Hull" ), - I18N_NOOP( "A polygon that corresponds to the convex hull of another polygon" ), - "convexhull" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_convexhull" ) ); - - /* ----------- end polygons --------- */ - - c = new LocusConstructor(); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_locus" ) ); - - // tests - c = new TestConstructor( - AreParallelType::instance(), - I18N_NOOP( "Parallel Test" ), - I18N_NOOP( "Test whether two given lines are parallel" ), - "testparallel" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_areparallel" ) ); - - c = new TestConstructor( - AreOrthogonalType::instance(), - I18N_NOOP( "Orthogonal Test" ), - I18N_NOOP( "Test whether two given lines are orthogonal" ), - "testorthogonal" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_areorthogonal" ) ); - - c = new TestConstructor( - AreCollinearType::instance(), - I18N_NOOP( "Collinear Test" ), - I18N_NOOP( "Test whether three given points are collinear" ), - "testcollinear" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_arecollinear" ) ); - - c = new TestConstructor( - ContainsTestType::instance(), - I18N_NOOP( "Contains Test" ), - I18N_NOOP( "Test whether a given curve contains a given point" ), - "testcontains" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_containstest" ) ); - - c = new TestConstructor( - InPolygonTestType::instance(), - I18N_NOOP( "In Polygon Test" ), - I18N_NOOP( "Test whether a given polygon contains a given point" ), - "test" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_inpolygontest" ) ); - - c = new TestConstructor( - ConvexPolygonTestType::instance(), - I18N_NOOP( "Convex Polygon Test" ), - I18N_NOOP( "Test whether a given polygon is convex" ), - "test" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_convexpolygontest" ) ); - - c = new TestConstructor( - SameDistanceType::instance(), - I18N_NOOP( "Distance Test" ), - I18N_NOOP( "Test whether a given point have the same distance from a given point " - "and from another given point" ), - "testdistance" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_distancetest" ) ); - - c = new TestConstructor( - VectorEqualityTestType::instance(), - I18N_NOOP( "Vector Equality Test" ), - I18N_NOOP( "Test whether two vectors are equal" ), - "test" ); -// "testequal" ); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_vectorequalitytest" ) ); - - c = new MeasureTransportConstructor(); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_measuretransport" )); - -// c = new SimpleObjectTypeConstructor( -// MeasureTransportType::instance(), -// I18N_NOOP( "Measure Transport" ), -// I18N_NOOP( "Transport the measure of a segment or arc over a line or circle." ), -// "measuretransport" ); -// ctors->add( c ); -// actions->add( new ConstructibleAction( c, "objects_new_measuretransport" ) ); - - // the generic intersection constructor.. - c = new GenericIntersectionConstructor(); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_intersection", TQt::Key_I ) ); - - // the generic tangent constructor - c = new TangentConstructor(); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_tangent", TQt::Key_T ) ); - - // the generic center of curvature constructor - c = new CocConstructor(); - ctors->add( c ); - actions->add( new ConstructibleAction( c, "objects_new_centerofcurvature" ) ); - - actions->add( new ConstructPointAction( "objects_new_normalpoint" ) ); - actions->add( new ConstructTextLabelAction( "objects_new_textlabel" ) ); - actions->add( new AddFixedPointAction( "objects_new_point_xy" ) ); - -#ifdef KIG_ENABLE_PYTHON_SCRIPTING -#include "../scripting/script-common.h" - actions->add( new NewScriptAction( - I18N_NOOP( "Python Script" ), - I18N_NOOP( "Construct a new Python script." ), - "objects_new_script_python", - ScriptType::Python ) ); -#endif - -#if 0 - actions->add( new TestAction( "test_stuff" ) ); -#endif - }; - - done = true; -} diff --git a/kig/misc/builtin_stuff.cpp b/kig/misc/builtin_stuff.cpp new file mode 100644 index 00000000..d42ef8ad --- /dev/null +++ b/kig/misc/builtin_stuff.cpp @@ -0,0 +1,596 @@ +// Copyright (C) 2003 Dominique Devriese + +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#include "builtin_stuff.h" + +#include + +#include "object_constructor.h" +#include "lists.h" +#include "special_constructors.h" +#include "guiaction.h" + +#include "../objects/angle_type.h" +#include "../objects/arc_type.h" +#include "../objects/circle_type.h" +#include "../objects/conic_types.h" +#include "../objects/cubic_type.h" +#include "../objects/intersection_types.h" +#include "../objects/inversion_type.h" +#include "../objects/line_imp.h" +#include "../objects/line_type.h" +#include "../objects/object_imp.h" +#include "../objects/other_imp.h" +#include "../objects/other_type.h" +#include "../objects/point_type.h" +#include "../objects/tests_type.h" +#include "../objects/transform_types.h" +#include "../objects/vector_type.h" +#include "../objects/polygon_type.h" + +#include + +void setupBuiltinStuff() +{ + static bool done = false; + if ( ! done ) + { + ObjectConstructorList* ctors = ObjectConstructorList::instance(); + GUIActionList* actions = GUIActionList::instance(); + ObjectConstructor* c = 0; + + // segment... + c = new SimpleObjectTypeConstructor( + SegmentABType::instance(), I18N_NOOP( "Segment" ), + I18N_NOOP( "A segment constructed from its start and end point" ), + "segment" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_segment", TQt::Key_S ) ); + + // line by two points.. + c = new SimpleObjectTypeConstructor( + LineABType::instance(), I18N_NOOP( "Line by Two Points" ), + I18N_NOOP( "A line constructed through two points"), "line" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_linettp", TQt::Key_L ) ); + + // ray by two points.. + c = new SimpleObjectTypeConstructor( + RayABType::instance(), I18N_NOOP( "Half-Line" ), + I18N_NOOP( "A half-line by its start point, and another point somewhere on it." ), + "ray" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_ray", TQt::Key_R ) ); + + // perpendicular line + c = new SimpleObjectTypeConstructor( + LinePerpendLPType::instance(), I18N_NOOP( "Perpendicular" ), + I18N_NOOP( "A line constructed through a point, perpendicular to another line or segment." ), + "perpendicular" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_lineperpend" ) ); + + // parallel line + c = new SimpleObjectTypeConstructor( + LineParallelLPType::instance(), I18N_NOOP( "Parallel" ), + I18N_NOOP( "A line constructed through a point, and parallel to another line or segment" ), + "parallel" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_lineparallel" ) ); + + // circle + c = new SimpleObjectTypeConstructor( + CircleBCPType::instance(), I18N_NOOP( "Circle by Center && Point" ), + I18N_NOOP( "A circle constructed by its center and a point that pertains to it" ), + "circlebcp" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_circlebcp", TQt::Key_C ) ); + + c = new SimpleObjectTypeConstructor( + CircleBTPType::instance(), I18N_NOOP( "Circle by Three Points" ), + I18N_NOOP( "A circle constructed through three points" ), + "circlebtp" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_circlebtp" ) ); + + // declare this object static to this function, so it gets deleted + // at the end of the program, without us having to wonder about + // deleting it.. We don't want to register this + // object-constructor, because that way, "construct the bisector" + // would appear twice in the angle popup menu: once as the generic + // construct a property stuff, and once because of this ctor.. + // we only register the guiaction, cause it makes sense to have a + // toolbar icon for this.. + static PropertyObjectConstructor anglebisectionctor( + AngleImp::stype(), + I18N_NOOP( "Construct Bisector of This Angle" ), + I18N_NOOP( "Select the angle you want to construct the bisector of..." ), + I18N_NOOP( "Angle Bisector" ), + I18N_NOOP( "The bisector of an angle" ), + "angle_bisector", + "angle-bisector" ); + actions->add( new ConstructibleAction( &anglebisectionctor, "objects_new_angle_bisector" ) ); + + // conic stuff + c = new SimpleObjectTypeConstructor( + ConicB5PType::instance(), I18N_NOOP( "Conic by Five Points" ), + I18N_NOOP( "A conic constructed through five points" ), + "conicb5p" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_conicb5p" ) ); + + c = new SimpleObjectTypeConstructor( + ConicBAAPType::instance(), + I18N_NOOP( "Hyperbola by Asymptotes && Point" ), + I18N_NOOP( "A hyperbola with given asymptotes through a point" ), + "conicbaap" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_conicbaap" ) ); + + c = new SimpleObjectTypeConstructor( + EllipseBFFPType::instance(), + I18N_NOOP( "Ellipse by Focuses && Point" ), // focuses is used in preference to foci + I18N_NOOP( "An ellipse constructed by its focuses and a point that pertains to it" ), + "ellipsebffp" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_ellipsebffp" ) ); + + c = new SimpleObjectTypeConstructor( + HyperbolaBFFPType::instance(), + I18N_NOOP( "Hyperbola by Focuses && Point" ), // focuses is used in preference to foci + I18N_NOOP( "A hyperbola constructed by its focuses and a point that pertains to it" ), + "hyperbolabffp" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_hyperbolabffp" ) ); + + c = new SimpleObjectTypeConstructor( + ConicBDFPType::instance(), + I18N_NOOP( "Conic by Directrix, Focus && Point" ), + I18N_NOOP( "A conic with given directrix and focus, through a point" ), + "conicbdfp" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_conicbdfp" ) ); + + c = new SimpleObjectTypeConstructor( + ParabolaBTPType::instance(), + I18N_NOOP( "Vertical Parabola by Three Points" ), + I18N_NOOP( "A vertical parabola constructed through three points" ), + "parabolabtp" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_parabolabtp" ) ); + + c = new SimpleObjectTypeConstructor( + CubicB9PType::instance(), + I18N_NOOP( "Cubic Curve by Nine Points" ), + I18N_NOOP( "A cubic curve constructed through nine points" ), + "cubicb9p" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_cubicb9p" ) ); + + c = new SimpleObjectTypeConstructor( + ConicPolarPointType::instance(), + I18N_NOOP( "Polar Point of a Line" ), + I18N_NOOP( "The polar point of a line with respect to a conic." ), + "polarpoint" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_pointpolar" ) ); + + c = new SimpleObjectTypeConstructor( + ConicPolarLineType::instance(), + I18N_NOOP( "Polar Line of a Point" ), + I18N_NOOP( "The polar line of a point with respect to a conic." ), + "polarline" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_linepolar" ) ); + + c = new SimpleObjectTypeConstructor( + CubicNodeB6PType::instance(), + I18N_NOOP( "Cubic Curve with Node by Six Points" ), + I18N_NOOP( "A cubic curve with a nodal point at the origin through six points" ), + "cubicnodeb6p" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_cubicnodeb6p" ) ); + + c = new SimpleObjectTypeConstructor( + CubicCuspB4PType::instance(), + I18N_NOOP( "Cubic Curve with Cusp by Four Points" ), + I18N_NOOP( "A cubic curve with a horizontal cusp at the origin through four points" ), + "cubiccuspb4p" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_cubiccuspb4p" ) ); + + c = new SimpleObjectTypeConstructor( + ConicDirectrixType::instance(), + I18N_NOOP( "Directrix of a Conic" ), + I18N_NOOP( "The directrix line of a conic." ), + "directrix" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_linedirectrix" ) ); + + c = new SimpleObjectTypeConstructor( + AngleType::instance(), + I18N_NOOP( "Angle by Three Points" ), + I18N_NOOP( "An angle defined by three points" ), + "angle" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_angle", TQt::Key_A ) ); + + c = new SimpleObjectTypeConstructor( + EquilateralHyperbolaB4PType::instance(), + I18N_NOOP( "Equilateral Hyperbola by Four Points" ), + I18N_NOOP( "An equilateral hyperbola constructed through four points" ), + "equilateralhyperbolab4p" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_equilateralhyperbolab4p" ) ); + + { + // now for the Mid Point action. It does both the mid point of + // a segment, and the mid point of two points. The midpoint of + // two segments just shows the mid point property, and therefore + // doesn't need to be added to the ctors, because there are + // already facilities to construct an object's properties.. + // therefore, we add only an mpotp to the ctors, and add the + // merged constructor only to the actions.. + ctors->add( new MidPointOfTwoPointsConstructor() ); + + ObjectConstructor* mpotp = new MidPointOfTwoPointsConstructor(); + ObjectConstructor* mpos = new PropertyObjectConstructor( + SegmentImp::stype(), I18N_NOOP( "Construct the midpoint of this segment" ), + "", "", "", "", "mid-point" ); + + // make this a static object, so it gets deleted at the end of + // the program. + static MergeObjectConstructor m( + I18N_NOOP( "Mid Point" ), + I18N_NOOP( "The midpoint of a segment or two other points" ), + "bisection" ); + m.merge( mpotp ); + m.merge( mpos ); + actions->add( new ConstructibleAction( &m, "objects_new_midpoint", TQt::Key_M ) ); + }; + + c = new SimpleObjectTypeConstructor( + VectorType::instance(), + I18N_NOOP( "Vector" ), + I18N_NOOP( "Construct a vector from two given points." ), + "vector" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_vector", TQt::Key_V ) ); + + c = new SimpleObjectTypeConstructor( + VectorSumType::instance(), + I18N_NOOP( "Vector Sum" ), + I18N_NOOP( "Construct the vector sum of two vectors." ), + "vectorsum" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_vectorsum", 0 ) ); + + c = new SimpleObjectTypeConstructor( + LineByVectorType::instance(), + I18N_NOOP( "Line by Vector" ), + I18N_NOOP( "Construct the line by a given vector though a given point." ), + "linebyvector" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_linebyvector", 0 ) ); + + c = new SimpleObjectTypeConstructor( + HalflineByVectorType::instance(), + I18N_NOOP( "Half-Line by Vector" ), + I18N_NOOP( "Construct the half-line by a given vector starting at given point." ), + "halflinebyvector" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_halflinebyvector", 0 ) ); + + c = new SimpleObjectTypeConstructor( + ArcBTPType::instance(), + I18N_NOOP( "Arc by Three Points" ), + I18N_NOOP( "Construct an arc through three points." ), + "arc" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_arcbtp" ) ); + + c = new SimpleObjectTypeConstructor( + ArcBCPAType::instance(), + I18N_NOOP( "Arc by Center, Angle && Point" ), + I18N_NOOP( "Construct an arc by its center and a given angle, " + "starting at a given point" ), + "arcbcpa" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_arcbcpa" ) ); + + c = new SimpleObjectTypeConstructor( + ParabolaBDPType::instance(), + I18N_NOOP( "Parabola by Directrix && Focus" ), + I18N_NOOP( "A parabola defined by its directrix and focus" ), + "parabolabdp" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_parabolabdp" ) ); + + // Transformation stuff.. + c = new InversionConstructor(); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_inversion" ) ); + + c = new SimpleObjectTypeConstructor( + TranslatedType::instance(), + I18N_NOOP( "Translate" ), + I18N_NOOP( "The translation of an object by a vector" ), + "translation" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_translation" ) ); + + c = new SimpleObjectTypeConstructor( + PointReflectionType::instance(), + I18N_NOOP( "Reflect in Point" ), + I18N_NOOP( "An object reflected in a point" ), + "centralsymmetry" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_pointreflection" ) ); + + c = new SimpleObjectTypeConstructor( + LineReflectionType::instance(), + I18N_NOOP( "Reflect in Line" ), + I18N_NOOP( "An object reflected in a line" ), + "mirrorpoint" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_linereflection" ) ); + + c = new SimpleObjectTypeConstructor( + RotationType::instance(), + I18N_NOOP( "Rotate" ), + I18N_NOOP( "An object rotated by an angle around a point" ), + "rotation" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_rotation" ) ); + + c = new SimpleObjectTypeConstructor( + ScalingOverCenterType::instance(), + I18N_NOOP( "Scale" ), + I18N_NOOP( "Scale an object over a point, by the ratio given by the length of a segment" ), + "scale" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_scalingovercenter" ) ); + + c = new SimpleObjectTypeConstructor( + ScalingOverLineType::instance(), + I18N_NOOP( "Scale over Line" ), + I18N_NOOP( "An object scaled over a line, by the ratio given by the length of a segment" ), + "stretch" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_scalingoverline" ) ); + + c = new SimpleObjectTypeConstructor( + ScalingOverCenter2Type::instance(), + I18N_NOOP( "Scale (ratio given by two segments)" ), + I18N_NOOP( "Scale an object over a point, by the ratio given by the length of two segments" ), + "scale" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_scalingovercenter2" ) ); + + c = new SimpleObjectTypeConstructor( + ScalingOverLine2Type::instance(), + I18N_NOOP( "Scale over Line (ratio given by two segments)" ), + I18N_NOOP( "An object scaled over a line, by the ratio given by the length of two segments" ), + "stretch" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_scalingoverline2" ) ); + + c = new SimpleObjectTypeConstructor( + SimilitudeType::instance(), + I18N_NOOP( "Apply Similitude" ), + I18N_NOOP( "Apply a similitude to an object ( the sequence of a scaling and rotation around a center )" ), + "similitude" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_similitude" ) ); + + c = new SimpleObjectTypeConstructor( + HarmonicHomologyType::instance(), + I18N_NOOP( "Harmonic Homology" ), + I18N_NOOP( "The harmonic homology with a given center and a given axis (this is a projective transformation)" ), + "harmonichomology" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_harmonichomology" ) ); + + c = new GenericAffinityConstructor(); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_genericaffinity" ) ); + + c = new GenericProjectivityConstructor(); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_genericprojectivity" ) ); + + c = new SimpleObjectTypeConstructor( + CastShadowType::instance(), + I18N_NOOP( "Draw Projective Shadow" ), + I18N_NOOP( "The shadow of an object with a given light source and projection plane (indicated by a line)" ), + "castshadow" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_castshadow" ) ); + +// c = new SimpleObjectTypeConstructor( +// ProjectiveRotationType::instance(), +// I18N_NOOP( "Rotate Projectively" ), +// I18N_NOOP( "An object projectively rotated by an angle and a half-line" ), +// "projectiverotation" ); +// ctors->add( c ); +// actions->add( new ConstructibleAction( c, "objects_new_projectiverotation" ) ); + + c = new MultiObjectTypeConstructor( + ConicAsymptoteType::instance(), + I18N_NOOP( "Asymptotes of a Hyperbola" ), + I18N_NOOP( "The two asymptotes of a hyperbola." ), + "conicasymptotes", -1, 1 ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_lineconicasymptotes" ) ); + + c = new ConicRadicalConstructor(); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_lineconicradical") ); + + /* ----------- start polygons --------- */ + + c = new SimpleObjectTypeConstructor( + TriangleB3PType::instance(), + I18N_NOOP( "Triangle by Its Vertices" ), + I18N_NOOP( "Construct a triangle given its three vertices." ), + "triangle" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_trianglebtp" ) ); + + c = new PolygonBNPTypeConstructor(); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_polygonbnp" )); + + c = new PolygonBCVConstructor(); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_polygonbcv" ) ); + + c = new PolygonVertexTypeConstructor(); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_polygonvertices" )); + + c = new PolygonSideTypeConstructor(); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_polygonsides" )); + + c = new SimpleObjectTypeConstructor( + ConvexHullType::instance(), I18N_NOOP( "Convex Hull" ), + I18N_NOOP( "A polygon that corresponds to the convex hull of another polygon" ), + "convexhull" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_convexhull" ) ); + + /* ----------- end polygons --------- */ + + c = new LocusConstructor(); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_locus" ) ); + + // tests + c = new TestConstructor( + AreParallelType::instance(), + I18N_NOOP( "Parallel Test" ), + I18N_NOOP( "Test whether two given lines are parallel" ), + "testparallel" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_areparallel" ) ); + + c = new TestConstructor( + AreOrthogonalType::instance(), + I18N_NOOP( "Orthogonal Test" ), + I18N_NOOP( "Test whether two given lines are orthogonal" ), + "testorthogonal" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_areorthogonal" ) ); + + c = new TestConstructor( + AreCollinearType::instance(), + I18N_NOOP( "Collinear Test" ), + I18N_NOOP( "Test whether three given points are collinear" ), + "testcollinear" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_arecollinear" ) ); + + c = new TestConstructor( + ContainsTestType::instance(), + I18N_NOOP( "Contains Test" ), + I18N_NOOP( "Test whether a given curve contains a given point" ), + "testcontains" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_containstest" ) ); + + c = new TestConstructor( + InPolygonTestType::instance(), + I18N_NOOP( "In Polygon Test" ), + I18N_NOOP( "Test whether a given polygon contains a given point" ), + "test" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_inpolygontest" ) ); + + c = new TestConstructor( + ConvexPolygonTestType::instance(), + I18N_NOOP( "Convex Polygon Test" ), + I18N_NOOP( "Test whether a given polygon is convex" ), + "test" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_convexpolygontest" ) ); + + c = new TestConstructor( + SameDistanceType::instance(), + I18N_NOOP( "Distance Test" ), + I18N_NOOP( "Test whether a given point have the same distance from a given point " + "and from another given point" ), + "testdistance" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_distancetest" ) ); + + c = new TestConstructor( + VectorEqualityTestType::instance(), + I18N_NOOP( "Vector Equality Test" ), + I18N_NOOP( "Test whether two vectors are equal" ), + "test" ); +// "testequal" ); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_vectorequalitytest" ) ); + + c = new MeasureTransportConstructor(); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_measuretransport" )); + +// c = new SimpleObjectTypeConstructor( +// MeasureTransportType::instance(), +// I18N_NOOP( "Measure Transport" ), +// I18N_NOOP( "Transport the measure of a segment or arc over a line or circle." ), +// "measuretransport" ); +// ctors->add( c ); +// actions->add( new ConstructibleAction( c, "objects_new_measuretransport" ) ); + + // the generic intersection constructor.. + c = new GenericIntersectionConstructor(); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_intersection", TQt::Key_I ) ); + + // the generic tangent constructor + c = new TangentConstructor(); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_tangent", TQt::Key_T ) ); + + // the generic center of curvature constructor + c = new CocConstructor(); + ctors->add( c ); + actions->add( new ConstructibleAction( c, "objects_new_centerofcurvature" ) ); + + actions->add( new ConstructPointAction( "objects_new_normalpoint" ) ); + actions->add( new ConstructTextLabelAction( "objects_new_textlabel" ) ); + actions->add( new AddFixedPointAction( "objects_new_point_xy" ) ); + +#ifdef KIG_ENABLE_PYTHON_SCRIPTING +#include "../scripting/script-common.h" + actions->add( new NewScriptAction( + I18N_NOOP( "Python Script" ), + I18N_NOOP( "Construct a new Python script." ), + "objects_new_script_python", + ScriptType::Python ) ); +#endif + +#if 0 + actions->add( new TestAction( "test_stuff" ) ); +#endif + }; + + done = true; +} diff --git a/kig/misc/calcpaths.cc b/kig/misc/calcpaths.cc deleted file mode 100644 index 1532715b..00000000 --- a/kig/misc/calcpaths.cc +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright (C) 2002 Dominique Devriese - -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -// 02110-1301, USA. - -#include "calcpaths.h" - -#include "../objects/object_calcer.h" -#include "../objects/object_imp.h" - -#include - -// mp: -// The previous algorithm by Dominique had an exponential complexity -// for some constructions (e.g. a sequence of "n" triangles each inscribed -// into the previous). -// The new version is directly taken from a book of Alan Bertossi -// "Algoritmi e strutture dati" - -// temporarily disabling the new algorithm due to the freeze: -// I previously misunderstood the semantics of this function -// and thought that the os vector had to be completed with all -// the subtree generated by it. On the contrary, the os vector -// contains *all* the objects that we want, we only have to -// reorder them. Now it *should* work, however we postpone -// activating this to a more proper moment - -// to deactivate the new algorithm change "define" into "undef" - -#define NEWCALCPATH -#ifdef NEWCALCPATH -void localdfs( ObjectCalcer* obj, - std::vector& visited, - std::vector& all); - -std::vector calcPath( const std::vector& os ) -{ - // "all" is the Objects var we're building, in reverse ordering - std::vector visited; - std::vector all; - - for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) - { - if ( std::find( visited.begin(), visited.end(), *i ) == visited.end() ) - { - localdfs( *i, visited, all ); - } - } - - // now, we need to remove all objects that are not in os - // (forgot to do this in previous fix :-( ) - std::vector ret; - for ( std::vector::reverse_iterator i = all.rbegin(); i != all.rend(); ++i ) - { - // we only add objects that appear in os - if ( std::find( os.begin(), os.end(), *i ) != os.end() ) ret.push_back( *i ); - }; - return ret; -} - -void localdfs( ObjectCalcer* obj, - std::vector& visited, - std::vector& all) -{ - visited.push_back( obj ); - const std::vector o = obj->children(); - for ( std::vector::const_iterator i = o.begin(); i != o.end(); ++i ) - { - if ( std::find( visited.begin(), visited.end(), *i ) == visited.end() ) - localdfs( *i, visited, all ); - } - all.push_back( obj ); -} - -// old calcPath commented out... - -#else -// these first two functions were written before i read stuff about -// graph theory and algorithms, so i'm sure they're far from optimal. -// However, they seem to work fine, and i don't think there's a real -// need for optimisation here.. -std::vector calcPath( const std::vector& os ) -{ - // this is a little experiment of mine, i don't know if it is the - // fastest way to do it, but it seems logical to me... - - // the general idea here: - // first we build a new Objects variable. For every object in os, - // we put all of its children at the end of it, and we do the same - // for the ones we add.. - - // "all" is the Objects var we're building... - std::vector all = os; - // tmp is the var containing the objects we're iterating over. The - // first time around this is the os variable, the next time, this - // contains the variables we added in the first round... - std::vector tmp = os; - // tmp2 is a temporary var. During a round, it receives all the - // variables we add ( to "all" ) in that round, and at the end of - // the round, it is assigned to tmp. - std::vector tmp2; - while ( ! tmp.empty() ) - { - for ( std::vector::const_iterator i = tmp.begin(); i != tmp.end(); ++i ) - { - const std::vector o = (*i)->children(); - std::copy( o.begin(), o.end(), std::back_inserter( all ) ); - std::copy( o.begin(), o.end(), std::back_inserter( tmp2 ) ); - }; - tmp = tmp2; - tmp2.clear(); - }; - - // now we know that if all objects appear at least once after all of - // their parents. So, we take all, and of every object, we remove - // every reference except the last one... - std::vector ret; - ret.reserve( os.size() ); - for ( std::vector::reverse_iterator i = all.rbegin(); i != all.rend(); ++i ) - { - // we only add objects that appear in os and only if they are not - // already in ret.. - if ( std::find( ret.begin(), ret.end(), *i ) == ret.end() && - std::find( os.begin(), os.end(), *i ) != os.end() ) ret.push_back( *i ); - }; - std::reverse( ret.begin(), ret.end() ); - return ret; -} -#endif - -bool addBranch( const std::vector& o, const ObjectCalcer* to, std::vector& ret ) -{ - bool rb = false; - for ( std::vector::const_iterator i = o.begin(); i != o.end(); ++i ) - { - if ( *i == to ) - rb = true; - else - if ( addBranch( (*i)->children(), to, ret ) ) - { - rb = true; - ret.push_back( *i ); - }; - }; - return rb; -} - -std::vector calcPath( const std::vector& from, const ObjectCalcer* to ) -{ - std::vector all; - - for ( std::vector::const_iterator i = from.begin(); i != from.end(); ++i ) - { - (void) addBranch( (*i)->children(), to, all ); - }; - - std::vector ret; - for ( std::vector::iterator i = all.begin(); i != all.end(); ++i ) - { - if ( std::find( ret.begin(), ret.end(), *i ) == ret.end() ) - ret.push_back( *i ); - }; - return std::vector( ret.rbegin(), ret.rend() ); -} - -static void addNonCache( ObjectCalcer* o, std::vector& ret ) -{ - if ( ! o->imp()->isCache() ) - if ( std::find( ret.begin(), ret.end(), o ) == ret.end() ) - ret.push_back( o ); - else - { - std::vector parents = o->parents(); - for ( uint i = 0; i < parents.size(); ++i ) - addNonCache( parents[i], ret ); - }; -} - -static bool visit( const ObjectCalcer* o, const std::vector& from, std::vector& ret ) -{ - // this function returns true if the visited object depends on one - // of the objects in from. If we encounter objects that are on the - // side of the tree path ( they do not depend on from themselves, - // but their direct children do ), then we add them to ret. - if ( std::find( from.begin(), from.end(), o ) != from.end() ) return true; - - std::vector deps( o->parents().size(), false ); - bool somedepend = false; - bool alldepend = true; - std::vector parents = o->parents(); - for ( uint i = 0; i < parents.size(); ++i ) - { - bool v = visit( parents[i], from, ret ); - somedepend |= v; - alldepend &= v; - deps[i] = v; - }; - if ( somedepend && ! alldepend ) - { - for ( uint i = 0; i < deps.size(); ++i ) - if ( ! deps[i] ) - addNonCache( parents[i], ret ); - }; - - return somedepend; -} - -std::vector sideOfTreePath( const std::vector& from, const ObjectCalcer* to ) -{ - std::vector ret; - visit( to, from, ret ); - return ret; -} - -std::vector getAllParents( const std::vector& objs ) -{ - using namespace std; - std::set ret( objs.begin(),objs.end() ); - std::set cur = ret; - while ( ! cur.empty() ) - { - std::set next; - for ( std::set::const_iterator i = cur.begin(); i != cur.end(); ++i ) - { - std::vector parents = (*i)->parents(); - next.insert( parents.begin(), parents.end() ); - }; - - ret.insert( next.begin(), next.end() ); - cur = next; - }; - return std::vector( ret.begin(), ret.end() ); -} - -std::vector getAllParents( ObjectCalcer* obj ) -{ - std::vector objs; - objs.push_back( obj ); - return getAllParents( objs ); -} - -bool isChild( const ObjectCalcer* o, const std::vector& os ) -{ - std::vector parents = o->parents(); - std::set cur( parents.begin(), parents.end() ); - while ( ! cur.empty() ) - { - std::set next; - for ( std::set::const_iterator i = cur.begin(); i != cur.end(); ++i ) - { - if ( std::find( os.begin(), os.end(), *i ) != os.end() ) return true; - std::vector parents = (*i)->parents(); - next.insert( parents.begin(), parents.end() ); - }; - cur = next; - }; - return false; -} - -std::set getAllChildren( ObjectCalcer* obj ) -{ - std::vector objs; - objs.push_back( obj ); - return getAllChildren( objs ); -} - -std::set getAllChildren( const std::vector objs ) -{ - std::set ret; - // objects to iterate over... - std::set cur( objs.begin(), objs.end() ); - while( !cur.empty() ) - { - // contains the objects to iterate over the next time around... - std::set next; - for( std::set::iterator i = cur.begin(); - i != cur.end(); ++i ) - { - ret.insert( *i ); - std::vector children = (*i)->children(); - next.insert( children.begin(), children.end() ); - }; - cur = next; - }; - return ret; -} - -bool isPointOnCurve( const ObjectCalcer* point, const ObjectCalcer* curve ) -{ - return point->isDefinedOnOrThrough( curve ) || curve->isDefinedOnOrThrough( point ); -} diff --git a/kig/misc/calcpaths.cpp b/kig/misc/calcpaths.cpp new file mode 100644 index 00000000..1532715b --- /dev/null +++ b/kig/misc/calcpaths.cpp @@ -0,0 +1,303 @@ +// Copyright (C) 2002 Dominique Devriese + +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#include "calcpaths.h" + +#include "../objects/object_calcer.h" +#include "../objects/object_imp.h" + +#include + +// mp: +// The previous algorithm by Dominique had an exponential complexity +// for some constructions (e.g. a sequence of "n" triangles each inscribed +// into the previous). +// The new version is directly taken from a book of Alan Bertossi +// "Algoritmi e strutture dati" + +// temporarily disabling the new algorithm due to the freeze: +// I previously misunderstood the semantics of this function +// and thought that the os vector had to be completed with all +// the subtree generated by it. On the contrary, the os vector +// contains *all* the objects that we want, we only have to +// reorder them. Now it *should* work, however we postpone +// activating this to a more proper moment + +// to deactivate the new algorithm change "define" into "undef" + +#define NEWCALCPATH +#ifdef NEWCALCPATH +void localdfs( ObjectCalcer* obj, + std::vector& visited, + std::vector& all); + +std::vector calcPath( const std::vector& os ) +{ + // "all" is the Objects var we're building, in reverse ordering + std::vector visited; + std::vector all; + + for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) + { + if ( std::find( visited.begin(), visited.end(), *i ) == visited.end() ) + { + localdfs( *i, visited, all ); + } + } + + // now, we need to remove all objects that are not in os + // (forgot to do this in previous fix :-( ) + std::vector ret; + for ( std::vector::reverse_iterator i = all.rbegin(); i != all.rend(); ++i ) + { + // we only add objects that appear in os + if ( std::find( os.begin(), os.end(), *i ) != os.end() ) ret.push_back( *i ); + }; + return ret; +} + +void localdfs( ObjectCalcer* obj, + std::vector& visited, + std::vector& all) +{ + visited.push_back( obj ); + const std::vector o = obj->children(); + for ( std::vector::const_iterator i = o.begin(); i != o.end(); ++i ) + { + if ( std::find( visited.begin(), visited.end(), *i ) == visited.end() ) + localdfs( *i, visited, all ); + } + all.push_back( obj ); +} + +// old calcPath commented out... + +#else +// these first two functions were written before i read stuff about +// graph theory and algorithms, so i'm sure they're far from optimal. +// However, they seem to work fine, and i don't think there's a real +// need for optimisation here.. +std::vector calcPath( const std::vector& os ) +{ + // this is a little experiment of mine, i don't know if it is the + // fastest way to do it, but it seems logical to me... + + // the general idea here: + // first we build a new Objects variable. For every object in os, + // we put all of its children at the end of it, and we do the same + // for the ones we add.. + + // "all" is the Objects var we're building... + std::vector all = os; + // tmp is the var containing the objects we're iterating over. The + // first time around this is the os variable, the next time, this + // contains the variables we added in the first round... + std::vector tmp = os; + // tmp2 is a temporary var. During a round, it receives all the + // variables we add ( to "all" ) in that round, and at the end of + // the round, it is assigned to tmp. + std::vector tmp2; + while ( ! tmp.empty() ) + { + for ( std::vector::const_iterator i = tmp.begin(); i != tmp.end(); ++i ) + { + const std::vector o = (*i)->children(); + std::copy( o.begin(), o.end(), std::back_inserter( all ) ); + std::copy( o.begin(), o.end(), std::back_inserter( tmp2 ) ); + }; + tmp = tmp2; + tmp2.clear(); + }; + + // now we know that if all objects appear at least once after all of + // their parents. So, we take all, and of every object, we remove + // every reference except the last one... + std::vector ret; + ret.reserve( os.size() ); + for ( std::vector::reverse_iterator i = all.rbegin(); i != all.rend(); ++i ) + { + // we only add objects that appear in os and only if they are not + // already in ret.. + if ( std::find( ret.begin(), ret.end(), *i ) == ret.end() && + std::find( os.begin(), os.end(), *i ) != os.end() ) ret.push_back( *i ); + }; + std::reverse( ret.begin(), ret.end() ); + return ret; +} +#endif + +bool addBranch( const std::vector& o, const ObjectCalcer* to, std::vector& ret ) +{ + bool rb = false; + for ( std::vector::const_iterator i = o.begin(); i != o.end(); ++i ) + { + if ( *i == to ) + rb = true; + else + if ( addBranch( (*i)->children(), to, ret ) ) + { + rb = true; + ret.push_back( *i ); + }; + }; + return rb; +} + +std::vector calcPath( const std::vector& from, const ObjectCalcer* to ) +{ + std::vector all; + + for ( std::vector::const_iterator i = from.begin(); i != from.end(); ++i ) + { + (void) addBranch( (*i)->children(), to, all ); + }; + + std::vector ret; + for ( std::vector::iterator i = all.begin(); i != all.end(); ++i ) + { + if ( std::find( ret.begin(), ret.end(), *i ) == ret.end() ) + ret.push_back( *i ); + }; + return std::vector( ret.rbegin(), ret.rend() ); +} + +static void addNonCache( ObjectCalcer* o, std::vector& ret ) +{ + if ( ! o->imp()->isCache() ) + if ( std::find( ret.begin(), ret.end(), o ) == ret.end() ) + ret.push_back( o ); + else + { + std::vector parents = o->parents(); + for ( uint i = 0; i < parents.size(); ++i ) + addNonCache( parents[i], ret ); + }; +} + +static bool visit( const ObjectCalcer* o, const std::vector& from, std::vector& ret ) +{ + // this function returns true if the visited object depends on one + // of the objects in from. If we encounter objects that are on the + // side of the tree path ( they do not depend on from themselves, + // but their direct children do ), then we add them to ret. + if ( std::find( from.begin(), from.end(), o ) != from.end() ) return true; + + std::vector deps( o->parents().size(), false ); + bool somedepend = false; + bool alldepend = true; + std::vector parents = o->parents(); + for ( uint i = 0; i < parents.size(); ++i ) + { + bool v = visit( parents[i], from, ret ); + somedepend |= v; + alldepend &= v; + deps[i] = v; + }; + if ( somedepend && ! alldepend ) + { + for ( uint i = 0; i < deps.size(); ++i ) + if ( ! deps[i] ) + addNonCache( parents[i], ret ); + }; + + return somedepend; +} + +std::vector sideOfTreePath( const std::vector& from, const ObjectCalcer* to ) +{ + std::vector ret; + visit( to, from, ret ); + return ret; +} + +std::vector getAllParents( const std::vector& objs ) +{ + using namespace std; + std::set ret( objs.begin(),objs.end() ); + std::set cur = ret; + while ( ! cur.empty() ) + { + std::set next; + for ( std::set::const_iterator i = cur.begin(); i != cur.end(); ++i ) + { + std::vector parents = (*i)->parents(); + next.insert( parents.begin(), parents.end() ); + }; + + ret.insert( next.begin(), next.end() ); + cur = next; + }; + return std::vector( ret.begin(), ret.end() ); +} + +std::vector getAllParents( ObjectCalcer* obj ) +{ + std::vector objs; + objs.push_back( obj ); + return getAllParents( objs ); +} + +bool isChild( const ObjectCalcer* o, const std::vector& os ) +{ + std::vector parents = o->parents(); + std::set cur( parents.begin(), parents.end() ); + while ( ! cur.empty() ) + { + std::set next; + for ( std::set::const_iterator i = cur.begin(); i != cur.end(); ++i ) + { + if ( std::find( os.begin(), os.end(), *i ) != os.end() ) return true; + std::vector parents = (*i)->parents(); + next.insert( parents.begin(), parents.end() ); + }; + cur = next; + }; + return false; +} + +std::set getAllChildren( ObjectCalcer* obj ) +{ + std::vector objs; + objs.push_back( obj ); + return getAllChildren( objs ); +} + +std::set getAllChildren( const std::vector objs ) +{ + std::set ret; + // objects to iterate over... + std::set cur( objs.begin(), objs.end() ); + while( !cur.empty() ) + { + // contains the objects to iterate over the next time around... + std::set next; + for( std::set::iterator i = cur.begin(); + i != cur.end(); ++i ) + { + ret.insert( *i ); + std::vector children = (*i)->children(); + next.insert( children.begin(), children.end() ); + }; + cur = next; + }; + return ret; +} + +bool isPointOnCurve( const ObjectCalcer* point, const ObjectCalcer* curve ) +{ + return point->isDefinedOnOrThrough( curve ) || curve->isDefinedOnOrThrough( point ); +} diff --git a/kig/misc/cubic-common.cc b/kig/misc/cubic-common.cc deleted file mode 100644 index 029f1194..00000000 --- a/kig/misc/cubic-common.cc +++ /dev/null @@ -1,527 +0,0 @@ -// Copyright (C) 2003 Dominique Devriese - -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -// 02110-1301, USA. - -#include - -#include "cubic-common.h" -#include "kignumerics.h" -#include "kigtransform.h" - -#ifdef HAVE_IEEEFP_H -#include -#endif - -/* - * coefficients of the cartesian equation for cubics - */ - -CubicCartesianData::CubicCartesianData() -{ - std::fill( coeffs, coeffs + 10, 0 ); -} - -CubicCartesianData::CubicCartesianData( - const double incoeffs[10] ) -{ - std::copy( incoeffs, incoeffs + 10, coeffs ); -} - -const CubicCartesianData calcCubicThroughPoints ( - const std::vector& points ) -{ - // points is a vector of at most 9 points through which the cubic is - // constrained. - // this routine should compute the coefficients in the cartesian equation - // they are defined up to a multiplicative factor. - // since we don't know (in advance) which one of them is nonzero, we - // simply keep all 10 parameters, obtaining a 9x10 linear system which - // we solve using gaussian elimination with complete pivoting - // If there are too few, then we choose some cool way to fill in the - // empty parts in the matrix according to the LinearConstraints - // given.. - - // 9 rows, 10 columns.. - double row0[10]; - double row1[10]; - double row2[10]; - double row3[10]; - double row4[10]; - double row5[10]; - double row6[10]; - double row7[10]; - double row8[10]; - double *matrix[9] = {row0, row1, row2, row3, row4, row5, row6, row7, row8}; - double solution[10]; - int scambio[10]; - - int numpoints = points.size(); - int numconstraints = 9; - - // fill in the matrix elements - for ( int i = 0; i < numpoints; ++i ) - { - double xi = points[i].x; - double yi = points[i].y; - matrix[i][0] = 1.0; - matrix[i][1] = xi; - matrix[i][2] = yi; - matrix[i][3] = xi*xi; - matrix[i][4] = xi*yi; - matrix[i][5] = yi*yi; - matrix[i][6] = xi*xi*xi; - matrix[i][7] = xi*xi*yi; - matrix[i][8] = xi*yi*yi; - matrix[i][9] = yi*yi*yi; - } - - for ( int i = 0; i < numconstraints; i++ ) - { - if (numpoints >= 9) break; // don't add constraints if we have enough - for (int j = 0; j < 10; ++j) matrix[numpoints][j] = 0.0; - bool addedconstraint = true; - switch (i) - { - case 0: - matrix[numpoints][7] = 1.0; - matrix[numpoints][8] = -1.0; - break; - case 1: - matrix[numpoints][7] = 1.0; - break; - case 2: - matrix[numpoints][9] = 1.0; - break; - case 3: - matrix[numpoints][4] = 1.0; - break; - case 4: - matrix[numpoints][5] = 1.0; - break; - case 5: - matrix[numpoints][3] = 1.0; - break; - case 6: - matrix[numpoints][1] = 1.0; - break; - - default: - addedconstraint = false; - break; - } - - if (addedconstraint) ++numpoints; - } - - if ( ! GaussianElimination( matrix, numpoints, 10, scambio ) ) - return CubicCartesianData::invalidData(); - // fine della fase di eliminazione - BackwardSubstitution( matrix, numpoints, 10, scambio, solution ); - - // now solution should contain the correct coefficients.. - return CubicCartesianData( solution ); -} - -const CubicCartesianData calcCubicCuspThroughPoints ( - const std::vector& points ) -{ - // points is a vector of at most 4 points through which the cubic is - // constrained. Moreover the cubic is required to have a cusp at the - // origin. - - // 9 rows, 10 columns.. - double row0[10]; - double row1[10]; - double row2[10]; - double row3[10]; - double row4[10]; - double row5[10]; - double row6[10]; - double row7[10]; - double row8[10]; - double *matrix[9] = {row0, row1, row2, row3, row4, row5, row6, row7, row8}; - double solution[10]; - int scambio[10]; - - int numpoints = points.size(); - int numconstraints = 9; - - // fill in the matrix elements - for ( int i = 0; i < numpoints; ++i ) - { - double xi = points[i].x; - double yi = points[i].y; - matrix[i][0] = 1.0; - matrix[i][1] = xi; - matrix[i][2] = yi; - matrix[i][3] = xi*xi; - matrix[i][4] = xi*yi; - matrix[i][5] = yi*yi; - matrix[i][6] = xi*xi*xi; - matrix[i][7] = xi*xi*yi; - matrix[i][8] = xi*yi*yi; - matrix[i][9] = yi*yi*yi; - } - - for ( int i = 0; i < numconstraints; i++ ) - { - if (numpoints >= 9) break; // don't add constraints if we have enough - for (int j = 0; j < 10; ++j) matrix[numpoints][j] = 0.0; - bool addedconstraint = true; - switch (i) - { - case 0: - matrix[numpoints][0] = 1.0; // through the origin - break; - case 1: - matrix[numpoints][1] = 1.0; - break; - case 2: - matrix[numpoints][2] = 1.0; // no first degree term - break; - case 3: - matrix[numpoints][3] = 1.0; // a011 (x^2 coeff) = 0 - break; - case 4: - matrix[numpoints][4] = 1.0; // a012 (xy coeff) = 0 - break; - case 5: - matrix[numpoints][7] = 1.0; - matrix[numpoints][8] = -1.0; - break; - case 6: - matrix[numpoints][7] = 1.0; - break; - case 7: - matrix[numpoints][9] = 1.0; - break; - case 8: - matrix[numpoints][6] = 1.0; - break; - - default: - addedconstraint = false; - break; - } - - if (addedconstraint) ++numpoints; - } - - if ( ! GaussianElimination( matrix, numpoints, 10, scambio ) ) - return CubicCartesianData::invalidData(); - // fine della fase di eliminazione - BackwardSubstitution( matrix, numpoints, 10, scambio, solution ); - - // now solution should contain the correct coefficients.. - return CubicCartesianData( solution ); -} - -const CubicCartesianData calcCubicNodeThroughPoints ( - const std::vector& points ) -{ - // points is a vector of at most 6 points through which the cubic is - // constrained. Moreover the cubic is required to have a node at the - // origin. - - // 9 rows, 10 columns.. - double row0[10]; - double row1[10]; - double row2[10]; - double row3[10]; - double row4[10]; - double row5[10]; - double row6[10]; - double row7[10]; - double row8[10]; - double *matrix[9] = {row0, row1, row2, row3, row4, row5, row6, row7, row8}; - double solution[10]; - int scambio[10]; - - int numpoints = points.size(); - int numconstraints = 9; - - // fill in the matrix elements - for ( int i = 0; i < numpoints; ++i ) - { - double xi = points[i].x; - double yi = points[i].y; - matrix[i][0] = 1.0; - matrix[i][1] = xi; - matrix[i][2] = yi; - matrix[i][3] = xi*xi; - matrix[i][4] = xi*yi; - matrix[i][5] = yi*yi; - matrix[i][6] = xi*xi*xi; - matrix[i][7] = xi*xi*yi; - matrix[i][8] = xi*yi*yi; - matrix[i][9] = yi*yi*yi; - } - - for ( int i = 0; i < numconstraints; i++ ) - { - if (numpoints >= 9) break; // don't add constraints if we have enough - for (int j = 0; j < 10; ++j) matrix[numpoints][j] = 0.0; - bool addedconstraint = true; - switch (i) - { - case 0: - matrix[numpoints][0] = 1.0; - break; - case 1: - matrix[numpoints][1] = 1.0; - break; - case 2: - matrix[numpoints][2] = 1.0; - break; - case 3: - matrix[numpoints][7] = 1.0; - matrix[numpoints][8] = -1.0; - break; - case 4: - matrix[numpoints][7] = 1.0; - break; - case 5: - matrix[numpoints][9] = 1.0; - break; - case 6: - matrix[numpoints][4] = 1.0; - break; - case 7: - matrix[numpoints][5] = 1.0; - break; - case 8: - matrix[numpoints][3] = 1.0; - break; - - default: - addedconstraint = false; - break; - } - - if (addedconstraint) ++numpoints; - } - - if ( ! GaussianElimination( matrix, numpoints, 10, scambio ) ) - return CubicCartesianData::invalidData(); - // fine della fase di eliminazione - BackwardSubstitution( matrix, numpoints, 10, scambio, solution ); - - // now solution should contain the correct coefficients.. - return CubicCartesianData( solution ); -} - -/* - * computation of the y value corresponding to some x value - */ - -double calcCubicYvalue ( double x, double ymin, double ymax, int root, - CubicCartesianData data, bool& valid, - int &numroots ) -{ - valid = true; - - // compute the third degree polinomial: - double a000 = data.coeffs[0]; - double a001 = data.coeffs[1]; - double a002 = data.coeffs[2]; - double a011 = data.coeffs[3]; - double a012 = data.coeffs[4]; - double a022 = data.coeffs[5]; - double a111 = data.coeffs[6]; - double a112 = data.coeffs[7]; - double a122 = data.coeffs[8]; - double a222 = data.coeffs[9]; - - // first the y^3 coefficient, it coming only from a222: - double a = a222; - // next the y^2 coefficient (from a122 and a022): - double b = a122*x + a022; - // next the y coefficient (from a112, a012 and a002): - double c = a112*x*x + a012*x + a002; - // finally the constant coefficient (from a111, a011, a001 and a000): - double d = a111*x*x*x + a011*x*x + a001*x + a000; - - return calcCubicRoot ( ymin, ymax, a, b, c, d, root, valid, numroots ); -} - -const Coordinate calcCubicLineIntersect( const CubicCartesianData& cu, - const LineData& l, - int root, bool& valid ) -{ - assert( root == 1 || root == 2 || root == 3 ); - - double a, b, c, d; - calcCubicLineRestriction ( cu, l.a, l.b-l.a, a, b, c, d ); - int numroots; - double param = - calcCubicRoot ( -1e10, 1e10, a, b, c, d, root, valid, numroots ); - return l.a + param*(l.b - l.a); -} - -/* - * calculate the cubic polynomial resulting from the restriction - * of a cubic to a line (defined by two "Coordinates": a point and a - * direction) - */ - -void calcCubicLineRestriction ( CubicCartesianData data, - Coordinate p, Coordinate v, - double& a, double& b, double& c, double& d ) -{ - a = b = c = d = 0; - - double a000 = data.coeffs[0]; - double a001 = data.coeffs[1]; - double a002 = data.coeffs[2]; - double a011 = data.coeffs[3]; - double a012 = data.coeffs[4]; - double a022 = data.coeffs[5]; - double a111 = data.coeffs[6]; - double a112 = data.coeffs[7]; - double a122 = data.coeffs[8]; - double a222 = data.coeffs[9]; - - // zero degree term - d += a000; - - // first degree terms - d += a001*p.x + a002*p.y; - c += a001*v.x + a002*v.y; - - // second degree terms - d += a011*p.x*p.x + a012*p.x*p.y + a022*p.y*p.y; - c += 2*a011*p.x*v.x + a012*(p.x*v.y + v.x*p.y) + 2*a022*p.y*v.y; - b += a011*v.x*v.x + a012*v.x*v.y + a022*v.y*v.y; - - // third degree terms: a111 x^3 + a222 y^3 - d += a111*p.x*p.x*p.x + a222*p.y*p.y*p.y; - c += 3*(a111*p.x*p.x*v.x + a222*p.y*p.y*v.y); - b += 3*(a111*p.x*v.x*v.x + a222*p.y*v.y*v.y); - a += a111*v.x*v.x*v.x + a222*v.y*v.y*v.y; - - // third degree terms: a112 x^2 y + a122 x y^2 - d += a112*p.x*p.x*p.y + a122*p.x*p.y*p.y; - c += a112*(p.x*p.x*v.y + 2*p.x*v.x*p.y) + a122*(v.x*p.y*p.y + 2*p.x*p.y*v.y); - b += a112*(v.x*v.x*p.y + 2*v.x*p.x*v.y) + a122*(p.x*v.y*v.y + 2*v.x*v.y*p.y); - a += a112*v.x*v.x*v.y + a122*v.x*v.y*v.y; -} - - -const CubicCartesianData calcCubicTransformation ( - const CubicCartesianData& data, - const Transformation& t, bool& valid ) -{ - double a[3][3][3]; - double b[3][3][3]; - CubicCartesianData dataout; - - int icount = 0; - for (int i=0; i < 3; i++) - { - for (int j=i; j < 3; j++) - { - for (int k=j; k < 3; k++) - { - a[i][j][k] = data.coeffs[icount++]; - if ( i < k ) - { - if ( i == j ) // case aiik - { - a[i][i][k] /= 3.; - a[i][k][i] = a[k][i][i] = a[i][i][k]; - } - else if ( j == k ) // case aijj - { - a[i][j][j] /= 3.; - a[j][i][j] = a[j][j][i] = a[i][j][j]; - } - else // case aijk (i + +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#include + +#include "cubic-common.h" +#include "kignumerics.h" +#include "kigtransform.h" + +#ifdef HAVE_IEEEFP_H +#include +#endif + +/* + * coefficients of the cartesian equation for cubics + */ + +CubicCartesianData::CubicCartesianData() +{ + std::fill( coeffs, coeffs + 10, 0 ); +} + +CubicCartesianData::CubicCartesianData( + const double incoeffs[10] ) +{ + std::copy( incoeffs, incoeffs + 10, coeffs ); +} + +const CubicCartesianData calcCubicThroughPoints ( + const std::vector& points ) +{ + // points is a vector of at most 9 points through which the cubic is + // constrained. + // this routine should compute the coefficients in the cartesian equation + // they are defined up to a multiplicative factor. + // since we don't know (in advance) which one of them is nonzero, we + // simply keep all 10 parameters, obtaining a 9x10 linear system which + // we solve using gaussian elimination with complete pivoting + // If there are too few, then we choose some cool way to fill in the + // empty parts in the matrix according to the LinearConstraints + // given.. + + // 9 rows, 10 columns.. + double row0[10]; + double row1[10]; + double row2[10]; + double row3[10]; + double row4[10]; + double row5[10]; + double row6[10]; + double row7[10]; + double row8[10]; + double *matrix[9] = {row0, row1, row2, row3, row4, row5, row6, row7, row8}; + double solution[10]; + int scambio[10]; + + int numpoints = points.size(); + int numconstraints = 9; + + // fill in the matrix elements + for ( int i = 0; i < numpoints; ++i ) + { + double xi = points[i].x; + double yi = points[i].y; + matrix[i][0] = 1.0; + matrix[i][1] = xi; + matrix[i][2] = yi; + matrix[i][3] = xi*xi; + matrix[i][4] = xi*yi; + matrix[i][5] = yi*yi; + matrix[i][6] = xi*xi*xi; + matrix[i][7] = xi*xi*yi; + matrix[i][8] = xi*yi*yi; + matrix[i][9] = yi*yi*yi; + } + + for ( int i = 0; i < numconstraints; i++ ) + { + if (numpoints >= 9) break; // don't add constraints if we have enough + for (int j = 0; j < 10; ++j) matrix[numpoints][j] = 0.0; + bool addedconstraint = true; + switch (i) + { + case 0: + matrix[numpoints][7] = 1.0; + matrix[numpoints][8] = -1.0; + break; + case 1: + matrix[numpoints][7] = 1.0; + break; + case 2: + matrix[numpoints][9] = 1.0; + break; + case 3: + matrix[numpoints][4] = 1.0; + break; + case 4: + matrix[numpoints][5] = 1.0; + break; + case 5: + matrix[numpoints][3] = 1.0; + break; + case 6: + matrix[numpoints][1] = 1.0; + break; + + default: + addedconstraint = false; + break; + } + + if (addedconstraint) ++numpoints; + } + + if ( ! GaussianElimination( matrix, numpoints, 10, scambio ) ) + return CubicCartesianData::invalidData(); + // fine della fase di eliminazione + BackwardSubstitution( matrix, numpoints, 10, scambio, solution ); + + // now solution should contain the correct coefficients.. + return CubicCartesianData( solution ); +} + +const CubicCartesianData calcCubicCuspThroughPoints ( + const std::vector& points ) +{ + // points is a vector of at most 4 points through which the cubic is + // constrained. Moreover the cubic is required to have a cusp at the + // origin. + + // 9 rows, 10 columns.. + double row0[10]; + double row1[10]; + double row2[10]; + double row3[10]; + double row4[10]; + double row5[10]; + double row6[10]; + double row7[10]; + double row8[10]; + double *matrix[9] = {row0, row1, row2, row3, row4, row5, row6, row7, row8}; + double solution[10]; + int scambio[10]; + + int numpoints = points.size(); + int numconstraints = 9; + + // fill in the matrix elements + for ( int i = 0; i < numpoints; ++i ) + { + double xi = points[i].x; + double yi = points[i].y; + matrix[i][0] = 1.0; + matrix[i][1] = xi; + matrix[i][2] = yi; + matrix[i][3] = xi*xi; + matrix[i][4] = xi*yi; + matrix[i][5] = yi*yi; + matrix[i][6] = xi*xi*xi; + matrix[i][7] = xi*xi*yi; + matrix[i][8] = xi*yi*yi; + matrix[i][9] = yi*yi*yi; + } + + for ( int i = 0; i < numconstraints; i++ ) + { + if (numpoints >= 9) break; // don't add constraints if we have enough + for (int j = 0; j < 10; ++j) matrix[numpoints][j] = 0.0; + bool addedconstraint = true; + switch (i) + { + case 0: + matrix[numpoints][0] = 1.0; // through the origin + break; + case 1: + matrix[numpoints][1] = 1.0; + break; + case 2: + matrix[numpoints][2] = 1.0; // no first degree term + break; + case 3: + matrix[numpoints][3] = 1.0; // a011 (x^2 coeff) = 0 + break; + case 4: + matrix[numpoints][4] = 1.0; // a012 (xy coeff) = 0 + break; + case 5: + matrix[numpoints][7] = 1.0; + matrix[numpoints][8] = -1.0; + break; + case 6: + matrix[numpoints][7] = 1.0; + break; + case 7: + matrix[numpoints][9] = 1.0; + break; + case 8: + matrix[numpoints][6] = 1.0; + break; + + default: + addedconstraint = false; + break; + } + + if (addedconstraint) ++numpoints; + } + + if ( ! GaussianElimination( matrix, numpoints, 10, scambio ) ) + return CubicCartesianData::invalidData(); + // fine della fase di eliminazione + BackwardSubstitution( matrix, numpoints, 10, scambio, solution ); + + // now solution should contain the correct coefficients.. + return CubicCartesianData( solution ); +} + +const CubicCartesianData calcCubicNodeThroughPoints ( + const std::vector& points ) +{ + // points is a vector of at most 6 points through which the cubic is + // constrained. Moreover the cubic is required to have a node at the + // origin. + + // 9 rows, 10 columns.. + double row0[10]; + double row1[10]; + double row2[10]; + double row3[10]; + double row4[10]; + double row5[10]; + double row6[10]; + double row7[10]; + double row8[10]; + double *matrix[9] = {row0, row1, row2, row3, row4, row5, row6, row7, row8}; + double solution[10]; + int scambio[10]; + + int numpoints = points.size(); + int numconstraints = 9; + + // fill in the matrix elements + for ( int i = 0; i < numpoints; ++i ) + { + double xi = points[i].x; + double yi = points[i].y; + matrix[i][0] = 1.0; + matrix[i][1] = xi; + matrix[i][2] = yi; + matrix[i][3] = xi*xi; + matrix[i][4] = xi*yi; + matrix[i][5] = yi*yi; + matrix[i][6] = xi*xi*xi; + matrix[i][7] = xi*xi*yi; + matrix[i][8] = xi*yi*yi; + matrix[i][9] = yi*yi*yi; + } + + for ( int i = 0; i < numconstraints; i++ ) + { + if (numpoints >= 9) break; // don't add constraints if we have enough + for (int j = 0; j < 10; ++j) matrix[numpoints][j] = 0.0; + bool addedconstraint = true; + switch (i) + { + case 0: + matrix[numpoints][0] = 1.0; + break; + case 1: + matrix[numpoints][1] = 1.0; + break; + case 2: + matrix[numpoints][2] = 1.0; + break; + case 3: + matrix[numpoints][7] = 1.0; + matrix[numpoints][8] = -1.0; + break; + case 4: + matrix[numpoints][7] = 1.0; + break; + case 5: + matrix[numpoints][9] = 1.0; + break; + case 6: + matrix[numpoints][4] = 1.0; + break; + case 7: + matrix[numpoints][5] = 1.0; + break; + case 8: + matrix[numpoints][3] = 1.0; + break; + + default: + addedconstraint = false; + break; + } + + if (addedconstraint) ++numpoints; + } + + if ( ! GaussianElimination( matrix, numpoints, 10, scambio ) ) + return CubicCartesianData::invalidData(); + // fine della fase di eliminazione + BackwardSubstitution( matrix, numpoints, 10, scambio, solution ); + + // now solution should contain the correct coefficients.. + return CubicCartesianData( solution ); +} + +/* + * computation of the y value corresponding to some x value + */ + +double calcCubicYvalue ( double x, double ymin, double ymax, int root, + CubicCartesianData data, bool& valid, + int &numroots ) +{ + valid = true; + + // compute the third degree polinomial: + double a000 = data.coeffs[0]; + double a001 = data.coeffs[1]; + double a002 = data.coeffs[2]; + double a011 = data.coeffs[3]; + double a012 = data.coeffs[4]; + double a022 = data.coeffs[5]; + double a111 = data.coeffs[6]; + double a112 = data.coeffs[7]; + double a122 = data.coeffs[8]; + double a222 = data.coeffs[9]; + + // first the y^3 coefficient, it coming only from a222: + double a = a222; + // next the y^2 coefficient (from a122 and a022): + double b = a122*x + a022; + // next the y coefficient (from a112, a012 and a002): + double c = a112*x*x + a012*x + a002; + // finally the constant coefficient (from a111, a011, a001 and a000): + double d = a111*x*x*x + a011*x*x + a001*x + a000; + + return calcCubicRoot ( ymin, ymax, a, b, c, d, root, valid, numroots ); +} + +const Coordinate calcCubicLineIntersect( const CubicCartesianData& cu, + const LineData& l, + int root, bool& valid ) +{ + assert( root == 1 || root == 2 || root == 3 ); + + double a, b, c, d; + calcCubicLineRestriction ( cu, l.a, l.b-l.a, a, b, c, d ); + int numroots; + double param = + calcCubicRoot ( -1e10, 1e10, a, b, c, d, root, valid, numroots ); + return l.a + param*(l.b - l.a); +} + +/* + * calculate the cubic polynomial resulting from the restriction + * of a cubic to a line (defined by two "Coordinates": a point and a + * direction) + */ + +void calcCubicLineRestriction ( CubicCartesianData data, + Coordinate p, Coordinate v, + double& a, double& b, double& c, double& d ) +{ + a = b = c = d = 0; + + double a000 = data.coeffs[0]; + double a001 = data.coeffs[1]; + double a002 = data.coeffs[2]; + double a011 = data.coeffs[3]; + double a012 = data.coeffs[4]; + double a022 = data.coeffs[5]; + double a111 = data.coeffs[6]; + double a112 = data.coeffs[7]; + double a122 = data.coeffs[8]; + double a222 = data.coeffs[9]; + + // zero degree term + d += a000; + + // first degree terms + d += a001*p.x + a002*p.y; + c += a001*v.x + a002*v.y; + + // second degree terms + d += a011*p.x*p.x + a012*p.x*p.y + a022*p.y*p.y; + c += 2*a011*p.x*v.x + a012*(p.x*v.y + v.x*p.y) + 2*a022*p.y*v.y; + b += a011*v.x*v.x + a012*v.x*v.y + a022*v.y*v.y; + + // third degree terms: a111 x^3 + a222 y^3 + d += a111*p.x*p.x*p.x + a222*p.y*p.y*p.y; + c += 3*(a111*p.x*p.x*v.x + a222*p.y*p.y*v.y); + b += 3*(a111*p.x*v.x*v.x + a222*p.y*v.y*v.y); + a += a111*v.x*v.x*v.x + a222*v.y*v.y*v.y; + + // third degree terms: a112 x^2 y + a122 x y^2 + d += a112*p.x*p.x*p.y + a122*p.x*p.y*p.y; + c += a112*(p.x*p.x*v.y + 2*p.x*v.x*p.y) + a122*(v.x*p.y*p.y + 2*p.x*p.y*v.y); + b += a112*(v.x*v.x*p.y + 2*v.x*p.x*v.y) + a122*(p.x*v.y*v.y + 2*v.x*v.y*p.y); + a += a112*v.x*v.x*v.y + a122*v.x*v.y*v.y; +} + + +const CubicCartesianData calcCubicTransformation ( + const CubicCartesianData& data, + const Transformation& t, bool& valid ) +{ + double a[3][3][3]; + double b[3][3][3]; + CubicCartesianData dataout; + + int icount = 0; + for (int i=0; i < 3; i++) + { + for (int j=i; j < 3; j++) + { + for (int k=j; k < 3; k++) + { + a[i][j][k] = data.coeffs[icount++]; + if ( i < k ) + { + if ( i == j ) // case aiik + { + a[i][i][k] /= 3.; + a[i][k][i] = a[k][i][i] = a[i][i][k]; + } + else if ( j == k ) // case aijj + { + a[i][j][j] /= 3.; + a[j][i][j] = a[j][j][i] = a[i][j][j]; + } + else // case aijk (i - Copyright (C) 2004 Pino Toscano - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA -**/ - - -#include "goniometry.h" - -#include - -#include -#include - -#include - -Goniometry::Goniometry() -{ - mvalue = 0.0; - msys = Rad; -} - -Goniometry::Goniometry( double value, Goniometry::System system ) -{ - mvalue = value; - msys = system; -} - -Goniometry::~Goniometry() -{ -} - -void Goniometry::setValue( double value ) -{ - mvalue = value; -} - -const double Goniometry::value() const -{ - return mvalue; -} - -void Goniometry::setSystem( Goniometry::System system ) -{ - msys = system; -} - -void Goniometry::convertTo( Goniometry::System system ) -{ - mvalue = convert( mvalue, msys, system ); - msys = system; -} - -const Goniometry::System Goniometry::system() const -{ - return msys; -} - -double Goniometry::getValue( Goniometry::System system ) -{ - return convert( mvalue, msys, system ); -} - -Goniometry& Goniometry::operator=( const Goniometry& g ) -{ - mvalue = g.value(); - msys = g.system(); - return *this; -} - -double Goniometry::convert( const double angle, const Goniometry::System from, const Goniometry::System to ) -{ - switch( from ) - { - case Deg: - { - if ( to == Rad ) - return angle * M_PI / 180; - if ( to == Grad ) - return angle * 10 / 9; - break; - } - case Rad: - { - if ( to == Deg ) - return angle * 180 / M_PI; - if ( to == Grad ) - return angle * 200 / M_PI; - break; - } - case Grad: - { - if ( to == Deg ) - return angle * 9 / 10; - if ( to == Rad ) - return angle * M_PI / 200; - break; - } - } - return angle; -} - -TQStringList Goniometry::systemList() -{ - TQStringList sl; - sl << i18n( "Translators: Degrees", "Deg" ); - sl << i18n( "Translators: Radians", "Rad" ); - sl << i18n( "Translators: Gradians", "Grad" ); - return sl; -} - -Goniometry::System Goniometry::intToSystem( const int index ) -{ - if( index == 0 ) - return Deg; - else if( index == 1 ) - return Rad; - else if( index == 2 ) - return Grad; - kdDebug() << "No goniometric system with index " << index << endl; - return Rad; -} diff --git a/kig/misc/goniometry.cpp b/kig/misc/goniometry.cpp new file mode 100644 index 00000000..ee4f75fa --- /dev/null +++ b/kig/misc/goniometry.cpp @@ -0,0 +1,137 @@ +/** + This file is part of Kig, a KDE program for Interactive Geometry... + Copyright (C) 2004 Dominique Devriese + Copyright (C) 2004 Pino Toscano + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA +**/ + + +#include "goniometry.h" + +#include + +#include +#include + +#include + +Goniometry::Goniometry() +{ + mvalue = 0.0; + msys = Rad; +} + +Goniometry::Goniometry( double value, Goniometry::System system ) +{ + mvalue = value; + msys = system; +} + +Goniometry::~Goniometry() +{ +} + +void Goniometry::setValue( double value ) +{ + mvalue = value; +} + +const double Goniometry::value() const +{ + return mvalue; +} + +void Goniometry::setSystem( Goniometry::System system ) +{ + msys = system; +} + +void Goniometry::convertTo( Goniometry::System system ) +{ + mvalue = convert( mvalue, msys, system ); + msys = system; +} + +const Goniometry::System Goniometry::system() const +{ + return msys; +} + +double Goniometry::getValue( Goniometry::System system ) +{ + return convert( mvalue, msys, system ); +} + +Goniometry& Goniometry::operator=( const Goniometry& g ) +{ + mvalue = g.value(); + msys = g.system(); + return *this; +} + +double Goniometry::convert( const double angle, const Goniometry::System from, const Goniometry::System to ) +{ + switch( from ) + { + case Deg: + { + if ( to == Rad ) + return angle * M_PI / 180; + if ( to == Grad ) + return angle * 10 / 9; + break; + } + case Rad: + { + if ( to == Deg ) + return angle * 180 / M_PI; + if ( to == Grad ) + return angle * 200 / M_PI; + break; + } + case Grad: + { + if ( to == Deg ) + return angle * 9 / 10; + if ( to == Rad ) + return angle * M_PI / 200; + break; + } + } + return angle; +} + +TQStringList Goniometry::systemList() +{ + TQStringList sl; + sl << i18n( "Translators: Degrees", "Deg" ); + sl << i18n( "Translators: Radians", "Rad" ); + sl << i18n( "Translators: Gradians", "Grad" ); + return sl; +} + +Goniometry::System Goniometry::intToSystem( const int index ) +{ + if( index == 0 ) + return Deg; + else if( index == 1 ) + return Rad; + else if( index == 2 ) + return Grad; + kdDebug() << "No goniometric system with index " << index << endl; + return Rad; +} diff --git a/kig/misc/guiaction.cc b/kig/misc/guiaction.cc deleted file mode 100644 index 0d7b35d9..00000000 --- a/kig/misc/guiaction.cc +++ /dev/null @@ -1,367 +0,0 @@ -// Copyright (C) 2002 Dominique Devriese - -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -// 02110-1301, USA. - -#include "guiaction.h" -#include "guiaction.moc" - -#include "coordinate_system.h" -#include "coordinate.h" -#include "object_constructor.h" - -#include "../kig/kig_part.h" -#include "../kig/kig_document.h" -#include "../misc/kiginputdialog.h" -#include "../modes/construct_mode.h" -#include "../modes/label.h" -#include "../objects/object_holder.h" -#include "../objects/object_factory.h" -#include "../objects/bogus_imp.h" - -#include -#include - -#include - -int GUIAction::shortcut() const -{ - return 0; -} - -GUIAction::~GUIAction() -{ -} - -ConstructibleAction::~ConstructibleAction() -{ -} - -ConstructibleAction::ConstructibleAction( - ObjectConstructor* ctor, - const TQCString& actionname, - int shortcut ) - : GUIAction(), mctor( ctor ), mactionname( actionname ), mshortcut( shortcut ) -{ -} - -TQString ConstructibleAction::description() const -{ - return mctor->description(); -} - -TQCString ConstructibleAction::iconFileName() const -{ - return mctor->iconFileName(); -} - -TQString ConstructibleAction::descriptiveName() const -{ - return mctor->descriptiveName(); -} - -void ConstructibleAction::act( KigPart& d ) -{ - BaseConstructMode* m = mctor->constructMode( d ); - d.runMode( m ); - delete m; -} - -KigGUIAction::KigGUIAction( GUIAction* act, - KigPart& doc, - TQObject* parent ) - : TDEAction( act->descriptiveName(), - doc.instance()->iconLoader()->loadIcon( - act->iconFileName(), TDEIcon::Toolbar, 0, TDEIcon::DefaultState, 0L, true ), - act->shortcut(), - 0, 0, // no slot connection - parent, act->actionName() ), - mact( act ), - mdoc( doc ) -{ - setWhatsThis( act->description() ); - TQString tooltip = act->descriptiveName(); - tooltip.replace( TQRegExp( "&&" ), "&" ); - setToolTip( tooltip ); -} - -void KigGUIAction::slotActivated() -{ - mact->act( mdoc ); -} - -const char* ConstructibleAction::actionName() const -{ - return mactionname; -} - -ConstructPointAction::~ConstructPointAction() -{ -} - -TQString ConstructPointAction::description() const -{ - return i18n( - "A normal point, i.e. one that is either independent or attached " - "to a line, circle, segment." - ); -} - -TQCString ConstructPointAction::iconFileName() const -{ - return "point"; -} - -TQString ConstructPointAction::descriptiveName() const -{ - return i18n("Point"); -} - -const char* ConstructPointAction::actionName() const -{ - return mactionname; -} - -int ConstructPointAction::shortcut() const -{ - return TQt::Key_P; -} - -void ConstructPointAction::act( KigPart& d ) -{ - PointConstructMode m( d ); - d.runMode( &m ); -} - -ConstructPointAction::ConstructPointAction( const char* actionname ) - : mactionname( actionname ) -{ -} - -GUIAction* KigGUIAction::guiAction() -{ - return mact; -} - -void KigGUIAction::plug( KigPart* doc ) -{ - mact->plug( doc, this ); -} - -void ConstructibleAction::plug( KigPart* doc, KigGUIAction* kact ) -{ - mctor->plug( doc, kact ); -} - -TQString ConstructTextLabelAction::description() const -{ - return i18n( "Construct a text label." ); -} - -TQCString ConstructTextLabelAction::iconFileName() const -{ - return "kig_text"; -} - -TQString ConstructTextLabelAction::descriptiveName() const -{ - return i18n( "Text Label" ); -} - -const char* ConstructTextLabelAction::actionName() const -{ - return mactionname; -} - -void ConstructTextLabelAction::act( KigPart& d ) -{ - TextLabelConstructionMode m( d ); - d.runMode( &m ); -} - -ConstructTextLabelAction::ConstructTextLabelAction( const char* actionname ) - : mactionname( actionname ) -{ -} - -TQString AddFixedPointAction::description() const -{ - return i18n( "Construct a Point by its Coordinates" ); -} - -TQCString AddFixedPointAction::iconFileName() const -{ - return "pointxy"; -} - -TQString AddFixedPointAction::descriptiveName() const -{ - return i18n( "Point by Coordinates" ); -} - -const char* AddFixedPointAction::actionName() const -{ - return mactionname; -} - -void AddFixedPointAction::act( KigPart& doc ) -{ - bool ok; - Coordinate c = Coordinate::invalidCoord(); - KigInputDialog::getCoordinate( - i18n( "Fixed Point" ), - i18n( "Enter the coordinates for the new point." ) + - TQString::fromLatin1( "
" ) + - doc.document().coordinateSystem().coordinateFormatNoticeMarkup(), - doc.widget(), &ok, doc.document(), &c ); - if ( ! ok ) return; - ObjectHolder* p = ObjectFactory::instance()->fixedPoint( c ); - p->calc( doc.document() ); - doc.addObject( p ); -} - -AddFixedPointAction::AddFixedPointAction( const char* actionname ) - : mactionname( actionname ) -{ -} - -AddFixedPointAction::~AddFixedPointAction() -{ -} - -void GUIAction::plug( KigPart*, KigGUIAction* ) -{ -} - -int ConstructibleAction::shortcut() const -{ - return mshortcut; -} - -int ConstructTextLabelAction::shortcut() const -{ - return TQt::Key_B; -} - -int AddFixedPointAction::shortcut() const -{ - return TQt::Key_F; -} - -#if 0 -TestAction::TestAction( const char* actionname ) - : mactionname( actionname ) -{ -} - -TestAction::~TestAction() -{ -} - -TQString TestAction::description() const -{ - return TQString::fromLatin1( "Test stuff !!!" ); -} - -TQCString TestAction::iconFileName() const -{ - return "new"; -} - -TQString TestAction::descriptiveName() const -{ - return TQString::fromLatin1( "Test stuff !!!" ); -} - -const char* TestAction::actionName() const -{ - return mactionname; -} - -void TestAction::act( KigPart& doc ) -{ - const char* script = - "def calc( a ):\n\treturn Point( a.coordinate() + Coordinate( 2, 0 ) )\n"; - Object* constantpoint = ObjectFactory::instance()->fixedPoint( Coordinate( -1, -1 ) ); - constantpoint->calc( doc ); - - Object* codeobject = new DataObject( new StringImp( TQString::fromLatin1( script ) ) ); - Object* compiledcode = new RealObject( PythonCompileType::instance(), Objects( codeobject ) ); - compiledcode->calc( doc ); - - Objects args( compiledcode ); - args.push_back( constantpoint ); - Object* scriptobject = new RealObject( PythonExecuteType::instance(), args ); - scriptobject->calc( doc ); - - doc.addObject( constantpoint ); - doc.addObject( scriptobject ); -} - -#endif // if 0 ( TestAction ) - -#ifdef KIG_ENABLE_PYTHON_SCRIPTING -#include "../scripting/python_type.h" -#include "../scripting/script_mode.h" - -NewScriptAction::NewScriptAction( const char* descname, const char* description, - const char* actionname, const ScriptType::Type type, - const char* icon ) - : GUIAction(), mactionname( actionname ), mdescname( descname ), - mdescription( description ), micon( icon ), mtype( type ) -{ - if ( TQString( micon ).isEmpty() ) - { - micon = ScriptType::icon( type ); - } -} - -NewScriptAction::~NewScriptAction() -{ -} - -TQString NewScriptAction::description() const -{ - return i18n( mdescription ); -} - -TQCString NewScriptAction::iconFileName() const -{ - return micon; -} - -TQString NewScriptAction::descriptiveName() const -{ - return i18n( mdescname ); -} - -const char* NewScriptAction::actionName() const -{ - return mactionname; -} - -void NewScriptAction::act( KigPart& doc ) -{ - ScriptCreationMode m( doc ); - m.setScriptType( mtype ); - doc.runMode( &m ); -} - -int NewScriptAction::shortcut() const -{ - return 0; -} - -#endif // if KIG_ENABLE_PYTHON_SCRIPTING ( NewScriptAction ) diff --git a/kig/misc/guiaction.cpp b/kig/misc/guiaction.cpp new file mode 100644 index 00000000..0d7b35d9 --- /dev/null +++ b/kig/misc/guiaction.cpp @@ -0,0 +1,367 @@ +// Copyright (C) 2002 Dominique Devriese + +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#include "guiaction.h" +#include "guiaction.moc" + +#include "coordinate_system.h" +#include "coordinate.h" +#include "object_constructor.h" + +#include "../kig/kig_part.h" +#include "../kig/kig_document.h" +#include "../misc/kiginputdialog.h" +#include "../modes/construct_mode.h" +#include "../modes/label.h" +#include "../objects/object_holder.h" +#include "../objects/object_factory.h" +#include "../objects/bogus_imp.h" + +#include +#include + +#include + +int GUIAction::shortcut() const +{ + return 0; +} + +GUIAction::~GUIAction() +{ +} + +ConstructibleAction::~ConstructibleAction() +{ +} + +ConstructibleAction::ConstructibleAction( + ObjectConstructor* ctor, + const TQCString& actionname, + int shortcut ) + : GUIAction(), mctor( ctor ), mactionname( actionname ), mshortcut( shortcut ) +{ +} + +TQString ConstructibleAction::description() const +{ + return mctor->description(); +} + +TQCString ConstructibleAction::iconFileName() const +{ + return mctor->iconFileName(); +} + +TQString ConstructibleAction::descriptiveName() const +{ + return mctor->descriptiveName(); +} + +void ConstructibleAction::act( KigPart& d ) +{ + BaseConstructMode* m = mctor->constructMode( d ); + d.runMode( m ); + delete m; +} + +KigGUIAction::KigGUIAction( GUIAction* act, + KigPart& doc, + TQObject* parent ) + : TDEAction( act->descriptiveName(), + doc.instance()->iconLoader()->loadIcon( + act->iconFileName(), TDEIcon::Toolbar, 0, TDEIcon::DefaultState, 0L, true ), + act->shortcut(), + 0, 0, // no slot connection + parent, act->actionName() ), + mact( act ), + mdoc( doc ) +{ + setWhatsThis( act->description() ); + TQString tooltip = act->descriptiveName(); + tooltip.replace( TQRegExp( "&&" ), "&" ); + setToolTip( tooltip ); +} + +void KigGUIAction::slotActivated() +{ + mact->act( mdoc ); +} + +const char* ConstructibleAction::actionName() const +{ + return mactionname; +} + +ConstructPointAction::~ConstructPointAction() +{ +} + +TQString ConstructPointAction::description() const +{ + return i18n( + "A normal point, i.e. one that is either independent or attached " + "to a line, circle, segment." + ); +} + +TQCString ConstructPointAction::iconFileName() const +{ + return "point"; +} + +TQString ConstructPointAction::descriptiveName() const +{ + return i18n("Point"); +} + +const char* ConstructPointAction::actionName() const +{ + return mactionname; +} + +int ConstructPointAction::shortcut() const +{ + return TQt::Key_P; +} + +void ConstructPointAction::act( KigPart& d ) +{ + PointConstructMode m( d ); + d.runMode( &m ); +} + +ConstructPointAction::ConstructPointAction( const char* actionname ) + : mactionname( actionname ) +{ +} + +GUIAction* KigGUIAction::guiAction() +{ + return mact; +} + +void KigGUIAction::plug( KigPart* doc ) +{ + mact->plug( doc, this ); +} + +void ConstructibleAction::plug( KigPart* doc, KigGUIAction* kact ) +{ + mctor->plug( doc, kact ); +} + +TQString ConstructTextLabelAction::description() const +{ + return i18n( "Construct a text label." ); +} + +TQCString ConstructTextLabelAction::iconFileName() const +{ + return "kig_text"; +} + +TQString ConstructTextLabelAction::descriptiveName() const +{ + return i18n( "Text Label" ); +} + +const char* ConstructTextLabelAction::actionName() const +{ + return mactionname; +} + +void ConstructTextLabelAction::act( KigPart& d ) +{ + TextLabelConstructionMode m( d ); + d.runMode( &m ); +} + +ConstructTextLabelAction::ConstructTextLabelAction( const char* actionname ) + : mactionname( actionname ) +{ +} + +TQString AddFixedPointAction::description() const +{ + return i18n( "Construct a Point by its Coordinates" ); +} + +TQCString AddFixedPointAction::iconFileName() const +{ + return "pointxy"; +} + +TQString AddFixedPointAction::descriptiveName() const +{ + return i18n( "Point by Coordinates" ); +} + +const char* AddFixedPointAction::actionName() const +{ + return mactionname; +} + +void AddFixedPointAction::act( KigPart& doc ) +{ + bool ok; + Coordinate c = Coordinate::invalidCoord(); + KigInputDialog::getCoordinate( + i18n( "Fixed Point" ), + i18n( "Enter the coordinates for the new point." ) + + TQString::fromLatin1( "
" ) + + doc.document().coordinateSystem().coordinateFormatNoticeMarkup(), + doc.widget(), &ok, doc.document(), &c ); + if ( ! ok ) return; + ObjectHolder* p = ObjectFactory::instance()->fixedPoint( c ); + p->calc( doc.document() ); + doc.addObject( p ); +} + +AddFixedPointAction::AddFixedPointAction( const char* actionname ) + : mactionname( actionname ) +{ +} + +AddFixedPointAction::~AddFixedPointAction() +{ +} + +void GUIAction::plug( KigPart*, KigGUIAction* ) +{ +} + +int ConstructibleAction::shortcut() const +{ + return mshortcut; +} + +int ConstructTextLabelAction::shortcut() const +{ + return TQt::Key_B; +} + +int AddFixedPointAction::shortcut() const +{ + return TQt::Key_F; +} + +#if 0 +TestAction::TestAction( const char* actionname ) + : mactionname( actionname ) +{ +} + +TestAction::~TestAction() +{ +} + +TQString TestAction::description() const +{ + return TQString::fromLatin1( "Test stuff !!!" ); +} + +TQCString TestAction::iconFileName() const +{ + return "new"; +} + +TQString TestAction::descriptiveName() const +{ + return TQString::fromLatin1( "Test stuff !!!" ); +} + +const char* TestAction::actionName() const +{ + return mactionname; +} + +void TestAction::act( KigPart& doc ) +{ + const char* script = + "def calc( a ):\n\treturn Point( a.coordinate() + Coordinate( 2, 0 ) )\n"; + Object* constantpoint = ObjectFactory::instance()->fixedPoint( Coordinate( -1, -1 ) ); + constantpoint->calc( doc ); + + Object* codeobject = new DataObject( new StringImp( TQString::fromLatin1( script ) ) ); + Object* compiledcode = new RealObject( PythonCompileType::instance(), Objects( codeobject ) ); + compiledcode->calc( doc ); + + Objects args( compiledcode ); + args.push_back( constantpoint ); + Object* scriptobject = new RealObject( PythonExecuteType::instance(), args ); + scriptobject->calc( doc ); + + doc.addObject( constantpoint ); + doc.addObject( scriptobject ); +} + +#endif // if 0 ( TestAction ) + +#ifdef KIG_ENABLE_PYTHON_SCRIPTING +#include "../scripting/python_type.h" +#include "../scripting/script_mode.h" + +NewScriptAction::NewScriptAction( const char* descname, const char* description, + const char* actionname, const ScriptType::Type type, + const char* icon ) + : GUIAction(), mactionname( actionname ), mdescname( descname ), + mdescription( description ), micon( icon ), mtype( type ) +{ + if ( TQString( micon ).isEmpty() ) + { + micon = ScriptType::icon( type ); + } +} + +NewScriptAction::~NewScriptAction() +{ +} + +TQString NewScriptAction::description() const +{ + return i18n( mdescription ); +} + +TQCString NewScriptAction::iconFileName() const +{ + return micon; +} + +TQString NewScriptAction::descriptiveName() const +{ + return i18n( mdescname ); +} + +const char* NewScriptAction::actionName() const +{ + return mactionname; +} + +void NewScriptAction::act( KigPart& doc ) +{ + ScriptCreationMode m( doc ); + m.setScriptType( mtype ); + doc.runMode( &m ); +} + +int NewScriptAction::shortcut() const +{ + return 0; +} + +#endif // if KIG_ENABLE_PYTHON_SCRIPTING ( NewScriptAction ) diff --git a/kig/misc/kigfiledialog.cc b/kig/misc/kigfiledialog.cc deleted file mode 100644 index 28d4dc74..00000000 --- a/kig/misc/kigfiledialog.cc +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (C) 2005 Pino Toscano - -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -// USA - -#include "kigfiledialog.h" -#include "kigfiledialog.moc" - -#include -#include - -#include -#include - -KigFileDialog::KigFileDialog( const TQString& startDir, const TQString& filter, - const TQString& caption, TQWidget* parent ) - : KFileDialog( startDir, filter, parent, "kigfiledialog", true ), - mow( 0L ) -{ - setCaption( caption ); - setOperationMode( Saving ); - setMode( KFile::File | KFile::LocalOnly ); - moptcaption = i18n( "Options" ); -} - -void KigFileDialog::setOptionsWidget( TQWidget* w ) -{ - mow = w; -} - -void KigFileDialog::accept() -{ - // i know this is an ugly hack, but i hadn't found other ways to get - // the selected file name _before_ the dialog is accept()'ed or - // reject()'ed... in every case, below we make sure to accept() or - // reject()... - setResult( TQDialog::Accepted ); - - TQString sFile = selectedFile(); - if ( TQFile::exists( sFile ) ) - { - int ret = KMessageBox::warningContinueCancel( this, - i18n( "The file \"%1\" already exists. Do you wish to overwrite it?" ) - .arg( sFile ), i18n( "Overwrite File?" ), i18n("Overwrite") ); - if ( ret != KMessageBox::Continue ) - { - KFileDialog::reject(); - return; - } - } - if ( mow ) - { - KDialogBase* optdlg = new KDialogBase( - this, "optdlg", true, moptcaption, Cancel|Ok, Cancel, true ); - mow->reparent( optdlg, TQPoint() ); - optdlg->setMainWidget( mow ); - optdlg->exec() == TQDialog::Accepted ? KFileDialog::accept() : KFileDialog::reject(); - } - else - KFileDialog::accept(); -} - -void KigFileDialog::setOptionCaption( const TQString& caption ) -{ - if ( caption.isEmpty() ) - return; - - moptcaption = caption; -} diff --git a/kig/misc/kigfiledialog.cpp b/kig/misc/kigfiledialog.cpp new file mode 100644 index 00000000..28d4dc74 --- /dev/null +++ b/kig/misc/kigfiledialog.cpp @@ -0,0 +1,81 @@ +// Copyright (C) 2005 Pino Toscano + +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 +// USA + +#include "kigfiledialog.h" +#include "kigfiledialog.moc" + +#include +#include + +#include +#include + +KigFileDialog::KigFileDialog( const TQString& startDir, const TQString& filter, + const TQString& caption, TQWidget* parent ) + : KFileDialog( startDir, filter, parent, "kigfiledialog", true ), + mow( 0L ) +{ + setCaption( caption ); + setOperationMode( Saving ); + setMode( KFile::File | KFile::LocalOnly ); + moptcaption = i18n( "Options" ); +} + +void KigFileDialog::setOptionsWidget( TQWidget* w ) +{ + mow = w; +} + +void KigFileDialog::accept() +{ + // i know this is an ugly hack, but i hadn't found other ways to get + // the selected file name _before_ the dialog is accept()'ed or + // reject()'ed... in every case, below we make sure to accept() or + // reject()... + setResult( TQDialog::Accepted ); + + TQString sFile = selectedFile(); + if ( TQFile::exists( sFile ) ) + { + int ret = KMessageBox::warningContinueCancel( this, + i18n( "The file \"%1\" already exists. Do you wish to overwrite it?" ) + .arg( sFile ), i18n( "Overwrite File?" ), i18n("Overwrite") ); + if ( ret != KMessageBox::Continue ) + { + KFileDialog::reject(); + return; + } + } + if ( mow ) + { + KDialogBase* optdlg = new KDialogBase( + this, "optdlg", true, moptcaption, Cancel|Ok, Cancel, true ); + mow->reparent( optdlg, TQPoint() ); + optdlg->setMainWidget( mow ); + optdlg->exec() == TQDialog::Accepted ? KFileDialog::accept() : KFileDialog::reject(); + } + else + KFileDialog::accept(); +} + +void KigFileDialog::setOptionCaption( const TQString& caption ) +{ + if ( caption.isEmpty() ) + return; + + moptcaption = caption; +} diff --git a/kig/misc/kiginputdialog.cc b/kig/misc/kiginputdialog.cc deleted file mode 100644 index a596c87c..00000000 --- a/kig/misc/kiginputdialog.cc +++ /dev/null @@ -1,283 +0,0 @@ -/** - This file is part of Kig, a KDE program for Interactive Geometry... - Copyright (C) 2005 Pino Toscano - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA -**/ - -#include "kiginputdialog.h" -#include "kiginputdialog.moc" - -#include "coordinate.h" -#include "coordinate_system.h" -#include "goniometry.h" - -#include "../kig/kig_document.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -class KigInputDialogPrivate -{ -public: - KigInputDialogPrivate(); - - TQLabel* m_label; - KLineEdit* m_lineEditFirst; - KLineEdit* m_lineEditSecond; - KComboBox* m_comboBox; - KTextEdit* m_textEdit; - - Coordinate m_coord1; - Coordinate m_coord2; - KigDocument m_doc; - TQValidator* m_vtor; - Goniometry m_gonio; - bool m_gonioIsNum; -}; - -KigInputDialogPrivate::KigInputDialogPrivate() - : m_label( 0L ), m_lineEditFirst( 0L ), m_lineEditSecond( 0L ), m_comboBox( 0L ), - m_textEdit( 0L ) -{ -} - -KigInputDialog::KigInputDialog( const TQString& caption, const TQString& label, - TQWidget* parent, const KigDocument& doc, Coordinate* c1, Coordinate* c2 ) - : KDialogBase( parent, "kigdialog", true, caption, Ok|Cancel, Cancel, true ), - d( new KigInputDialogPrivate() ) -{ - d->m_coord1 = c1 ? Coordinate( *c1 ) : Coordinate::invalidCoord(); - d->m_coord2 = c2 ? Coordinate( *c2 ) : Coordinate::invalidCoord(); - d->m_doc = doc; - d->m_vtor = d->m_doc.coordinateSystem().coordinateValidator(); - - int deltay = 0; - bool ok = false; - - TQFrame* frame = makeMainWidget(); - TQVBoxLayout* mainlay = new TQVBoxLayout( frame, 0, spacingHint() ); - mainlay->activate(); - - d->m_textEdit = new KTextEdit( frame ); - d->m_textEdit->setText( label ); - d->m_textEdit->setReadOnly( true ); - d->m_textEdit->setFocusPolicy( TQ_NoFocus ); -// d->m_textEdit->setAlignment( d->m_textEdit->alignment() | TQt::WordBreak ); - d->m_textEdit->setFrameStyle( TQFrame::NoFrame ); - mainlay->addWidget( d->m_textEdit ); - - d->m_lineEditFirst = new KLineEdit( frame ); -// d->m_lineEditFirst->setValidator( d->m_vtor ); - if ( d->m_coord1.valid() ) - { - d->m_lineEditFirst->setText( d->m_doc.coordinateSystem().fromScreen( d->m_coord1, d->m_doc ) ); - ok = true; - } - mainlay->addWidget( d->m_lineEditFirst ); - - connect( d->m_lineEditFirst, TQT_SIGNAL(textChanged(const TQString&)), - this, TQT_SLOT(slotCoordsChanged(const TQString&)) ); - - if ( d->m_coord2.valid() ) - { - d->m_lineEditSecond = new KLineEdit( frame ); -// d->m_lineEditSecond->setValidator( d->m_vtor ); - d->m_lineEditSecond->setText( d->m_doc.coordinateSystem().fromScreen( d->m_coord2, d->m_doc ) ); - mainlay->addWidget( d->m_lineEditSecond ); - - connect( d->m_lineEditSecond, TQT_SIGNAL(textChanged(const TQString&)), - this, TQT_SLOT(slotCoordsChanged(const TQString&)) ); - - deltay += d->m_lineEditSecond->height() + spacingHint(); - } - - resize( 400, 160 + deltay ); - - d->m_lineEditFirst->setFocus(); - - enableButtonOK( ok ); -} - -KigInputDialog::KigInputDialog( TQWidget* parent, const Goniometry& g ) - : KDialogBase( parent, "kigdialog", true, i18n( "Set Angle Size" ), Ok|Cancel, Cancel, true ), - d( new KigInputDialogPrivate() ) -{ - d->m_gonio = g; - d->m_gonioIsNum = true; - - TQFrame* frame = makeMainWidget(); - TQVBoxLayout* mainlay = new TQVBoxLayout( frame, 0, spacingHint() ); - mainlay->activate(); - - d->m_label = new TQLabel( frame ); - d->m_label->setText( i18n( "Insert the new size of this angle:" ) ); - mainlay->addWidget( d->m_label ); - - TQHBoxLayout* horlay = new TQHBoxLayout( 0, 0, spacingHint() ); - horlay->activate(); - - d->m_lineEditFirst = new KLineEdit( frame ); - d->m_lineEditFirst->setText( TQString::number( d->m_gonio.value() ) ); - TQWhatsThis::add( - d->m_lineEditFirst, - i18n( "Use this edit field to modify the size of this angle." ) ); - horlay->addWidget( d->m_lineEditFirst ); - - d->m_comboBox = new KComboBox( frame ); - d->m_comboBox->insertStringList( Goniometry::systemList() ); - d->m_comboBox->setCurrentItem( d->m_gonio.system() ); - TQWhatsThis::add( - d->m_comboBox, - i18n( "Choose from this list the goniometric unit you want to use to " - "modify the size of this angle.
\n" - "If you switch to another unit, the value in the edit field on " - "the left will be converted to the new selected unit." ) ); - horlay->addWidget( d->m_comboBox ); - - mainlay->addLayout( horlay ); - - connect( d->m_lineEditFirst, TQT_SIGNAL(textChanged(const TQString&)), - this, TQT_SLOT(slotGonioTextChanged(const TQString&)) ); - connect( d->m_comboBox, TQT_SIGNAL(activated(int)), - this, TQT_SLOT(slotGonioSystemChanged(int)) ); - - resize( 350, 100 ); - - d->m_lineEditFirst->setFocus(); -} - -void KigInputDialog::keyPressEvent( TQKeyEvent* e ) -{ - if ( ( e->key() == TQt::Key_Return ) && ( e->state() == 0 ) ) - { - if ( actionButton( Ok )->isEnabled() ) - { - actionButton( Ok )->animateClick(); - e->accept(); - return; - } - } - else if ( ( e->key() == TQt::Key_Escape ) && ( e->state() == 0 ) ) - { - actionButton( Cancel )->animateClick(); - e->accept(); - return; - } - -} - -void KigInputDialog::slotCoordsChanged( const TQString& ) -{ - int p = 0; - TQString t = d->m_lineEditFirst->text(); - bool ok = d->m_vtor->validate( t, p ) == TQValidator::Acceptable; - if ( ok ) - d->m_coord1 = d->m_doc.coordinateSystem().toScreen( t, ok ); - if ( d->m_lineEditSecond ) - { - p = 0; - t = d->m_lineEditSecond->text(); - ok &= d->m_vtor->validate( t, p ) == TQValidator::Acceptable; - if ( ok ) - d->m_coord2 = d->m_doc.coordinateSystem().toScreen( t, ok ); - } - - enableButtonOK( ok ); -} - -void KigInputDialog::slotGonioSystemChanged( int index ) -{ - if ( d->m_gonioIsNum ) - { - Goniometry::System newsys = Goniometry::intToSystem( index ); - d->m_gonio.convertTo( newsys ); - d->m_lineEditFirst->setText( TQString::number( d->m_gonio.value() ) ); - } -} - -void KigInputDialog::slotGonioTextChanged( const TQString& txt ) -{ - if ( txt.isNull() ) - d->m_gonioIsNum = false; - else - { - double v = txt.toDouble( &(d->m_gonioIsNum) ); - d->m_gonio.setValue( v ); - } - enableButtonOK( d->m_gonioIsNum ); -} - - -Coordinate KigInputDialog::coordinateFirst() const -{ - return d->m_coord1; -} - -Coordinate KigInputDialog::coordinateSecond() const -{ - return d->m_coord2; -} - -Goniometry KigInputDialog::goniometry() const -{ - return d->m_gonio; -} - -void KigInputDialog::getCoordinate( const TQString& caption, const TQString& label, - TQWidget* parent, bool* ok, const KigDocument& doc, Coordinate* cvalue ) -{ - getTwoCoordinates( caption, label, parent, ok, doc, cvalue, 0 ); -} - -void KigInputDialog::getTwoCoordinates( const TQString& caption, const TQString& label, - TQWidget* parent, bool* ok, const KigDocument& doc, Coordinate* cvalue, - Coordinate* cvalue2 ) -{ - KigInputDialog dlg( caption, label, parent, doc, cvalue, cvalue2 ); - - *ok = ( dlg.exec() == Accepted ); - - if ( *ok ) - { - Coordinate a = dlg.coordinateFirst(); - *cvalue = a; - if ( cvalue2 ) - { - Coordinate b = dlg.coordinateSecond(); - *cvalue2 = b; - } - } - -} - -Goniometry KigInputDialog::getAngle( TQWidget* parent, bool* ok, const Goniometry& g ) -{ - KigInputDialog dlg( parent, g ); - - *ok = ( dlg.exec() == Accepted ); - - return dlg.goniometry(); -} diff --git a/kig/misc/kiginputdialog.cpp b/kig/misc/kiginputdialog.cpp new file mode 100644 index 00000000..a596c87c --- /dev/null +++ b/kig/misc/kiginputdialog.cpp @@ -0,0 +1,283 @@ +/** + This file is part of Kig, a KDE program for Interactive Geometry... + Copyright (C) 2005 Pino Toscano + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA +**/ + +#include "kiginputdialog.h" +#include "kiginputdialog.moc" + +#include "coordinate.h" +#include "coordinate_system.h" +#include "goniometry.h" + +#include "../kig/kig_document.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +class KigInputDialogPrivate +{ +public: + KigInputDialogPrivate(); + + TQLabel* m_label; + KLineEdit* m_lineEditFirst; + KLineEdit* m_lineEditSecond; + KComboBox* m_comboBox; + KTextEdit* m_textEdit; + + Coordinate m_coord1; + Coordinate m_coord2; + KigDocument m_doc; + TQValidator* m_vtor; + Goniometry m_gonio; + bool m_gonioIsNum; +}; + +KigInputDialogPrivate::KigInputDialogPrivate() + : m_label( 0L ), m_lineEditFirst( 0L ), m_lineEditSecond( 0L ), m_comboBox( 0L ), + m_textEdit( 0L ) +{ +} + +KigInputDialog::KigInputDialog( const TQString& caption, const TQString& label, + TQWidget* parent, const KigDocument& doc, Coordinate* c1, Coordinate* c2 ) + : KDialogBase( parent, "kigdialog", true, caption, Ok|Cancel, Cancel, true ), + d( new KigInputDialogPrivate() ) +{ + d->m_coord1 = c1 ? Coordinate( *c1 ) : Coordinate::invalidCoord(); + d->m_coord2 = c2 ? Coordinate( *c2 ) : Coordinate::invalidCoord(); + d->m_doc = doc; + d->m_vtor = d->m_doc.coordinateSystem().coordinateValidator(); + + int deltay = 0; + bool ok = false; + + TQFrame* frame = makeMainWidget(); + TQVBoxLayout* mainlay = new TQVBoxLayout( frame, 0, spacingHint() ); + mainlay->activate(); + + d->m_textEdit = new KTextEdit( frame ); + d->m_textEdit->setText( label ); + d->m_textEdit->setReadOnly( true ); + d->m_textEdit->setFocusPolicy( TQ_NoFocus ); +// d->m_textEdit->setAlignment( d->m_textEdit->alignment() | TQt::WordBreak ); + d->m_textEdit->setFrameStyle( TQFrame::NoFrame ); + mainlay->addWidget( d->m_textEdit ); + + d->m_lineEditFirst = new KLineEdit( frame ); +// d->m_lineEditFirst->setValidator( d->m_vtor ); + if ( d->m_coord1.valid() ) + { + d->m_lineEditFirst->setText( d->m_doc.coordinateSystem().fromScreen( d->m_coord1, d->m_doc ) ); + ok = true; + } + mainlay->addWidget( d->m_lineEditFirst ); + + connect( d->m_lineEditFirst, TQT_SIGNAL(textChanged(const TQString&)), + this, TQT_SLOT(slotCoordsChanged(const TQString&)) ); + + if ( d->m_coord2.valid() ) + { + d->m_lineEditSecond = new KLineEdit( frame ); +// d->m_lineEditSecond->setValidator( d->m_vtor ); + d->m_lineEditSecond->setText( d->m_doc.coordinateSystem().fromScreen( d->m_coord2, d->m_doc ) ); + mainlay->addWidget( d->m_lineEditSecond ); + + connect( d->m_lineEditSecond, TQT_SIGNAL(textChanged(const TQString&)), + this, TQT_SLOT(slotCoordsChanged(const TQString&)) ); + + deltay += d->m_lineEditSecond->height() + spacingHint(); + } + + resize( 400, 160 + deltay ); + + d->m_lineEditFirst->setFocus(); + + enableButtonOK( ok ); +} + +KigInputDialog::KigInputDialog( TQWidget* parent, const Goniometry& g ) + : KDialogBase( parent, "kigdialog", true, i18n( "Set Angle Size" ), Ok|Cancel, Cancel, true ), + d( new KigInputDialogPrivate() ) +{ + d->m_gonio = g; + d->m_gonioIsNum = true; + + TQFrame* frame = makeMainWidget(); + TQVBoxLayout* mainlay = new TQVBoxLayout( frame, 0, spacingHint() ); + mainlay->activate(); + + d->m_label = new TQLabel( frame ); + d->m_label->setText( i18n( "Insert the new size of this angle:" ) ); + mainlay->addWidget( d->m_label ); + + TQHBoxLayout* horlay = new TQHBoxLayout( 0, 0, spacingHint() ); + horlay->activate(); + + d->m_lineEditFirst = new KLineEdit( frame ); + d->m_lineEditFirst->setText( TQString::number( d->m_gonio.value() ) ); + TQWhatsThis::add( + d->m_lineEditFirst, + i18n( "Use this edit field to modify the size of this angle." ) ); + horlay->addWidget( d->m_lineEditFirst ); + + d->m_comboBox = new KComboBox( frame ); + d->m_comboBox->insertStringList( Goniometry::systemList() ); + d->m_comboBox->setCurrentItem( d->m_gonio.system() ); + TQWhatsThis::add( + d->m_comboBox, + i18n( "Choose from this list the goniometric unit you want to use to " + "modify the size of this angle.
\n" + "If you switch to another unit, the value in the edit field on " + "the left will be converted to the new selected unit." ) ); + horlay->addWidget( d->m_comboBox ); + + mainlay->addLayout( horlay ); + + connect( d->m_lineEditFirst, TQT_SIGNAL(textChanged(const TQString&)), + this, TQT_SLOT(slotGonioTextChanged(const TQString&)) ); + connect( d->m_comboBox, TQT_SIGNAL(activated(int)), + this, TQT_SLOT(slotGonioSystemChanged(int)) ); + + resize( 350, 100 ); + + d->m_lineEditFirst->setFocus(); +} + +void KigInputDialog::keyPressEvent( TQKeyEvent* e ) +{ + if ( ( e->key() == TQt::Key_Return ) && ( e->state() == 0 ) ) + { + if ( actionButton( Ok )->isEnabled() ) + { + actionButton( Ok )->animateClick(); + e->accept(); + return; + } + } + else if ( ( e->key() == TQt::Key_Escape ) && ( e->state() == 0 ) ) + { + actionButton( Cancel )->animateClick(); + e->accept(); + return; + } + +} + +void KigInputDialog::slotCoordsChanged( const TQString& ) +{ + int p = 0; + TQString t = d->m_lineEditFirst->text(); + bool ok = d->m_vtor->validate( t, p ) == TQValidator::Acceptable; + if ( ok ) + d->m_coord1 = d->m_doc.coordinateSystem().toScreen( t, ok ); + if ( d->m_lineEditSecond ) + { + p = 0; + t = d->m_lineEditSecond->text(); + ok &= d->m_vtor->validate( t, p ) == TQValidator::Acceptable; + if ( ok ) + d->m_coord2 = d->m_doc.coordinateSystem().toScreen( t, ok ); + } + + enableButtonOK( ok ); +} + +void KigInputDialog::slotGonioSystemChanged( int index ) +{ + if ( d->m_gonioIsNum ) + { + Goniometry::System newsys = Goniometry::intToSystem( index ); + d->m_gonio.convertTo( newsys ); + d->m_lineEditFirst->setText( TQString::number( d->m_gonio.value() ) ); + } +} + +void KigInputDialog::slotGonioTextChanged( const TQString& txt ) +{ + if ( txt.isNull() ) + d->m_gonioIsNum = false; + else + { + double v = txt.toDouble( &(d->m_gonioIsNum) ); + d->m_gonio.setValue( v ); + } + enableButtonOK( d->m_gonioIsNum ); +} + + +Coordinate KigInputDialog::coordinateFirst() const +{ + return d->m_coord1; +} + +Coordinate KigInputDialog::coordinateSecond() const +{ + return d->m_coord2; +} + +Goniometry KigInputDialog::goniometry() const +{ + return d->m_gonio; +} + +void KigInputDialog::getCoordinate( const TQString& caption, const TQString& label, + TQWidget* parent, bool* ok, const KigDocument& doc, Coordinate* cvalue ) +{ + getTwoCoordinates( caption, label, parent, ok, doc, cvalue, 0 ); +} + +void KigInputDialog::getTwoCoordinates( const TQString& caption, const TQString& label, + TQWidget* parent, bool* ok, const KigDocument& doc, Coordinate* cvalue, + Coordinate* cvalue2 ) +{ + KigInputDialog dlg( caption, label, parent, doc, cvalue, cvalue2 ); + + *ok = ( dlg.exec() == Accepted ); + + if ( *ok ) + { + Coordinate a = dlg.coordinateFirst(); + *cvalue = a; + if ( cvalue2 ) + { + Coordinate b = dlg.coordinateSecond(); + *cvalue2 = b; + } + } + +} + +Goniometry KigInputDialog::getAngle( TQWidget* parent, bool* ok, const Goniometry& g ) +{ + KigInputDialog dlg( parent, g ); + + *ok = ( dlg.exec() == Accepted ); + + return dlg.goniometry(); +} diff --git a/kig/misc/lists.cc b/kig/misc/lists.cc deleted file mode 100644 index f0e0c3f7..00000000 --- a/kig/misc/lists.cc +++ /dev/null @@ -1,389 +0,0 @@ -// Copyright (C) 2003 Dominique Devriese - -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -// 02110-1301, USA. - -#include "lists.h" - -#include "object_constructor.h" -#include "guiaction.h" -#include "object_hierarchy.h" -#include "../kig/kig_part.h" - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -using namespace std; - -template -void vect_remove( std::vector& v, const T& t ) -{ - typename std::vector::iterator new_end = std::remove( v.begin(), v.end(), t ); - v.erase( new_end, v.end() ); -} - -GUIActionList* GUIActionList::instance() -{ - static GUIActionList l; - return &l; -} - -GUIActionList::~GUIActionList() -{ - for ( avectype::iterator i = mactions.begin(); i != mactions.end(); ++i ) - delete *i; -} - -GUIActionList::GUIActionList() -{ -} - -void GUIActionList::regDoc( KigPart* d ) -{ - mdocs.insert( d ); -} - -void GUIActionList::unregDoc( KigPart* d ) -{ - mdocs.erase( d ); -} - -void GUIActionList::add( const std::vector& a ) -{ - copy( a.begin(), a.end(), inserter( mactions, mactions.begin() ) ); - for ( dvectype::iterator i = mdocs.begin(); i != mdocs.end(); ++i ) - { - KigPart::GUIUpdateToken t = (*i)->startGUIActionUpdate(); - for ( uint j = 0; j < a.size(); ++j ) - (*i)->actionAdded( a[j], t ); - (*i)->endGUIActionUpdate( t ); - }; -} - -void GUIActionList::add( GUIAction* a ) -{ - mactions.insert( a ); - for ( dvectype::iterator i = mdocs.begin(); i != mdocs.end(); ++i ) - { - KigPart::GUIUpdateToken t = (*i)->startGUIActionUpdate(); - (*i)->actionAdded( a, t ); - (*i)->endGUIActionUpdate( t ); - }; -} - -void GUIActionList::remove( const std::vector& a ) -{ - for ( uint i = 0; i < a.size(); ++i ) - { - mactions.erase( a[i] ); - }; - for ( dvectype::iterator i = mdocs.begin(); i != mdocs.end(); ++i ) - { - KigPart::GUIUpdateToken t = (*i)->startGUIActionUpdate(); - for ( uint j = 0; j < a.size(); ++j ) - (*i)->actionRemoved( a[j], t ); - (*i)->endGUIActionUpdate( t ); - }; - delete_all( a.begin(), a.end() ); -} - -void GUIActionList::remove( GUIAction* a ) -{ - mactions.erase( a ); - for ( dvectype::iterator i = mdocs.begin(); i != mdocs.end(); ++i ) - { - KigPart::GUIUpdateToken t = (*i)->startGUIActionUpdate(); - (*i)->actionRemoved( a, t ); - (*i)->endGUIActionUpdate( t ); - }; - delete a; -} - -ObjectConstructorList::ObjectConstructorList() -{ -} - -ObjectConstructorList::~ObjectConstructorList() -{ - for ( vectype::iterator i = mctors.begin(); i != mctors.end(); ++i ) - delete *i; -} - -ObjectConstructorList* ObjectConstructorList::instance() -{ - static ObjectConstructorList s; - return &s; -} - -ObjectConstructorList::vectype ObjectConstructorList::ctorsThatWantArgs( - const std::vector& os, const KigDocument& d, - const KigWidget& w, bool co ) const -{ - vectype ret; - for ( vectype::const_iterator i = mctors.begin(); i != mctors.end(); ++i ) - { - int r = (*i)->wantArgs( os, d, w ); - if ( r == ArgsParser::Complete || ( !co && r == ArgsParser::Valid ) ) - ret.push_back( *i ); - }; - return ret; -} - -void ObjectConstructorList::remove( ObjectConstructor* a ) -{ - vect_remove( mctors, a ); - delete a; -} - -void ObjectConstructorList::add( ObjectConstructor* a ) -{ - mctors.push_back( a ); -} - -Macro::Macro( GUIAction* a, MacroConstructor* c ) - : action( a ), ctor( c ) -{ -} - -bool operator==( const Macro& l, const Macro& r ) -{ - return ( l.action->descriptiveName() == r.action->descriptiveName() ) && - ( l.action->description() == r.action->description() ) && - ( l.action->iconFileName() == r.action->iconFileName() ); -} - -MacroList::MacroList() -{ -} - -MacroList::~MacroList() -{ - std::vector actions; - std::vector ctors; - for ( vectype::iterator i = mdata.begin(); i != mdata.end(); ++i ) - { - Macro* m = *i; - GUIAction* a = m->action; - actions.push_back( a ); - ObjectConstructor* c = m->ctor; - ctors.push_back( c ); - delete m; - }; - mdata.clear(); - GUIActionList::instance()->remove( actions ); - for ( uint i = 0; i < ctors.size(); ++i ) - ObjectConstructorList::instance()->remove( ctors[i] ); -} - -MacroList* MacroList::instance() -{ - static MacroList t; - return &t; -} - -void MacroList::add( const std::vector& ms ) -{ - copy( ms.begin(), ms.end(), back_inserter( mdata ) ); - std::vector acts; - for ( uint i = 0; i < ms.size(); ++i ) - { - ObjectConstructorList::instance()->add( ms[i]->ctor ); - acts.push_back( ms[i]->action ); - }; - GUIActionList::instance()->add( acts ); -} - -void MacroList::add( Macro* m ) -{ - mdata.push_back( m ); - ObjectConstructorList::instance()->add( m->ctor ); - GUIActionList::instance()->add( m->action ); -} - -void MacroList::remove( Macro* m ) -{ - GUIAction* a = m->action; - ObjectConstructor* c = m->ctor; - mdata.erase( std::remove( mdata.begin(), mdata.end(), m ), - mdata.end() ); - delete m; - GUIActionList::instance()->remove( a ); - ObjectConstructorList::instance()->remove( c ); -} - -const MacroList::vectype& MacroList::macros() const -{ - return mdata; -} - -Macro::~Macro() -{ -} - -bool MacroList::save( Macro* m, const TQString& f ) -{ - std::vector ms; - ms.push_back( m ); - return save( ms, f ); -} - -bool MacroList::save( const std::vector& ms, const TQString& f ) -{ - TQDomDocument doc( "KigMacroFile" ); - - TQDomElement docelem = doc.createElement( "KigMacroFile" ); - docelem.setAttribute( "Version", KIGVERSION ); - docelem.setAttribute( "Number", ms.size() ); - - for ( uint i = 0; i < ms.size(); ++i ) - { - MacroConstructor* ctor = ms[i]->ctor; - - TQDomElement macroelem = doc.createElement( "Macro" ); - - // name - TQDomElement nameelem = doc.createElement( "Name" ); - nameelem.appendChild( doc.createTextNode( ctor->descriptiveName() ) ); - macroelem.appendChild( nameelem ); - - // desc - TQDomElement descelem = doc.createElement( "Description" ); - descelem.appendChild( doc.createTextNode( ctor->description() ) ); - macroelem.appendChild( descelem ); - - // icon - TQCString icon = ctor->iconFileName( true ); - if ( !icon.isNull() ) - { - TQDomElement descelem = doc.createElement( "IconFileName" ); - descelem.appendChild( doc.createTextNode( icon ) ); - macroelem.appendChild( descelem ); - } - - // data - TQDomElement hierelem = doc.createElement( "Construction" ); - ctor->hierarchy().serialize( hierelem, doc ); - macroelem.appendChild( hierelem ); - - docelem.appendChild( macroelem ); - }; - - doc.appendChild( docelem ); - - TQFile file( f ); - if ( ! file.open( IO_WriteOnly ) ) - return false; - TQTextStream stream( &file ); - stream << doc.toCString(); - return true; -} - -bool MacroList::load( const TQString& f, std::vector& ret, const KigPart& kdoc ) -{ - TQFile file( f ); - if ( ! file.open( IO_ReadOnly ) ) - { - KMessageBox::sorry( 0, i18n( "Could not open macro file '%1'" ).arg( f ) ); - return false; - } - TQDomDocument doc( "KigMacroFile" ); - if ( !doc.setContent( &file ) ) - { - KMessageBox::sorry( 0, i18n( "Could not open macro file '%1'" ).arg( f ) ); - return false; - } - file.close(); - TQDomElement main = doc.documentElement(); - - if ( main.tagName() == "KigMacroFile" ) - return loadNew( main, ret, kdoc ); - else - { - KMessageBox::detailedSorry( - 0, i18n( "Kig cannot open the macro file \"%1\"." ).arg( f ), - i18n( "This file was created by a very old Kig version (pre-0.4). " - "Support for this format has been removed from recent Kig versions. " - "You can try to import this macro using a previous Kig version " - "(0.4 to 0.6) and then export it again in the new format." ), - i18n( "Not Supported" ) ); - return false; - } -} - -bool MacroList::loadNew( const TQDomElement& docelem, std::vector& ret, const KigPart& ) -{ - bool sok = true; - // unused.. -// int number = docelem.attribute( "Number" ).toInt( &sok ); - if ( ! sok ) return false; - - TQString version = docelem.attribute( "Version" ); -// TQRegExp re( "(\\d+)\\.(\\d+)\\.(\\d+)" ); -// re.match( version ); - // unused.. -// int major = re.cap( 1 ).toInt( &sok ); -// int minor = re.cap( 2 ).toInt( &sok ); -// int mminor = re.cap( 3 ).toInt( &sok ); -// if ( ! sok ) return false; - - int unnamedindex = 1; - TQString tmp; - - for ( TQDomElement macroelem = docelem.firstChild().toElement(); - ! macroelem.isNull(); macroelem = macroelem.nextSibling().toElement() ) - { - TQString name, description; - ObjectHierarchy* hierarchy = 0; - TQCString actionname, iconfile; - if ( macroelem.tagName() != "Macro" ) continue; // forward compat ? - for ( TQDomElement dataelem = macroelem.firstChild().toElement(); - ! dataelem.isNull(); dataelem = dataelem.nextSibling().toElement() ) - { - if ( dataelem.tagName() == "Name" ) - name = dataelem.text(); - else if ( dataelem.tagName() == "Description" ) - description = dataelem.text(); - else if ( dataelem.tagName() == "Construction" ) - hierarchy = ObjectHierarchy::buildSafeObjectHierarchy( dataelem, tmp ); - else if ( dataelem.tagName() == "ActionName" ) - actionname = dataelem.text().latin1(); - else if ( dataelem.tagName() == "IconFileName" ) - iconfile = dataelem.text().latin1(); - else continue; - }; - assert( hierarchy ); - // if the macro has no name, we give it a bogus name... - if ( name.isEmpty() ) - name = i18n( "Unnamed Macro #%1" ).arg( unnamedindex++ ); - MacroConstructor* ctor = - new MacroConstructor( *hierarchy, i18n( name.latin1() ), i18n( description.latin1() ), iconfile ); - delete hierarchy; - GUIAction* act = new ConstructibleAction( ctor, actionname ); - Macro* macro = new Macro( act, ctor ); - ret.push_back( macro ); - }; - return true; -} - -const ObjectConstructorList::vectype& ObjectConstructorList::constructors() const -{ - return mctors; -} diff --git a/kig/misc/lists.cpp b/kig/misc/lists.cpp new file mode 100644 index 00000000..f0e0c3f7 --- /dev/null +++ b/kig/misc/lists.cpp @@ -0,0 +1,389 @@ +// Copyright (C) 2003 Dominique Devriese + +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#include "lists.h" + +#include "object_constructor.h" +#include "guiaction.h" +#include "object_hierarchy.h" +#include "../kig/kig_part.h" + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +template +void vect_remove( std::vector& v, const T& t ) +{ + typename std::vector::iterator new_end = std::remove( v.begin(), v.end(), t ); + v.erase( new_end, v.end() ); +} + +GUIActionList* GUIActionList::instance() +{ + static GUIActionList l; + return &l; +} + +GUIActionList::~GUIActionList() +{ + for ( avectype::iterator i = mactions.begin(); i != mactions.end(); ++i ) + delete *i; +} + +GUIActionList::GUIActionList() +{ +} + +void GUIActionList::regDoc( KigPart* d ) +{ + mdocs.insert( d ); +} + +void GUIActionList::unregDoc( KigPart* d ) +{ + mdocs.erase( d ); +} + +void GUIActionList::add( const std::vector& a ) +{ + copy( a.begin(), a.end(), inserter( mactions, mactions.begin() ) ); + for ( dvectype::iterator i = mdocs.begin(); i != mdocs.end(); ++i ) + { + KigPart::GUIUpdateToken t = (*i)->startGUIActionUpdate(); + for ( uint j = 0; j < a.size(); ++j ) + (*i)->actionAdded( a[j], t ); + (*i)->endGUIActionUpdate( t ); + }; +} + +void GUIActionList::add( GUIAction* a ) +{ + mactions.insert( a ); + for ( dvectype::iterator i = mdocs.begin(); i != mdocs.end(); ++i ) + { + KigPart::GUIUpdateToken t = (*i)->startGUIActionUpdate(); + (*i)->actionAdded( a, t ); + (*i)->endGUIActionUpdate( t ); + }; +} + +void GUIActionList::remove( const std::vector& a ) +{ + for ( uint i = 0; i < a.size(); ++i ) + { + mactions.erase( a[i] ); + }; + for ( dvectype::iterator i = mdocs.begin(); i != mdocs.end(); ++i ) + { + KigPart::GUIUpdateToken t = (*i)->startGUIActionUpdate(); + for ( uint j = 0; j < a.size(); ++j ) + (*i)->actionRemoved( a[j], t ); + (*i)->endGUIActionUpdate( t ); + }; + delete_all( a.begin(), a.end() ); +} + +void GUIActionList::remove( GUIAction* a ) +{ + mactions.erase( a ); + for ( dvectype::iterator i = mdocs.begin(); i != mdocs.end(); ++i ) + { + KigPart::GUIUpdateToken t = (*i)->startGUIActionUpdate(); + (*i)->actionRemoved( a, t ); + (*i)->endGUIActionUpdate( t ); + }; + delete a; +} + +ObjectConstructorList::ObjectConstructorList() +{ +} + +ObjectConstructorList::~ObjectConstructorList() +{ + for ( vectype::iterator i = mctors.begin(); i != mctors.end(); ++i ) + delete *i; +} + +ObjectConstructorList* ObjectConstructorList::instance() +{ + static ObjectConstructorList s; + return &s; +} + +ObjectConstructorList::vectype ObjectConstructorList::ctorsThatWantArgs( + const std::vector& os, const KigDocument& d, + const KigWidget& w, bool co ) const +{ + vectype ret; + for ( vectype::const_iterator i = mctors.begin(); i != mctors.end(); ++i ) + { + int r = (*i)->wantArgs( os, d, w ); + if ( r == ArgsParser::Complete || ( !co && r == ArgsParser::Valid ) ) + ret.push_back( *i ); + }; + return ret; +} + +void ObjectConstructorList::remove( ObjectConstructor* a ) +{ + vect_remove( mctors, a ); + delete a; +} + +void ObjectConstructorList::add( ObjectConstructor* a ) +{ + mctors.push_back( a ); +} + +Macro::Macro( GUIAction* a, MacroConstructor* c ) + : action( a ), ctor( c ) +{ +} + +bool operator==( const Macro& l, const Macro& r ) +{ + return ( l.action->descriptiveName() == r.action->descriptiveName() ) && + ( l.action->description() == r.action->description() ) && + ( l.action->iconFileName() == r.action->iconFileName() ); +} + +MacroList::MacroList() +{ +} + +MacroList::~MacroList() +{ + std::vector actions; + std::vector ctors; + for ( vectype::iterator i = mdata.begin(); i != mdata.end(); ++i ) + { + Macro* m = *i; + GUIAction* a = m->action; + actions.push_back( a ); + ObjectConstructor* c = m->ctor; + ctors.push_back( c ); + delete m; + }; + mdata.clear(); + GUIActionList::instance()->remove( actions ); + for ( uint i = 0; i < ctors.size(); ++i ) + ObjectConstructorList::instance()->remove( ctors[i] ); +} + +MacroList* MacroList::instance() +{ + static MacroList t; + return &t; +} + +void MacroList::add( const std::vector& ms ) +{ + copy( ms.begin(), ms.end(), back_inserter( mdata ) ); + std::vector acts; + for ( uint i = 0; i < ms.size(); ++i ) + { + ObjectConstructorList::instance()->add( ms[i]->ctor ); + acts.push_back( ms[i]->action ); + }; + GUIActionList::instance()->add( acts ); +} + +void MacroList::add( Macro* m ) +{ + mdata.push_back( m ); + ObjectConstructorList::instance()->add( m->ctor ); + GUIActionList::instance()->add( m->action ); +} + +void MacroList::remove( Macro* m ) +{ + GUIAction* a = m->action; + ObjectConstructor* c = m->ctor; + mdata.erase( std::remove( mdata.begin(), mdata.end(), m ), + mdata.end() ); + delete m; + GUIActionList::instance()->remove( a ); + ObjectConstructorList::instance()->remove( c ); +} + +const MacroList::vectype& MacroList::macros() const +{ + return mdata; +} + +Macro::~Macro() +{ +} + +bool MacroList::save( Macro* m, const TQString& f ) +{ + std::vector ms; + ms.push_back( m ); + return save( ms, f ); +} + +bool MacroList::save( const std::vector& ms, const TQString& f ) +{ + TQDomDocument doc( "KigMacroFile" ); + + TQDomElement docelem = doc.createElement( "KigMacroFile" ); + docelem.setAttribute( "Version", KIGVERSION ); + docelem.setAttribute( "Number", ms.size() ); + + for ( uint i = 0; i < ms.size(); ++i ) + { + MacroConstructor* ctor = ms[i]->ctor; + + TQDomElement macroelem = doc.createElement( "Macro" ); + + // name + TQDomElement nameelem = doc.createElement( "Name" ); + nameelem.appendChild( doc.createTextNode( ctor->descriptiveName() ) ); + macroelem.appendChild( nameelem ); + + // desc + TQDomElement descelem = doc.createElement( "Description" ); + descelem.appendChild( doc.createTextNode( ctor->description() ) ); + macroelem.appendChild( descelem ); + + // icon + TQCString icon = ctor->iconFileName( true ); + if ( !icon.isNull() ) + { + TQDomElement descelem = doc.createElement( "IconFileName" ); + descelem.appendChild( doc.createTextNode( icon ) ); + macroelem.appendChild( descelem ); + } + + // data + TQDomElement hierelem = doc.createElement( "Construction" ); + ctor->hierarchy().serialize( hierelem, doc ); + macroelem.appendChild( hierelem ); + + docelem.appendChild( macroelem ); + }; + + doc.appendChild( docelem ); + + TQFile file( f ); + if ( ! file.open( IO_WriteOnly ) ) + return false; + TQTextStream stream( &file ); + stream << doc.toCString(); + return true; +} + +bool MacroList::load( const TQString& f, std::vector& ret, const KigPart& kdoc ) +{ + TQFile file( f ); + if ( ! file.open( IO_ReadOnly ) ) + { + KMessageBox::sorry( 0, i18n( "Could not open macro file '%1'" ).arg( f ) ); + return false; + } + TQDomDocument doc( "KigMacroFile" ); + if ( !doc.setContent( &file ) ) + { + KMessageBox::sorry( 0, i18n( "Could not open macro file '%1'" ).arg( f ) ); + return false; + } + file.close(); + TQDomElement main = doc.documentElement(); + + if ( main.tagName() == "KigMacroFile" ) + return loadNew( main, ret, kdoc ); + else + { + KMessageBox::detailedSorry( + 0, i18n( "Kig cannot open the macro file \"%1\"." ).arg( f ), + i18n( "This file was created by a very old Kig version (pre-0.4). " + "Support for this format has been removed from recent Kig versions. " + "You can try to import this macro using a previous Kig version " + "(0.4 to 0.6) and then export it again in the new format." ), + i18n( "Not Supported" ) ); + return false; + } +} + +bool MacroList::loadNew( const TQDomElement& docelem, std::vector& ret, const KigPart& ) +{ + bool sok = true; + // unused.. +// int number = docelem.attribute( "Number" ).toInt( &sok ); + if ( ! sok ) return false; + + TQString version = docelem.attribute( "Version" ); +// TQRegExp re( "(\\d+)\\.(\\d+)\\.(\\d+)" ); +// re.match( version ); + // unused.. +// int major = re.cap( 1 ).toInt( &sok ); +// int minor = re.cap( 2 ).toInt( &sok ); +// int mminor = re.cap( 3 ).toInt( &sok ); +// if ( ! sok ) return false; + + int unnamedindex = 1; + TQString tmp; + + for ( TQDomElement macroelem = docelem.firstChild().toElement(); + ! macroelem.isNull(); macroelem = macroelem.nextSibling().toElement() ) + { + TQString name, description; + ObjectHierarchy* hierarchy = 0; + TQCString actionname, iconfile; + if ( macroelem.tagName() != "Macro" ) continue; // forward compat ? + for ( TQDomElement dataelem = macroelem.firstChild().toElement(); + ! dataelem.isNull(); dataelem = dataelem.nextSibling().toElement() ) + { + if ( dataelem.tagName() == "Name" ) + name = dataelem.text(); + else if ( dataelem.tagName() == "Description" ) + description = dataelem.text(); + else if ( dataelem.tagName() == "Construction" ) + hierarchy = ObjectHierarchy::buildSafeObjectHierarchy( dataelem, tmp ); + else if ( dataelem.tagName() == "ActionName" ) + actionname = dataelem.text().latin1(); + else if ( dataelem.tagName() == "IconFileName" ) + iconfile = dataelem.text().latin1(); + else continue; + }; + assert( hierarchy ); + // if the macro has no name, we give it a bogus name... + if ( name.isEmpty() ) + name = i18n( "Unnamed Macro #%1" ).arg( unnamedindex++ ); + MacroConstructor* ctor = + new MacroConstructor( *hierarchy, i18n( name.latin1() ), i18n( description.latin1() ), iconfile ); + delete hierarchy; + GUIAction* act = new ConstructibleAction( ctor, actionname ); + Macro* macro = new Macro( act, ctor ); + ret.push_back( macro ); + }; + return true; +} + +const ObjectConstructorList::vectype& ObjectConstructorList::constructors() const +{ + return mctors; +} diff --git a/kig/misc/object_constructor.cc b/kig/misc/object_constructor.cc deleted file mode 100644 index ae2a37d0..00000000 --- a/kig/misc/object_constructor.cc +++ /dev/null @@ -1,609 +0,0 @@ -// Copyright (C) 2002 Dominique Devriese - -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -// 02110-1301, USA. - -#include "object_constructor.h" - -#include "argsparser.h" -#include "kigpainter.h" -#include "guiaction.h" - -#include "../kig/kig_part.h" -#include "../kig/kig_view.h" - -#include "../objects/object_holder.h" -#include "../objects/object_drawer.h" -#include "../objects/object_type.h" -#include "../objects/other_type.h" -#include "../objects/object_imp.h" -#include "../objects/bogus_imp.h" -#include "../objects/line_imp.h" -#include "../objects/circle_imp.h" -#include "../objects/point_imp.h" - -#include "../modes/construct_mode.h" - -#include - -#include - -#include -#include - -const TQString StandardConstructorBase::descriptiveName() const -{ - return i18n( mdescname ); -} - -const TQString StandardConstructorBase::description() const -{ - return i18n( mdesc ); -} - -const TQCString StandardConstructorBase::iconFileName( const bool ) const -{ - return miconfile; -} - -const bool StandardConstructorBase::isAlreadySelectedOK( const std::vector&, const int& ) const -{ - return false; -} - -StandardConstructorBase::StandardConstructorBase( - const char* descname, const char* desc, - const char* iconfile, const ArgsParser& parser ) - : mdescname( descname ), - mdesc( desc ), - miconfile( iconfile ), - margsparser( parser ) -{ -} - -const int StandardConstructorBase::wantArgs( const std::vector& os, - const KigDocument&, - const KigWidget& ) const -{ - return margsparser.check( os ); -} - -void StandardConstructorBase::handleArgs( - const std::vector& os, KigPart& d, - KigWidget& v ) const -{ - std::vector bos = build( os, d.document(), v ); - for ( std::vector::iterator i = bos.begin(); - i != bos.end(); ++i ) - { - (*i)->calc( d.document() ); - } - - d.addObjects( bos ); -} - -void StandardConstructorBase::handlePrelim( - KigPainter& p, const std::vector& os, - const KigDocument& d, const KigWidget& - ) const -{ - assert ( margsparser.check( os ) != ArgsParser::Invalid ); - std::vector args = margsparser.parse( os ); - p.setBrushStyle( Qt::NoBrush ); - p.setBrushColor( TQt::red ); - p.setPen( TQPen ( TQt::red, 1) ); - p.setWidth( -1 ); // -1 means the default width for the object being - // drawn.. - - ObjectDrawer drawer( TQt::red ); - drawprelim( drawer, p, args, d ); -} - -SimpleObjectTypeConstructor::SimpleObjectTypeConstructor( - const ArgsParserObjectType* t, const char* descname, - const char* desc, const char* iconfile ) - : StandardConstructorBase( descname, desc, iconfile, - t->argsParser() ), - mtype( t ) -{ -} - -SimpleObjectTypeConstructor::~SimpleObjectTypeConstructor() -{ -} - -void SimpleObjectTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, - const KigDocument& doc ) const -{ - Args args; - using namespace std; - transform( parents.begin(), parents.end(), - back_inserter( args ), mem_fun( &ObjectCalcer::imp ) ); - ObjectImp* data = mtype->calc( args, doc ); - drawer.draw( *data, p, true ); - delete data; -} - -std::vector SimpleObjectTypeConstructor::build( - const std::vector& os, KigDocument&, KigWidget& ) const -{ - ObjectTypeCalcer* calcer = new ObjectTypeCalcer( mtype, os ); - ObjectHolder* h = new ObjectHolder( calcer ); - std::vector ret; - ret.push_back( h ); - return ret; -} - -StandardConstructorBase::~StandardConstructorBase() -{ -} - -MultiObjectTypeConstructor::MultiObjectTypeConstructor( - const ArgsParserObjectType* t, const char* descname, - const char* desc, const char* iconfile, - const std::vector& params ) - : StandardConstructorBase( descname, desc, iconfile, mparser ), - mtype( t ), mparams( params ), - mparser( t->argsParser().without( IntImp::stype() ) ) -{ -} - -MultiObjectTypeConstructor::MultiObjectTypeConstructor( - const ArgsParserObjectType* t, const char* descname, - const char* desc, const char* iconfile, - int a, int b, int c, int d ) - : StandardConstructorBase( descname, desc, iconfile, mparser ), - mtype( t ), mparams(), - mparser( t->argsParser().without( IntImp::stype() ) ) -{ - mparams.push_back( a ); - mparams.push_back( b ); - if ( c != -999 ) mparams.push_back( c ); - if ( d != -999 ) mparams.push_back( d ); -} - -MultiObjectTypeConstructor::~MultiObjectTypeConstructor() -{ -} - -void MultiObjectTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, - const KigDocument& doc ) const -{ - Args args; - using namespace std; - transform( parents.begin(), parents.end(), - back_inserter( args ), mem_fun( &ObjectCalcer::imp ) ); - - for ( vector::const_iterator i = mparams.begin(); i != mparams.end(); ++i ) - { - IntImp param( *i ); - args.push_back( ¶m ); - ObjectImp* data = mtype->calc( args, doc ); - drawer.draw( *data, p, true ); - delete data; - args.pop_back(); - }; -} - -std::vector MultiObjectTypeConstructor::build( - const std::vector& os, KigDocument&, KigWidget& ) const -{ - std::vector ret; - for ( std::vector::const_iterator i = mparams.begin(); - i != mparams.end(); ++i ) - { - ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( *i ) ); - - std::vector args( os ); - args.push_back( d ); - - ret.push_back( new ObjectHolder( new ObjectTypeCalcer( mtype, args ) ) ); - }; - return ret; -} - -MergeObjectConstructor::~MergeObjectConstructor() -{ - for ( vectype::iterator i = mctors.begin(); i != mctors.end(); ++i ) - delete *i; -} - -MergeObjectConstructor::MergeObjectConstructor( - const char* descname, const char* desc, const char* iconfilename ) - : ObjectConstructor(), mdescname( descname ), mdesc( desc ), - miconfilename( iconfilename ), mctors() -{ -} - -ObjectConstructor::~ObjectConstructor() -{ -} - -void MergeObjectConstructor::merge( ObjectConstructor* e ) -{ - mctors.push_back( e ); -} - -const TQString MergeObjectConstructor::descriptiveName() const -{ - return i18n( mdescname ); -} - -const TQString MergeObjectConstructor::description() const -{ - return i18n( mdesc ); -} - -const TQCString MergeObjectConstructor::iconFileName( const bool ) const -{ - return miconfilename; -} - -const bool MergeObjectConstructor::isAlreadySelectedOK( const std::vector&, const int& ) const -{ - return false; -} - -const int MergeObjectConstructor::wantArgs( - const std::vector& os, const KigDocument& d, const KigWidget& v ) const -{ - for ( vectype::const_iterator i = mctors.begin(); i != mctors.end(); ++i ) - { - int w = (*i)->wantArgs( os, d, v ); - if ( w != ArgsParser::Invalid ) return w; - }; - return ArgsParser::Invalid; -} - -void MergeObjectConstructor::handleArgs( - const std::vector& os, KigPart& d, KigWidget& v ) const -{ - for ( vectype::const_iterator i = mctors.begin(); i != mctors.end(); ++i ) - { - int w = (*i)->wantArgs( os, d.document(), v ); - if ( w == ArgsParser::Complete ) - { - (*i)->handleArgs( os, d, v ); - return; - }; - }; - assert( false ); -} - -void MergeObjectConstructor::handlePrelim( - KigPainter& p, const std::vector& sel, - const KigDocument& d, const KigWidget& v ) const -{ - for ( vectype::const_iterator i = mctors.begin(); i != mctors.end(); ++i ) - { - int w = (*i)->wantArgs( sel, d, v ); - if ( w != ArgsParser::Invalid ) - { - (*i)->handlePrelim( p, sel, d, v ); - return; - }; - }; -} - -TQString StandardConstructorBase::useText( const ObjectCalcer& o, const std::vector& sel, - const KigDocument&, const KigWidget& ) const -{ - using namespace std; - Args args; - transform( sel.begin(), sel.end(), back_inserter( args ), mem_fun( &ObjectCalcer::imp ) ); - - std::string ret = margsparser.usetext( o.imp(), args ); - if ( ret.empty() ) return TQString(); - return i18n( ret.c_str() ); -} - -TQString StandardConstructorBase::selectStatement( - const std::vector& sel, const KigDocument&, - const KigWidget& ) const -{ - using namespace std; - Args args; - transform( sel.begin(), sel.end(), back_inserter( args ), mem_fun( &ObjectCalcer::imp ) ); - - std::string ret = margsparser.selectStatement( args ); - if ( ret.empty() ) return TQString(); - return i18n( ret.c_str() ); -} - -TQString MergeObjectConstructor::useText( const ObjectCalcer& o, const std::vector& sel, - const KigDocument& d, const KigWidget& v ) const -{ - for ( vectype::const_iterator i = mctors.begin(); i != mctors.end(); ++i ) - { - std::vector args( sel ); - int w = (*i)->wantArgs( args, d, v ); - if ( w != ArgsParser::Invalid ) return (*i)->useText( o, sel, d, v ); - }; - return TQString(); -} - -TQString MergeObjectConstructor::selectStatement( - const std::vector& sel, const KigDocument& d, - const KigWidget& w ) const -{ - for ( vectype::const_iterator i = mctors.begin(); i != mctors.end(); ++i ) - { - std::vector args( sel ); - int wa = (*i)->wantArgs( args, d, w ); - if ( wa != ArgsParser::Invalid ) return (*i)->selectStatement( sel, d, w ); - }; - return TQString(); -} - -MacroConstructor::MacroConstructor( const ObjectHierarchy& hier, const TQString& name, - const TQString& desc, const TQCString& iconfile ) - : ObjectConstructor(), mhier( hier ), mname( name ), mdesc( desc ), - mbuiltin( false ), miconfile( iconfile ), - mparser( mhier.argParser() ) -{ -} - -MacroConstructor::MacroConstructor( - const std::vector& input, const std::vector& output, - const TQString& name, const TQString& description, - const TQCString& iconfile ) - : ObjectConstructor(), mhier( input, output ), - mname( name ), mdesc( description ), mbuiltin( false ), - miconfile( iconfile ), - mparser( mhier.argParser() ) -{ -} - -MacroConstructor::~MacroConstructor() -{ -} - -const TQString MacroConstructor::descriptiveName() const -{ - return mname; -} - -const TQString MacroConstructor::description() const -{ - return mdesc; -} - -const TQCString MacroConstructor::iconFileName( const bool canBeNull ) const -{ - return ( miconfile.isNull() && !canBeNull ) ? TQCString( "gear" ) : miconfile; -} - -const bool MacroConstructor::isAlreadySelectedOK( const std::vector&, const int& ) const -{ - return false; -} - -const int MacroConstructor::wantArgs( const std::vector& os, const KigDocument&, - const KigWidget& ) const -{ - return mparser.check( os ); -} - -void MacroConstructor::handleArgs( const std::vector& os, KigPart& d, - KigWidget& ) const -{ - std::vector args = mparser.parse( os ); - std::vector bos = mhier.buildObjects( args, d.document() ); - std::vector hos; - for ( std::vector::iterator i = bos.begin(); - i != bos.end(); ++i ) - { - hos.push_back( new ObjectHolder( *i ) ); - hos.back()->calc( d.document() ); - } - - d.addObjects( hos ); -} - -TQString MacroConstructor::selectStatement( - const std::vector& sel, const KigDocument&, - const KigWidget& ) const -{ - using namespace std; - Args args; - transform( sel.begin(), sel.end(), back_inserter( args ), - mem_fun( &ObjectCalcer::imp ) ); - std::string ret = mparser.selectStatement( args ); - if ( ret.empty() ) return TQString(); - else return i18n( ret.c_str() ); -} - -TQString MacroConstructor::useText( const ObjectCalcer& o, const std::vector& sel, - const KigDocument&, const KigWidget& - ) const -{ - using namespace std; - Args args; - transform( sel.begin(), sel.end(), back_inserter( args ), - mem_fun( &ObjectCalcer::imp ) ); - std::string ret = mparser.usetext( o.imp(), args ); - if ( ret.empty() ) return TQString(); - else return i18n( ret.c_str() ); -} - -void MacroConstructor::handlePrelim( KigPainter& p, const std::vector& sel, - const KigDocument& doc, const KigWidget& - ) const -{ - if ( sel.size() != mhier.numberOfArgs() ) return; - - using namespace std; - Args args; - transform( sel.begin(), sel.end(), back_inserter( args ), - mem_fun( &ObjectCalcer::imp ) ); - args = mparser.parse( args ); - std::vector ret = mhier.calc( args, doc ); - for ( uint i = 0; i < ret.size(); ++i ) - { - ObjectDrawer d; - d.draw( *ret[i], p, true ); - ret[i]->draw( p ); - delete ret[i]; - }; -} - -void SimpleObjectTypeConstructor::plug( KigPart*, KigGUIAction* ) -{ -} - -void MultiObjectTypeConstructor::plug( KigPart*, KigGUIAction* ) -{ -} - -void MergeObjectConstructor::plug( KigPart*, KigGUIAction* ) -{ -} - -void MacroConstructor::plug( KigPart* doc, KigGUIAction* kact ) -{ - if ( mbuiltin ) return; - if ( mhier.numberOfResults() != 1 ) - doc->aMNewOther.append( kact ); - else - { - if ( mhier.idOfLastResult() == SegmentImp::stype() ) - doc->aMNewSegment.append( kact ); - else if ( mhier.idOfLastResult() == PointImp::stype() ) - doc->aMNewPoint.append( kact ); - else if ( mhier.idOfLastResult() == CircleImp::stype() ) - doc->aMNewCircle.append( kact ); - else if ( mhier.idOfLastResult()->inherits( AbstractLineImp::stype() ) ) - // line or ray - doc->aMNewLine.append( kact ); - else if ( mhier.idOfLastResult() == ConicImp::stype() ) - doc->aMNewConic.append( kact ); - else doc->aMNewOther.append( kact ); - }; - doc->aMNewAll.append( kact ); -} - -const ObjectHierarchy& MacroConstructor::hierarchy() const -{ - return mhier; -} - -bool SimpleObjectTypeConstructor::isTransform() const -{ - return mtype->isTransform(); -} - -bool MultiObjectTypeConstructor::isTransform() const -{ - return mtype->isTransform(); -} - -bool MergeObjectConstructor::isTransform() const -{ - bool ret = false; - for ( vectype::const_iterator i = mctors.begin(); i != mctors.end(); ++i ) - ret |= (*i)->isTransform(); - return ret; -} - -bool MacroConstructor::isTransform() const -{ - return false; -} - -void MacroConstructor::setBuiltin( bool builtin ) -{ - mbuiltin = builtin; -} - -bool ObjectConstructor::isIntersection() const -{ - return false; -} - -PropertyObjectConstructor::PropertyObjectConstructor( - const ObjectImpType* imprequirement, const char* usetext, - const char* selectstat, const char* descname, const char* desc, - const char* iconfile, const char* propertyinternalname ) - : StandardConstructorBase( descname, desc, iconfile, mparser ), - mpropinternalname( propertyinternalname ) -{ - ArgsParser::spec argsspec[1]; - argsspec[0].type = imprequirement; - argsspec[0].usetext = usetext; - argsspec[0].selectstat = selectstat; - mparser.initialize( argsspec, 1 ); -} - -PropertyObjectConstructor::~PropertyObjectConstructor() -{ -} - -void PropertyObjectConstructor::drawprelim( - const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, - const KigDocument& d ) const -{ - int index = parents[0]->imp()->propertiesInternalNames().findIndex( mpropinternalname ); - assert ( index != -1 ); - ObjectImp* imp = parents[0]->imp()->property( index, d ); - drawer.draw( *imp, p, true ); - delete imp; -} - -std::vector PropertyObjectConstructor::build( - const std::vector& parents, KigDocument&, - KigWidget& ) const -{ - int index = parents[0]->imp()->propertiesInternalNames().findIndex( mpropinternalname ); - assert( index != -1 ); - std::vector ret; - ret.push_back( - new ObjectHolder( - new ObjectPropertyCalcer( parents[0], index ) ) ); - return ret; -} - -void PropertyObjectConstructor::plug( KigPart*, KigGUIAction* ) -{ -} - -bool PropertyObjectConstructor::isTransform() const -{ - return false; -} - -bool ObjectConstructor::isTest() const -{ - return false; -} - -BaseConstructMode* ObjectConstructor::constructMode( KigPart& doc ) -{ - return new ConstructMode( doc, this ); -} - -void MacroConstructor::setName( const TQString& name ) -{ - mname = name; -} - -void MacroConstructor::setDescription( const TQString& desc ) -{ - mdesc = desc; -} - -void MacroConstructor::setIcon( TQCString& icon ) -{ - miconfile = icon; -} diff --git a/kig/misc/object_constructor.cpp b/kig/misc/object_constructor.cpp new file mode 100644 index 00000000..ae2a37d0 --- /dev/null +++ b/kig/misc/object_constructor.cpp @@ -0,0 +1,609 @@ +// Copyright (C) 2002 Dominique Devriese + +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#include "object_constructor.h" + +#include "argsparser.h" +#include "kigpainter.h" +#include "guiaction.h" + +#include "../kig/kig_part.h" +#include "../kig/kig_view.h" + +#include "../objects/object_holder.h" +#include "../objects/object_drawer.h" +#include "../objects/object_type.h" +#include "../objects/other_type.h" +#include "../objects/object_imp.h" +#include "../objects/bogus_imp.h" +#include "../objects/line_imp.h" +#include "../objects/circle_imp.h" +#include "../objects/point_imp.h" + +#include "../modes/construct_mode.h" + +#include + +#include + +#include +#include + +const TQString StandardConstructorBase::descriptiveName() const +{ + return i18n( mdescname ); +} + +const TQString StandardConstructorBase::description() const +{ + return i18n( mdesc ); +} + +const TQCString StandardConstructorBase::iconFileName( const bool ) const +{ + return miconfile; +} + +const bool StandardConstructorBase::isAlreadySelectedOK( const std::vector&, const int& ) const +{ + return false; +} + +StandardConstructorBase::StandardConstructorBase( + const char* descname, const char* desc, + const char* iconfile, const ArgsParser& parser ) + : mdescname( descname ), + mdesc( desc ), + miconfile( iconfile ), + margsparser( parser ) +{ +} + +const int StandardConstructorBase::wantArgs( const std::vector& os, + const KigDocument&, + const KigWidget& ) const +{ + return margsparser.check( os ); +} + +void StandardConstructorBase::handleArgs( + const std::vector& os, KigPart& d, + KigWidget& v ) const +{ + std::vector bos = build( os, d.document(), v ); + for ( std::vector::iterator i = bos.begin(); + i != bos.end(); ++i ) + { + (*i)->calc( d.document() ); + } + + d.addObjects( bos ); +} + +void StandardConstructorBase::handlePrelim( + KigPainter& p, const std::vector& os, + const KigDocument& d, const KigWidget& + ) const +{ + assert ( margsparser.check( os ) != ArgsParser::Invalid ); + std::vector args = margsparser.parse( os ); + p.setBrushStyle( Qt::NoBrush ); + p.setBrushColor( TQt::red ); + p.setPen( TQPen ( TQt::red, 1) ); + p.setWidth( -1 ); // -1 means the default width for the object being + // drawn.. + + ObjectDrawer drawer( TQt::red ); + drawprelim( drawer, p, args, d ); +} + +SimpleObjectTypeConstructor::SimpleObjectTypeConstructor( + const ArgsParserObjectType* t, const char* descname, + const char* desc, const char* iconfile ) + : StandardConstructorBase( descname, desc, iconfile, + t->argsParser() ), + mtype( t ) +{ +} + +SimpleObjectTypeConstructor::~SimpleObjectTypeConstructor() +{ +} + +void SimpleObjectTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, + const KigDocument& doc ) const +{ + Args args; + using namespace std; + transform( parents.begin(), parents.end(), + back_inserter( args ), mem_fun( &ObjectCalcer::imp ) ); + ObjectImp* data = mtype->calc( args, doc ); + drawer.draw( *data, p, true ); + delete data; +} + +std::vector SimpleObjectTypeConstructor::build( + const std::vector& os, KigDocument&, KigWidget& ) const +{ + ObjectTypeCalcer* calcer = new ObjectTypeCalcer( mtype, os ); + ObjectHolder* h = new ObjectHolder( calcer ); + std::vector ret; + ret.push_back( h ); + return ret; +} + +StandardConstructorBase::~StandardConstructorBase() +{ +} + +MultiObjectTypeConstructor::MultiObjectTypeConstructor( + const ArgsParserObjectType* t, const char* descname, + const char* desc, const char* iconfile, + const std::vector& params ) + : StandardConstructorBase( descname, desc, iconfile, mparser ), + mtype( t ), mparams( params ), + mparser( t->argsParser().without( IntImp::stype() ) ) +{ +} + +MultiObjectTypeConstructor::MultiObjectTypeConstructor( + const ArgsParserObjectType* t, const char* descname, + const char* desc, const char* iconfile, + int a, int b, int c, int d ) + : StandardConstructorBase( descname, desc, iconfile, mparser ), + mtype( t ), mparams(), + mparser( t->argsParser().without( IntImp::stype() ) ) +{ + mparams.push_back( a ); + mparams.push_back( b ); + if ( c != -999 ) mparams.push_back( c ); + if ( d != -999 ) mparams.push_back( d ); +} + +MultiObjectTypeConstructor::~MultiObjectTypeConstructor() +{ +} + +void MultiObjectTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, + const KigDocument& doc ) const +{ + Args args; + using namespace std; + transform( parents.begin(), parents.end(), + back_inserter( args ), mem_fun( &ObjectCalcer::imp ) ); + + for ( vector::const_iterator i = mparams.begin(); i != mparams.end(); ++i ) + { + IntImp param( *i ); + args.push_back( ¶m ); + ObjectImp* data = mtype->calc( args, doc ); + drawer.draw( *data, p, true ); + delete data; + args.pop_back(); + }; +} + +std::vector MultiObjectTypeConstructor::build( + const std::vector& os, KigDocument&, KigWidget& ) const +{ + std::vector ret; + for ( std::vector::const_iterator i = mparams.begin(); + i != mparams.end(); ++i ) + { + ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( *i ) ); + + std::vector args( os ); + args.push_back( d ); + + ret.push_back( new ObjectHolder( new ObjectTypeCalcer( mtype, args ) ) ); + }; + return ret; +} + +MergeObjectConstructor::~MergeObjectConstructor() +{ + for ( vectype::iterator i = mctors.begin(); i != mctors.end(); ++i ) + delete *i; +} + +MergeObjectConstructor::MergeObjectConstructor( + const char* descname, const char* desc, const char* iconfilename ) + : ObjectConstructor(), mdescname( descname ), mdesc( desc ), + miconfilename( iconfilename ), mctors() +{ +} + +ObjectConstructor::~ObjectConstructor() +{ +} + +void MergeObjectConstructor::merge( ObjectConstructor* e ) +{ + mctors.push_back( e ); +} + +const TQString MergeObjectConstructor::descriptiveName() const +{ + return i18n( mdescname ); +} + +const TQString MergeObjectConstructor::description() const +{ + return i18n( mdesc ); +} + +const TQCString MergeObjectConstructor::iconFileName( const bool ) const +{ + return miconfilename; +} + +const bool MergeObjectConstructor::isAlreadySelectedOK( const std::vector&, const int& ) const +{ + return false; +} + +const int MergeObjectConstructor::wantArgs( + const std::vector& os, const KigDocument& d, const KigWidget& v ) const +{ + for ( vectype::const_iterator i = mctors.begin(); i != mctors.end(); ++i ) + { + int w = (*i)->wantArgs( os, d, v ); + if ( w != ArgsParser::Invalid ) return w; + }; + return ArgsParser::Invalid; +} + +void MergeObjectConstructor::handleArgs( + const std::vector& os, KigPart& d, KigWidget& v ) const +{ + for ( vectype::const_iterator i = mctors.begin(); i != mctors.end(); ++i ) + { + int w = (*i)->wantArgs( os, d.document(), v ); + if ( w == ArgsParser::Complete ) + { + (*i)->handleArgs( os, d, v ); + return; + }; + }; + assert( false ); +} + +void MergeObjectConstructor::handlePrelim( + KigPainter& p, const std::vector& sel, + const KigDocument& d, const KigWidget& v ) const +{ + for ( vectype::const_iterator i = mctors.begin(); i != mctors.end(); ++i ) + { + int w = (*i)->wantArgs( sel, d, v ); + if ( w != ArgsParser::Invalid ) + { + (*i)->handlePrelim( p, sel, d, v ); + return; + }; + }; +} + +TQString StandardConstructorBase::useText( const ObjectCalcer& o, const std::vector& sel, + const KigDocument&, const KigWidget& ) const +{ + using namespace std; + Args args; + transform( sel.begin(), sel.end(), back_inserter( args ), mem_fun( &ObjectCalcer::imp ) ); + + std::string ret = margsparser.usetext( o.imp(), args ); + if ( ret.empty() ) return TQString(); + return i18n( ret.c_str() ); +} + +TQString StandardConstructorBase::selectStatement( + const std::vector& sel, const KigDocument&, + const KigWidget& ) const +{ + using namespace std; + Args args; + transform( sel.begin(), sel.end(), back_inserter( args ), mem_fun( &ObjectCalcer::imp ) ); + + std::string ret = margsparser.selectStatement( args ); + if ( ret.empty() ) return TQString(); + return i18n( ret.c_str() ); +} + +TQString MergeObjectConstructor::useText( const ObjectCalcer& o, const std::vector& sel, + const KigDocument& d, const KigWidget& v ) const +{ + for ( vectype::const_iterator i = mctors.begin(); i != mctors.end(); ++i ) + { + std::vector args( sel ); + int w = (*i)->wantArgs( args, d, v ); + if ( w != ArgsParser::Invalid ) return (*i)->useText( o, sel, d, v ); + }; + return TQString(); +} + +TQString MergeObjectConstructor::selectStatement( + const std::vector& sel, const KigDocument& d, + const KigWidget& w ) const +{ + for ( vectype::const_iterator i = mctors.begin(); i != mctors.end(); ++i ) + { + std::vector args( sel ); + int wa = (*i)->wantArgs( args, d, w ); + if ( wa != ArgsParser::Invalid ) return (*i)->selectStatement( sel, d, w ); + }; + return TQString(); +} + +MacroConstructor::MacroConstructor( const ObjectHierarchy& hier, const TQString& name, + const TQString& desc, const TQCString& iconfile ) + : ObjectConstructor(), mhier( hier ), mname( name ), mdesc( desc ), + mbuiltin( false ), miconfile( iconfile ), + mparser( mhier.argParser() ) +{ +} + +MacroConstructor::MacroConstructor( + const std::vector& input, const std::vector& output, + const TQString& name, const TQString& description, + const TQCString& iconfile ) + : ObjectConstructor(), mhier( input, output ), + mname( name ), mdesc( description ), mbuiltin( false ), + miconfile( iconfile ), + mparser( mhier.argParser() ) +{ +} + +MacroConstructor::~MacroConstructor() +{ +} + +const TQString MacroConstructor::descriptiveName() const +{ + return mname; +} + +const TQString MacroConstructor::description() const +{ + return mdesc; +} + +const TQCString MacroConstructor::iconFileName( const bool canBeNull ) const +{ + return ( miconfile.isNull() && !canBeNull ) ? TQCString( "gear" ) : miconfile; +} + +const bool MacroConstructor::isAlreadySelectedOK( const std::vector&, const int& ) const +{ + return false; +} + +const int MacroConstructor::wantArgs( const std::vector& os, const KigDocument&, + const KigWidget& ) const +{ + return mparser.check( os ); +} + +void MacroConstructor::handleArgs( const std::vector& os, KigPart& d, + KigWidget& ) const +{ + std::vector args = mparser.parse( os ); + std::vector bos = mhier.buildObjects( args, d.document() ); + std::vector hos; + for ( std::vector::iterator i = bos.begin(); + i != bos.end(); ++i ) + { + hos.push_back( new ObjectHolder( *i ) ); + hos.back()->calc( d.document() ); + } + + d.addObjects( hos ); +} + +TQString MacroConstructor::selectStatement( + const std::vector& sel, const KigDocument&, + const KigWidget& ) const +{ + using namespace std; + Args args; + transform( sel.begin(), sel.end(), back_inserter( args ), + mem_fun( &ObjectCalcer::imp ) ); + std::string ret = mparser.selectStatement( args ); + if ( ret.empty() ) return TQString(); + else return i18n( ret.c_str() ); +} + +TQString MacroConstructor::useText( const ObjectCalcer& o, const std::vector& sel, + const KigDocument&, const KigWidget& + ) const +{ + using namespace std; + Args args; + transform( sel.begin(), sel.end(), back_inserter( args ), + mem_fun( &ObjectCalcer::imp ) ); + std::string ret = mparser.usetext( o.imp(), args ); + if ( ret.empty() ) return TQString(); + else return i18n( ret.c_str() ); +} + +void MacroConstructor::handlePrelim( KigPainter& p, const std::vector& sel, + const KigDocument& doc, const KigWidget& + ) const +{ + if ( sel.size() != mhier.numberOfArgs() ) return; + + using namespace std; + Args args; + transform( sel.begin(), sel.end(), back_inserter( args ), + mem_fun( &ObjectCalcer::imp ) ); + args = mparser.parse( args ); + std::vector ret = mhier.calc( args, doc ); + for ( uint i = 0; i < ret.size(); ++i ) + { + ObjectDrawer d; + d.draw( *ret[i], p, true ); + ret[i]->draw( p ); + delete ret[i]; + }; +} + +void SimpleObjectTypeConstructor::plug( KigPart*, KigGUIAction* ) +{ +} + +void MultiObjectTypeConstructor::plug( KigPart*, KigGUIAction* ) +{ +} + +void MergeObjectConstructor::plug( KigPart*, KigGUIAction* ) +{ +} + +void MacroConstructor::plug( KigPart* doc, KigGUIAction* kact ) +{ + if ( mbuiltin ) return; + if ( mhier.numberOfResults() != 1 ) + doc->aMNewOther.append( kact ); + else + { + if ( mhier.idOfLastResult() == SegmentImp::stype() ) + doc->aMNewSegment.append( kact ); + else if ( mhier.idOfLastResult() == PointImp::stype() ) + doc->aMNewPoint.append( kact ); + else if ( mhier.idOfLastResult() == CircleImp::stype() ) + doc->aMNewCircle.append( kact ); + else if ( mhier.idOfLastResult()->inherits( AbstractLineImp::stype() ) ) + // line or ray + doc->aMNewLine.append( kact ); + else if ( mhier.idOfLastResult() == ConicImp::stype() ) + doc->aMNewConic.append( kact ); + else doc->aMNewOther.append( kact ); + }; + doc->aMNewAll.append( kact ); +} + +const ObjectHierarchy& MacroConstructor::hierarchy() const +{ + return mhier; +} + +bool SimpleObjectTypeConstructor::isTransform() const +{ + return mtype->isTransform(); +} + +bool MultiObjectTypeConstructor::isTransform() const +{ + return mtype->isTransform(); +} + +bool MergeObjectConstructor::isTransform() const +{ + bool ret = false; + for ( vectype::const_iterator i = mctors.begin(); i != mctors.end(); ++i ) + ret |= (*i)->isTransform(); + return ret; +} + +bool MacroConstructor::isTransform() const +{ + return false; +} + +void MacroConstructor::setBuiltin( bool builtin ) +{ + mbuiltin = builtin; +} + +bool ObjectConstructor::isIntersection() const +{ + return false; +} + +PropertyObjectConstructor::PropertyObjectConstructor( + const ObjectImpType* imprequirement, const char* usetext, + const char* selectstat, const char* descname, const char* desc, + const char* iconfile, const char* propertyinternalname ) + : StandardConstructorBase( descname, desc, iconfile, mparser ), + mpropinternalname( propertyinternalname ) +{ + ArgsParser::spec argsspec[1]; + argsspec[0].type = imprequirement; + argsspec[0].usetext = usetext; + argsspec[0].selectstat = selectstat; + mparser.initialize( argsspec, 1 ); +} + +PropertyObjectConstructor::~PropertyObjectConstructor() +{ +} + +void PropertyObjectConstructor::drawprelim( + const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, + const KigDocument& d ) const +{ + int index = parents[0]->imp()->propertiesInternalNames().findIndex( mpropinternalname ); + assert ( index != -1 ); + ObjectImp* imp = parents[0]->imp()->property( index, d ); + drawer.draw( *imp, p, true ); + delete imp; +} + +std::vector PropertyObjectConstructor::build( + const std::vector& parents, KigDocument&, + KigWidget& ) const +{ + int index = parents[0]->imp()->propertiesInternalNames().findIndex( mpropinternalname ); + assert( index != -1 ); + std::vector ret; + ret.push_back( + new ObjectHolder( + new ObjectPropertyCalcer( parents[0], index ) ) ); + return ret; +} + +void PropertyObjectConstructor::plug( KigPart*, KigGUIAction* ) +{ +} + +bool PropertyObjectConstructor::isTransform() const +{ + return false; +} + +bool ObjectConstructor::isTest() const +{ + return false; +} + +BaseConstructMode* ObjectConstructor::constructMode( KigPart& doc ) +{ + return new ConstructMode( doc, this ); +} + +void MacroConstructor::setName( const TQString& name ) +{ + mname = name; +} + +void MacroConstructor::setDescription( const TQString& desc ) +{ + mdesc = desc; +} + +void MacroConstructor::setIcon( TQCString& icon ) +{ + miconfile = icon; +} diff --git a/kig/misc/object_hierarchy.cc b/kig/misc/object_hierarchy.cc deleted file mode 100644 index 7861c56e..00000000 --- a/kig/misc/object_hierarchy.cc +++ /dev/null @@ -1,774 +0,0 @@ -// Copyright (C) 2003 Dominique Devriese - -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -// 02110-1301, USA. - -#include "object_hierarchy.h" - -#include "../objects/object_holder.h" -#include "../objects/other_type.h" -#include "../objects/object_imp.h" -#include "../objects/object_imp_factory.h" -#include "../objects/object_type_factory.h" -#include "../objects/bogus_imp.h" -#include "../objects/transform_types.h" -#include "../objects/object_type.h" - -#include -#include - -class ObjectHierarchy::Node -{ -public: - enum { ID_PushStack, ID_ApplyType, ID_FetchProp }; - virtual int id() const = 0; - - virtual ~Node(); - virtual Node* copy() const = 0; - - virtual void apply( std::vector& stack, int loc, - const KigDocument& ) const = 0; - - virtual void apply( std::vector& stack, int loc ) const = 0; - - // this function is used to check whether the final objects depend - // on the given objects. The dependsstack contains a set of - // booleans telling which parts of the hierarchy certainly depend on - // the given objects. In this function, the node should check - // whether any of its parents have true set, and if so, set its own - // value to true. - virtual void checkDependsOnGiven( std::vector& dependsstack, int loc ) const = 0; - // this function is used to check whether the given objects are all - // used by one or more of the final objects. The usedstack contains - // a set of booleans telling which parts of the hierarchy are - // certainly ancestors of the final objects. In this function, the - // node should set all of its parents' booleans to true. - virtual void checkArgumentsUsed( std::vector& usedstack ) const = 0; -}; - -ObjectHierarchy::Node::~Node() -{ -} - -class PushStackNode - : public ObjectHierarchy::Node -{ - ObjectImp* mimp; -public: - PushStackNode( ObjectImp* imp ) : mimp( imp ) {} - ~PushStackNode(); - - const ObjectImp* imp() const { return mimp; } - - int id() const; - Node* copy() const; - void apply( std::vector& stack, - int loc, const KigDocument& ) const; - void apply( std::vector& stack, int loc ) const; - - void checkDependsOnGiven( std::vector& dependsstack, int loc ) const; - void checkArgumentsUsed( std::vector& usedstack ) const; -}; - -void PushStackNode::checkArgumentsUsed( std::vector& ) const -{ -} - -void PushStackNode::apply( std::vector& stack, int loc ) const -{ - stack[loc] = new ObjectConstCalcer( mimp->copy() ); -} - -void PushStackNode::checkDependsOnGiven( std::vector&, int ) const { - // pushstacknode depends on nothing.. - return; -} - -int PushStackNode::id() const { return ID_PushStack; } - -PushStackNode::~PushStackNode() -{ - delete mimp; -} - -ObjectHierarchy::Node* PushStackNode::copy() const -{ - return new PushStackNode( mimp->copy() ); -} - -void PushStackNode::apply( std::vector& stack, - int loc, const KigDocument& ) const -{ - stack[loc] = mimp->copy(); -} - -class ApplyTypeNode - : public ObjectHierarchy::Node -{ - const ObjectType* mtype; - std::vector mparents; -public: - ApplyTypeNode( const ObjectType* type, const std::vector& parents ) - : mtype( type ), mparents( parents ) {} - ~ApplyTypeNode(); - Node* copy() const; - - const ObjectType* type() const { return mtype; } - const std::vector& parents() const { return mparents; } - - int id() const; - void apply( std::vector& stack, - int loc, const KigDocument& ) const; - void apply( std::vector& stack, int loc ) const; - - void checkDependsOnGiven( std::vector& dependsstack, int loc ) const; - void checkArgumentsUsed( std::vector& usedstack ) const; -}; - -int ApplyTypeNode::id() const { return ID_ApplyType; } - -void ApplyTypeNode::checkArgumentsUsed( std::vector& usedstack ) const -{ - for ( uint i = 0; i < mparents.size(); ++i ) - { - usedstack[mparents[i]] = true; - } -} - -void ApplyTypeNode::checkDependsOnGiven( std::vector& dependsstack, int loc ) const -{ - bool result = false; - for ( uint i = 0; i < mparents.size(); ++i ) - if ( dependsstack[mparents[i]] == true ) result = true; - dependsstack[loc] = result; -} - -ApplyTypeNode::~ApplyTypeNode() -{ -} - -ObjectHierarchy::Node* ApplyTypeNode::copy() const -{ - return new ApplyTypeNode( mtype, mparents ); -} - -void ApplyTypeNode::apply( std::vector& stack, int loc ) const -{ - std::vector parents; - for ( uint i = 0; i < mparents.size(); ++i ) - parents.push_back( stack[ mparents[i] ] ); - stack[loc] = new ObjectTypeCalcer( mtype, parents ); -} - -void ApplyTypeNode::apply( std::vector& stack, - int loc, const KigDocument& doc ) const -{ - Args args; - for ( uint i = 0; i < mparents.size(); ++i ) - args.push_back( stack[mparents[i]] ); - args = mtype->sortArgs( args ); - stack[loc] = mtype->calc( args, doc ); -} - -class FetchPropertyNode - : public ObjectHierarchy::Node -{ - mutable int mpropid; - int mparent; - const TQCString mname; -public: - // propid is a cache of the location of name in the parent's - // propertiesInternalNames(), just as it is in PropertyObject. We - // don't want to ever save this value, since we cannot guarantee it - // remains consistent if we add properties some place.. - FetchPropertyNode( const int parent, const TQCString& name, const int propid = -1 ) - : mpropid( propid ), mparent( parent ), mname( name ) {} - ~FetchPropertyNode(); - Node* copy() const; - - void checkDependsOnGiven( std::vector& dependsstack, int loc ) const; - void checkArgumentsUsed( std::vector& usedstack ) const; - int parent() const { return mparent; } - const TQCString& propinternalname() const { return mname; } - - int id() const; - void apply( std::vector& stack, - int loc, const KigDocument& ) const; - void apply( std::vector& stack, int loc ) const; -}; - -FetchPropertyNode::~FetchPropertyNode() -{ -} - -void FetchPropertyNode::checkArgumentsUsed( std::vector& usedstack ) const -{ - usedstack[mparent] = true; -} - -void FetchPropertyNode::checkDependsOnGiven( std::vector& dependsstack, int loc ) const -{ - dependsstack[loc] = dependsstack[mparent]; -} - -ObjectHierarchy::Node* FetchPropertyNode::copy() const -{ - return new FetchPropertyNode( mparent, mname, mpropid ); -} - -int FetchPropertyNode::id() const -{ - return ID_FetchProp; -} - -void FetchPropertyNode::apply( std::vector& stack, - int loc, const KigDocument& d ) const -{ - assert( stack[mparent] ); - if ( mpropid == -1 ) mpropid = stack[mparent]->propertiesInternalNames().findIndex( mname ); - if ( mpropid != -1 ) - stack[loc] = stack[mparent]->property( mpropid, d ); - else - stack[loc] = new InvalidImp(); -} - -void FetchPropertyNode::apply( std::vector& stack, int loc ) const -{ - if ( mpropid == -1 ) - mpropid = stack[mparent]->imp()->propertiesInternalNames().findIndex( mname ); - assert( mpropid != -1 ); - stack[loc] = new ObjectPropertyCalcer( stack[mparent], mpropid ); -} - -std::vector ObjectHierarchy::calc( const Args& a, const KigDocument& doc ) const -{ - assert( a.size() == mnumberofargs ); - for ( uint i = 0; i < a.size(); ++i ) - assert( a[i]->inherits( margrequirements[i] ) ); - - std::vector stack; - stack.resize( mnodes.size() + mnumberofargs, 0 ); - std::copy( a.begin(), a.end(), stack.begin() ); - for( uint i = 0; i < mnodes.size(); ++i ) - { - mnodes[i]->apply( stack, mnumberofargs + i, doc ); - }; - for ( uint i = mnumberofargs; i < stack.size() - mnumberofresults; ++i ) - delete stack[i]; - if ( stack.size() < mnumberofargs + mnumberofresults ) - { - std::vector ret; - ret.push_back( new InvalidImp ); - return ret; - } - else - { - std::vector ret; - for ( uint i = stack.size() - mnumberofresults; i < stack.size(); ++i ) - ret.push_back( const_cast( stack[i] ) ); - return ret; - }; -} - -int ObjectHierarchy::visit( const ObjectCalcer* o, std::map& seenmap, - bool needed, bool neededatend ) -{ - using namespace std; - - std::map::iterator smi = seenmap.find( o ); - if ( smi != seenmap.end() ) - { - if ( neededatend ) - { - // neededatend means that this object is one of the resultant - // objects. Therefore, its node has to appear at the end, - // because that's where we expect it.. We therefore copy it - // there using CopyObjectType.. - int ret = mnumberofargs + mnodes.size(); - std::vector parents; - parents.push_back( smi->second ); - mnodes.push_back( new ApplyTypeNode( CopyObjectType::instance(), parents ) ); - return ret; - } - else return smi->second; - } - - std::vector p( o->parents() ); - // we check if o descends from the given objects.. - bool descendsfromgiven = false; - std::vector parents; - parents.resize( p.size(), -1 ); - for ( uint i = 0; i < p.size(); ++i ) - { - int v = visit( p[i], seenmap, false ); - parents[i] = v; - descendsfromgiven |= (v != -1); - }; - - if ( ! descendsfromgiven && ! ( needed && o->imp()->isCache() ) ) - { - if ( needed ) - { - assert( ! o->imp()->isCache() ); - // o is an object that does not depend on the given objects, but - // is needed by other objects, so we just have to just save its - // current value here. - Node* node = new PushStackNode( o->imp()->copy() ); - mnodes.push_back( node ); - int ret = mnodes.size() + mnumberofargs - 1; - seenmap[o] = ret; - return ret; - } - else - return -1; - }; - - return storeObject( o, p, parents, seenmap ); -} - -ObjectHierarchy::~ObjectHierarchy() -{ - for ( uint i = 0; i < mnodes.size(); ++i ) delete mnodes[i]; -} - -ObjectHierarchy::ObjectHierarchy( const ObjectHierarchy& h ) - : mnumberofargs( h.mnumberofargs ), mnumberofresults( h.mnumberofresults ), - margrequirements( h.margrequirements ), musetexts( h.musetexts ), - mselectstatements( h.mselectstatements ) -{ - mnodes.reserve( h.mnodes.size() ); - for ( uint i = 0; i < h.mnodes.size(); ++i ) - mnodes.push_back( h.mnodes[i]->copy() ); -} - -ObjectHierarchy ObjectHierarchy::withFixedArgs( const Args& a ) const -{ - assert( a.size() <= mnumberofargs ); - ObjectHierarchy ret( *this ); - - ret.mnumberofargs -= a.size(); - ret.margrequirements.resize( ret.mnumberofargs ); - - std::vector newnodes( mnodes.size() + a.size() ); - std::vector::iterator newnodesiter = newnodes.begin(); - for ( uint i = 0; i < a.size(); ++i ) - { - assert( ! a[i]->isCache() ); - *newnodesiter++ = new PushStackNode( a[i]->copy() ); - }; - std::copy( ret.mnodes.begin(), ret.mnodes.end(), newnodesiter ); - ret.mnodes = newnodes; - - return ret; -} - -void ObjectHierarchy::init( const std::vector& from, const std::vector& to ) -{ - mnumberofargs = from.size(); - mnumberofresults = to.size(); - margrequirements.resize( from.size(), ObjectImp::stype() ); - musetexts.resize( margrequirements.size(), "" ); - std::map seenmap; - for ( uint i = 0; i < from.size(); ++i ) - seenmap[from[i]] = i; - for ( std::vector::const_iterator i = to.begin(); i != to.end(); ++i ) - { - std::vector parents = (*i)->parents(); - for ( std::vector::const_iterator j = parents.begin(); - j != parents.end(); ++j ) - visit( *j, seenmap, true ); - } - for ( std::vector::const_iterator i = to.begin(); i != to.end(); ++i ) - visit( *i, seenmap, true, true ); - - mselectstatements.resize( margrequirements.size(), "" ); -} - -ObjectHierarchy::ObjectHierarchy( const std::vector& from, const ObjectCalcer* to ) -{ - std::vector tov; - tov.push_back( const_cast( to ) ); - init( from, tov ); -} - -ObjectHierarchy::ObjectHierarchy( const std::vector& from, const std::vector& to ) -{ - init( from, to ); -} - -void ObjectHierarchy::serialize( TQDomElement& parent, TQDomDocument& doc ) const -{ - int id = 1; - for ( uint i = 0; i < mnumberofargs; ++i ) - { - TQDomElement e = doc.createElement( "input" ); - e.setAttribute( "id", id++ ); - e.setAttribute( "requirement", margrequirements[i]->internalName() ); - // we don't save these atm, since the user can't define them. - // we only load them from builtin macro's. -// TQDomElement ut = doc.createElement( "UseText" ); -// ut.appendChild( doc.createTextNode( TQString::fromLatin1(musetexts[i].c_str() ) ) ); -// e.appendChild( ut ); -// TQDomElement ss = doc.createElement( "SelectStatement" ); -// ss.appendChild( doc.createTextNode( TQString::fromLatin1(mselectstatements[i].c_str() ) ) ); -// e.appendChild( ss ); - parent.appendChild( e ); - } - - for ( uint i = 0; i < mnodes.size(); ++i ) - { - bool result = mnodes.size() - ( id - mnumberofargs - 1 ) <= mnumberofresults; - TQDomElement e = doc.createElement( result ? "result" : "intermediate" ); - e.setAttribute( "id", id++ ); - - if ( mnodes[i]->id() == Node::ID_ApplyType ) - { - const ApplyTypeNode* node = static_cast( mnodes[i] ); - e.setAttribute( "action", "calc" ); - e.setAttribute( "type", TQString::fromLatin1( node->type()->fullName() ) ); - for ( uint i = 0; i < node->parents().size(); ++i ) - { - int parent = node->parents()[i] + 1; - TQDomElement arge = doc.createElement( "arg" ); - arge.appendChild( doc.createTextNode( TQString::number( parent ) ) ); - e.appendChild( arge ); - }; - } - else if ( mnodes[i]->id() == Node::ID_FetchProp ) - { - const FetchPropertyNode* node = static_cast( mnodes[i] ); - e.setAttribute( "action", "fetch-property" ); - e.setAttribute( TQString("property"), TQString(node->propinternalname()) ); - TQDomElement arge = doc.createElement( "arg" ); - arge.appendChild( doc.createTextNode( TQString::number( node->parent() + 1 ) ) ); - e.appendChild( arge ); - } - else - { - assert( mnodes[i]->id() == ObjectHierarchy::Node::ID_PushStack ); - const PushStackNode* node = static_cast( mnodes[i] ); - e.setAttribute( "action", "push" ); - TQString type = ObjectImpFactory::instance()->serialize( *node->imp(), e, doc ); - e.setAttribute( "type", type ); - }; - - parent.appendChild( e ); - }; -} - -ObjectHierarchy::ObjectHierarchy() - : mnumberofargs( 0 ), mnumberofresults( 0 ) -{ -} - -ObjectHierarchy* ObjectHierarchy::buildSafeObjectHierarchy( const TQDomElement& parent, TQString& error ) -{ -#define KIG_GENERIC_PARSE_ERROR \ - { \ - error = i18n( "An error was encountered at line %1 in file %2." ) \ - .arg( __LINE__ ).arg( __FILE__ ); \ - return 0; \ - } - - ObjectHierarchy* obhi = new ObjectHierarchy(); - - bool ok = true; - TQString tmp; - TQDomElement e = parent.firstChild().toElement(); - for (; !e.isNull(); e = e.nextSibling().toElement() ) - { - if ( e.tagName() != "input" ) break; - - tmp = e.attribute( "id" ); - uint id = tmp.toInt( &ok ); - if ( !ok ) KIG_GENERIC_PARSE_ERROR; - - obhi->mnumberofargs = kMax( id, obhi->mnumberofargs ); - - tmp = e.attribute( "requirement" ); - const ObjectImpType* req = ObjectImpType::typeFromInternalName( tmp.latin1() ); - if ( req == 0 ) req = ObjectImp::stype(); // sucks, i know.. - obhi->margrequirements.resize( obhi->mnumberofargs, ObjectImp::stype() ); - obhi->musetexts.resize( obhi->mnumberofargs, "" ); - obhi->mselectstatements.resize( obhi->mnumberofargs, "" ); - obhi->margrequirements[id - 1] = req; - obhi->musetexts[id - 1] = req->selectStatement(); - TQDomElement esub = e.firstChild().toElement(); - for ( ; !esub.isNull(); esub = esub.nextSibling().toElement() ) - { - if ( esub.tagName() == "UseText" ) - { - obhi->musetexts[id - 1] = esub.text().latin1(); - } - else if ( esub.tagName() == "SelectStatement" ) - { - obhi->mselectstatements[id - 1] = esub.text().latin1(); - } - else - { - // broken file ? ignore... - } - } - } - for (; !e.isNull(); e = e.nextSibling().toElement() ) - { - bool result = e.tagName() == "result"; - if ( result ) ++obhi->mnumberofresults; - - tmp = e.attribute( "id" ); - int id = tmp.toInt( &ok ); - if ( !ok ) KIG_GENERIC_PARSE_ERROR; - - tmp = e.attribute( "action" ); - Node* newnode = 0; - if ( tmp == "calc" ) - { - // ApplyTypeNode - TQCString typen = e.attribute( "type" ).latin1(); - const ObjectType* type = ObjectTypeFactory::instance()->find( typen ); - if ( ! type ) - { - error = i18n( "This Kig file uses an object of type \"%1\", " - "which this Kig version does not support." - "Perhaps you have compiled Kig without support " - "for this object type," - "or perhaps you are using an older Kig version." ).arg( TQString(typen) ); - return 0; - } - - std::vector parents; - for ( TQDomNode p = e.firstChild(); !p.isNull(); p = p.nextSibling() ) - { - TQDomElement q = p.toElement(); - if ( q.isNull() ) KIG_GENERIC_PARSE_ERROR; // see above - if ( q.tagName() != "arg" ) KIG_GENERIC_PARSE_ERROR; - int pid = q.text().toInt(&ok ); - if ( !ok ) KIG_GENERIC_PARSE_ERROR; - parents.push_back( pid - 1 ); - }; - newnode = new ApplyTypeNode( type, parents ); - } - else if ( tmp == "fetch-property" ) - { - // FetchPropertyNode - TQCString propname = e.attribute( "property" ).latin1(); - TQDomElement arge = e.firstChild().toElement(); - int parent = arge.text().toInt( &ok ); - if ( !ok ) KIG_GENERIC_PARSE_ERROR; - newnode = new FetchPropertyNode( parent - 1, propname ); - } - else - { - // PushStackNode - if ( e.attribute( "action" ) != "push" ) KIG_GENERIC_PARSE_ERROR; - TQString typen = e.attribute( "type" ); - if ( typen.isNull() ) KIG_GENERIC_PARSE_ERROR; - ObjectImp* imp = ObjectImpFactory::instance()->deserialize( typen, e, error ); - if ( ( ! imp ) && !error.isEmpty() ) return 0; - newnode = new PushStackNode( imp ); - }; - obhi->mnodes.resize( kMax( size_t(id - obhi->mnumberofargs), obhi->mnodes.size() ) ); - obhi->mnodes[id - obhi->mnumberofargs - 1] = newnode; - }; - - // if we are here, all went fine - return obhi; -} - -ArgsParser ObjectHierarchy::argParser() const -{ - std::vector specs; - for ( uint i = 0; i < margrequirements.size(); ++i ) - { - const ObjectImpType* req = margrequirements[i]; - ArgsParser::spec spec; - spec.type = req; - spec.usetext = musetexts[i]; - spec.selectstat = mselectstatements[i]; - specs.push_back( spec ); - }; - return ArgsParser( specs ); -} - -std::vector ObjectHierarchy::buildObjects( const std::vector& os, const KigDocument& doc ) const -{ - assert( os.size() == mnumberofargs ); - for ( uint i = 0; i < os.size(); ++i ) - assert( os[i]->imp()->inherits( margrequirements[i] ) ); - - std::vector stack; - stack.resize( mnodes.size() + mnumberofargs, 0 ); - std::copy( os.begin(), os.end(), stack.begin() ); - - for( uint i = 0; i < mnodes.size(); ++i ) - { - mnodes[i]->apply( stack, mnumberofargs + i ); - stack[mnumberofargs + i]->calc( doc ); - }; - - std::vector ret( stack.end() - mnumberofresults, stack.end() ); - - return ret; -} - -const ObjectImpType* ObjectHierarchy::idOfLastResult() const -{ - const Node* n = mnodes.back(); - if ( n->id() == Node::ID_PushStack ) - return static_cast( n )->imp()->type(); - else if ( n->id() == Node::ID_FetchProp ) - return ObjectImp::stype(); - else - return static_cast( n )->type()->resultId(); -} - -ObjectHierarchy ObjectHierarchy::transformFinalObject( const Transformation& t ) const -{ - assert( mnumberofresults == 1 ); - ObjectHierarchy ret( *this ); - ret.mnodes.push_back( new PushStackNode( new TransformationImp( t ) ) ); - - std::vector parents; - parents.push_back( ret.mnodes.size() - 1); - parents.push_back( ret.mnodes.size() ); - const ObjectType* type = ApplyTransformationObjectType::instance(); - ret.mnodes.push_back( new ApplyTypeNode( type, parents ) ); - return ret; -} - -bool operator==( const ObjectHierarchy& lhs, const ObjectHierarchy& rhs ) -{ - if ( ! ( lhs.mnumberofargs == rhs.mnumberofargs && - lhs.mnumberofresults == rhs.mnumberofresults && - lhs.margrequirements == rhs.margrequirements && - lhs.mnodes.size() == rhs.mnodes.size() ) ) - return false; - - // this isn't entirely correct, but it will do, because we don't - // really want to know whether the hierarchies are different, but - // whether rhs has changed with regard to lhs.. - for ( uint i = 0; i < lhs.mnodes.size(); ++i ) - if ( lhs.mnodes[i] != lhs.mnodes[i] ) - return false; - - return true; -} - -bool ObjectHierarchy::resultDoesNotDependOnGiven() const -{ - std::vector dependsstack( mnodes.size() + mnumberofargs, false ); - - for ( uint i = 0; i < mnumberofargs; ++i ) - dependsstack[i] = true; - for ( uint i = 0; i < mnodes.size(); ++i ) - mnodes[i]->checkDependsOnGiven( dependsstack, i + mnumberofargs ); - for ( uint i = dependsstack.size() - mnumberofresults; i < dependsstack.size(); ++i ) - if ( !dependsstack[i] ) - return true; - return false; -} - -// returns the "minimum" of a and b ( in the partially ordered set of -// ObjectImpType's, using the inherits member function as comparison, -// if you for some reason like this sort of non-sense ;) ). This -// basically means: return the type that inherits the other type, -// because if another type inherits the lowermost type, then it will -// also inherit the other.. -const ObjectImpType* lowermost( const ObjectImpType* a, const ObjectImpType* b ) -{ - if ( a->inherits( b ) ) return a; - assert( b->inherits( a ) ); - return b; -} - -// this function is part of the visit procedure really. It is -// factored out, because it recurses for cache ObjectImp's. What this -// does is, it makes sure that object o is calcable, by putting -// appropriate Node's in mnodes.. po is o->parents() and pl contains -// the location of objects that are already in mnodes and -1 -// otherwise.. -1 means we have to store their ObjectImp, unless -// they're cache ObjectImp's etc. -int ObjectHierarchy::storeObject( const ObjectCalcer* o, const std::vector& po, std::vector& pl, - std::map& seenmap ) -{ - for ( uint i = 0; i < po.size(); ++i ) - { - if ( pl[i] == -1 ) - { - // we can't store cache ObjectImp's.. - if ( po[i]->imp()->isCache() ) - { - pl[i] = visit( po[i], seenmap, true, false ); - } - else - { - Node* argnode = new PushStackNode( po[i]->imp()->copy() ); - mnodes.push_back( argnode ); - int argloc = mnumberofargs + mnodes.size() - 1; - seenmap[po[i]] = argloc; - pl[i] = argloc; - }; - } - else if ( (uint) pl[i] < mnumberofargs ) - { - ObjectCalcer* parent = o->parents()[i]; - std::vector opl = o->parents(); - - margrequirements[pl[i]] = - lowermost( margrequirements[pl[i]], - o->impRequirement( parent, opl ) ); - musetexts[pl[i]] = margrequirements[pl[i]]->selectStatement(); - }; - }; - if ( dynamic_cast( o ) ) - mnodes.push_back( new ApplyTypeNode( static_cast( o )->type(), pl ) ); - else if ( dynamic_cast( o ) ) - { - assert( pl.size() == 1 ); - int parent = pl.front(); - ObjectCalcer* op = po.front(); - assert( op ); - uint propid = static_cast( o )->propId(); - assert( propid < op->imp()->propertiesInternalNames().size() ); - mnodes.push_back( new FetchPropertyNode( parent, op->imp()->propertiesInternalNames()[propid], propid ) ); - } - else - assert( false ); - seenmap[o] = mnumberofargs + mnodes.size() - 1; - return mnumberofargs + mnodes.size() - 1; -} - -ObjectHierarchy::ObjectHierarchy( const ObjectCalcer* from, const ObjectCalcer* to ) -{ - std::vector fromv; - fromv.push_back( const_cast( from ) ); - std::vector tov; - tov.push_back( const_cast( to ) ); - init( fromv, tov ); -} - -bool ObjectHierarchy::allGivenObjectsUsed() const -{ - std::vector usedstack( mnodes.size() + mnumberofargs, false ); - for ( uint i = mnodes.size() - mnumberofresults; i < mnodes.size(); ++i ) - usedstack[i + mnumberofargs] = true; - for ( int i = mnodes.size() - 1; i >= 0; --i ) - if ( usedstack[i + mnumberofargs] ) - mnodes[i]->checkArgumentsUsed( usedstack ); - for ( uint i = 0; i < mnumberofargs; ++i ) - if ( ! usedstack[i] ) return false; - return true; -} - diff --git a/kig/misc/object_hierarchy.cpp b/kig/misc/object_hierarchy.cpp new file mode 100644 index 00000000..7861c56e --- /dev/null +++ b/kig/misc/object_hierarchy.cpp @@ -0,0 +1,774 @@ +// Copyright (C) 2003 Dominique Devriese + +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#include "object_hierarchy.h" + +#include "../objects/object_holder.h" +#include "../objects/other_type.h" +#include "../objects/object_imp.h" +#include "../objects/object_imp_factory.h" +#include "../objects/object_type_factory.h" +#include "../objects/bogus_imp.h" +#include "../objects/transform_types.h" +#include "../objects/object_type.h" + +#include +#include + +class ObjectHierarchy::Node +{ +public: + enum { ID_PushStack, ID_ApplyType, ID_FetchProp }; + virtual int id() const = 0; + + virtual ~Node(); + virtual Node* copy() const = 0; + + virtual void apply( std::vector& stack, int loc, + const KigDocument& ) const = 0; + + virtual void apply( std::vector& stack, int loc ) const = 0; + + // this function is used to check whether the final objects depend + // on the given objects. The dependsstack contains a set of + // booleans telling which parts of the hierarchy certainly depend on + // the given objects. In this function, the node should check + // whether any of its parents have true set, and if so, set its own + // value to true. + virtual void checkDependsOnGiven( std::vector& dependsstack, int loc ) const = 0; + // this function is used to check whether the given objects are all + // used by one or more of the final objects. The usedstack contains + // a set of booleans telling which parts of the hierarchy are + // certainly ancestors of the final objects. In this function, the + // node should set all of its parents' booleans to true. + virtual void checkArgumentsUsed( std::vector& usedstack ) const = 0; +}; + +ObjectHierarchy::Node::~Node() +{ +} + +class PushStackNode + : public ObjectHierarchy::Node +{ + ObjectImp* mimp; +public: + PushStackNode( ObjectImp* imp ) : mimp( imp ) {} + ~PushStackNode(); + + const ObjectImp* imp() const { return mimp; } + + int id() const; + Node* copy() const; + void apply( std::vector& stack, + int loc, const KigDocument& ) const; + void apply( std::vector& stack, int loc ) const; + + void checkDependsOnGiven( std::vector& dependsstack, int loc ) const; + void checkArgumentsUsed( std::vector& usedstack ) const; +}; + +void PushStackNode::checkArgumentsUsed( std::vector& ) const +{ +} + +void PushStackNode::apply( std::vector& stack, int loc ) const +{ + stack[loc] = new ObjectConstCalcer( mimp->copy() ); +} + +void PushStackNode::checkDependsOnGiven( std::vector&, int ) const { + // pushstacknode depends on nothing.. + return; +} + +int PushStackNode::id() const { return ID_PushStack; } + +PushStackNode::~PushStackNode() +{ + delete mimp; +} + +ObjectHierarchy::Node* PushStackNode::copy() const +{ + return new PushStackNode( mimp->copy() ); +} + +void PushStackNode::apply( std::vector& stack, + int loc, const KigDocument& ) const +{ + stack[loc] = mimp->copy(); +} + +class ApplyTypeNode + : public ObjectHierarchy::Node +{ + const ObjectType* mtype; + std::vector mparents; +public: + ApplyTypeNode( const ObjectType* type, const std::vector& parents ) + : mtype( type ), mparents( parents ) {} + ~ApplyTypeNode(); + Node* copy() const; + + const ObjectType* type() const { return mtype; } + const std::vector& parents() const { return mparents; } + + int id() const; + void apply( std::vector& stack, + int loc, const KigDocument& ) const; + void apply( std::vector& stack, int loc ) const; + + void checkDependsOnGiven( std::vector& dependsstack, int loc ) const; + void checkArgumentsUsed( std::vector& usedstack ) const; +}; + +int ApplyTypeNode::id() const { return ID_ApplyType; } + +void ApplyTypeNode::checkArgumentsUsed( std::vector& usedstack ) const +{ + for ( uint i = 0; i < mparents.size(); ++i ) + { + usedstack[mparents[i]] = true; + } +} + +void ApplyTypeNode::checkDependsOnGiven( std::vector& dependsstack, int loc ) const +{ + bool result = false; + for ( uint i = 0; i < mparents.size(); ++i ) + if ( dependsstack[mparents[i]] == true ) result = true; + dependsstack[loc] = result; +} + +ApplyTypeNode::~ApplyTypeNode() +{ +} + +ObjectHierarchy::Node* ApplyTypeNode::copy() const +{ + return new ApplyTypeNode( mtype, mparents ); +} + +void ApplyTypeNode::apply( std::vector& stack, int loc ) const +{ + std::vector parents; + for ( uint i = 0; i < mparents.size(); ++i ) + parents.push_back( stack[ mparents[i] ] ); + stack[loc] = new ObjectTypeCalcer( mtype, parents ); +} + +void ApplyTypeNode::apply( std::vector& stack, + int loc, const KigDocument& doc ) const +{ + Args args; + for ( uint i = 0; i < mparents.size(); ++i ) + args.push_back( stack[mparents[i]] ); + args = mtype->sortArgs( args ); + stack[loc] = mtype->calc( args, doc ); +} + +class FetchPropertyNode + : public ObjectHierarchy::Node +{ + mutable int mpropid; + int mparent; + const TQCString mname; +public: + // propid is a cache of the location of name in the parent's + // propertiesInternalNames(), just as it is in PropertyObject. We + // don't want to ever save this value, since we cannot guarantee it + // remains consistent if we add properties some place.. + FetchPropertyNode( const int parent, const TQCString& name, const int propid = -1 ) + : mpropid( propid ), mparent( parent ), mname( name ) {} + ~FetchPropertyNode(); + Node* copy() const; + + void checkDependsOnGiven( std::vector& dependsstack, int loc ) const; + void checkArgumentsUsed( std::vector& usedstack ) const; + int parent() const { return mparent; } + const TQCString& propinternalname() const { return mname; } + + int id() const; + void apply( std::vector& stack, + int loc, const KigDocument& ) const; + void apply( std::vector& stack, int loc ) const; +}; + +FetchPropertyNode::~FetchPropertyNode() +{ +} + +void FetchPropertyNode::checkArgumentsUsed( std::vector& usedstack ) const +{ + usedstack[mparent] = true; +} + +void FetchPropertyNode::checkDependsOnGiven( std::vector& dependsstack, int loc ) const +{ + dependsstack[loc] = dependsstack[mparent]; +} + +ObjectHierarchy::Node* FetchPropertyNode::copy() const +{ + return new FetchPropertyNode( mparent, mname, mpropid ); +} + +int FetchPropertyNode::id() const +{ + return ID_FetchProp; +} + +void FetchPropertyNode::apply( std::vector& stack, + int loc, const KigDocument& d ) const +{ + assert( stack[mparent] ); + if ( mpropid == -1 ) mpropid = stack[mparent]->propertiesInternalNames().findIndex( mname ); + if ( mpropid != -1 ) + stack[loc] = stack[mparent]->property( mpropid, d ); + else + stack[loc] = new InvalidImp(); +} + +void FetchPropertyNode::apply( std::vector& stack, int loc ) const +{ + if ( mpropid == -1 ) + mpropid = stack[mparent]->imp()->propertiesInternalNames().findIndex( mname ); + assert( mpropid != -1 ); + stack[loc] = new ObjectPropertyCalcer( stack[mparent], mpropid ); +} + +std::vector ObjectHierarchy::calc( const Args& a, const KigDocument& doc ) const +{ + assert( a.size() == mnumberofargs ); + for ( uint i = 0; i < a.size(); ++i ) + assert( a[i]->inherits( margrequirements[i] ) ); + + std::vector stack; + stack.resize( mnodes.size() + mnumberofargs, 0 ); + std::copy( a.begin(), a.end(), stack.begin() ); + for( uint i = 0; i < mnodes.size(); ++i ) + { + mnodes[i]->apply( stack, mnumberofargs + i, doc ); + }; + for ( uint i = mnumberofargs; i < stack.size() - mnumberofresults; ++i ) + delete stack[i]; + if ( stack.size() < mnumberofargs + mnumberofresults ) + { + std::vector ret; + ret.push_back( new InvalidImp ); + return ret; + } + else + { + std::vector ret; + for ( uint i = stack.size() - mnumberofresults; i < stack.size(); ++i ) + ret.push_back( const_cast( stack[i] ) ); + return ret; + }; +} + +int ObjectHierarchy::visit( const ObjectCalcer* o, std::map& seenmap, + bool needed, bool neededatend ) +{ + using namespace std; + + std::map::iterator smi = seenmap.find( o ); + if ( smi != seenmap.end() ) + { + if ( neededatend ) + { + // neededatend means that this object is one of the resultant + // objects. Therefore, its node has to appear at the end, + // because that's where we expect it.. We therefore copy it + // there using CopyObjectType.. + int ret = mnumberofargs + mnodes.size(); + std::vector parents; + parents.push_back( smi->second ); + mnodes.push_back( new ApplyTypeNode( CopyObjectType::instance(), parents ) ); + return ret; + } + else return smi->second; + } + + std::vector p( o->parents() ); + // we check if o descends from the given objects.. + bool descendsfromgiven = false; + std::vector parents; + parents.resize( p.size(), -1 ); + for ( uint i = 0; i < p.size(); ++i ) + { + int v = visit( p[i], seenmap, false ); + parents[i] = v; + descendsfromgiven |= (v != -1); + }; + + if ( ! descendsfromgiven && ! ( needed && o->imp()->isCache() ) ) + { + if ( needed ) + { + assert( ! o->imp()->isCache() ); + // o is an object that does not depend on the given objects, but + // is needed by other objects, so we just have to just save its + // current value here. + Node* node = new PushStackNode( o->imp()->copy() ); + mnodes.push_back( node ); + int ret = mnodes.size() + mnumberofargs - 1; + seenmap[o] = ret; + return ret; + } + else + return -1; + }; + + return storeObject( o, p, parents, seenmap ); +} + +ObjectHierarchy::~ObjectHierarchy() +{ + for ( uint i = 0; i < mnodes.size(); ++i ) delete mnodes[i]; +} + +ObjectHierarchy::ObjectHierarchy( const ObjectHierarchy& h ) + : mnumberofargs( h.mnumberofargs ), mnumberofresults( h.mnumberofresults ), + margrequirements( h.margrequirements ), musetexts( h.musetexts ), + mselectstatements( h.mselectstatements ) +{ + mnodes.reserve( h.mnodes.size() ); + for ( uint i = 0; i < h.mnodes.size(); ++i ) + mnodes.push_back( h.mnodes[i]->copy() ); +} + +ObjectHierarchy ObjectHierarchy::withFixedArgs( const Args& a ) const +{ + assert( a.size() <= mnumberofargs ); + ObjectHierarchy ret( *this ); + + ret.mnumberofargs -= a.size(); + ret.margrequirements.resize( ret.mnumberofargs ); + + std::vector newnodes( mnodes.size() + a.size() ); + std::vector::iterator newnodesiter = newnodes.begin(); + for ( uint i = 0; i < a.size(); ++i ) + { + assert( ! a[i]->isCache() ); + *newnodesiter++ = new PushStackNode( a[i]->copy() ); + }; + std::copy( ret.mnodes.begin(), ret.mnodes.end(), newnodesiter ); + ret.mnodes = newnodes; + + return ret; +} + +void ObjectHierarchy::init( const std::vector& from, const std::vector& to ) +{ + mnumberofargs = from.size(); + mnumberofresults = to.size(); + margrequirements.resize( from.size(), ObjectImp::stype() ); + musetexts.resize( margrequirements.size(), "" ); + std::map seenmap; + for ( uint i = 0; i < from.size(); ++i ) + seenmap[from[i]] = i; + for ( std::vector::const_iterator i = to.begin(); i != to.end(); ++i ) + { + std::vector parents = (*i)->parents(); + for ( std::vector::const_iterator j = parents.begin(); + j != parents.end(); ++j ) + visit( *j, seenmap, true ); + } + for ( std::vector::const_iterator i = to.begin(); i != to.end(); ++i ) + visit( *i, seenmap, true, true ); + + mselectstatements.resize( margrequirements.size(), "" ); +} + +ObjectHierarchy::ObjectHierarchy( const std::vector& from, const ObjectCalcer* to ) +{ + std::vector tov; + tov.push_back( const_cast( to ) ); + init( from, tov ); +} + +ObjectHierarchy::ObjectHierarchy( const std::vector& from, const std::vector& to ) +{ + init( from, to ); +} + +void ObjectHierarchy::serialize( TQDomElement& parent, TQDomDocument& doc ) const +{ + int id = 1; + for ( uint i = 0; i < mnumberofargs; ++i ) + { + TQDomElement e = doc.createElement( "input" ); + e.setAttribute( "id", id++ ); + e.setAttribute( "requirement", margrequirements[i]->internalName() ); + // we don't save these atm, since the user can't define them. + // we only load them from builtin macro's. +// TQDomElement ut = doc.createElement( "UseText" ); +// ut.appendChild( doc.createTextNode( TQString::fromLatin1(musetexts[i].c_str() ) ) ); +// e.appendChild( ut ); +// TQDomElement ss = doc.createElement( "SelectStatement" ); +// ss.appendChild( doc.createTextNode( TQString::fromLatin1(mselectstatements[i].c_str() ) ) ); +// e.appendChild( ss ); + parent.appendChild( e ); + } + + for ( uint i = 0; i < mnodes.size(); ++i ) + { + bool result = mnodes.size() - ( id - mnumberofargs - 1 ) <= mnumberofresults; + TQDomElement e = doc.createElement( result ? "result" : "intermediate" ); + e.setAttribute( "id", id++ ); + + if ( mnodes[i]->id() == Node::ID_ApplyType ) + { + const ApplyTypeNode* node = static_cast( mnodes[i] ); + e.setAttribute( "action", "calc" ); + e.setAttribute( "type", TQString::fromLatin1( node->type()->fullName() ) ); + for ( uint i = 0; i < node->parents().size(); ++i ) + { + int parent = node->parents()[i] + 1; + TQDomElement arge = doc.createElement( "arg" ); + arge.appendChild( doc.createTextNode( TQString::number( parent ) ) ); + e.appendChild( arge ); + }; + } + else if ( mnodes[i]->id() == Node::ID_FetchProp ) + { + const FetchPropertyNode* node = static_cast( mnodes[i] ); + e.setAttribute( "action", "fetch-property" ); + e.setAttribute( TQString("property"), TQString(node->propinternalname()) ); + TQDomElement arge = doc.createElement( "arg" ); + arge.appendChild( doc.createTextNode( TQString::number( node->parent() + 1 ) ) ); + e.appendChild( arge ); + } + else + { + assert( mnodes[i]->id() == ObjectHierarchy::Node::ID_PushStack ); + const PushStackNode* node = static_cast( mnodes[i] ); + e.setAttribute( "action", "push" ); + TQString type = ObjectImpFactory::instance()->serialize( *node->imp(), e, doc ); + e.setAttribute( "type", type ); + }; + + parent.appendChild( e ); + }; +} + +ObjectHierarchy::ObjectHierarchy() + : mnumberofargs( 0 ), mnumberofresults( 0 ) +{ +} + +ObjectHierarchy* ObjectHierarchy::buildSafeObjectHierarchy( const TQDomElement& parent, TQString& error ) +{ +#define KIG_GENERIC_PARSE_ERROR \ + { \ + error = i18n( "An error was encountered at line %1 in file %2." ) \ + .arg( __LINE__ ).arg( __FILE__ ); \ + return 0; \ + } + + ObjectHierarchy* obhi = new ObjectHierarchy(); + + bool ok = true; + TQString tmp; + TQDomElement e = parent.firstChild().toElement(); + for (; !e.isNull(); e = e.nextSibling().toElement() ) + { + if ( e.tagName() != "input" ) break; + + tmp = e.attribute( "id" ); + uint id = tmp.toInt( &ok ); + if ( !ok ) KIG_GENERIC_PARSE_ERROR; + + obhi->mnumberofargs = kMax( id, obhi->mnumberofargs ); + + tmp = e.attribute( "requirement" ); + const ObjectImpType* req = ObjectImpType::typeFromInternalName( tmp.latin1() ); + if ( req == 0 ) req = ObjectImp::stype(); // sucks, i know.. + obhi->margrequirements.resize( obhi->mnumberofargs, ObjectImp::stype() ); + obhi->musetexts.resize( obhi->mnumberofargs, "" ); + obhi->mselectstatements.resize( obhi->mnumberofargs, "" ); + obhi->margrequirements[id - 1] = req; + obhi->musetexts[id - 1] = req->selectStatement(); + TQDomElement esub = e.firstChild().toElement(); + for ( ; !esub.isNull(); esub = esub.nextSibling().toElement() ) + { + if ( esub.tagName() == "UseText" ) + { + obhi->musetexts[id - 1] = esub.text().latin1(); + } + else if ( esub.tagName() == "SelectStatement" ) + { + obhi->mselectstatements[id - 1] = esub.text().latin1(); + } + else + { + // broken file ? ignore... + } + } + } + for (; !e.isNull(); e = e.nextSibling().toElement() ) + { + bool result = e.tagName() == "result"; + if ( result ) ++obhi->mnumberofresults; + + tmp = e.attribute( "id" ); + int id = tmp.toInt( &ok ); + if ( !ok ) KIG_GENERIC_PARSE_ERROR; + + tmp = e.attribute( "action" ); + Node* newnode = 0; + if ( tmp == "calc" ) + { + // ApplyTypeNode + TQCString typen = e.attribute( "type" ).latin1(); + const ObjectType* type = ObjectTypeFactory::instance()->find( typen ); + if ( ! type ) + { + error = i18n( "This Kig file uses an object of type \"%1\", " + "which this Kig version does not support." + "Perhaps you have compiled Kig without support " + "for this object type," + "or perhaps you are using an older Kig version." ).arg( TQString(typen) ); + return 0; + } + + std::vector parents; + for ( TQDomNode p = e.firstChild(); !p.isNull(); p = p.nextSibling() ) + { + TQDomElement q = p.toElement(); + if ( q.isNull() ) KIG_GENERIC_PARSE_ERROR; // see above + if ( q.tagName() != "arg" ) KIG_GENERIC_PARSE_ERROR; + int pid = q.text().toInt(&ok ); + if ( !ok ) KIG_GENERIC_PARSE_ERROR; + parents.push_back( pid - 1 ); + }; + newnode = new ApplyTypeNode( type, parents ); + } + else if ( tmp == "fetch-property" ) + { + // FetchPropertyNode + TQCString propname = e.attribute( "property" ).latin1(); + TQDomElement arge = e.firstChild().toElement(); + int parent = arge.text().toInt( &ok ); + if ( !ok ) KIG_GENERIC_PARSE_ERROR; + newnode = new FetchPropertyNode( parent - 1, propname ); + } + else + { + // PushStackNode + if ( e.attribute( "action" ) != "push" ) KIG_GENERIC_PARSE_ERROR; + TQString typen = e.attribute( "type" ); + if ( typen.isNull() ) KIG_GENERIC_PARSE_ERROR; + ObjectImp* imp = ObjectImpFactory::instance()->deserialize( typen, e, error ); + if ( ( ! imp ) && !error.isEmpty() ) return 0; + newnode = new PushStackNode( imp ); + }; + obhi->mnodes.resize( kMax( size_t(id - obhi->mnumberofargs), obhi->mnodes.size() ) ); + obhi->mnodes[id - obhi->mnumberofargs - 1] = newnode; + }; + + // if we are here, all went fine + return obhi; +} + +ArgsParser ObjectHierarchy::argParser() const +{ + std::vector specs; + for ( uint i = 0; i < margrequirements.size(); ++i ) + { + const ObjectImpType* req = margrequirements[i]; + ArgsParser::spec spec; + spec.type = req; + spec.usetext = musetexts[i]; + spec.selectstat = mselectstatements[i]; + specs.push_back( spec ); + }; + return ArgsParser( specs ); +} + +std::vector ObjectHierarchy::buildObjects( const std::vector& os, const KigDocument& doc ) const +{ + assert( os.size() == mnumberofargs ); + for ( uint i = 0; i < os.size(); ++i ) + assert( os[i]->imp()->inherits( margrequirements[i] ) ); + + std::vector stack; + stack.resize( mnodes.size() + mnumberofargs, 0 ); + std::copy( os.begin(), os.end(), stack.begin() ); + + for( uint i = 0; i < mnodes.size(); ++i ) + { + mnodes[i]->apply( stack, mnumberofargs + i ); + stack[mnumberofargs + i]->calc( doc ); + }; + + std::vector ret( stack.end() - mnumberofresults, stack.end() ); + + return ret; +} + +const ObjectImpType* ObjectHierarchy::idOfLastResult() const +{ + const Node* n = mnodes.back(); + if ( n->id() == Node::ID_PushStack ) + return static_cast( n )->imp()->type(); + else if ( n->id() == Node::ID_FetchProp ) + return ObjectImp::stype(); + else + return static_cast( n )->type()->resultId(); +} + +ObjectHierarchy ObjectHierarchy::transformFinalObject( const Transformation& t ) const +{ + assert( mnumberofresults == 1 ); + ObjectHierarchy ret( *this ); + ret.mnodes.push_back( new PushStackNode( new TransformationImp( t ) ) ); + + std::vector parents; + parents.push_back( ret.mnodes.size() - 1); + parents.push_back( ret.mnodes.size() ); + const ObjectType* type = ApplyTransformationObjectType::instance(); + ret.mnodes.push_back( new ApplyTypeNode( type, parents ) ); + return ret; +} + +bool operator==( const ObjectHierarchy& lhs, const ObjectHierarchy& rhs ) +{ + if ( ! ( lhs.mnumberofargs == rhs.mnumberofargs && + lhs.mnumberofresults == rhs.mnumberofresults && + lhs.margrequirements == rhs.margrequirements && + lhs.mnodes.size() == rhs.mnodes.size() ) ) + return false; + + // this isn't entirely correct, but it will do, because we don't + // really want to know whether the hierarchies are different, but + // whether rhs has changed with regard to lhs.. + for ( uint i = 0; i < lhs.mnodes.size(); ++i ) + if ( lhs.mnodes[i] != lhs.mnodes[i] ) + return false; + + return true; +} + +bool ObjectHierarchy::resultDoesNotDependOnGiven() const +{ + std::vector dependsstack( mnodes.size() + mnumberofargs, false ); + + for ( uint i = 0; i < mnumberofargs; ++i ) + dependsstack[i] = true; + for ( uint i = 0; i < mnodes.size(); ++i ) + mnodes[i]->checkDependsOnGiven( dependsstack, i + mnumberofargs ); + for ( uint i = dependsstack.size() - mnumberofresults; i < dependsstack.size(); ++i ) + if ( !dependsstack[i] ) + return true; + return false; +} + +// returns the "minimum" of a and b ( in the partially ordered set of +// ObjectImpType's, using the inherits member function as comparison, +// if you for some reason like this sort of non-sense ;) ). This +// basically means: return the type that inherits the other type, +// because if another type inherits the lowermost type, then it will +// also inherit the other.. +const ObjectImpType* lowermost( const ObjectImpType* a, const ObjectImpType* b ) +{ + if ( a->inherits( b ) ) return a; + assert( b->inherits( a ) ); + return b; +} + +// this function is part of the visit procedure really. It is +// factored out, because it recurses for cache ObjectImp's. What this +// does is, it makes sure that object o is calcable, by putting +// appropriate Node's in mnodes.. po is o->parents() and pl contains +// the location of objects that are already in mnodes and -1 +// otherwise.. -1 means we have to store their ObjectImp, unless +// they're cache ObjectImp's etc. +int ObjectHierarchy::storeObject( const ObjectCalcer* o, const std::vector& po, std::vector& pl, + std::map& seenmap ) +{ + for ( uint i = 0; i < po.size(); ++i ) + { + if ( pl[i] == -1 ) + { + // we can't store cache ObjectImp's.. + if ( po[i]->imp()->isCache() ) + { + pl[i] = visit( po[i], seenmap, true, false ); + } + else + { + Node* argnode = new PushStackNode( po[i]->imp()->copy() ); + mnodes.push_back( argnode ); + int argloc = mnumberofargs + mnodes.size() - 1; + seenmap[po[i]] = argloc; + pl[i] = argloc; + }; + } + else if ( (uint) pl[i] < mnumberofargs ) + { + ObjectCalcer* parent = o->parents()[i]; + std::vector opl = o->parents(); + + margrequirements[pl[i]] = + lowermost( margrequirements[pl[i]], + o->impRequirement( parent, opl ) ); + musetexts[pl[i]] = margrequirements[pl[i]]->selectStatement(); + }; + }; + if ( dynamic_cast( o ) ) + mnodes.push_back( new ApplyTypeNode( static_cast( o )->type(), pl ) ); + else if ( dynamic_cast( o ) ) + { + assert( pl.size() == 1 ); + int parent = pl.front(); + ObjectCalcer* op = po.front(); + assert( op ); + uint propid = static_cast( o )->propId(); + assert( propid < op->imp()->propertiesInternalNames().size() ); + mnodes.push_back( new FetchPropertyNode( parent, op->imp()->propertiesInternalNames()[propid], propid ) ); + } + else + assert( false ); + seenmap[o] = mnumberofargs + mnodes.size() - 1; + return mnumberofargs + mnodes.size() - 1; +} + +ObjectHierarchy::ObjectHierarchy( const ObjectCalcer* from, const ObjectCalcer* to ) +{ + std::vector fromv; + fromv.push_back( const_cast( from ) ); + std::vector tov; + tov.push_back( const_cast( to ) ); + init( fromv, tov ); +} + +bool ObjectHierarchy::allGivenObjectsUsed() const +{ + std::vector usedstack( mnodes.size() + mnumberofargs, false ); + for ( uint i = mnodes.size() - mnumberofresults; i < mnodes.size(); ++i ) + usedstack[i + mnumberofargs] = true; + for ( int i = mnodes.size() - 1; i >= 0; --i ) + if ( usedstack[i + mnumberofargs] ) + mnodes[i]->checkArgumentsUsed( usedstack ); + for ( uint i = 0; i < mnumberofargs; ++i ) + if ( ! usedstack[i] ) return false; + return true; +} + diff --git a/kig/misc/rect.cc b/kig/misc/rect.cc deleted file mode 100644 index 6a7ded12..00000000 --- a/kig/misc/rect.cc +++ /dev/null @@ -1,308 +0,0 @@ -// Copyright (C) 2002 Dominique Devriese - -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -// 02110-1301, USA. - -#include "rect.h" -#include "common.h" - -bool operator==( const Rect& r, const Rect& s ) -{ - return ( r.bottomLeft() == s.bottomLeft() - && r.width() == s.width() - && r.height() == s.height() ); -} - -kdbgstream& operator<<( kdbgstream& s, const Rect& t ) -{ - s << "left: " << t.left() - << "bottom: " << t.bottom() - << "right: " << t.right() - << "top: " << t.top() - << endl; - return s; -} - -Rect::Rect( const Coordinate bottomLeft, const Coordinate topRight ) - : mBottomLeft(bottomLeft) -{ - mwidth = topRight.x - bottomLeft.x; - mheight = topRight.y - bottomLeft.y; - normalize(); -} - -Rect::Rect( const Coordinate p, const double width, const double height ) - : mBottomLeft(p), - mwidth(width), - mheight(height) -{ - normalize(); -} - -Rect::Rect( double xa, double ya, double width, double height ) - : mBottomLeft( xa, ya ), - mwidth( width ), - mheight( height ) -{ - normalize(); -} - -Rect::Rect( const Rect& r ) - : mBottomLeft (r.mBottomLeft), - mwidth(r.mwidth), - mheight(r.mheight) -{ - normalize(); -} - -Rect::Rect() - : mwidth(0), - mheight(0) -{ -} - -void Rect::setBottomLeft( const Coordinate p ) -{ - mBottomLeft = p; -} - -void Rect::setBottomRight( const Coordinate p ) -{ - mBottomLeft = p - Coordinate(mwidth,0); -} - -void Rect::setTopRight( const Coordinate p ) -{ - mBottomLeft = p - Coordinate(mwidth, mheight); -} - -void Rect::setCenter( const Coordinate p ) -{ - mBottomLeft = p - Coordinate(mwidth, mheight)/2; -} - -void Rect::setLeft( const double p ) -{ - double r = right(); - mBottomLeft.x = p; - setRight( r ); -} - -void Rect::setRight( const double p ) -{ - mwidth = p - left(); -} - -void Rect::setBottom( const double p ) -{ - double t = top(); - mBottomLeft.y = p; - setTop( t ); -} - -void Rect::setTop( const double p ) -{ - mheight = p - bottom(); -} - -void Rect::setWidth( const double w ) -{ - mwidth = w; -} - -void Rect::setHeight( const double h ) -{ - mheight = h; -} - -void Rect::normalize() -{ - if ( mwidth < 0 ) - { - mBottomLeft.x += mwidth; - mwidth = -mwidth; - }; - if ( mheight < 0 ) - { - mBottomLeft.y += mheight; - mheight = -mheight; - }; -} - -void Rect::moveBy( const Coordinate p ) -{ - mBottomLeft += p; -} - -void Rect::scale( const double r ) -{ - mwidth *= r; - mheight *= r; -} - - -TQRect Rect::toTQRect() const -{ - return TQRect(mBottomLeft.toTQPoint(), topRight().toTQPoint()); -} - -Coordinate Rect::bottomLeft() const -{ - return mBottomLeft; -} - -Coordinate Rect::bottomRight() const -{ - return mBottomLeft + Coordinate(mwidth, 0); -} - -Coordinate Rect::topLeft() const -{ - return mBottomLeft + Coordinate(0, mheight); -} - -Coordinate Rect::topRight() const -{ - return mBottomLeft + Coordinate(mwidth, mheight); -} - -Coordinate Rect::center() const -{ - return mBottomLeft + Coordinate(mwidth, mheight)/2; -} - -double Rect::left() const -{ - return mBottomLeft.x; -} -double Rect::right() const -{ - return left() + mwidth; -} -double Rect::bottom() const -{ - return mBottomLeft.y; -} - -double Rect::top() const -{ - return bottom() + mheight; -} - -double Rect::width() const -{ - return mwidth; -} - -double Rect::height() const -{ - return mheight; -} - -bool Rect::contains( const Coordinate& p, double allowed_miss ) const -{ - return p.x - left() >= - allowed_miss && - p.y - bottom() >= - allowed_miss && - p.x - left() - width() <= allowed_miss && - p.y - bottom() - height() <= allowed_miss; -} - -bool Rect::contains( const Coordinate& p ) const -{ - return p.x >= left() && - p.y >= bottom() && - p.x - left() <= width() && - p.y - bottom() <= height(); -} - -bool Rect::intersects( const Rect& p ) const -{ - // never thought it was this simple :) - if( p.left() < left() && p.right() < left()) return false; - if( p.left() > right() && p.right() > right()) return false; - if( p.bottom() < bottom() && p.top() < bottom()) return false; - if( p.bottom() > top() && p.top() > top()) return false; - return true; -} - -void Rect::setContains( Coordinate p ) -{ - normalize(); - if( p.x < left() ) setLeft( p.x ); - if( p.x > right() ) setRight(p.x); - if( p.y < bottom() ) setBottom( p.y ); - if( p.y > top() ) setTop( p.y ); -} - -Rect Rect::normalized() const -{ - Rect t = *this; - (void) t.normalize(); - return t; -} - -Rect Rect::fromTQRect( const TQRect& r ) -{ - return Rect( r.left(), r.top(), r.right(), r.bottom() ); -} - -void Rect::setTopLeft( const Coordinate p ) -{ - Coordinate bl = Coordinate( p.x, p.y - mheight ); - setBottomLeft( bl ); -} - -Rect operator|( const Rect& lhs, const Rect& rhs ) -{ - Rect r( lhs ); - r |= rhs; - return r; -} - -void Rect::eat( const Rect& r ) -{ - setLeft( kigMin( left(), r.left() ) ); - setRight( kigMax( right(), r.right() ) ); - setBottom( kigMin( bottom(), r.bottom() ) ); - setTop( kigMax( top(), r.top() ) ); -} - -Rect Rect::matchShape( const Rect& rhs, bool shrink ) const -{ - Rect ret = *this; - Coordinate c = center(); - double v = width()/height(); // current ratio - double w = rhs.width()/rhs.height(); // wanted ratio - - // we don't show less than r, if the dimensions don't match, we - // extend r into some dimension... - if( ( v > w ) ^ shrink ) - ret.setHeight( ret.width() / w ); - else - ret.setWidth( ret.height() * w ); - - ret.setCenter(c); - return ret.normalized(); -} - -bool Rect::valid() -{ - return mBottomLeft.valid() && mwidth != double_inf && mheight != double_inf; -} - -Rect Rect::invalidRect() -{ - return Rect( Coordinate::invalidCoord(), double_inf, double_inf ); -} diff --git a/kig/misc/rect.cpp b/kig/misc/rect.cpp new file mode 100644 index 00000000..6a7ded12 --- /dev/null +++ b/kig/misc/rect.cpp @@ -0,0 +1,308 @@ +// Copyright (C) 2002 Dominique Devriese + +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#include "rect.h" +#include "common.h" + +bool operator==( const Rect& r, const Rect& s ) +{ + return ( r.bottomLeft() == s.bottomLeft() + && r.width() == s.width() + && r.height() == s.height() ); +} + +kdbgstream& operator<<( kdbgstream& s, const Rect& t ) +{ + s << "left: " << t.left() + << "bottom: " << t.bottom() + << "right: " << t.right() + << "top: " << t.top() + << endl; + return s; +} + +Rect::Rect( const Coordinate bottomLeft, const Coordinate topRight ) + : mBottomLeft(bottomLeft) +{ + mwidth = topRight.x - bottomLeft.x; + mheight = topRight.y - bottomLeft.y; + normalize(); +} + +Rect::Rect( const Coordinate p, const double width, const double height ) + : mBottomLeft(p), + mwidth(width), + mheight(height) +{ + normalize(); +} + +Rect::Rect( double xa, double ya, double width, double height ) + : mBottomLeft( xa, ya ), + mwidth( width ), + mheight( height ) +{ + normalize(); +} + +Rect::Rect( const Rect& r ) + : mBottomLeft (r.mBottomLeft), + mwidth(r.mwidth), + mheight(r.mheight) +{ + normalize(); +} + +Rect::Rect() + : mwidth(0), + mheight(0) +{ +} + +void Rect::setBottomLeft( const Coordinate p ) +{ + mBottomLeft = p; +} + +void Rect::setBottomRight( const Coordinate p ) +{ + mBottomLeft = p - Coordinate(mwidth,0); +} + +void Rect::setTopRight( const Coordinate p ) +{ + mBottomLeft = p - Coordinate(mwidth, mheight); +} + +void Rect::setCenter( const Coordinate p ) +{ + mBottomLeft = p - Coordinate(mwidth, mheight)/2; +} + +void Rect::setLeft( const double p ) +{ + double r = right(); + mBottomLeft.x = p; + setRight( r ); +} + +void Rect::setRight( const double p ) +{ + mwidth = p - left(); +} + +void Rect::setBottom( const double p ) +{ + double t = top(); + mBottomLeft.y = p; + setTop( t ); +} + +void Rect::setTop( const double p ) +{ + mheight = p - bottom(); +} + +void Rect::setWidth( const double w ) +{ + mwidth = w; +} + +void Rect::setHeight( const double h ) +{ + mheight = h; +} + +void Rect::normalize() +{ + if ( mwidth < 0 ) + { + mBottomLeft.x += mwidth; + mwidth = -mwidth; + }; + if ( mheight < 0 ) + { + mBottomLeft.y += mheight; + mheight = -mheight; + }; +} + +void Rect::moveBy( const Coordinate p ) +{ + mBottomLeft += p; +} + +void Rect::scale( const double r ) +{ + mwidth *= r; + mheight *= r; +} + + +TQRect Rect::toTQRect() const +{ + return TQRect(mBottomLeft.toTQPoint(), topRight().toTQPoint()); +} + +Coordinate Rect::bottomLeft() const +{ + return mBottomLeft; +} + +Coordinate Rect::bottomRight() const +{ + return mBottomLeft + Coordinate(mwidth, 0); +} + +Coordinate Rect::topLeft() const +{ + return mBottomLeft + Coordinate(0, mheight); +} + +Coordinate Rect::topRight() const +{ + return mBottomLeft + Coordinate(mwidth, mheight); +} + +Coordinate Rect::center() const +{ + return mBottomLeft + Coordinate(mwidth, mheight)/2; +} + +double Rect::left() const +{ + return mBottomLeft.x; +} +double Rect::right() const +{ + return left() + mwidth; +} +double Rect::bottom() const +{ + return mBottomLeft.y; +} + +double Rect::top() const +{ + return bottom() + mheight; +} + +double Rect::width() const +{ + return mwidth; +} + +double Rect::height() const +{ + return mheight; +} + +bool Rect::contains( const Coordinate& p, double allowed_miss ) const +{ + return p.x - left() >= - allowed_miss && + p.y - bottom() >= - allowed_miss && + p.x - left() - width() <= allowed_miss && + p.y - bottom() - height() <= allowed_miss; +} + +bool Rect::contains( const Coordinate& p ) const +{ + return p.x >= left() && + p.y >= bottom() && + p.x - left() <= width() && + p.y - bottom() <= height(); +} + +bool Rect::intersects( const Rect& p ) const +{ + // never thought it was this simple :) + if( p.left() < left() && p.right() < left()) return false; + if( p.left() > right() && p.right() > right()) return false; + if( p.bottom() < bottom() && p.top() < bottom()) return false; + if( p.bottom() > top() && p.top() > top()) return false; + return true; +} + +void Rect::setContains( Coordinate p ) +{ + normalize(); + if( p.x < left() ) setLeft( p.x ); + if( p.x > right() ) setRight(p.x); + if( p.y < bottom() ) setBottom( p.y ); + if( p.y > top() ) setTop( p.y ); +} + +Rect Rect::normalized() const +{ + Rect t = *this; + (void) t.normalize(); + return t; +} + +Rect Rect::fromTQRect( const TQRect& r ) +{ + return Rect( r.left(), r.top(), r.right(), r.bottom() ); +} + +void Rect::setTopLeft( const Coordinate p ) +{ + Coordinate bl = Coordinate( p.x, p.y - mheight ); + setBottomLeft( bl ); +} + +Rect operator|( const Rect& lhs, const Rect& rhs ) +{ + Rect r( lhs ); + r |= rhs; + return r; +} + +void Rect::eat( const Rect& r ) +{ + setLeft( kigMin( left(), r.left() ) ); + setRight( kigMax( right(), r.right() ) ); + setBottom( kigMin( bottom(), r.bottom() ) ); + setTop( kigMax( top(), r.top() ) ); +} + +Rect Rect::matchShape( const Rect& rhs, bool shrink ) const +{ + Rect ret = *this; + Coordinate c = center(); + double v = width()/height(); // current ratio + double w = rhs.width()/rhs.height(); // wanted ratio + + // we don't show less than r, if the dimensions don't match, we + // extend r into some dimension... + if( ( v > w ) ^ shrink ) + ret.setHeight( ret.width() / w ); + else + ret.setWidth( ret.height() * w ); + + ret.setCenter(c); + return ret.normalized(); +} + +bool Rect::valid() +{ + return mBottomLeft.valid() && mwidth != double_inf && mheight != double_inf; +} + +Rect Rect::invalidRect() +{ + return Rect( Coordinate::invalidCoord(), double_inf, double_inf ); +} diff --git a/kig/misc/screeninfo.cc b/kig/misc/screeninfo.cc deleted file mode 100644 index 91a6cb74..00000000 --- a/kig/misc/screeninfo.cc +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (C) 2002 Dominique Devriese - -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -// 02110-1301, USA. - -#include "screeninfo.h" - -#include - -ScreenInfo::ScreenInfo( const Rect& docRect, const TQRect& viewRect ) - : mkrect( docRect.normalized() ), mqrect( viewRect.normalize() ) -{ -} - -Rect ScreenInfo::fromScreen( const TQRect& r ) const -{ - return Rect( - fromScreen( r.topLeft() ), - fromScreen( r.bottomRight() ) - ).normalized(); -} - -Coordinate ScreenInfo::fromScreen( const TQPoint& p ) const -{ - // invert the y-axis: 0 is at the bottom ! - Coordinate t( p.x(), mqrect.height() - p.y() ); - t *= mkrect.width(); - t /= mqrect.width(); - return t + mkrect.bottomLeft(); -} - -TQPoint ScreenInfo::toScreen( const Coordinate& p ) const -{ - Coordinate t = p - mkrect.bottomLeft(); - t *= mqrect.width(); - t /= mkrect.width(); - // invert the y-axis: 0 is at the bottom ! - return TQPoint( (int) t.x, mqrect.height() - (int) t.y ); -} - -TQRect ScreenInfo::toScreen( const Rect& r ) const -{ - return TQRect( - toScreen( r.bottomLeft() ), - toScreen( r.topRight() ) - ).normalize(); -} - -double ScreenInfo::pixelWidth() const -{ - Coordinate a = fromScreen( TQPoint( 0, 0 ) ); - Coordinate b = fromScreen( TQPoint( 0, 1000 ) ); - return std::fabs( b.y - a.y ) / 1000; -} - -const Rect& ScreenInfo::shownRect() const -{ - return mkrect; -} - -void ScreenInfo::setShownRect( const Rect& r ) -{ - mkrect = r; -} - -const TQRect ScreenInfo::viewRect() const -{ - return mqrect; -} - -void ScreenInfo::setViewRect( const TQRect& r ) -{ - mqrect = r; -} - -double ScreenInfo::normalMiss( int width ) const -{ - int twidth = width == -1 ? 1 : width; - return (twidth+2)*pixelWidth(); -} diff --git a/kig/misc/screeninfo.cpp b/kig/misc/screeninfo.cpp new file mode 100644 index 00000000..91a6cb74 --- /dev/null +++ b/kig/misc/screeninfo.cpp @@ -0,0 +1,92 @@ +// Copyright (C) 2002 Dominique Devriese + +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#include "screeninfo.h" + +#include + +ScreenInfo::ScreenInfo( const Rect& docRect, const TQRect& viewRect ) + : mkrect( docRect.normalized() ), mqrect( viewRect.normalize() ) +{ +} + +Rect ScreenInfo::fromScreen( const TQRect& r ) const +{ + return Rect( + fromScreen( r.topLeft() ), + fromScreen( r.bottomRight() ) + ).normalized(); +} + +Coordinate ScreenInfo::fromScreen( const TQPoint& p ) const +{ + // invert the y-axis: 0 is at the bottom ! + Coordinate t( p.x(), mqrect.height() - p.y() ); + t *= mkrect.width(); + t /= mqrect.width(); + return t + mkrect.bottomLeft(); +} + +TQPoint ScreenInfo::toScreen( const Coordinate& p ) const +{ + Coordinate t = p - mkrect.bottomLeft(); + t *= mqrect.width(); + t /= mkrect.width(); + // invert the y-axis: 0 is at the bottom ! + return TQPoint( (int) t.x, mqrect.height() - (int) t.y ); +} + +TQRect ScreenInfo::toScreen( const Rect& r ) const +{ + return TQRect( + toScreen( r.bottomLeft() ), + toScreen( r.topRight() ) + ).normalize(); +} + +double ScreenInfo::pixelWidth() const +{ + Coordinate a = fromScreen( TQPoint( 0, 0 ) ); + Coordinate b = fromScreen( TQPoint( 0, 1000 ) ); + return std::fabs( b.y - a.y ) / 1000; +} + +const Rect& ScreenInfo::shownRect() const +{ + return mkrect; +} + +void ScreenInfo::setShownRect( const Rect& r ) +{ + mkrect = r; +} + +const TQRect ScreenInfo::viewRect() const +{ + return mqrect; +} + +void ScreenInfo::setViewRect( const TQRect& r ) +{ + mqrect = r; +} + +double ScreenInfo::normalMiss( int width ) const +{ + int twidth = width == -1 ? 1 : width; + return (twidth+2)*pixelWidth(); +} diff --git a/kig/misc/special_constructors.cc b/kig/misc/special_constructors.cc deleted file mode 100644 index 9618bc90..00000000 --- a/kig/misc/special_constructors.cc +++ /dev/null @@ -1,1628 +0,0 @@ -// Copyright (C) 2003 Dominique Devriese - -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -// 02110-1301, USA. - -#include "special_constructors.h" - -#include "calcpaths.h" -#include "common.h" -#include "conic-common.h" -#include "guiaction.h" -#include "kigpainter.h" - -#include "../kig/kig_part.h" -#include "../modes/construct_mode.h" -#include "../objects/bogus_imp.h" -#include "../objects/centerofcurvature_type.h" -#include "../objects/circle_imp.h" -#include "../objects/conic_imp.h" -#include "../objects/conic_types.h" -#include "../objects/cubic_imp.h" -#include "../objects/intersection_types.h" -#include "../objects/inversion_type.h" -#include "../objects/line_imp.h" -#include "../objects/line_type.h" -#include "../objects/locus_imp.h" -#include "../objects/object_calcer.h" -#include "../objects/object_drawer.h" -#include "../objects/object_factory.h" -#include "../objects/object_holder.h" -#include "../objects/object_imp.h" -#include "../objects/object_type.h" -#include "../objects/other_imp.h" -#include "../objects/other_type.h" -#include "../objects/point_imp.h" -#include "../objects/point_type.h" -#include "../objects/polygon_imp.h" -#include "../objects/polygon_type.h" -#include "../objects/tangent_type.h" -#include "../objects/text_imp.h" -#include "../objects/transform_types.h" - -#include - -#include - -#include -#include - -class ConicConicIntersectionConstructor - : public StandardConstructorBase -{ -protected: - ArgsParser mparser; -public: - ConicConicIntersectionConstructor(); - ~ConicConicIntersectionConstructor(); - - void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, - const KigDocument& ) const; - std::vector build( const std::vector& os, KigDocument& d, KigWidget& w ) const; - void plug( KigPart* doc, KigGUIAction* kact ); - - bool isTransform() const; -}; - -class ConicLineIntersectionConstructor - : public MultiObjectTypeConstructor -{ -public: - ConicLineIntersectionConstructor(); - ~ConicLineIntersectionConstructor(); -}; - -class ArcLineIntersectionConstructor - : public MultiObjectTypeConstructor -{ -public: - ArcLineIntersectionConstructor(); - ~ArcLineIntersectionConstructor(); -}; - -ConicRadicalConstructor::ConicRadicalConstructor() - : StandardConstructorBase( - I18N_NOOP( "Radical Lines for Conics" ), - I18N_NOOP( "The lines constructed through the intersections " - "of two conics. This is also defined for " - "non-intersecting conics." ), - "conicsradicalline", mparser ), - mtype( ConicRadicalType::instance() ), - mparser( mtype->argsParser().without( IntImp::stype() ) ) -{ -} - -ConicRadicalConstructor::~ConicRadicalConstructor() -{ -} - -void ConicRadicalConstructor::drawprelim( - const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& doc ) const -{ - if ( parents.size() == 2 && parents[0]->imp()->inherits( ConicImp::stype() ) && - parents[1]->imp()->inherits( ConicImp::stype() ) ) - { - Args args; - std::transform( parents.begin(), parents.end(), - std::back_inserter( args ), std::mem_fun( &ObjectCalcer::imp ) ); - for ( int i = -1; i < 2; i += 2 ) - { - IntImp root( i ); - IntImp zeroindex( 1 ); - args.push_back( &root ); - args.push_back( &zeroindex ); - ObjectImp* data = mtype->calc( args, doc ); - drawer.draw( *data, p, true ); - delete data; data = 0; - args.pop_back(); - args.pop_back(); - }; - }; -} - -std::vector ConicRadicalConstructor::build( const std::vector& os, KigDocument&, KigWidget& ) const -{ - using namespace std; - std::vector ret; - ObjectCalcer* zeroindexcalcer = new ObjectConstCalcer( new IntImp( 1 ) ); - for ( int i = -1; i < 2; i += 2 ) - { - std::vector args; - std::copy( os.begin(), os.end(), back_inserter( args ) ); - args.push_back( new ObjectConstCalcer( new IntImp( i ) ) ); - // we use only one zeroindex dataobject, so that if you switch one - // radical line around, then the other switches along.. - args.push_back( zeroindexcalcer ); - ret.push_back( - new ObjectHolder( new ObjectTypeCalcer( mtype, args ) ) ); - }; - return ret; -} - -static const struct ArgsParser::spec argsspecpp[] = -{ - { PointImp::stype(), I18N_NOOP( "Moving Point" ), - I18N_NOOP( "Select the moving point, which will be moved around while drawing the locus..." ), false }, - { PointImp::stype(), I18N_NOOP( "Following Point" ), - I18N_NOOP( "Select the following point, whose locations the locus will be drawn through..." ), true } -}; - -LocusConstructor::LocusConstructor() - : StandardConstructorBase( I18N_NOOP( "Locus" ), I18N_NOOP( "A locus" ), - "locus", margsparser ), - margsparser( argsspecpp, 2 ) -{ -} - -LocusConstructor::~LocusConstructor() -{ -} - -void LocusConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, - const KigDocument& ) const -{ - // this function is rather ugly, but it is necessary to do it this - // way in order to play nice with Kig's design.. - - if ( parents.size() != 2 ) return; - const ObjectTypeCalcer* constrained = dynamic_cast( parents.front() ); - const ObjectCalcer* moving = parents.back(); - if ( ! constrained || ! constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) - { - // moving is in fact the constrained point.. swap them.. - moving = parents.front(); - constrained = dynamic_cast( parents.back() ); - assert( constrained ); - }; - assert( constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) ); - - const ObjectImp* oimp = constrained->parents().back()->imp(); - if( !oimp->inherits( CurveImp::stype() ) ) - oimp = constrained->parents().front()->imp(); - assert( oimp->inherits( CurveImp::stype() ) ); - const CurveImp* cimp = static_cast( oimp ); - - ObjectHierarchy hier( constrained, moving ); - - LocusImp limp( cimp->copy(), hier ); - drawer.draw( limp, p, true ); -} - -const int LocusConstructor::wantArgs( - const std::vector& os, const KigDocument&, const KigWidget& - ) const -{ - int ret = margsparser.check( os ); - if ( ret == ArgsParser::Invalid ) return ret; - else if ( os.size() != 2 ) return ret; - if ( dynamic_cast( os.front() ) && - static_cast( os.front() )->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) - { - std::set children = getAllChildren( os.front() ); - return children.find( os.back() ) != children.end() ? ret : ArgsParser::Invalid; - } - if ( dynamic_cast( os.back() ) && - static_cast( os.back() )->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) - { - std::set children = getAllChildren( os.back() ); - return children.find( os.front() ) != children.end() ? ret : ArgsParser::Invalid; - } - return ArgsParser::Invalid; -} - -std::vector LocusConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const -{ - std::vector ret; - assert( parents.size() == 2 ); - - ObjectTypeCalcer* constrained = dynamic_cast( parents.front() ); - ObjectCalcer* moving = parents.back(); - if ( ! constrained || ! constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) - { - // moving is in fact the constrained point.. swap them.. - moving = parents.front(); - constrained = dynamic_cast( parents.back() ); - assert( constrained ); - }; - assert( constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) ); - - ret.push_back( ObjectFactory::instance()->locus( constrained, moving ) ); - return ret; -} - -TQString LocusConstructor::useText( const ObjectCalcer& o, const std::vector& os, - const KigDocument&, const KigWidget& ) const -{ - if ( dynamic_cast( &o ) && - static_cast( o ).type()->inherits( ObjectType::ID_ConstrainedPointType ) && - ( os.empty() || !dynamic_cast( os[0] ) || - !static_cast( os[0] )->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) - ) return i18n( "Moving Point" ); - else return i18n( "Dependent Point" ); -} - -void ConicRadicalConstructor::plug( KigPart*, KigGUIAction* ) -{ -} - -void LocusConstructor::plug( KigPart*, KigGUIAction* ) -{ -} - -bool ConicRadicalConstructor::isTransform() const -{ - return mtype->isTransform(); -} - -bool LocusConstructor::isTransform() const -{ - return false; -} - -/* - * generic polygon constructor - */ - -PolygonBNPTypeConstructor::PolygonBNPTypeConstructor() - : mtype( PolygonBNPType::instance() ) -{ -} - -PolygonBNPTypeConstructor::~PolygonBNPTypeConstructor() -{ -} - -const TQString PolygonBNPTypeConstructor::descriptiveName() const -{ - return i18n("Polygon by Its Vertices"); -} - -const TQString PolygonBNPTypeConstructor::description() const -{ - return i18n("Construct a polygon by giving its vertices"); -} - -const TQCString PolygonBNPTypeConstructor::iconFileName( const bool ) const -{ - return "kig_polygon"; -} - -const bool PolygonBNPTypeConstructor::isAlreadySelectedOK( - const std::vector& os, const int& pos ) const -{ - if ( pos == 0 && os.size() >= 3 ) return true; - return false; -} - -const int PolygonBNPTypeConstructor::wantArgs( const std::vector& os, - const KigDocument&, - const KigWidget& ) const -{ - int count=os.size() - 1; - - for ( int i = 0; i <= count; i++ ) - { - if ( ! ( os[i]->imp()->inherits( PointImp::stype() ) ) ) return ArgsParser::Invalid; - } - if ( count < 3 ) return ArgsParser::Valid; - if ( os[0] == os[count] ) return ArgsParser::Complete; - return ArgsParser::Valid; -} - -void PolygonBNPTypeConstructor::handleArgs( - const std::vector& os, KigPart& d, - KigWidget& v ) const -{ - std::vector bos = build( os, d.document(), v ); - for ( std::vector::iterator i = bos.begin(); - i != bos.end(); ++i ) - { - (*i)->calc( d.document() ); - } - - d.addObjects( bos ); -} - -void PolygonBNPTypeConstructor::handlePrelim( - KigPainter& p, const std::vector& os, - const KigDocument& d, const KigWidget& - ) const -{ - uint count = os.size(); - if ( count < 2 ) return; - - for ( uint i = 0; i < count; i++ ) - { - assert ( os[i]->imp()->inherits( PointImp::stype() ) ); - } - - std::vector args = os; - p.setBrushStyle( Qt::NoBrush ); - p.setBrushColor( TQt::red ); - p.setPen( TQPen ( TQt::red, 1) ); - p.setWidth( -1 ); // -1 means the default width for the object being - // drawn.. - - ObjectDrawer drawer( TQt::red ); - drawprelim( drawer, p, args, d ); -} - -TQString PolygonBNPTypeConstructor::useText( const ObjectCalcer&, const std::vector& os, - const KigDocument&, const KigWidget& ) const -{ - if ( os.size() > 3 ) - return i18n("... with this vertex (click on the first vertex to terminate construction)"); - else return i18n("Construct a polygon with this vertex"); -} - -TQString PolygonBNPTypeConstructor::selectStatement( - const std::vector&, const KigDocument&, - const KigWidget& ) const -{ - return i18n("Select a point to be a vertex of the new polygon..."); -} - -void PolygonBNPTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, - const KigDocument& ) const -{ - if ( parents.size() < 2 ) return; - - std::vector points; - - for ( uint i = 0; i < parents.size(); ++i ) - { - const Coordinate vertex = - static_cast( parents[i]->imp() )->coordinate(); - points.push_back( vertex ); - } - - if ( parents.size() == 2 ) - { - SegmentImp segment = SegmentImp( points[0], points[1] ); - drawer.draw( segment, p, true ); - } else { - PolygonImp polygon = PolygonImp( points ); - drawer.draw( polygon, p, true ); - } -} - -std::vector PolygonBNPTypeConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const -{ - uint count = parents.size() - 1; - assert ( count >= 3 ); - std::vector args; - for ( uint i = 0; i < count; ++i ) args.push_back( parents[i] ); - ObjectTypeCalcer* calcer = new ObjectTypeCalcer( mtype, args ); - ObjectHolder* h = new ObjectHolder( calcer ); - std::vector ret; - ret.push_back( h ); - return ret; -} - -void PolygonBNPTypeConstructor::plug( KigPart*, KigGUIAction* ) -{ -} - -bool PolygonBNPTypeConstructor::isTransform() const -{ - return false; -} - -/* - * construction of polygon vertices - */ - -static const struct ArgsParser::spec argsspecpv[] = -{ - { PolygonImp::stype(), I18N_NOOP( "Polygon" ), - I18N_NOOP( "Construct the vertices of this polygon..." ), true } -}; - -PolygonVertexTypeConstructor::PolygonVertexTypeConstructor() - : StandardConstructorBase( I18N_NOOP( "Vertices of a Polygon" ), - I18N_NOOP( "The vertices of a polygon." ), - "polygonvertices", margsparser ), - mtype( PolygonVertexType::instance() ), - margsparser( argsspecpv, 1 ) -{ -} - -PolygonVertexTypeConstructor::~PolygonVertexTypeConstructor() -{ -} - -void PolygonVertexTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, - const KigDocument& ) const -{ - if ( parents.size() != 1 ) return; - - const PolygonImp* polygon = dynamic_cast( parents.front()->imp() ); - const std::vector points = polygon->points(); - - int sides = points.size(); - for ( int i = 0; i < sides; ++i ) - { - PointImp point = PointImp( points[i] ); - drawer.draw( point, p, true ); - } -} - -std::vector PolygonVertexTypeConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const -{ - std::vector ret; - assert( parents.size() == 1 ); - const PolygonImp* polygon = dynamic_cast( parents.front()->imp() ); - const std::vector points = polygon->points(); - - int sides = points.size(); - - for ( int i = 0; i < sides; ++i ) - { - ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( i ) ); - std::vector args( parents ); - args.push_back( d ); - ret.push_back( new ObjectHolder( new ObjectTypeCalcer( mtype, args ) ) ); - } - return ret; -} - -void PolygonVertexTypeConstructor::plug( KigPart*, KigGUIAction* ) -{ -} - -bool PolygonVertexTypeConstructor::isTransform() const -{ - return false; -} - -/* - * construction of polygon sides - */ - -static const struct ArgsParser::spec argsspecps[] = -{ - { PolygonImp::stype(), I18N_NOOP( "Polygon" ), - I18N_NOOP( "Construct the sides of this polygon..." ), false } -}; - -PolygonSideTypeConstructor::PolygonSideTypeConstructor() - : StandardConstructorBase( I18N_NOOP( "Sides of a Polygon" ), - I18N_NOOP( "The sides of a polygon." ), - "polygonsides", margsparser ), - mtype( PolygonSideType::instance() ), - margsparser( argsspecps, 1 ) -{ -} - -PolygonSideTypeConstructor::~PolygonSideTypeConstructor() -{ -} - -void PolygonSideTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, - const KigDocument& ) const -{ - if ( parents.size() != 1 ) return; - - const PolygonImp* polygon = dynamic_cast( parents.front()->imp() ); - const std::vector points = polygon->points(); - - uint sides = points.size(); - for ( uint i = 0; i < sides; ++i ) - { - uint nexti = ( i + 1 < sides )?(i + 1):0; - SegmentImp segment = SegmentImp( points[i], points[nexti] ); - drawer.draw( segment, p, true ); - } -} - -std::vector PolygonSideTypeConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const -{ - std::vector ret; - assert( parents.size() == 1 ); - const PolygonImp* polygon = dynamic_cast( parents.front()->imp() ); - const std::vector points = polygon->points(); - - uint sides = points.size(); - - for ( uint i = 0; i < sides; ++i ) - { - ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( i ) ); - std::vector args( parents ); - args.push_back( d ); - ret.push_back( new ObjectHolder( new ObjectTypeCalcer( mtype, args ) ) ); - } - return ret; -} - -void PolygonSideTypeConstructor::plug( KigPart*, KigGUIAction* ) -{ -} - -bool PolygonSideTypeConstructor::isTransform() const -{ - return false; -} - -/* - * polygon by center and vertex - */ - -PolygonBCVConstructor::PolygonBCVConstructor() - : mtype( PolygonBCVType::instance() ) -{ -} - -PolygonBCVConstructor::~PolygonBCVConstructor() -{ -} - -const TQString PolygonBCVConstructor::descriptiveName() const -{ - return i18n("Regular Polygon with Given Center"); -} - -const TQString PolygonBCVConstructor::description() const -{ - return i18n("Construct a regular polygon with a given center and vertex"); -} - -const TQCString PolygonBCVConstructor::iconFileName( const bool ) const -{ - return "hexagonbcv"; -} - -const bool PolygonBCVConstructor::isAlreadySelectedOK( - const std::vector&, const int& ) const -{ - return false; -} - -const int PolygonBCVConstructor::wantArgs( const std::vector& os, - const KigDocument&, - const KigWidget& ) const -{ - if ( os.size() > 3 ) return ArgsParser::Invalid; - - uint imax = ( os.size() <= 2) ? os.size() : 2; - for ( uint i = 0; i < imax; ++i ) - if ( ! ( os[i]->imp()->inherits( PointImp::stype() ) ) ) return ArgsParser::Invalid; - - if ( os.size() < 3 ) return ArgsParser::Valid; - - if ( ! ( os[2]->imp()->inherits( BogusPointImp::stype() ) ) ) - return ArgsParser::Invalid; - - return ArgsParser::Complete; -} - -void PolygonBCVConstructor::handleArgs( - const std::vector& os, KigPart& d, - KigWidget& v ) const -{ - std::vector bos = build( os, d.document(), v ); - for ( std::vector::iterator i = bos.begin(); - i != bos.end(); ++i ) - { - (*i)->calc( d.document() ); - } - - d.addObjects( bos ); -} - -void PolygonBCVConstructor::handlePrelim( - KigPainter& p, const std::vector& os, - const KigDocument& d, const KigWidget& - ) const -{ - if ( os.size() < 2 ) return; - - for ( uint i = 0; i < 2; i++ ) - { - assert ( os[i]->imp()->inherits( PointImp::stype() ) ); - } - - Coordinate c = static_cast( os[0]->imp() )->coordinate(); - Coordinate v = static_cast( os[1]->imp() )->coordinate(); - - int nsides = 6; - bool moreinfo = false; - int winding = 0; // 0 means allow winding > 1 - if ( os.size() == 3 ) - { - assert ( os[2]->imp()->inherits( BogusPointImp::stype() ) ); - Coordinate cntrl = static_cast( os[2]->imp() )->coordinate(); - nsides = computeNsides( c, v, cntrl, winding ); - moreinfo = true; - } - - std::vector args; - args.push_back( os[0] ); - args.push_back( os[1] ); - ObjectConstCalcer* ns = new ObjectConstCalcer( new IntImp( nsides ) ); - args.push_back( ns ); - if ( winding > 1 ) - { - ns = new ObjectConstCalcer( new IntImp( winding ) ); - args.push_back( ns ); - } - - p.setBrushStyle( Qt::NoBrush ); - p.setBrushColor( TQt::red ); - p.setPen( TQPen ( TQt::red, 1) ); - p.setWidth( -1 ); // -1 means the default width for the object being - // drawn.. - - ObjectDrawer drawer( TQt::red ); - drawprelim( drawer, p, args, d ); - if ( moreinfo ) - { - p.setPointStyle( 1 ); - p.setWidth( 6 ); - double ro = 1.0/(2.5); - Coordinate where = getRotatedCoord( c, (1-ro)*c+ro*v, 4*M_PI/5.0 ); - PointImp ptn = PointImp( where ); - TextImp text = TextImp( "(5,2)", where, false ); - ptn.draw( p ); - text.draw( p ); - for ( int i = 3; i < 9; ++i ) - { - where = getRotatedCoord( c, v, 2.0*M_PI/i ); - ptn = PointImp( where ); - ptn.draw( p ); - if ( i > 5 ) continue; - text = TextImp( TQString( "(%1)" ).arg(i), where, false ); - text.draw( p ); - } - p.setStyle( Qt::DotLine ); - p.setWidth( 1 ); - double radius = ( v - c ).length(); - CircleImp circle = CircleImp( c, radius ); - circle.draw( p ); - for ( int i = 2; i < 5; i++ ) - { - ro = 1.0/(i+0.5); - CircleImp circle = CircleImp( c, ro*radius ); - circle.draw( p ); - } - } - delete_all( args.begin() + 2, args.end() ); -} - -std::vector PolygonBCVConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const -{ - assert ( parents.size() == 3 ); - std::vector args; - - Coordinate c = static_cast( parents[0]->imp() )->coordinate(); - Coordinate v = static_cast( parents[1]->imp() )->coordinate(); - Coordinate cntrl = static_cast( parents[2]->imp() )->coordinate(); - - args.push_back( parents[0] ); - args.push_back( parents[1] ); - int winding = 0; - int nsides = computeNsides( c, v, cntrl, winding ); - ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( nsides ) ); - args.push_back( d ); - if ( winding > 1 ) - { - d = new ObjectConstCalcer( new IntImp( winding ) ); - args.push_back( d ); - } - - ObjectTypeCalcer* calcer = new ObjectTypeCalcer( mtype, args ); - ObjectHolder* h = new ObjectHolder( calcer ); - std::vector ret; - ret.push_back( h ); - return ret; -} - -TQString PolygonBCVConstructor::useText( const ObjectCalcer&, const std::vector& os, - const KigDocument&, const KigWidget& ) const -{ - switch ( os.size() ) - { - case 1: - return i18n( "Construct a regular polygon with this center" ); - break; - - case 2: - return i18n( "Construct a regular polygon with this vertex" ); - break; - - case 3: - Coordinate c = static_cast( os[0]->imp() )->coordinate(); - Coordinate v = static_cast( os[1]->imp() )->coordinate(); - Coordinate cntrl = static_cast( os[2]->imp() )->coordinate(); - int winding = 0; - int nsides = computeNsides( c, v, cntrl, winding ); - - if ( winding > 1 ) - { - TQString result = TQString( - i18n( "Adjust the number of sides (%1/%2)" ) - ).arg( nsides ).arg( winding ); - return result; - } else - { - TQString result = TQString( - i18n( "Adjust the number of sides (%1)" ) - ).arg( nsides ); - return result; - } - break; - } - - return ""; -} - -TQString PolygonBCVConstructor::selectStatement( - const std::vector& os, const KigDocument&, - const KigWidget& ) const -{ - switch ( os.size() ) - { - case 1: - return i18n( "Select the center of the new polygon..." ); - break; - - case 2: - return i18n( "Select a vertex for the new polygon..." ); - break; - - case 3: - return i18n( "Move the cursor to get the desired number of sides..." ); - break; - } - - return ""; -} - -void PolygonBCVConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, - const KigDocument& doc ) const -{ - if ( parents.size() < 3 || parents.size() > 4 ) return; - - assert ( parents[0]->imp()->inherits( PointImp::stype() ) && - parents[1]->imp()->inherits( PointImp::stype() ) && - parents[2]->imp()->inherits( IntImp::stype() ) ); - - if ( parents.size() == 4 ) - assert ( parents[3]->imp()->inherits( IntImp::stype() ) ); - - Args args; - std::transform( parents.begin(), parents.end(), - std::back_inserter( args ), std::mem_fun( &ObjectCalcer::imp ) ); - - ObjectImp* data = mtype->calc( args, doc ); - drawer.draw( *data, p, true ); - delete data; - data = 0; -} - -void PolygonBCVConstructor::plug( KigPart*, KigGUIAction* ) -{ -} - -bool PolygonBCVConstructor::isTransform() const -{ - return false; -} - -Coordinate PolygonBCVConstructor::getRotatedCoord( const Coordinate& c, - const Coordinate& v, double alpha ) const -{ - double cosalpha = cos(alpha); - double sinalpha = sin(alpha); - double dx = v.x - c.x; - double dy = v.y - c.y; - return c + Coordinate( cosalpha*dx - sinalpha*dy, sinalpha*dx + cosalpha*dy ); -} - -int PolygonBCVConstructor::computeNsides ( const Coordinate& c, - const Coordinate& v, const Coordinate& cntrl, int& winding ) const -{ - Coordinate lvect = v - c; - Coordinate rvect = cntrl - c; - - double angle = atan2( rvect.y, rvect.x ) - atan2( lvect.y, lvect.x ); - angle = fabs( angle/(2*M_PI) ); - while ( angle > 1 ) angle -= 1; - if ( angle > 0.5 ) angle = 1 - angle; - - double realsides = 1.0/angle; // this is bigger that 2 - if ( angle == 0. ) realsides = 3; - if ( winding <= 0 ) // free to compute winding - { - winding = 1; - double ratio = lvect.length()/rvect.length(); - winding = int ( ratio ); - if ( winding < 1 ) winding = 1; - if ( winding > 50 ) winding = 50; - } - int nsides = int( winding*realsides + 0.5 ); // nsides/winding should be reduced! - if ( nsides > 100 ) nsides = 100; // well, 100 seems large enough! - if ( nsides < 3 ) nsides = 3; - while ( !relativePrimes ( nsides, winding ) ) ++nsides; - return nsides; -} - -/* - * ConicConic intersection... - */ - -static const ArgsParser::spec argsspectc[] = { - { ConicImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", true }, - { ConicImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", true } -}; - -ConicConicIntersectionConstructor::ConicConicIntersectionConstructor() - : StandardConstructorBase( "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "curvelineintersection", mparser ), - mparser( argsspectc, 2 ) -{ -} - -ConicConicIntersectionConstructor::~ConicConicIntersectionConstructor() -{ -} - -void ConicConicIntersectionConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, - const KigDocument& ) const -{ - if ( parents.size() != 2 ) return; - assert ( parents[0]->imp()->inherits( ConicImp::stype() ) && - parents[1]->imp()->inherits( ConicImp::stype() ) ); - const ConicCartesianData conica = - static_cast( parents[0]->imp() )->cartesianData(); - const ConicCartesianData conicb = - static_cast( parents[1]->imp() )->cartesianData(); - bool ok = true; - for ( int wr = -1; wr < 2; wr += 2 ) - { - LineData radical = calcConicRadical( conica, conicb, wr, 1, ok ); - if ( ok ) - { - for ( int wi = -1; wi < 2; wi += 2 ) - { - Coordinate c = calcConicLineIntersect( conica, radical, 0.0, wi ); - if ( c.valid() ) { - PointImp pi( c ); - drawer.draw( pi, p, true ); - } - }; - }; - }; -} - -std::vector ConicConicIntersectionConstructor::build( - const std::vector& os, KigDocument& doc, KigWidget& ) const -{ - assert( os.size() == 2 ); - std::vector ret; - ObjectCalcer* conica = os[0]; - ObjectConstCalcer* zeroindexdo = new ObjectConstCalcer( new IntImp( 1 ) ); - - for ( int wr = -1; wr < 2; wr += 2 ) - { - std::vector args = os; - args.push_back( new ObjectConstCalcer( new IntImp( wr ) ) ); - args.push_back( zeroindexdo ); - ObjectTypeCalcer* radical = - new ObjectTypeCalcer( ConicRadicalType::instance(), args ); - radical->calc( doc ); - for ( int wi = -1; wi < 2; wi += 2 ) - { - args.clear(); - args.push_back( conica ); - args.push_back( radical ); - args.push_back( new ObjectConstCalcer( new IntImp( wi ) ) ); - ret.push_back( - new ObjectHolder( - new ObjectTypeCalcer( - ConicLineIntersectionType::instance(), args ) ) ); - }; - }; - return ret; -} - -void ConicConicIntersectionConstructor::plug( KigPart*, KigGUIAction* ) -{ -} - -bool ConicConicIntersectionConstructor::isTransform() const -{ - return false; -} - -ConicLineIntersectionConstructor::ConicLineIntersectionConstructor() - : MultiObjectTypeConstructor( - ConicLineIntersectionType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "curvelineintersection", -1, 1 ) -{ -} - -ConicLineIntersectionConstructor::~ConicLineIntersectionConstructor() -{ -} - -ArcLineIntersectionConstructor::ArcLineIntersectionConstructor() - : MultiObjectTypeConstructor( - ArcLineIntersectionType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "curvelineintersection", -1, 1 ) -{ -} - -ArcLineIntersectionConstructor::~ArcLineIntersectionConstructor() -{ -} - -TQString ConicRadicalConstructor::useText( const ObjectCalcer& o, const std::vector&, - const KigDocument&, const KigWidget& ) const -{ - if ( o.imp()->inherits( CircleImp::stype() ) ) - return i18n( "Construct the Radical Lines of This Circle" ); - else - return i18n( "Construct the Radical Lines of This Conic" ); -} - -/* - * generic affinity and generic projectivity. A unique affinity can be - * obtained by specifying the image of three points (four for projectivity) - * in the end we need, besides the object to be transformed, a total of - * six point or (alternatively) two triangles; our affinity will map the - * first triangle onto the second with corresponding ordering of their - * vertices. Since we allow for two different ways of specifying the six - * points we shall use a Generic constructor, like that for intersections. - */ - -GenericAffinityConstructor::GenericAffinityConstructor() - : MergeObjectConstructor( - I18N_NOOP( "Generic Affinity" ), - I18N_NOOP( "The unique affinity that maps three points (or a triangle) onto three other points (or a triangle)" ), - "genericaffinity" ) -{ - SimpleObjectTypeConstructor* b2tr = - new SimpleObjectTypeConstructor( - AffinityB2TrType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "genericaffinity" ); - - SimpleObjectTypeConstructor* gi3p = - new SimpleObjectTypeConstructor( - AffinityGI3PType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "genericaffinity" ); - - merge( b2tr ); - merge( gi3p ); -} - -GenericAffinityConstructor::~GenericAffinityConstructor() {} - -GenericProjectivityConstructor::GenericProjectivityConstructor() - : MergeObjectConstructor( - I18N_NOOP( "Generic Projective Transformation" ), - I18N_NOOP( "The unique projective transformation that maps four points (or a quadrilateral) onto four other points (or a quadrilateral)" ), - "genericprojectivity" ) -{ - SimpleObjectTypeConstructor* b2qu = - new SimpleObjectTypeConstructor( - ProjectivityB2QuType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "genericprojectivity" ); - - SimpleObjectTypeConstructor* gi4p = - new SimpleObjectTypeConstructor( - ProjectivityGI4PType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "genericprojectivity" ); - - merge( b2qu ); - merge( gi4p ); -} - -GenericProjectivityConstructor::~GenericProjectivityConstructor() {} - -/* - * inversion of points, lines with respect to a circle - */ - -InversionConstructor::InversionConstructor() - : MergeObjectConstructor( - I18N_NOOP( "Inversion of Point, Line or Circle" ), - I18N_NOOP( "The inversion of a point, line or circle with respect to a circle" ), - "inversion" ) -{ - SimpleObjectTypeConstructor* pointobj = - new SimpleObjectTypeConstructor( - InvertPointType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "inversion" ); - - SimpleObjectTypeConstructor* lineobj = - new SimpleObjectTypeConstructor( - InvertLineType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "inversion" ); - - SimpleObjectTypeConstructor* segmentobj = - new SimpleObjectTypeConstructor( - InvertSegmentType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "inversion" ); - - SimpleObjectTypeConstructor* circleobj = - new SimpleObjectTypeConstructor( - InvertCircleType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "inversion" ); - - SimpleObjectTypeConstructor* arcobj = - new SimpleObjectTypeConstructor( - InvertArcType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "inversion" ); - - merge( arcobj ); - merge( circleobj ); - merge( pointobj ); - merge( segmentobj ); - merge( lineobj ); -} - -InversionConstructor::~InversionConstructor() {} - -/* - * Transport of Measure - */ - -MeasureTransportConstructor::MeasureTransportConstructor() - : mtype( MeasureTransportType::instance() ) -{ -} - -MeasureTransportConstructor::~MeasureTransportConstructor() -{ -} - -const TQString MeasureTransportConstructor::descriptiveName() const -{ - return i18n("Measure Transport"); -} - -const TQString MeasureTransportConstructor::description() const -{ - return i18n("Transport the measure of a segment or arc over a line or circle."); -} - -const TQCString MeasureTransportConstructor::iconFileName( const bool ) const -{ - return "measuretransport"; -} - -const bool MeasureTransportConstructor::isAlreadySelectedOK( - const std::vector&, const int& ) const -{ - return false; -} - -/* - * we want the arguments in the exact order, this makes - * the code simpler, but I guess it is also less confusing - * to the user - */ - -const int MeasureTransportConstructor::wantArgs( - const std::vector& os, - const KigDocument&, - const KigWidget& ) const -{ - if ( os.size() == 0 ) return ArgsParser::Valid; - - if ( ! os[0]->imp()->inherits( SegmentImp::stype() ) && - ! os[0]->imp()->inherits( ArcImp::stype() ) ) - return ArgsParser::Invalid; - - if ( os.size() == 1 ) return ArgsParser::Valid; - - if ( ! os[1]->imp()->inherits( LineImp::stype() ) && - ! os[1]->imp()->inherits( CircleImp::stype() ) ) - return ArgsParser::Invalid; - - if ( os.size() == 2 ) return ArgsParser::Valid; - - if ( ! os[2]->imp()->inherits( PointImp::stype() ) ) - return ArgsParser::Invalid; - - // we here use the "isPointOnCurve", which relies on - // "by construction" incidence, instead of a numerical - // check - if ( ! isPointOnCurve( os[2], os[1] ) ) - return ArgsParser::Invalid; - - if ( os.size() == 3 ) return ArgsParser::Complete; - - return ArgsParser::Invalid; -} - -void MeasureTransportConstructor::handleArgs( - const std::vector& os, KigPart& d, - KigWidget& v ) const -{ - std::vector bos = build( os, d.document(), v ); - for ( std::vector::iterator i = bos.begin(); - i != bos.end(); ++i ) - { - (*i)->calc( d.document() ); - } - - d.addObjects( bos ); -} - -void MeasureTransportConstructor::handlePrelim( - KigPainter& p, const std::vector& os, - const KigDocument& d, const KigWidget& - ) const -{ - p.setBrushStyle( Qt::NoBrush ); - p.setBrushColor( TQt::red ); - p.setPen( TQPen ( TQt::red, 1) ); - p.setWidth( -1 ); // -1 means the default width for the object being - // drawn.. - - ObjectDrawer drawer( TQt::red ); - drawprelim( drawer, p, os, d ); -} - -void MeasureTransportConstructor::drawprelim( const ObjectDrawer& drawer, - KigPainter& p, - const std::vector& parents, - const KigDocument& doc ) const -{ - Args args; - using namespace std; - transform( parents.begin(), parents.end(), - back_inserter( args ), mem_fun( &ObjectCalcer::imp ) ); - ObjectImp* data = mtype->calc( args, doc ); - drawer.draw( *data, p, true ); - delete data; -} - -TQString MeasureTransportConstructor::useText( const ObjectCalcer& o, - const std::vector& os, - const KigDocument&, const KigWidget& ) const -{ - if ( o.imp()->inherits( SegmentImp::stype() ) ) - return i18n("Segment to transport"); - if ( o.imp()->inherits( ArcImp::stype() ) ) - return i18n("Arc to transport"); - if ( o.imp()->inherits( LineImp::stype() ) ) - return i18n("Transport a measure on this line"); - if ( o.imp()->inherits( CircleImp::stype() ) ) - return i18n("Transport a measure on this circle"); - if ( o.imp()->inherits( PointImp::stype() ) ) - { - if ( os[1]->imp()->inherits( CircleImp::stype() ) ) - return i18n("Start transport from this point of the circle"); - if ( os[1]->imp()->inherits( LineImp::stype() ) ) - return i18n("Start transport from this point of the line"); - else - return i18n("Start transport from this point of the curve"); - // well, this isn't impemented yet, should never get here - } - return ""; -} - -TQString MeasureTransportConstructor::selectStatement( - const std::vector&, const KigDocument&, - const KigWidget& ) const -{ -//TODO - return i18n("Select a point to be a vertex of the new polygon..."); -} - -std::vector MeasureTransportConstructor::build( - const std::vector& parents, - KigDocument&, KigWidget& ) const -{ - assert ( parents.size() == 3 ); -// std::vector args; -// for ( uint i = 0; i < count; ++i ) args.push_back( parents[i] ); - ObjectTypeCalcer* calcer = new ObjectTypeCalcer( mtype, parents ); - ObjectHolder* h = new ObjectHolder( calcer ); - std::vector ret; - ret.push_back( h ); - return ret; -} - -void MeasureTransportConstructor::plug( KigPart*, KigGUIAction* ) -{ -} - -bool MeasureTransportConstructor::isTransform() const -{ - return false; -} - -/* - * Generic intersection - */ - -GenericIntersectionConstructor::GenericIntersectionConstructor() - : MergeObjectConstructor( - I18N_NOOP( "Intersect" ), - I18N_NOOP( "The intersection of two objects" ), - "curvelineintersection" ) -{ - // intersection type.. - // There is one "toplevel" object_constructor, that is composed - // of multiple subconstructors.. First we build the - // subconstructors: - SimpleObjectTypeConstructor* lineline = - new SimpleObjectTypeConstructor( - LineLineIntersectionType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "curvelineintersection" ); - - ObjectConstructor* lineconic = - new ConicLineIntersectionConstructor(); - - ObjectConstructor* arcline = - new ArcLineIntersectionConstructor(); - - MultiObjectTypeConstructor* linecubic = - new MultiObjectTypeConstructor( - LineCubicIntersectionType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "curvelineintersection", 1, 2, 3 ); - - ObjectConstructor* conicconic = - new ConicConicIntersectionConstructor(); - - MultiObjectTypeConstructor* circlecircle = - new MultiObjectTypeConstructor( - CircleCircleIntersectionType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "circlecircleintersection", -1, 1 ); - - SimpleObjectTypeConstructor* polygonline = - new SimpleObjectTypeConstructor( - PolygonLineIntersectionType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "curvelineintersection" ); - - merge( lineline ); - merge( circlecircle ); - merge( lineconic ); - merge( linecubic ); - merge( conicconic ); - merge( arcline ); - merge( polygonline ); -} - -GenericIntersectionConstructor::~GenericIntersectionConstructor() -{ -} - -bool GenericIntersectionConstructor::isIntersection() const -{ - return true; -} - -TQString GenericIntersectionConstructor::useText( - const ObjectCalcer& o, const std::vector& os, - const KigDocument&, const KigWidget& ) const -{ - TQString preamble; - switch (os.size()) - { - case 1: - if ( o.imp()->inherits( CircleImp::stype() ) ) - return i18n( "Intersect this Circle" ); - else if ( o.imp()->inherits( ConicImp::stype() ) ) - return i18n( "Intersect this Conic" ); - else if ( o.imp()->inherits( AbstractLineImp::stype() ) ) - return i18n( "Intersect this Line" ); - else if ( o.imp()->inherits( CubicImp::stype() ) ) - return i18n( "Intersect this Cubic Curve" ); - else if ( o.imp()->inherits( ArcImp::stype() ) ) - return i18n( "Intersect this Arc" ); - else if ( o.imp()->inherits( PolygonImp::stype() ) ) - return i18n( "Intersect this Polygon" ); - else assert( false ); - break; - case 2: - if ( o.imp()->inherits( CircleImp::stype() ) ) - return i18n( "with this Circle" ); - else if ( o.imp()->inherits( ConicImp::stype() ) ) - return i18n( "with this Conic" ); - else if ( o.imp()->inherits( AbstractLineImp::stype() ) ) - return i18n( "with this Line" ); - else if ( o.imp()->inherits( CubicImp::stype() ) ) - return i18n( "with this Cubic Curve" ); - else if ( o.imp()->inherits( ArcImp::stype() ) ) - return i18n( "with this Arc" ); - else if ( o.imp()->inherits( PolygonImp::stype() ) ) - return i18n( "with this Polygon" ); - else assert( false ); - break; - } - - return TQString(); -} - -static const ArgsParser::spec argsspecMidPointOfTwoPoints[] = -{ - { PointImp::stype(), I18N_NOOP( "Construct Midpoint of This Point and Another One" ), - I18N_NOOP( "Select the first of the points of which you want to construct the midpoint..." ), false }, - { PointImp::stype(), I18N_NOOP( "Construct the midpoint of this point and another one" ), - I18N_NOOP( "Select the other of the points of which to construct the midpoint..." ), false } -}; - -MidPointOfTwoPointsConstructor::MidPointOfTwoPointsConstructor() - : StandardConstructorBase( "Mid Point", - "Construct the midpoint of two points", - "bisection", mparser ), - mparser( argsspecMidPointOfTwoPoints, 2 ) -{ -} - -MidPointOfTwoPointsConstructor::~MidPointOfTwoPointsConstructor() -{ -} - -void MidPointOfTwoPointsConstructor::drawprelim( - const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, - const KigDocument& ) const -{ - if ( parents.size() != 2 ) return; - assert( parents[0]->imp()->inherits( PointImp::stype() ) ); - assert( parents[1]->imp()->inherits( PointImp::stype() ) ); - const Coordinate m = - ( static_cast( parents[0]->imp() )->coordinate() + - static_cast( parents[1]->imp() )->coordinate() ) / 2; - drawer.draw( PointImp( m ), p, true ); -} - -std::vector MidPointOfTwoPointsConstructor::build( - const std::vector& os, KigDocument& d, KigWidget& ) const -{ - ObjectTypeCalcer* seg = new ObjectTypeCalcer( SegmentABType::instance(), os ); - seg->calc( d ); - int index = seg->imp()->propertiesInternalNames().findIndex( "mid-point" ); - assert( index != -1 ); - ObjectPropertyCalcer* prop = new ObjectPropertyCalcer( seg, index ); - prop->calc( d ); - std::vector ret; - ret.push_back( new ObjectHolder( prop ) ); - return ret; -} - -void MidPointOfTwoPointsConstructor::plug( KigPart*, KigGUIAction* ) -{ -} - -bool MidPointOfTwoPointsConstructor::isTransform() const -{ - return false; -} - -TestConstructor::TestConstructor( const ArgsParserObjectType* type, const char* descname, - const char* desc, const char* iconfile ) - : StandardConstructorBase( descname, desc, iconfile, type->argsParser() ), - mtype( type ) -{ -} - -TestConstructor::~TestConstructor() -{ -} - -void TestConstructor::drawprelim( const ObjectDrawer&, KigPainter&, const std::vector&, - const KigDocument& ) const -{ - // not used, only here because of the wrong - // ObjectConstructor-GUIAction design. See the TODO -} - -std::vector TestConstructor::build( const std::vector&, KigDocument&, - KigWidget& ) const -{ - // not used, only here because of the wrong - // ObjectConstructor-GUIAction design. See the TODO - std::vector ret; - return ret; -} - -void TestConstructor::plug( KigPart*, KigGUIAction* ) -{ -} - -bool TestConstructor::isTransform() const -{ - return false; -} - -bool TestConstructor::isTest() const -{ - return true; -} - -BaseConstructMode* TestConstructor::constructMode( KigPart& doc ) -{ - return new TestConstructMode( doc, mtype ); -} - -const int TestConstructor::wantArgs( const std::vector& os, - const KigDocument& d, const KigWidget& v ) const -{ - int ret = StandardConstructorBase::wantArgs( os, d, v ); - if ( ret == ArgsParser::Complete ) ret = ArgsParser::Valid; - return ret; -} - -TQString GenericIntersectionConstructor::selectStatement( - const std::vector& sel, const KigDocument&, - const KigWidget& ) const -{ - if ( sel.size() == 0 ) - return i18n( "Select the first object to intersect..." ); - else - return i18n( "Select the second object to intersect..." ); -} - -TangentConstructor::TangentConstructor() - : MergeObjectConstructor( - I18N_NOOP( "Tangent" ), - I18N_NOOP( "The line tangent to a curve" ), - "tangent" ) -{ - SimpleObjectTypeConstructor* conic = - new SimpleObjectTypeConstructor( - TangentConicType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "tangentconic" ); - - SimpleObjectTypeConstructor* arc = - new SimpleObjectTypeConstructor( - TangentArcType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "tangentarc" ); - - SimpleObjectTypeConstructor* cubic = - new SimpleObjectTypeConstructor( - TangentCubicType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "tangentcubic" ); - - SimpleObjectTypeConstructor* curve = - new SimpleObjectTypeConstructor( - TangentCurveType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "tangentcurve" ); - - merge( conic ); - merge( arc ); - merge( cubic ); - merge( curve ); -} - -TangentConstructor::~TangentConstructor() -{ -} - -TQString TangentConstructor::useText( - const ObjectCalcer& o, const std::vector&, - const KigDocument&, const KigWidget& ) const -{ - if ( o.imp()->inherits( CircleImp::stype() ) ) - return i18n( "Tangent to This Circle" ); - else if ( o.imp()->inherits( ConicImp::stype() ) ) - return i18n( "Tangent to This Conic" ); - else if ( o.imp()->inherits( ArcImp::stype() ) ) - return i18n( "Tangent to This Arc" ); - else if ( o.imp()->inherits( CubicImp::stype() ) ) - return i18n( "Tangent to This Cubic Curve" ); - else if ( o.imp()->inherits( CurveImp::stype() ) ) - return i18n( "Tangent to This Curve" ); - else if ( o.imp()->inherits( PointImp::stype() ) ) - return i18n( "Tangent at This Point" ); -// else assert( false ); - return TQString(); -} - -//TQString TangentConstructor::selectStatement( -// const std::vector& sel, const KigDocument&, -// const KigWidget& ) const -//{ -// if ( sel.size() == 0 ) -// return i18n( "Select the object..." ); -// else -// return i18n( "Select the point for the tangent to go through..." ); -//} - -/* - * center of curvature of a curve - */ - -CocConstructor::CocConstructor() - : MergeObjectConstructor( - I18N_NOOP( "Center Of Curvature" ), - I18N_NOOP( "The center of the osculating circle to a curve" ), - "centerofcurvature" ) -{ - SimpleObjectTypeConstructor* conic = - new SimpleObjectTypeConstructor( - CocConicType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "cocconic" ); - - SimpleObjectTypeConstructor* cubic = - new SimpleObjectTypeConstructor( - CocCubicType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "coccubic" ); - - SimpleObjectTypeConstructor* curve = - new SimpleObjectTypeConstructor( - CocCurveType::instance(), - "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", - "coccurve" ); - - merge( conic ); - merge( cubic ); - merge( curve ); -} - -CocConstructor::~CocConstructor() -{ -} - -TQString CocConstructor::useText( - const ObjectCalcer& o, const std::vector&, - const KigDocument&, const KigWidget& ) const -{ - if ( o.imp()->inherits( ConicImp::stype() ) ) - return i18n( "Center of Curvature of This Conic" ); - else if ( o.imp()->inherits( CubicImp::stype() ) ) - return i18n( "Center of Curvature of This Cubic Curve" ); - else if ( o.imp()->inherits( CurveImp::stype() ) ) - return i18n( "Center of Curvature of This Curve" ); - else if ( o.imp()->inherits( PointImp::stype() ) ) - return i18n( "Center of Curvature at This Point" ); - return TQString(); -} - -bool relativePrimes( int n, int p ) -{ - if ( p > n ) return relativePrimes( p, n ); - assert ( p >= 0 ); - if ( p == 0 ) return false; - if ( p == 1 ) return true; - int d = int( n/p ); - return relativePrimes( p, n-d*p ); -} - -//TQString CocConstructor::selectStatement( -// const std::vector& sel, const KigDocument&, -// const KigWidget& ) const -//{ -// if ( sel.size() == 0 ) -// return i18n( "Select the object..." ); -// else -// return i18n( "Select the point where to compute the center of curvature..." ); -//} diff --git a/kig/misc/special_constructors.cpp b/kig/misc/special_constructors.cpp new file mode 100644 index 00000000..9618bc90 --- /dev/null +++ b/kig/misc/special_constructors.cpp @@ -0,0 +1,1628 @@ +// Copyright (C) 2003 Dominique Devriese + +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#include "special_constructors.h" + +#include "calcpaths.h" +#include "common.h" +#include "conic-common.h" +#include "guiaction.h" +#include "kigpainter.h" + +#include "../kig/kig_part.h" +#include "../modes/construct_mode.h" +#include "../objects/bogus_imp.h" +#include "../objects/centerofcurvature_type.h" +#include "../objects/circle_imp.h" +#include "../objects/conic_imp.h" +#include "../objects/conic_types.h" +#include "../objects/cubic_imp.h" +#include "../objects/intersection_types.h" +#include "../objects/inversion_type.h" +#include "../objects/line_imp.h" +#include "../objects/line_type.h" +#include "../objects/locus_imp.h" +#include "../objects/object_calcer.h" +#include "../objects/object_drawer.h" +#include "../objects/object_factory.h" +#include "../objects/object_holder.h" +#include "../objects/object_imp.h" +#include "../objects/object_type.h" +#include "../objects/other_imp.h" +#include "../objects/other_type.h" +#include "../objects/point_imp.h" +#include "../objects/point_type.h" +#include "../objects/polygon_imp.h" +#include "../objects/polygon_type.h" +#include "../objects/tangent_type.h" +#include "../objects/text_imp.h" +#include "../objects/transform_types.h" + +#include + +#include + +#include +#include + +class ConicConicIntersectionConstructor + : public StandardConstructorBase +{ +protected: + ArgsParser mparser; +public: + ConicConicIntersectionConstructor(); + ~ConicConicIntersectionConstructor(); + + void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, + const KigDocument& ) const; + std::vector build( const std::vector& os, KigDocument& d, KigWidget& w ) const; + void plug( KigPart* doc, KigGUIAction* kact ); + + bool isTransform() const; +}; + +class ConicLineIntersectionConstructor + : public MultiObjectTypeConstructor +{ +public: + ConicLineIntersectionConstructor(); + ~ConicLineIntersectionConstructor(); +}; + +class ArcLineIntersectionConstructor + : public MultiObjectTypeConstructor +{ +public: + ArcLineIntersectionConstructor(); + ~ArcLineIntersectionConstructor(); +}; + +ConicRadicalConstructor::ConicRadicalConstructor() + : StandardConstructorBase( + I18N_NOOP( "Radical Lines for Conics" ), + I18N_NOOP( "The lines constructed through the intersections " + "of two conics. This is also defined for " + "non-intersecting conics." ), + "conicsradicalline", mparser ), + mtype( ConicRadicalType::instance() ), + mparser( mtype->argsParser().without( IntImp::stype() ) ) +{ +} + +ConicRadicalConstructor::~ConicRadicalConstructor() +{ +} + +void ConicRadicalConstructor::drawprelim( + const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& doc ) const +{ + if ( parents.size() == 2 && parents[0]->imp()->inherits( ConicImp::stype() ) && + parents[1]->imp()->inherits( ConicImp::stype() ) ) + { + Args args; + std::transform( parents.begin(), parents.end(), + std::back_inserter( args ), std::mem_fun( &ObjectCalcer::imp ) ); + for ( int i = -1; i < 2; i += 2 ) + { + IntImp root( i ); + IntImp zeroindex( 1 ); + args.push_back( &root ); + args.push_back( &zeroindex ); + ObjectImp* data = mtype->calc( args, doc ); + drawer.draw( *data, p, true ); + delete data; data = 0; + args.pop_back(); + args.pop_back(); + }; + }; +} + +std::vector ConicRadicalConstructor::build( const std::vector& os, KigDocument&, KigWidget& ) const +{ + using namespace std; + std::vector ret; + ObjectCalcer* zeroindexcalcer = new ObjectConstCalcer( new IntImp( 1 ) ); + for ( int i = -1; i < 2; i += 2 ) + { + std::vector args; + std::copy( os.begin(), os.end(), back_inserter( args ) ); + args.push_back( new ObjectConstCalcer( new IntImp( i ) ) ); + // we use only one zeroindex dataobject, so that if you switch one + // radical line around, then the other switches along.. + args.push_back( zeroindexcalcer ); + ret.push_back( + new ObjectHolder( new ObjectTypeCalcer( mtype, args ) ) ); + }; + return ret; +} + +static const struct ArgsParser::spec argsspecpp[] = +{ + { PointImp::stype(), I18N_NOOP( "Moving Point" ), + I18N_NOOP( "Select the moving point, which will be moved around while drawing the locus..." ), false }, + { PointImp::stype(), I18N_NOOP( "Following Point" ), + I18N_NOOP( "Select the following point, whose locations the locus will be drawn through..." ), true } +}; + +LocusConstructor::LocusConstructor() + : StandardConstructorBase( I18N_NOOP( "Locus" ), I18N_NOOP( "A locus" ), + "locus", margsparser ), + margsparser( argsspecpp, 2 ) +{ +} + +LocusConstructor::~LocusConstructor() +{ +} + +void LocusConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, + const KigDocument& ) const +{ + // this function is rather ugly, but it is necessary to do it this + // way in order to play nice with Kig's design.. + + if ( parents.size() != 2 ) return; + const ObjectTypeCalcer* constrained = dynamic_cast( parents.front() ); + const ObjectCalcer* moving = parents.back(); + if ( ! constrained || ! constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) + { + // moving is in fact the constrained point.. swap them.. + moving = parents.front(); + constrained = dynamic_cast( parents.back() ); + assert( constrained ); + }; + assert( constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) ); + + const ObjectImp* oimp = constrained->parents().back()->imp(); + if( !oimp->inherits( CurveImp::stype() ) ) + oimp = constrained->parents().front()->imp(); + assert( oimp->inherits( CurveImp::stype() ) ); + const CurveImp* cimp = static_cast( oimp ); + + ObjectHierarchy hier( constrained, moving ); + + LocusImp limp( cimp->copy(), hier ); + drawer.draw( limp, p, true ); +} + +const int LocusConstructor::wantArgs( + const std::vector& os, const KigDocument&, const KigWidget& + ) const +{ + int ret = margsparser.check( os ); + if ( ret == ArgsParser::Invalid ) return ret; + else if ( os.size() != 2 ) return ret; + if ( dynamic_cast( os.front() ) && + static_cast( os.front() )->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) + { + std::set children = getAllChildren( os.front() ); + return children.find( os.back() ) != children.end() ? ret : ArgsParser::Invalid; + } + if ( dynamic_cast( os.back() ) && + static_cast( os.back() )->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) + { + std::set children = getAllChildren( os.back() ); + return children.find( os.front() ) != children.end() ? ret : ArgsParser::Invalid; + } + return ArgsParser::Invalid; +} + +std::vector LocusConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const +{ + std::vector ret; + assert( parents.size() == 2 ); + + ObjectTypeCalcer* constrained = dynamic_cast( parents.front() ); + ObjectCalcer* moving = parents.back(); + if ( ! constrained || ! constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) + { + // moving is in fact the constrained point.. swap them.. + moving = parents.front(); + constrained = dynamic_cast( parents.back() ); + assert( constrained ); + }; + assert( constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) ); + + ret.push_back( ObjectFactory::instance()->locus( constrained, moving ) ); + return ret; +} + +TQString LocusConstructor::useText( const ObjectCalcer& o, const std::vector& os, + const KigDocument&, const KigWidget& ) const +{ + if ( dynamic_cast( &o ) && + static_cast( o ).type()->inherits( ObjectType::ID_ConstrainedPointType ) && + ( os.empty() || !dynamic_cast( os[0] ) || + !static_cast( os[0] )->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) + ) return i18n( "Moving Point" ); + else return i18n( "Dependent Point" ); +} + +void ConicRadicalConstructor::plug( KigPart*, KigGUIAction* ) +{ +} + +void LocusConstructor::plug( KigPart*, KigGUIAction* ) +{ +} + +bool ConicRadicalConstructor::isTransform() const +{ + return mtype->isTransform(); +} + +bool LocusConstructor::isTransform() const +{ + return false; +} + +/* + * generic polygon constructor + */ + +PolygonBNPTypeConstructor::PolygonBNPTypeConstructor() + : mtype( PolygonBNPType::instance() ) +{ +} + +PolygonBNPTypeConstructor::~PolygonBNPTypeConstructor() +{ +} + +const TQString PolygonBNPTypeConstructor::descriptiveName() const +{ + return i18n("Polygon by Its Vertices"); +} + +const TQString PolygonBNPTypeConstructor::description() const +{ + return i18n("Construct a polygon by giving its vertices"); +} + +const TQCString PolygonBNPTypeConstructor::iconFileName( const bool ) const +{ + return "kig_polygon"; +} + +const bool PolygonBNPTypeConstructor::isAlreadySelectedOK( + const std::vector& os, const int& pos ) const +{ + if ( pos == 0 && os.size() >= 3 ) return true; + return false; +} + +const int PolygonBNPTypeConstructor::wantArgs( const std::vector& os, + const KigDocument&, + const KigWidget& ) const +{ + int count=os.size() - 1; + + for ( int i = 0; i <= count; i++ ) + { + if ( ! ( os[i]->imp()->inherits( PointImp::stype() ) ) ) return ArgsParser::Invalid; + } + if ( count < 3 ) return ArgsParser::Valid; + if ( os[0] == os[count] ) return ArgsParser::Complete; + return ArgsParser::Valid; +} + +void PolygonBNPTypeConstructor::handleArgs( + const std::vector& os, KigPart& d, + KigWidget& v ) const +{ + std::vector bos = build( os, d.document(), v ); + for ( std::vector::iterator i = bos.begin(); + i != bos.end(); ++i ) + { + (*i)->calc( d.document() ); + } + + d.addObjects( bos ); +} + +void PolygonBNPTypeConstructor::handlePrelim( + KigPainter& p, const std::vector& os, + const KigDocument& d, const KigWidget& + ) const +{ + uint count = os.size(); + if ( count < 2 ) return; + + for ( uint i = 0; i < count; i++ ) + { + assert ( os[i]->imp()->inherits( PointImp::stype() ) ); + } + + std::vector args = os; + p.setBrushStyle( Qt::NoBrush ); + p.setBrushColor( TQt::red ); + p.setPen( TQPen ( TQt::red, 1) ); + p.setWidth( -1 ); // -1 means the default width for the object being + // drawn.. + + ObjectDrawer drawer( TQt::red ); + drawprelim( drawer, p, args, d ); +} + +TQString PolygonBNPTypeConstructor::useText( const ObjectCalcer&, const std::vector& os, + const KigDocument&, const KigWidget& ) const +{ + if ( os.size() > 3 ) + return i18n("... with this vertex (click on the first vertex to terminate construction)"); + else return i18n("Construct a polygon with this vertex"); +} + +TQString PolygonBNPTypeConstructor::selectStatement( + const std::vector&, const KigDocument&, + const KigWidget& ) const +{ + return i18n("Select a point to be a vertex of the new polygon..."); +} + +void PolygonBNPTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, + const KigDocument& ) const +{ + if ( parents.size() < 2 ) return; + + std::vector points; + + for ( uint i = 0; i < parents.size(); ++i ) + { + const Coordinate vertex = + static_cast( parents[i]->imp() )->coordinate(); + points.push_back( vertex ); + } + + if ( parents.size() == 2 ) + { + SegmentImp segment = SegmentImp( points[0], points[1] ); + drawer.draw( segment, p, true ); + } else { + PolygonImp polygon = PolygonImp( points ); + drawer.draw( polygon, p, true ); + } +} + +std::vector PolygonBNPTypeConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const +{ + uint count = parents.size() - 1; + assert ( count >= 3 ); + std::vector args; + for ( uint i = 0; i < count; ++i ) args.push_back( parents[i] ); + ObjectTypeCalcer* calcer = new ObjectTypeCalcer( mtype, args ); + ObjectHolder* h = new ObjectHolder( calcer ); + std::vector ret; + ret.push_back( h ); + return ret; +} + +void PolygonBNPTypeConstructor::plug( KigPart*, KigGUIAction* ) +{ +} + +bool PolygonBNPTypeConstructor::isTransform() const +{ + return false; +} + +/* + * construction of polygon vertices + */ + +static const struct ArgsParser::spec argsspecpv[] = +{ + { PolygonImp::stype(), I18N_NOOP( "Polygon" ), + I18N_NOOP( "Construct the vertices of this polygon..." ), true } +}; + +PolygonVertexTypeConstructor::PolygonVertexTypeConstructor() + : StandardConstructorBase( I18N_NOOP( "Vertices of a Polygon" ), + I18N_NOOP( "The vertices of a polygon." ), + "polygonvertices", margsparser ), + mtype( PolygonVertexType::instance() ), + margsparser( argsspecpv, 1 ) +{ +} + +PolygonVertexTypeConstructor::~PolygonVertexTypeConstructor() +{ +} + +void PolygonVertexTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, + const KigDocument& ) const +{ + if ( parents.size() != 1 ) return; + + const PolygonImp* polygon = dynamic_cast( parents.front()->imp() ); + const std::vector points = polygon->points(); + + int sides = points.size(); + for ( int i = 0; i < sides; ++i ) + { + PointImp point = PointImp( points[i] ); + drawer.draw( point, p, true ); + } +} + +std::vector PolygonVertexTypeConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const +{ + std::vector ret; + assert( parents.size() == 1 ); + const PolygonImp* polygon = dynamic_cast( parents.front()->imp() ); + const std::vector points = polygon->points(); + + int sides = points.size(); + + for ( int i = 0; i < sides; ++i ) + { + ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( i ) ); + std::vector args( parents ); + args.push_back( d ); + ret.push_back( new ObjectHolder( new ObjectTypeCalcer( mtype, args ) ) ); + } + return ret; +} + +void PolygonVertexTypeConstructor::plug( KigPart*, KigGUIAction* ) +{ +} + +bool PolygonVertexTypeConstructor::isTransform() const +{ + return false; +} + +/* + * construction of polygon sides + */ + +static const struct ArgsParser::spec argsspecps[] = +{ + { PolygonImp::stype(), I18N_NOOP( "Polygon" ), + I18N_NOOP( "Construct the sides of this polygon..." ), false } +}; + +PolygonSideTypeConstructor::PolygonSideTypeConstructor() + : StandardConstructorBase( I18N_NOOP( "Sides of a Polygon" ), + I18N_NOOP( "The sides of a polygon." ), + "polygonsides", margsparser ), + mtype( PolygonSideType::instance() ), + margsparser( argsspecps, 1 ) +{ +} + +PolygonSideTypeConstructor::~PolygonSideTypeConstructor() +{ +} + +void PolygonSideTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, + const KigDocument& ) const +{ + if ( parents.size() != 1 ) return; + + const PolygonImp* polygon = dynamic_cast( parents.front()->imp() ); + const std::vector points = polygon->points(); + + uint sides = points.size(); + for ( uint i = 0; i < sides; ++i ) + { + uint nexti = ( i + 1 < sides )?(i + 1):0; + SegmentImp segment = SegmentImp( points[i], points[nexti] ); + drawer.draw( segment, p, true ); + } +} + +std::vector PolygonSideTypeConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const +{ + std::vector ret; + assert( parents.size() == 1 ); + const PolygonImp* polygon = dynamic_cast( parents.front()->imp() ); + const std::vector points = polygon->points(); + + uint sides = points.size(); + + for ( uint i = 0; i < sides; ++i ) + { + ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( i ) ); + std::vector args( parents ); + args.push_back( d ); + ret.push_back( new ObjectHolder( new ObjectTypeCalcer( mtype, args ) ) ); + } + return ret; +} + +void PolygonSideTypeConstructor::plug( KigPart*, KigGUIAction* ) +{ +} + +bool PolygonSideTypeConstructor::isTransform() const +{ + return false; +} + +/* + * polygon by center and vertex + */ + +PolygonBCVConstructor::PolygonBCVConstructor() + : mtype( PolygonBCVType::instance() ) +{ +} + +PolygonBCVConstructor::~PolygonBCVConstructor() +{ +} + +const TQString PolygonBCVConstructor::descriptiveName() const +{ + return i18n("Regular Polygon with Given Center"); +} + +const TQString PolygonBCVConstructor::description() const +{ + return i18n("Construct a regular polygon with a given center and vertex"); +} + +const TQCString PolygonBCVConstructor::iconFileName( const bool ) const +{ + return "hexagonbcv"; +} + +const bool PolygonBCVConstructor::isAlreadySelectedOK( + const std::vector&, const int& ) const +{ + return false; +} + +const int PolygonBCVConstructor::wantArgs( const std::vector& os, + const KigDocument&, + const KigWidget& ) const +{ + if ( os.size() > 3 ) return ArgsParser::Invalid; + + uint imax = ( os.size() <= 2) ? os.size() : 2; + for ( uint i = 0; i < imax; ++i ) + if ( ! ( os[i]->imp()->inherits( PointImp::stype() ) ) ) return ArgsParser::Invalid; + + if ( os.size() < 3 ) return ArgsParser::Valid; + + if ( ! ( os[2]->imp()->inherits( BogusPointImp::stype() ) ) ) + return ArgsParser::Invalid; + + return ArgsParser::Complete; +} + +void PolygonBCVConstructor::handleArgs( + const std::vector& os, KigPart& d, + KigWidget& v ) const +{ + std::vector bos = build( os, d.document(), v ); + for ( std::vector::iterator i = bos.begin(); + i != bos.end(); ++i ) + { + (*i)->calc( d.document() ); + } + + d.addObjects( bos ); +} + +void PolygonBCVConstructor::handlePrelim( + KigPainter& p, const std::vector& os, + const KigDocument& d, const KigWidget& + ) const +{ + if ( os.size() < 2 ) return; + + for ( uint i = 0; i < 2; i++ ) + { + assert ( os[i]->imp()->inherits( PointImp::stype() ) ); + } + + Coordinate c = static_cast( os[0]->imp() )->coordinate(); + Coordinate v = static_cast( os[1]->imp() )->coordinate(); + + int nsides = 6; + bool moreinfo = false; + int winding = 0; // 0 means allow winding > 1 + if ( os.size() == 3 ) + { + assert ( os[2]->imp()->inherits( BogusPointImp::stype() ) ); + Coordinate cntrl = static_cast( os[2]->imp() )->coordinate(); + nsides = computeNsides( c, v, cntrl, winding ); + moreinfo = true; + } + + std::vector args; + args.push_back( os[0] ); + args.push_back( os[1] ); + ObjectConstCalcer* ns = new ObjectConstCalcer( new IntImp( nsides ) ); + args.push_back( ns ); + if ( winding > 1 ) + { + ns = new ObjectConstCalcer( new IntImp( winding ) ); + args.push_back( ns ); + } + + p.setBrushStyle( Qt::NoBrush ); + p.setBrushColor( TQt::red ); + p.setPen( TQPen ( TQt::red, 1) ); + p.setWidth( -1 ); // -1 means the default width for the object being + // drawn.. + + ObjectDrawer drawer( TQt::red ); + drawprelim( drawer, p, args, d ); + if ( moreinfo ) + { + p.setPointStyle( 1 ); + p.setWidth( 6 ); + double ro = 1.0/(2.5); + Coordinate where = getRotatedCoord( c, (1-ro)*c+ro*v, 4*M_PI/5.0 ); + PointImp ptn = PointImp( where ); + TextImp text = TextImp( "(5,2)", where, false ); + ptn.draw( p ); + text.draw( p ); + for ( int i = 3; i < 9; ++i ) + { + where = getRotatedCoord( c, v, 2.0*M_PI/i ); + ptn = PointImp( where ); + ptn.draw( p ); + if ( i > 5 ) continue; + text = TextImp( TQString( "(%1)" ).arg(i), where, false ); + text.draw( p ); + } + p.setStyle( Qt::DotLine ); + p.setWidth( 1 ); + double radius = ( v - c ).length(); + CircleImp circle = CircleImp( c, radius ); + circle.draw( p ); + for ( int i = 2; i < 5; i++ ) + { + ro = 1.0/(i+0.5); + CircleImp circle = CircleImp( c, ro*radius ); + circle.draw( p ); + } + } + delete_all( args.begin() + 2, args.end() ); +} + +std::vector PolygonBCVConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const +{ + assert ( parents.size() == 3 ); + std::vector args; + + Coordinate c = static_cast( parents[0]->imp() )->coordinate(); + Coordinate v = static_cast( parents[1]->imp() )->coordinate(); + Coordinate cntrl = static_cast( parents[2]->imp() )->coordinate(); + + args.push_back( parents[0] ); + args.push_back( parents[1] ); + int winding = 0; + int nsides = computeNsides( c, v, cntrl, winding ); + ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( nsides ) ); + args.push_back( d ); + if ( winding > 1 ) + { + d = new ObjectConstCalcer( new IntImp( winding ) ); + args.push_back( d ); + } + + ObjectTypeCalcer* calcer = new ObjectTypeCalcer( mtype, args ); + ObjectHolder* h = new ObjectHolder( calcer ); + std::vector ret; + ret.push_back( h ); + return ret; +} + +TQString PolygonBCVConstructor::useText( const ObjectCalcer&, const std::vector& os, + const KigDocument&, const KigWidget& ) const +{ + switch ( os.size() ) + { + case 1: + return i18n( "Construct a regular polygon with this center" ); + break; + + case 2: + return i18n( "Construct a regular polygon with this vertex" ); + break; + + case 3: + Coordinate c = static_cast( os[0]->imp() )->coordinate(); + Coordinate v = static_cast( os[1]->imp() )->coordinate(); + Coordinate cntrl = static_cast( os[2]->imp() )->coordinate(); + int winding = 0; + int nsides = computeNsides( c, v, cntrl, winding ); + + if ( winding > 1 ) + { + TQString result = TQString( + i18n( "Adjust the number of sides (%1/%2)" ) + ).arg( nsides ).arg( winding ); + return result; + } else + { + TQString result = TQString( + i18n( "Adjust the number of sides (%1)" ) + ).arg( nsides ); + return result; + } + break; + } + + return ""; +} + +TQString PolygonBCVConstructor::selectStatement( + const std::vector& os, const KigDocument&, + const KigWidget& ) const +{ + switch ( os.size() ) + { + case 1: + return i18n( "Select the center of the new polygon..." ); + break; + + case 2: + return i18n( "Select a vertex for the new polygon..." ); + break; + + case 3: + return i18n( "Move the cursor to get the desired number of sides..." ); + break; + } + + return ""; +} + +void PolygonBCVConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, + const KigDocument& doc ) const +{ + if ( parents.size() < 3 || parents.size() > 4 ) return; + + assert ( parents[0]->imp()->inherits( PointImp::stype() ) && + parents[1]->imp()->inherits( PointImp::stype() ) && + parents[2]->imp()->inherits( IntImp::stype() ) ); + + if ( parents.size() == 4 ) + assert ( parents[3]->imp()->inherits( IntImp::stype() ) ); + + Args args; + std::transform( parents.begin(), parents.end(), + std::back_inserter( args ), std::mem_fun( &ObjectCalcer::imp ) ); + + ObjectImp* data = mtype->calc( args, doc ); + drawer.draw( *data, p, true ); + delete data; + data = 0; +} + +void PolygonBCVConstructor::plug( KigPart*, KigGUIAction* ) +{ +} + +bool PolygonBCVConstructor::isTransform() const +{ + return false; +} + +Coordinate PolygonBCVConstructor::getRotatedCoord( const Coordinate& c, + const Coordinate& v, double alpha ) const +{ + double cosalpha = cos(alpha); + double sinalpha = sin(alpha); + double dx = v.x - c.x; + double dy = v.y - c.y; + return c + Coordinate( cosalpha*dx - sinalpha*dy, sinalpha*dx + cosalpha*dy ); +} + +int PolygonBCVConstructor::computeNsides ( const Coordinate& c, + const Coordinate& v, const Coordinate& cntrl, int& winding ) const +{ + Coordinate lvect = v - c; + Coordinate rvect = cntrl - c; + + double angle = atan2( rvect.y, rvect.x ) - atan2( lvect.y, lvect.x ); + angle = fabs( angle/(2*M_PI) ); + while ( angle > 1 ) angle -= 1; + if ( angle > 0.5 ) angle = 1 - angle; + + double realsides = 1.0/angle; // this is bigger that 2 + if ( angle == 0. ) realsides = 3; + if ( winding <= 0 ) // free to compute winding + { + winding = 1; + double ratio = lvect.length()/rvect.length(); + winding = int ( ratio ); + if ( winding < 1 ) winding = 1; + if ( winding > 50 ) winding = 50; + } + int nsides = int( winding*realsides + 0.5 ); // nsides/winding should be reduced! + if ( nsides > 100 ) nsides = 100; // well, 100 seems large enough! + if ( nsides < 3 ) nsides = 3; + while ( !relativePrimes ( nsides, winding ) ) ++nsides; + return nsides; +} + +/* + * ConicConic intersection... + */ + +static const ArgsParser::spec argsspectc[] = { + { ConicImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", true }, + { ConicImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", true } +}; + +ConicConicIntersectionConstructor::ConicConicIntersectionConstructor() + : StandardConstructorBase( "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "curvelineintersection", mparser ), + mparser( argsspectc, 2 ) +{ +} + +ConicConicIntersectionConstructor::~ConicConicIntersectionConstructor() +{ +} + +void ConicConicIntersectionConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, + const KigDocument& ) const +{ + if ( parents.size() != 2 ) return; + assert ( parents[0]->imp()->inherits( ConicImp::stype() ) && + parents[1]->imp()->inherits( ConicImp::stype() ) ); + const ConicCartesianData conica = + static_cast( parents[0]->imp() )->cartesianData(); + const ConicCartesianData conicb = + static_cast( parents[1]->imp() )->cartesianData(); + bool ok = true; + for ( int wr = -1; wr < 2; wr += 2 ) + { + LineData radical = calcConicRadical( conica, conicb, wr, 1, ok ); + if ( ok ) + { + for ( int wi = -1; wi < 2; wi += 2 ) + { + Coordinate c = calcConicLineIntersect( conica, radical, 0.0, wi ); + if ( c.valid() ) { + PointImp pi( c ); + drawer.draw( pi, p, true ); + } + }; + }; + }; +} + +std::vector ConicConicIntersectionConstructor::build( + const std::vector& os, KigDocument& doc, KigWidget& ) const +{ + assert( os.size() == 2 ); + std::vector ret; + ObjectCalcer* conica = os[0]; + ObjectConstCalcer* zeroindexdo = new ObjectConstCalcer( new IntImp( 1 ) ); + + for ( int wr = -1; wr < 2; wr += 2 ) + { + std::vector args = os; + args.push_back( new ObjectConstCalcer( new IntImp( wr ) ) ); + args.push_back( zeroindexdo ); + ObjectTypeCalcer* radical = + new ObjectTypeCalcer( ConicRadicalType::instance(), args ); + radical->calc( doc ); + for ( int wi = -1; wi < 2; wi += 2 ) + { + args.clear(); + args.push_back( conica ); + args.push_back( radical ); + args.push_back( new ObjectConstCalcer( new IntImp( wi ) ) ); + ret.push_back( + new ObjectHolder( + new ObjectTypeCalcer( + ConicLineIntersectionType::instance(), args ) ) ); + }; + }; + return ret; +} + +void ConicConicIntersectionConstructor::plug( KigPart*, KigGUIAction* ) +{ +} + +bool ConicConicIntersectionConstructor::isTransform() const +{ + return false; +} + +ConicLineIntersectionConstructor::ConicLineIntersectionConstructor() + : MultiObjectTypeConstructor( + ConicLineIntersectionType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "curvelineintersection", -1, 1 ) +{ +} + +ConicLineIntersectionConstructor::~ConicLineIntersectionConstructor() +{ +} + +ArcLineIntersectionConstructor::ArcLineIntersectionConstructor() + : MultiObjectTypeConstructor( + ArcLineIntersectionType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "curvelineintersection", -1, 1 ) +{ +} + +ArcLineIntersectionConstructor::~ArcLineIntersectionConstructor() +{ +} + +TQString ConicRadicalConstructor::useText( const ObjectCalcer& o, const std::vector&, + const KigDocument&, const KigWidget& ) const +{ + if ( o.imp()->inherits( CircleImp::stype() ) ) + return i18n( "Construct the Radical Lines of This Circle" ); + else + return i18n( "Construct the Radical Lines of This Conic" ); +} + +/* + * generic affinity and generic projectivity. A unique affinity can be + * obtained by specifying the image of three points (four for projectivity) + * in the end we need, besides the object to be transformed, a total of + * six point or (alternatively) two triangles; our affinity will map the + * first triangle onto the second with corresponding ordering of their + * vertices. Since we allow for two different ways of specifying the six + * points we shall use a Generic constructor, like that for intersections. + */ + +GenericAffinityConstructor::GenericAffinityConstructor() + : MergeObjectConstructor( + I18N_NOOP( "Generic Affinity" ), + I18N_NOOP( "The unique affinity that maps three points (or a triangle) onto three other points (or a triangle)" ), + "genericaffinity" ) +{ + SimpleObjectTypeConstructor* b2tr = + new SimpleObjectTypeConstructor( + AffinityB2TrType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "genericaffinity" ); + + SimpleObjectTypeConstructor* gi3p = + new SimpleObjectTypeConstructor( + AffinityGI3PType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "genericaffinity" ); + + merge( b2tr ); + merge( gi3p ); +} + +GenericAffinityConstructor::~GenericAffinityConstructor() {} + +GenericProjectivityConstructor::GenericProjectivityConstructor() + : MergeObjectConstructor( + I18N_NOOP( "Generic Projective Transformation" ), + I18N_NOOP( "The unique projective transformation that maps four points (or a quadrilateral) onto four other points (or a quadrilateral)" ), + "genericprojectivity" ) +{ + SimpleObjectTypeConstructor* b2qu = + new SimpleObjectTypeConstructor( + ProjectivityB2QuType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "genericprojectivity" ); + + SimpleObjectTypeConstructor* gi4p = + new SimpleObjectTypeConstructor( + ProjectivityGI4PType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "genericprojectivity" ); + + merge( b2qu ); + merge( gi4p ); +} + +GenericProjectivityConstructor::~GenericProjectivityConstructor() {} + +/* + * inversion of points, lines with respect to a circle + */ + +InversionConstructor::InversionConstructor() + : MergeObjectConstructor( + I18N_NOOP( "Inversion of Point, Line or Circle" ), + I18N_NOOP( "The inversion of a point, line or circle with respect to a circle" ), + "inversion" ) +{ + SimpleObjectTypeConstructor* pointobj = + new SimpleObjectTypeConstructor( + InvertPointType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "inversion" ); + + SimpleObjectTypeConstructor* lineobj = + new SimpleObjectTypeConstructor( + InvertLineType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "inversion" ); + + SimpleObjectTypeConstructor* segmentobj = + new SimpleObjectTypeConstructor( + InvertSegmentType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "inversion" ); + + SimpleObjectTypeConstructor* circleobj = + new SimpleObjectTypeConstructor( + InvertCircleType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "inversion" ); + + SimpleObjectTypeConstructor* arcobj = + new SimpleObjectTypeConstructor( + InvertArcType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "inversion" ); + + merge( arcobj ); + merge( circleobj ); + merge( pointobj ); + merge( segmentobj ); + merge( lineobj ); +} + +InversionConstructor::~InversionConstructor() {} + +/* + * Transport of Measure + */ + +MeasureTransportConstructor::MeasureTransportConstructor() + : mtype( MeasureTransportType::instance() ) +{ +} + +MeasureTransportConstructor::~MeasureTransportConstructor() +{ +} + +const TQString MeasureTransportConstructor::descriptiveName() const +{ + return i18n("Measure Transport"); +} + +const TQString MeasureTransportConstructor::description() const +{ + return i18n("Transport the measure of a segment or arc over a line or circle."); +} + +const TQCString MeasureTransportConstructor::iconFileName( const bool ) const +{ + return "measuretransport"; +} + +const bool MeasureTransportConstructor::isAlreadySelectedOK( + const std::vector&, const int& ) const +{ + return false; +} + +/* + * we want the arguments in the exact order, this makes + * the code simpler, but I guess it is also less confusing + * to the user + */ + +const int MeasureTransportConstructor::wantArgs( + const std::vector& os, + const KigDocument&, + const KigWidget& ) const +{ + if ( os.size() == 0 ) return ArgsParser::Valid; + + if ( ! os[0]->imp()->inherits( SegmentImp::stype() ) && + ! os[0]->imp()->inherits( ArcImp::stype() ) ) + return ArgsParser::Invalid; + + if ( os.size() == 1 ) return ArgsParser::Valid; + + if ( ! os[1]->imp()->inherits( LineImp::stype() ) && + ! os[1]->imp()->inherits( CircleImp::stype() ) ) + return ArgsParser::Invalid; + + if ( os.size() == 2 ) return ArgsParser::Valid; + + if ( ! os[2]->imp()->inherits( PointImp::stype() ) ) + return ArgsParser::Invalid; + + // we here use the "isPointOnCurve", which relies on + // "by construction" incidence, instead of a numerical + // check + if ( ! isPointOnCurve( os[2], os[1] ) ) + return ArgsParser::Invalid; + + if ( os.size() == 3 ) return ArgsParser::Complete; + + return ArgsParser::Invalid; +} + +void MeasureTransportConstructor::handleArgs( + const std::vector& os, KigPart& d, + KigWidget& v ) const +{ + std::vector bos = build( os, d.document(), v ); + for ( std::vector::iterator i = bos.begin(); + i != bos.end(); ++i ) + { + (*i)->calc( d.document() ); + } + + d.addObjects( bos ); +} + +void MeasureTransportConstructor::handlePrelim( + KigPainter& p, const std::vector& os, + const KigDocument& d, const KigWidget& + ) const +{ + p.setBrushStyle( Qt::NoBrush ); + p.setBrushColor( TQt::red ); + p.setPen( TQPen ( TQt::red, 1) ); + p.setWidth( -1 ); // -1 means the default width for the object being + // drawn.. + + ObjectDrawer drawer( TQt::red ); + drawprelim( drawer, p, os, d ); +} + +void MeasureTransportConstructor::drawprelim( const ObjectDrawer& drawer, + KigPainter& p, + const std::vector& parents, + const KigDocument& doc ) const +{ + Args args; + using namespace std; + transform( parents.begin(), parents.end(), + back_inserter( args ), mem_fun( &ObjectCalcer::imp ) ); + ObjectImp* data = mtype->calc( args, doc ); + drawer.draw( *data, p, true ); + delete data; +} + +TQString MeasureTransportConstructor::useText( const ObjectCalcer& o, + const std::vector& os, + const KigDocument&, const KigWidget& ) const +{ + if ( o.imp()->inherits( SegmentImp::stype() ) ) + return i18n("Segment to transport"); + if ( o.imp()->inherits( ArcImp::stype() ) ) + return i18n("Arc to transport"); + if ( o.imp()->inherits( LineImp::stype() ) ) + return i18n("Transport a measure on this line"); + if ( o.imp()->inherits( CircleImp::stype() ) ) + return i18n("Transport a measure on this circle"); + if ( o.imp()->inherits( PointImp::stype() ) ) + { + if ( os[1]->imp()->inherits( CircleImp::stype() ) ) + return i18n("Start transport from this point of the circle"); + if ( os[1]->imp()->inherits( LineImp::stype() ) ) + return i18n("Start transport from this point of the line"); + else + return i18n("Start transport from this point of the curve"); + // well, this isn't impemented yet, should never get here + } + return ""; +} + +TQString MeasureTransportConstructor::selectStatement( + const std::vector&, const KigDocument&, + const KigWidget& ) const +{ +//TODO + return i18n("Select a point to be a vertex of the new polygon..."); +} + +std::vector MeasureTransportConstructor::build( + const std::vector& parents, + KigDocument&, KigWidget& ) const +{ + assert ( parents.size() == 3 ); +// std::vector args; +// for ( uint i = 0; i < count; ++i ) args.push_back( parents[i] ); + ObjectTypeCalcer* calcer = new ObjectTypeCalcer( mtype, parents ); + ObjectHolder* h = new ObjectHolder( calcer ); + std::vector ret; + ret.push_back( h ); + return ret; +} + +void MeasureTransportConstructor::plug( KigPart*, KigGUIAction* ) +{ +} + +bool MeasureTransportConstructor::isTransform() const +{ + return false; +} + +/* + * Generic intersection + */ + +GenericIntersectionConstructor::GenericIntersectionConstructor() + : MergeObjectConstructor( + I18N_NOOP( "Intersect" ), + I18N_NOOP( "The intersection of two objects" ), + "curvelineintersection" ) +{ + // intersection type.. + // There is one "toplevel" object_constructor, that is composed + // of multiple subconstructors.. First we build the + // subconstructors: + SimpleObjectTypeConstructor* lineline = + new SimpleObjectTypeConstructor( + LineLineIntersectionType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "curvelineintersection" ); + + ObjectConstructor* lineconic = + new ConicLineIntersectionConstructor(); + + ObjectConstructor* arcline = + new ArcLineIntersectionConstructor(); + + MultiObjectTypeConstructor* linecubic = + new MultiObjectTypeConstructor( + LineCubicIntersectionType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "curvelineintersection", 1, 2, 3 ); + + ObjectConstructor* conicconic = + new ConicConicIntersectionConstructor(); + + MultiObjectTypeConstructor* circlecircle = + new MultiObjectTypeConstructor( + CircleCircleIntersectionType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "circlecircleintersection", -1, 1 ); + + SimpleObjectTypeConstructor* polygonline = + new SimpleObjectTypeConstructor( + PolygonLineIntersectionType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "curvelineintersection" ); + + merge( lineline ); + merge( circlecircle ); + merge( lineconic ); + merge( linecubic ); + merge( conicconic ); + merge( arcline ); + merge( polygonline ); +} + +GenericIntersectionConstructor::~GenericIntersectionConstructor() +{ +} + +bool GenericIntersectionConstructor::isIntersection() const +{ + return true; +} + +TQString GenericIntersectionConstructor::useText( + const ObjectCalcer& o, const std::vector& os, + const KigDocument&, const KigWidget& ) const +{ + TQString preamble; + switch (os.size()) + { + case 1: + if ( o.imp()->inherits( CircleImp::stype() ) ) + return i18n( "Intersect this Circle" ); + else if ( o.imp()->inherits( ConicImp::stype() ) ) + return i18n( "Intersect this Conic" ); + else if ( o.imp()->inherits( AbstractLineImp::stype() ) ) + return i18n( "Intersect this Line" ); + else if ( o.imp()->inherits( CubicImp::stype() ) ) + return i18n( "Intersect this Cubic Curve" ); + else if ( o.imp()->inherits( ArcImp::stype() ) ) + return i18n( "Intersect this Arc" ); + else if ( o.imp()->inherits( PolygonImp::stype() ) ) + return i18n( "Intersect this Polygon" ); + else assert( false ); + break; + case 2: + if ( o.imp()->inherits( CircleImp::stype() ) ) + return i18n( "with this Circle" ); + else if ( o.imp()->inherits( ConicImp::stype() ) ) + return i18n( "with this Conic" ); + else if ( o.imp()->inherits( AbstractLineImp::stype() ) ) + return i18n( "with this Line" ); + else if ( o.imp()->inherits( CubicImp::stype() ) ) + return i18n( "with this Cubic Curve" ); + else if ( o.imp()->inherits( ArcImp::stype() ) ) + return i18n( "with this Arc" ); + else if ( o.imp()->inherits( PolygonImp::stype() ) ) + return i18n( "with this Polygon" ); + else assert( false ); + break; + } + + return TQString(); +} + +static const ArgsParser::spec argsspecMidPointOfTwoPoints[] = +{ + { PointImp::stype(), I18N_NOOP( "Construct Midpoint of This Point and Another One" ), + I18N_NOOP( "Select the first of the points of which you want to construct the midpoint..." ), false }, + { PointImp::stype(), I18N_NOOP( "Construct the midpoint of this point and another one" ), + I18N_NOOP( "Select the other of the points of which to construct the midpoint..." ), false } +}; + +MidPointOfTwoPointsConstructor::MidPointOfTwoPointsConstructor() + : StandardConstructorBase( "Mid Point", + "Construct the midpoint of two points", + "bisection", mparser ), + mparser( argsspecMidPointOfTwoPoints, 2 ) +{ +} + +MidPointOfTwoPointsConstructor::~MidPointOfTwoPointsConstructor() +{ +} + +void MidPointOfTwoPointsConstructor::drawprelim( + const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, + const KigDocument& ) const +{ + if ( parents.size() != 2 ) return; + assert( parents[0]->imp()->inherits( PointImp::stype() ) ); + assert( parents[1]->imp()->inherits( PointImp::stype() ) ); + const Coordinate m = + ( static_cast( parents[0]->imp() )->coordinate() + + static_cast( parents[1]->imp() )->coordinate() ) / 2; + drawer.draw( PointImp( m ), p, true ); +} + +std::vector MidPointOfTwoPointsConstructor::build( + const std::vector& os, KigDocument& d, KigWidget& ) const +{ + ObjectTypeCalcer* seg = new ObjectTypeCalcer( SegmentABType::instance(), os ); + seg->calc( d ); + int index = seg->imp()->propertiesInternalNames().findIndex( "mid-point" ); + assert( index != -1 ); + ObjectPropertyCalcer* prop = new ObjectPropertyCalcer( seg, index ); + prop->calc( d ); + std::vector ret; + ret.push_back( new ObjectHolder( prop ) ); + return ret; +} + +void MidPointOfTwoPointsConstructor::plug( KigPart*, KigGUIAction* ) +{ +} + +bool MidPointOfTwoPointsConstructor::isTransform() const +{ + return false; +} + +TestConstructor::TestConstructor( const ArgsParserObjectType* type, const char* descname, + const char* desc, const char* iconfile ) + : StandardConstructorBase( descname, desc, iconfile, type->argsParser() ), + mtype( type ) +{ +} + +TestConstructor::~TestConstructor() +{ +} + +void TestConstructor::drawprelim( const ObjectDrawer&, KigPainter&, const std::vector&, + const KigDocument& ) const +{ + // not used, only here because of the wrong + // ObjectConstructor-GUIAction design. See the TODO +} + +std::vector TestConstructor::build( const std::vector&, KigDocument&, + KigWidget& ) const +{ + // not used, only here because of the wrong + // ObjectConstructor-GUIAction design. See the TODO + std::vector ret; + return ret; +} + +void TestConstructor::plug( KigPart*, KigGUIAction* ) +{ +} + +bool TestConstructor::isTransform() const +{ + return false; +} + +bool TestConstructor::isTest() const +{ + return true; +} + +BaseConstructMode* TestConstructor::constructMode( KigPart& doc ) +{ + return new TestConstructMode( doc, mtype ); +} + +const int TestConstructor::wantArgs( const std::vector& os, + const KigDocument& d, const KigWidget& v ) const +{ + int ret = StandardConstructorBase::wantArgs( os, d, v ); + if ( ret == ArgsParser::Complete ) ret = ArgsParser::Valid; + return ret; +} + +TQString GenericIntersectionConstructor::selectStatement( + const std::vector& sel, const KigDocument&, + const KigWidget& ) const +{ + if ( sel.size() == 0 ) + return i18n( "Select the first object to intersect..." ); + else + return i18n( "Select the second object to intersect..." ); +} + +TangentConstructor::TangentConstructor() + : MergeObjectConstructor( + I18N_NOOP( "Tangent" ), + I18N_NOOP( "The line tangent to a curve" ), + "tangent" ) +{ + SimpleObjectTypeConstructor* conic = + new SimpleObjectTypeConstructor( + TangentConicType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "tangentconic" ); + + SimpleObjectTypeConstructor* arc = + new SimpleObjectTypeConstructor( + TangentArcType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "tangentarc" ); + + SimpleObjectTypeConstructor* cubic = + new SimpleObjectTypeConstructor( + TangentCubicType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "tangentcubic" ); + + SimpleObjectTypeConstructor* curve = + new SimpleObjectTypeConstructor( + TangentCurveType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "tangentcurve" ); + + merge( conic ); + merge( arc ); + merge( cubic ); + merge( curve ); +} + +TangentConstructor::~TangentConstructor() +{ +} + +TQString TangentConstructor::useText( + const ObjectCalcer& o, const std::vector&, + const KigDocument&, const KigWidget& ) const +{ + if ( o.imp()->inherits( CircleImp::stype() ) ) + return i18n( "Tangent to This Circle" ); + else if ( o.imp()->inherits( ConicImp::stype() ) ) + return i18n( "Tangent to This Conic" ); + else if ( o.imp()->inherits( ArcImp::stype() ) ) + return i18n( "Tangent to This Arc" ); + else if ( o.imp()->inherits( CubicImp::stype() ) ) + return i18n( "Tangent to This Cubic Curve" ); + else if ( o.imp()->inherits( CurveImp::stype() ) ) + return i18n( "Tangent to This Curve" ); + else if ( o.imp()->inherits( PointImp::stype() ) ) + return i18n( "Tangent at This Point" ); +// else assert( false ); + return TQString(); +} + +//TQString TangentConstructor::selectStatement( +// const std::vector& sel, const KigDocument&, +// const KigWidget& ) const +//{ +// if ( sel.size() == 0 ) +// return i18n( "Select the object..." ); +// else +// return i18n( "Select the point for the tangent to go through..." ); +//} + +/* + * center of curvature of a curve + */ + +CocConstructor::CocConstructor() + : MergeObjectConstructor( + I18N_NOOP( "Center Of Curvature" ), + I18N_NOOP( "The center of the osculating circle to a curve" ), + "centerofcurvature" ) +{ + SimpleObjectTypeConstructor* conic = + new SimpleObjectTypeConstructor( + CocConicType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "cocconic" ); + + SimpleObjectTypeConstructor* cubic = + new SimpleObjectTypeConstructor( + CocCubicType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "coccubic" ); + + SimpleObjectTypeConstructor* curve = + new SimpleObjectTypeConstructor( + CocCurveType::instance(), + "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", + "coccurve" ); + + merge( conic ); + merge( cubic ); + merge( curve ); +} + +CocConstructor::~CocConstructor() +{ +} + +TQString CocConstructor::useText( + const ObjectCalcer& o, const std::vector&, + const KigDocument&, const KigWidget& ) const +{ + if ( o.imp()->inherits( ConicImp::stype() ) ) + return i18n( "Center of Curvature of This Conic" ); + else if ( o.imp()->inherits( CubicImp::stype() ) ) + return i18n( "Center of Curvature of This Cubic Curve" ); + else if ( o.imp()->inherits( CurveImp::stype() ) ) + return i18n( "Center of Curvature of This Curve" ); + else if ( o.imp()->inherits( PointImp::stype() ) ) + return i18n( "Center of Curvature at This Point" ); + return TQString(); +} + +bool relativePrimes( int n, int p ) +{ + if ( p > n ) return relativePrimes( p, n ); + assert ( p >= 0 ); + if ( p == 0 ) return false; + if ( p == 1 ) return true; + int d = int( n/p ); + return relativePrimes( p, n-d*p ); +} + +//TQString CocConstructor::selectStatement( +// const std::vector& sel, const KigDocument&, +// const KigWidget& ) const +//{ +// if ( sel.size() == 0 ) +// return i18n( "Select the object..." ); +// else +// return i18n( "Select the point where to compute the center of curvature..." ); +//} -- cgit v1.2.1