From a3dcc6228458572e91916d3e837bc1c06c55cb0a 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 (cherry picked from commit 65a9f54e1051ee8ab936975e78dcb7117b265ef5) --- kig/ChangeLog | 8 +- kig/DESIGN | 2 +- kig/Makefile.am | 4 +- kig/filters/CMakeLists.txt | 24 +- kig/filters/Makefile.am | 24 +- kig/filters/cabri-filter.cc | 577 ----------- kig/filters/cabri-filter.cpp | 577 +++++++++++ kig/filters/drgeo-filter-chooser.cc | 65 -- kig/filters/drgeo-filter-chooser.cpp | 65 ++ kig/filters/drgeo-filter.cc | 809 ---------------- kig/filters/drgeo-filter.cpp | 809 ++++++++++++++++ kig/filters/exporter.cc | 624 ------------ kig/filters/exporter.cpp | 624 ++++++++++++ kig/filters/filter.cc | 114 --- kig/filters/filter.cpp | 114 +++ kig/filters/filters-common.cc | 39 - kig/filters/filters-common.cpp | 39 + kig/filters/imageexporteroptions.cc | 57 -- kig/filters/imageexporteroptions.cpp | 57 ++ kig/filters/kgeo-filter.cc | 374 -------- kig/filters/kgeo-filter.cpp | 374 ++++++++ kig/filters/kseg-filter.cc | 679 ------------- kig/filters/kseg-filter.cpp | 679 +++++++++++++ kig/filters/latexexporter.cc | 608 ------------ kig/filters/latexexporter.cpp | 608 ++++++++++++ kig/filters/native-filter.cc | 747 --------------- kig/filters/native-filter.cpp | 747 +++++++++++++++ kig/filters/svgexporter.cc | 111 --- kig/filters/svgexporter.cpp | 111 +++ kig/kig/CMakeLists.txt | 2 +- kig/kig/Makefile.am | 2 +- kig/kig/kig_document.cc | 200 ---- kig/kig/kig_document.cpp | 200 ++++ 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 ++++++++++++++++++++++++++++++++ kig/modes/CMakeLists.txt | 24 +- kig/modes/Makefile.am | 24 +- kig/modes/base_mode.cc | 160 ---- kig/modes/base_mode.cpp | 160 ++++ kig/modes/construct_mode.cc | 572 ----------- kig/modes/construct_mode.cpp | 572 +++++++++++ kig/modes/dragrectmode.cc | 180 ---- kig/modes/dragrectmode.cpp | 180 ++++ kig/modes/edittype.cc | 107 --- kig/modes/edittype.cpp | 107 +++ kig/modes/label.cc | 589 ------------ kig/modes/label.cpp | 589 ++++++++++++ kig/modes/macro.cc | 245 ----- kig/modes/macro.cpp | 245 +++++ kig/modes/macrowizard.cc | 90 -- kig/modes/macrowizard.cpp | 90 ++ kig/modes/mode.cc | 133 --- kig/modes/mode.cpp | 133 +++ kig/modes/moving.cc | 245 ----- kig/modes/moving.cpp | 245 +++++ kig/modes/normal.cc | 306 ------ kig/modes/normal.cpp | 306 ++++++ kig/modes/popup.cc | 1200 ----------------------- kig/modes/popup.cpp | 1200 +++++++++++++++++++++++ kig/modes/textlabelwizard.cc | 95 -- kig/modes/textlabelwizard.cpp | 95 ++ kig/objects/CMakeLists.txt | 76 +- kig/objects/Makefile.am | 76 +- kig/objects/angle_type.cc | 208 ---- kig/objects/angle_type.cpp | 208 ++++ kig/objects/arc_type.cc | 199 ---- kig/objects/arc_type.cpp | 199 ++++ kig/objects/base_type.cc | 112 --- kig/objects/base_type.cpp | 112 +++ kig/objects/bogus_imp.cc | 388 -------- kig/objects/bogus_imp.cpp | 388 ++++++++ kig/objects/centerofcurvature_type.cc | 304 ------ kig/objects/centerofcurvature_type.cpp | 304 ++++++ kig/objects/circle_imp.cc | 356 ------- kig/objects/circle_imp.cpp | 356 +++++++ kig/objects/circle_type.cc | 181 ---- kig/objects/circle_type.cpp | 181 ++++ kig/objects/common.cc | 43 - kig/objects/common.cpp | 43 + kig/objects/conic_imp.cc | 385 -------- kig/objects/conic_imp.cpp | 385 ++++++++ kig/objects/conic_types.cc | 689 -------------- kig/objects/conic_types.cpp | 689 ++++++++++++++ kig/objects/cubic_imp.cc | 437 --------- kig/objects/cubic_imp.cpp | 437 +++++++++ kig/objects/cubic_type.cc | 185 ---- kig/objects/cubic_type.cpp | 185 ++++ kig/objects/curve_imp.cc | 41 - kig/objects/curve_imp.cpp | 41 + kig/objects/intersection_types.cc | 338 ------- kig/objects/intersection_types.cpp | 338 +++++++ kig/objects/inversion_type.cc | 412 -------- kig/objects/inversion_type.cpp | 412 ++++++++ kig/objects/line_imp.cc | 571 ----------- kig/objects/line_imp.cpp | 571 +++++++++++ kig/objects/line_type.cc | 334 ------- kig/objects/line_type.cpp | 334 +++++++ kig/objects/locus_imp.cc | 397 -------- kig/objects/locus_imp.cpp | 397 ++++++++ kig/objects/object_calcer.cc | 323 ------- kig/objects/object_calcer.cpp | 323 +++++++ kig/objects/object_calcer.h | 2 +- kig/objects/object_drawer.cc | 204 ---- kig/objects/object_drawer.cpp | 204 ++++ kig/objects/object_factory.cc | 369 -------- kig/objects/object_factory.cpp | 369 ++++++++ kig/objects/object_holder.cc | 164 ---- kig/objects/object_holder.cpp | 164 ++++ kig/objects/object_imp.cc | 308 ------ kig/objects/object_imp.cpp | 308 ++++++ kig/objects/object_imp_factory.cc | 510 ---------- kig/objects/object_imp_factory.cpp | 510 ++++++++++ kig/objects/object_type.cc | 125 --- kig/objects/object_type.cpp | 125 +++ kig/objects/object_type_factory.cc | 148 --- kig/objects/object_type_factory.cpp | 148 +++ kig/objects/other_imp.cc | 710 -------------- kig/objects/other_imp.cpp | 710 ++++++++++++++ kig/objects/other_type.cc | 189 ---- kig/objects/other_type.cpp | 189 ++++ kig/objects/point_imp.cc | 223 ----- kig/objects/point_imp.cpp | 223 +++++ kig/objects/point_type.cc | 665 ------------- kig/objects/point_type.cpp | 665 +++++++++++++ kig/objects/polygon_imp.cc | 550 ----------- kig/objects/polygon_imp.cpp | 550 +++++++++++ kig/objects/polygon_type.cc | 669 ------------- kig/objects/polygon_type.cpp | 669 +++++++++++++ kig/objects/special_calcers.cc | 84 -- kig/objects/special_calcers.cpp | 84 ++ kig/objects/tangent_type.cc | 285 ------ kig/objects/tangent_type.cpp | 285 ++++++ kig/objects/tests_type.cc | 382 -------- kig/objects/tests_type.cpp | 382 ++++++++ kig/objects/text_imp.cc | 173 ---- kig/objects/text_imp.cpp | 173 ++++ kig/objects/text_type.cc | 215 ----- kig/objects/text_type.cpp | 215 +++++ kig/objects/transform_types.cc | 874 ----------------- kig/objects/transform_types.cpp | 874 +++++++++++++++++ kig/objects/vector_type.cc | 100 -- kig/objects/vector_type.cpp | 100 ++ kig/scripting/CMakeLists.txt | 10 +- kig/scripting/Makefile.am | 10 +- kig/scripting/newscriptwizard.cc | 234 ----- kig/scripting/newscriptwizard.cpp | 234 +++++ kig/scripting/python_scripter.cc | 579 ------------ kig/scripting/python_scripter.cpp | 579 ++++++++++++ kig/scripting/python_type.cc | 195 ---- kig/scripting/python_type.cpp | 195 ++++ kig/scripting/script-common.cc | 95 -- kig/scripting/script-common.cpp | 95 ++ kig/scripting/script_mode.cc | 362 ------- kig/scripting/script_mode.cpp | 362 +++++++ 182 files changed, 29760 insertions(+), 29760 deletions(-) delete mode 100644 kig/filters/cabri-filter.cc create mode 100644 kig/filters/cabri-filter.cpp delete mode 100644 kig/filters/drgeo-filter-chooser.cc create mode 100644 kig/filters/drgeo-filter-chooser.cpp delete mode 100644 kig/filters/drgeo-filter.cc create mode 100644 kig/filters/drgeo-filter.cpp delete mode 100644 kig/filters/exporter.cc create mode 100644 kig/filters/exporter.cpp delete mode 100644 kig/filters/filter.cc create mode 100644 kig/filters/filter.cpp delete mode 100644 kig/filters/filters-common.cc create mode 100644 kig/filters/filters-common.cpp delete mode 100644 kig/filters/imageexporteroptions.cc create mode 100644 kig/filters/imageexporteroptions.cpp delete mode 100644 kig/filters/kgeo-filter.cc create mode 100644 kig/filters/kgeo-filter.cpp delete mode 100644 kig/filters/kseg-filter.cc create mode 100644 kig/filters/kseg-filter.cpp delete mode 100644 kig/filters/latexexporter.cc create mode 100644 kig/filters/latexexporter.cpp delete mode 100644 kig/filters/native-filter.cc create mode 100644 kig/filters/native-filter.cpp delete mode 100644 kig/filters/svgexporter.cc create mode 100644 kig/filters/svgexporter.cpp delete mode 100644 kig/kig/kig_document.cc create mode 100644 kig/kig/kig_document.cpp 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 delete mode 100644 kig/modes/base_mode.cc create mode 100644 kig/modes/base_mode.cpp delete mode 100644 kig/modes/construct_mode.cc create mode 100644 kig/modes/construct_mode.cpp delete mode 100644 kig/modes/dragrectmode.cc create mode 100644 kig/modes/dragrectmode.cpp delete mode 100644 kig/modes/edittype.cc create mode 100644 kig/modes/edittype.cpp delete mode 100644 kig/modes/label.cc create mode 100644 kig/modes/label.cpp delete mode 100644 kig/modes/macro.cc create mode 100644 kig/modes/macro.cpp delete mode 100644 kig/modes/macrowizard.cc create mode 100644 kig/modes/macrowizard.cpp delete mode 100644 kig/modes/mode.cc create mode 100644 kig/modes/mode.cpp delete mode 100644 kig/modes/moving.cc create mode 100644 kig/modes/moving.cpp delete mode 100644 kig/modes/normal.cc create mode 100644 kig/modes/normal.cpp delete mode 100644 kig/modes/popup.cc create mode 100644 kig/modes/popup.cpp delete mode 100644 kig/modes/textlabelwizard.cc create mode 100644 kig/modes/textlabelwizard.cpp delete mode 100644 kig/objects/angle_type.cc create mode 100644 kig/objects/angle_type.cpp delete mode 100644 kig/objects/arc_type.cc create mode 100644 kig/objects/arc_type.cpp delete mode 100644 kig/objects/base_type.cc create mode 100644 kig/objects/base_type.cpp delete mode 100644 kig/objects/bogus_imp.cc create mode 100644 kig/objects/bogus_imp.cpp delete mode 100644 kig/objects/centerofcurvature_type.cc create mode 100644 kig/objects/centerofcurvature_type.cpp delete mode 100644 kig/objects/circle_imp.cc create mode 100644 kig/objects/circle_imp.cpp delete mode 100644 kig/objects/circle_type.cc create mode 100644 kig/objects/circle_type.cpp delete mode 100644 kig/objects/common.cc create mode 100644 kig/objects/common.cpp delete mode 100644 kig/objects/conic_imp.cc create mode 100644 kig/objects/conic_imp.cpp delete mode 100644 kig/objects/conic_types.cc create mode 100644 kig/objects/conic_types.cpp delete mode 100644 kig/objects/cubic_imp.cc create mode 100644 kig/objects/cubic_imp.cpp delete mode 100644 kig/objects/cubic_type.cc create mode 100644 kig/objects/cubic_type.cpp delete mode 100644 kig/objects/curve_imp.cc create mode 100644 kig/objects/curve_imp.cpp delete mode 100644 kig/objects/intersection_types.cc create mode 100644 kig/objects/intersection_types.cpp delete mode 100644 kig/objects/inversion_type.cc create mode 100644 kig/objects/inversion_type.cpp delete mode 100644 kig/objects/line_imp.cc create mode 100644 kig/objects/line_imp.cpp delete mode 100644 kig/objects/line_type.cc create mode 100644 kig/objects/line_type.cpp delete mode 100644 kig/objects/locus_imp.cc create mode 100644 kig/objects/locus_imp.cpp delete mode 100644 kig/objects/object_calcer.cc create mode 100644 kig/objects/object_calcer.cpp delete mode 100644 kig/objects/object_drawer.cc create mode 100644 kig/objects/object_drawer.cpp delete mode 100644 kig/objects/object_factory.cc create mode 100644 kig/objects/object_factory.cpp delete mode 100644 kig/objects/object_holder.cc create mode 100644 kig/objects/object_holder.cpp delete mode 100644 kig/objects/object_imp.cc create mode 100644 kig/objects/object_imp.cpp delete mode 100644 kig/objects/object_imp_factory.cc create mode 100644 kig/objects/object_imp_factory.cpp delete mode 100644 kig/objects/object_type.cc create mode 100644 kig/objects/object_type.cpp delete mode 100644 kig/objects/object_type_factory.cc create mode 100644 kig/objects/object_type_factory.cpp delete mode 100644 kig/objects/other_imp.cc create mode 100644 kig/objects/other_imp.cpp delete mode 100644 kig/objects/other_type.cc create mode 100644 kig/objects/other_type.cpp delete mode 100644 kig/objects/point_imp.cc create mode 100644 kig/objects/point_imp.cpp delete mode 100644 kig/objects/point_type.cc create mode 100644 kig/objects/point_type.cpp delete mode 100644 kig/objects/polygon_imp.cc create mode 100644 kig/objects/polygon_imp.cpp delete mode 100644 kig/objects/polygon_type.cc create mode 100644 kig/objects/polygon_type.cpp delete mode 100644 kig/objects/special_calcers.cc create mode 100644 kig/objects/special_calcers.cpp delete mode 100644 kig/objects/tangent_type.cc create mode 100644 kig/objects/tangent_type.cpp delete mode 100644 kig/objects/tests_type.cc create mode 100644 kig/objects/tests_type.cpp delete mode 100644 kig/objects/text_imp.cc create mode 100644 kig/objects/text_imp.cpp delete mode 100644 kig/objects/text_type.cc create mode 100644 kig/objects/text_type.cpp delete mode 100644 kig/objects/transform_types.cc create mode 100644 kig/objects/transform_types.cpp delete mode 100644 kig/objects/vector_type.cc create mode 100644 kig/objects/vector_type.cpp delete mode 100644 kig/scripting/newscriptwizard.cc create mode 100644 kig/scripting/newscriptwizard.cpp delete mode 100644 kig/scripting/python_scripter.cc create mode 100644 kig/scripting/python_scripter.cpp delete mode 100644 kig/scripting/python_type.cc create mode 100644 kig/scripting/python_type.cpp delete mode 100644 kig/scripting/script-common.cc create mode 100644 kig/scripting/script-common.cpp delete mode 100644 kig/scripting/script_mode.cc create mode 100644 kig/scripting/script_mode.cpp (limited to 'kig') diff --git a/kig/ChangeLog b/kig/ChangeLog index ddbb1309..50e1c288 100644 --- a/kig/ChangeLog +++ b/kig/ChangeLog @@ -234,7 +234,7 @@ 2005-02-07 Maurizio Paolini - * Bug fix: new algorithm for calcPath in calcpath.cc; the + * Bug fix: new algorithm for calcPath in calcpath.cpp; the previous had exponential complexity for some examples 2005-02-03 Dominique Devriese @@ -1052,7 +1052,7 @@ 2004-02-14 Dominique Devriese - * Fix a bug waiting to pop up in construct_mode.cc, where you + * Fix a bug waiting to pop up in construct_mode.cpp, where you select the same object twice. * Add documentation about the locus and textlabel design to the @@ -1061,7 +1061,7 @@ 2004-02-10 Dominique Devriese * Fix a bug which caused Kig to crash on moving a text label by - removing a wrong assertion in objects/object_calcer.cc + removing a wrong assertion in objects/object_calcer.cpp 2004-02-09 Dominique Devriese @@ -1286,7 +1286,7 @@ 2003-07-17 Dominique Devriese * fix the "conversion from const char* to char*" problem in - python_scripter.cc. This introduces a small, harmless memory leak + python_scripter.cpp. This introduces a small, harmless memory leak because of how the python libs work.. 2003-07-16 Dominique Devriese diff --git a/kig/DESIGN b/kig/DESIGN index fd887779..0de0c986 100644 --- a/kig/DESIGN +++ b/kig/DESIGN @@ -31,7 +31,7 @@ holding data for other objects to use. Examples are StringImp, IntImp, ConicImp etc. There are a lot of ObjectImp's in Kig, most of them are in files -called *_imp.h and *_imp.cc or *_imp.cpp in the objects subdirectory. +called *_imp.h and *_imp.cpp in the objects subdirectory. Examples are PointImp, LineImp, ConicImp, CircleImp, CubicImp, AngleImp etc. diff --git a/kig/Makefile.am b/kig/Makefile.am index 5081c354..eea9593b 100644 --- a/kig/Makefile.am +++ b/kig/Makefile.am @@ -41,7 +41,7 @@ messages: rc.cpp cat "$$file" | grep '' | sed -e 's/^ *\([^<]*\)<\/UseText>/i18n( "\1" );/' | sed -e 's/&/\&/g' >> rc.cpp; \ cat "$$file" | grep '' | sed -e 's/^ *\([^<]*\)<\/SelectStatement>/i18n( "\1" );/' | sed -e 's/&/\&/g' >> rc.cpp; \ done - $(XGETTEXT) tips.cpp rc.cpp filters/*.h kig/*.h misc/*.h modes/*.h objects/*.h scripting/*.h */*.cc kig/*.cpp misc/*.cpp modes/*.cpp -o $(podir)/kig.pot + $(XGETTEXT) tips.cpp rc.cpp filters/*.h kig/*.h misc/*.h modes/*.h objects/*.h scripting/*.h */*.cpp kig/*.cpp misc/*.cpp modes/*.cpp -o $(podir)/kig.pot $(XGETTEXT) tdefile/tdefile_drgeo.cpp tdefile/tdefile_drgeo.h -o $(podir)/tdefile_drgeo.pot $(XGETTEXT) tdefile/tdefile_kig.cpp tdefile/tdefile_kig.h -o $(podir)/tdefile_kig.pot @@ -51,7 +51,7 @@ dummy.cpp: touch dummy.cpp TAGS: - find -name '*.cc' -o -name '*.cpp' -o -name '*.h' | etags - + find -name '*.cpp' -o -name '*.h' | etags - # Want to do the scripting part separately, but # include everything else. diff --git a/kig/filters/CMakeLists.txt b/kig/filters/CMakeLists.txt index 35ded394..1685098e 100644 --- a/kig/filters/CMakeLists.txt +++ b/kig/filters/CMakeLists.txt @@ -23,18 +23,18 @@ tde_add_library( kigfilters STATIC_PIC AUTOMOC latexexporteroptions.ui svgexporteroptions.ui drgeo-filter-chooserbase.ui - cabri-filter.cc - exporter.cc - filter.cc - filters-common.cc - imageexporteroptions.cc - kgeo-filter.cc - kseg-filter.cc - latexexporter.cc - native-filter.cc - svgexporter.cc - drgeo-filter.cc - drgeo-filter-chooser.cc + cabri-filter.cpp + exporter.cpp + filter.cpp + filters-common.cpp + imageexporteroptions.cpp + kgeo-filter.cpp + kseg-filter.cpp + latexexporter.cpp + native-filter.cpp + svgexporter.cpp + drgeo-filter.cpp + drgeo-filter-chooser.cpp LINK kigmisc-static diff --git a/kig/filters/Makefile.am b/kig/filters/Makefile.am index bb827b5a..c7e82bb8 100644 --- a/kig/filters/Makefile.am +++ b/kig/filters/Makefile.am @@ -19,20 +19,20 @@ noinst_HEADERS= \ drgeo-filter.h \ drgeo-filter-chooser.h libfilters_la_SOURCES= \ - cabri-filter.cc \ - exporter.cc \ - filter.cc \ - filters-common.cc \ - imageexporteroptions.cc \ + cabri-filter.cpp \ + exporter.cpp \ + filter.cpp \ + filters-common.cpp \ + imageexporteroptions.cpp \ imageexporteroptionsbase.ui \ - kgeo-filter.cc \ - kseg-filter.cc \ - latexexporter.cc \ + kgeo-filter.cpp \ + kseg-filter.cpp \ + latexexporter.cpp \ latexexporteroptions.ui \ - native-filter.cc \ - svgexporter.cc \ + native-filter.cpp \ + svgexporter.cpp \ svgexporteroptions.ui \ - drgeo-filter.cc \ - drgeo-filter-chooser.cc \ + drgeo-filter.cpp \ + drgeo-filter-chooser.cpp \ drgeo-filter-chooserbase.ui diff --git a/kig/filters/cabri-filter.cc b/kig/filters/cabri-filter.cc deleted file mode 100644 index 0a94f140..00000000 --- a/kig/filters/cabri-filter.cc +++ /dev/null @@ -1,577 +0,0 @@ -/** - This file is part of Kig, a KDE program for Interactive Geometry... - 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 "cabri-filter.h" - -#include "../kig/kig_document.h" -#include "../kig/kig_part.h" -#include "../misc/coordinate.h" -#include "../objects/arc_type.h" -#include "../objects/bogus_imp.h" -#include "../objects/circle_type.h" -#include "../objects/conic_types.h" -#include "../objects/curve_imp.h" -#include "../objects/line_imp.h" -#include "../objects/line_type.h" -#include "../objects/object_calcer.h" -#include "../objects/object_drawer.h" -#include "../objects/object_factory.h" -#include "../objects/object_holder.h" -#include "../objects/other_imp.h" -#include "../objects/other_type.h" -#include "../objects/point_type.h" -#include "../objects/polygon_type.h" -#include "../objects/transform_types.h" -#include "../objects/vector_type.h" - -#include -#include -#include - -#include -#include - -/** - * a line: - * "Nr": Type, Unknown, "CN:"NumberOfParents, "VN:"Unknown - * Color, FillType, Thickness, "DS":Dots, "GT":SpecialAppearance, Visible, Fixed - * ["Const": Parents] ["Val": Constants] - * - * Nr: Simple sequential numbering of the objects in a file. - * Type: seen so far: Pt, Axes, Line, Cir - * NumberOfParents: The number of parents that will be specified in - * Parents - * Color: - * R -> red - * O -> purple - * Y -> yellow - * P -> dark purple - * V -> dark blue - * Bl -> blue - * lBl -> bright blue - * G -> bright green - * dG -> dark green - * Br -> brown - * dBr -> beige - * lGr -> light grey - * Gr -> grey - * dGr -> dark grey - * B -> black - * FillType: - * W -> not filled ( white ? ) - * all values of the Color item are valid here too.. - * Thickness: - * t -> thin - * tT -> medium - * T -> Thick - * Dots: - * a specification for how a line should be drawn ( with many - * dots, with short lines, it's a pretty generic format: the first - * number signifies the number of sequential dots to draw first, and - * the next is the sum of this first number with the number of - * spaces to leave before starting a new segment. - * SpecialAppearance: - * a number indicating some way of specially drawing an object. This - * can be modified using the "Modify Appearance" button in - * Cabri. For example, for a segment, the number indicates the - * amount of ticks to put on the segment, to indicate - * correspondances between segments.. - * Visible: - * V means visible, I means invisible - * Fixed: - * St means fix this object ( if you move one of its parents, it - * won't move ), nSt ( the default ) means don't fix this object. - * Parents: - * The numbers of the objects this object depends on - * Constants: - * Constants whose meaning depends on the type of object. E.g. for - * a point, this means first x, then y component. - */ - -struct CabriObject -{ - uint id; - TQCString type; - uint numberOfParents; - TQColor color; - TQColor fillColor; - int thick; - int lineSegLength; - int lineSegSplit; - int specialAppearanceSwitch; - bool visible; - bool fixed; - std::vector parents; - std::vector data; -}; - -KigFilterCabri::KigFilterCabri() -{ -} - -KigFilterCabri::~KigFilterCabri() -{ -} - -bool KigFilterCabri::supportMime( const TQString& mime ) -{ - // ugly hack to avoid duplicate extension ( XFig and Cabri files - // have the same .fig extension ). - return ( mime == "image/x-xfig" ) || - ( mime == "application/x-cabri" ); -} - -static TQString readLine( TQFile& file ) -{ - TQString ret; - file.readLine( ret, 10000L ); - if ( ret[ret.length() - 1] == '\n' ) - ret.truncate( ret.length() - 1 ); - if ( ret[ret.length() - 1] == '\r' ) - ret.truncate( ret.length() - 1 ); - return ret; -} - -static TQColor translatecolor( const TQString& s ) -{ - if ( s == "R" ) return TQt::red; - if ( s == "O" ) return TQt::magenta; - if ( s == "Y" ) return TQt::yellow; - if ( s == "P" ) return TQt::darkMagenta; - if ( s == "V" ) return TQt::darkBlue; - if ( s == "Bl" ) return TQt::blue; - if ( s == "lBl" ) return TQt::cyan; // TODO: bright blue - if ( s == "G" ) return TQt::green; - if ( s == "dG" ) return TQt::darkGreen; - if ( s == "Br" ) return TQColor( 165, 42, 42 ); - if ( s == "dBr" ) return TQColor( 128, 128, 0 ); - if ( s == "lGr" ) return TQt::lightGray; - if ( s == "Gr" ) return TQt::gray; - if ( s == "dGr" ) return TQt::darkGray; - if ( s == "B" ) return TQt::black; - if ( s == "W" ) return TQt::white; - - kdDebug() << k_funcinfo << "unknown color: " << s << endl; - return TQt::black; -} - -bool KigFilterCabri::readObject( TQFile& f, CabriObject& myobj ) -{ - // there are 4 lines per object in the file, so we read them all - // four now. - TQString line1, line2, line3, s; - TQString file = f.name(); - line1 = readLine( f ); - line2 = readLine( f ); - line3 = readLine( f ); - // ignore line 4, it is empty.. - s = readLine( f ); - - TQRegExp firstlinere( "^([^:]+): ([^,]+), ([^,]+), CN:([^,]*), VN:(.*)$" ); - if ( ! firstlinere.exactMatch( line1 ) ) - KIG_FILTER_PARSE_ERROR; - - bool ok; - TQString tmp; - - tmp = firstlinere.cap( 1 ); - myobj.id = tmp.toInt( &ok ); - if ( !ok ) KIG_FILTER_PARSE_ERROR; - - tmp = firstlinere.cap( 2 ); - myobj.type = tmp.latin1(); - - tmp = firstlinere.cap( 3 ); - // i have no idea what this number means.. - - tmp = firstlinere.cap( 4 ); - myobj.numberOfParents = tmp.toInt( &ok ); - if ( ! ok ) KIG_FILTER_PARSE_ERROR; - - tmp = firstlinere.cap( 5 ); - // i have no idea what this number means.. - - TQRegExp secondlinere( "^([^,]+), ([^,]+), ([^,]+), DS:([^ ]+) ([^,]+), GT:([^,]+), ([^,]+), (.*)$" ); - if ( ! secondlinere.exactMatch( line2 ) ) - KIG_FILTER_PARSE_ERROR; - - tmp = secondlinere.cap( 1 ); - myobj.color = translatecolor( tmp ); -// if ( ! color.isValid() ) KIG_FILTER_PARSE_ERROR; - - tmp = secondlinere.cap( 2 ); - myobj.fillColor = translatecolor( tmp ); -// if ( ! fillcolor.isValid() ) KIG_FILTER_PARSE_ERROR; - - tmp = secondlinere.cap( 3 ); - myobj.thick = tmp == "t" ? 1 : tmp == "tT" ? 2 : 3; - - tmp = secondlinere.cap( 4 ); - myobj.lineSegLength = tmp.toInt( &ok ); - if ( ! ok ) KIG_FILTER_PARSE_ERROR; - - tmp = secondlinere.cap( 5 ); - myobj.lineSegSplit = tmp.toInt( &ok ); - if ( ! ok ) KIG_FILTER_PARSE_ERROR; - - tmp = secondlinere.cap( 6 ); - myobj.specialAppearanceSwitch = tmp.toInt( &ok ); - if ( ! ok ) KIG_FILTER_PARSE_ERROR; - - tmp = secondlinere.cap( 7 ); - myobj.visible = tmp == "V"; - - tmp = secondlinere.cap( 8 ); - myobj.fixed = tmp == "St"; - - TQRegExp thirdlinere( "^(Const: ([^,]*),? ?)?(Val: (.*))?$" ); - if ( ! thirdlinere.exactMatch( line3 ) ) - KIG_FILTER_PARSE_ERROR; - - tmp = thirdlinere.cap( 2 ); - TQStringList parentsids = TQStringList::split( ' ', tmp ); - for ( TQStringList::iterator i = parentsids.begin(); - i != parentsids.end(); ++i ) - { - myobj.parents.push_back( ( *i ).toInt( &ok ) ); - if ( ! ok ) KIG_FILTER_PARSE_ERROR; - } - if ( myobj.parents.size() != myobj.numberOfParents ) - KIG_FILTER_PARSE_ERROR; - - tmp = thirdlinere.cap( 4 ); - TQStringList valIds = TQStringList::split( ' ', tmp ); - for ( TQStringList::iterator i = valIds.begin(); - i != valIds.end(); ++i ) - { - myobj.data.push_back( ( *i ).toDouble( &ok ) ); - if ( ! ok ) KIG_FILTER_PARSE_ERROR; - } -// kdDebug() -// << k_funcinfo << endl -// << "id = " << myobj.id << endl -// << "type = " << myobj.type << endl -// << "numberOfParents = " << myobj.numberOfParents << endl -// << "color = " << myobj.color.name() << endl -// << "fillcolor = " << myobj.fillColor.name() << endl -// << "thick = " << myobj.thick << endl -// << "lineseglength = " << myobj.lineSegLength << endl -// << "linesegsplit = " << myobj.lineSegSplit << endl -// << "specialAppearanceSwitch = " << myobj.specialAppearanceSwitch << endl -// << "visible = " << visible << endl -// << "fixed = " << myobj.fixed << endl -// << "parents =" << endl; -// for ( std::vector::iterator i = myobj.parents.begin(); i != myobj.parents.end(); ++i ) -// kdDebug() << " " << *i << endl; -// kdDebug() << "vals = " << endl; -// for ( std::vector::iterator i = myobj.data.begin(); i != myobj.data.end(); ++i ) -// kdDebug() << " " << *i << endl; - - return true; -} - -KigDocument* KigFilterCabri::load( const TQString& file ) -{ - TQFile f( file ); - if ( ! f.open( IO_ReadOnly ) ) - { - fileNotFound( file ); - return 0; - } - - KigDocument* ret = new KigDocument(); - - TQString s = readLine( f ); - TQString a = s.left( 21 ); - TQString b = s.mid( 21 ); - if( a != "FIGURE CabriII vers. " || - ( b != "DOS 1.0" && b != "MS-Windows 1.0" ) ) - { - if ( s.left( 5 ) == "#FIG " ) - { - notSupported( file, i18n( "This is an XFig file, not a Cabri figure." ) ); - return 0; - } - else - KIG_FILTER_PARSE_ERROR; - } - - // next we have: - // line 2: empty line - // line 3: window dimensions -> we don't need/use that... - // line 4: empty line - // line 5 through 8: center point - // line 9 through 12: axes - // so we skip 11 lines... - for( int i = 0; i != 11; ++i) - s = readLine( f ); - - // all Cabri files seem to at least have these center and axes... - if ( f.atEnd() ) - KIG_FILTER_PARSE_ERROR; - - std::vector holders; - std::vector calcers; - - const ObjectFactory* fact = ObjectFactory::instance(); - - std::vector args; - ObjectCalcer* oc = 0; - - while ( ! f.atEnd() ) - { - CabriObject obj; - // we do one object each iteration.. - if ( !readObject( f, obj ) ) - return 0; - -// reading linestyle - Qt::PenStyle ls = Qt::SolidLine; - if ( ( obj.lineSegLength > 1 ) && ( obj.lineSegLength < 6 ) && - ( obj.lineSegSplit > 1 ) && ( obj.lineSegSplit <= 10 ) ) - ls = Qt::DotLine; - else if ( ( obj.lineSegLength >= 6 ) && ( obj.lineSegSplit > 10 ) ) - ls = Qt::DashLine; - int ps = 0; - - args.clear(); - for ( std::vector::iterator i = obj.parents.begin(); - i != obj.parents.end(); ++i ) - args.push_back( calcers[*i-3] ); - - // two fake objects at the start ( origin and axes.. ) - if ( obj.id != calcers.size() + 3 ) KIG_FILTER_PARSE_ERROR; - oc = 0; - if ( obj.type == "Pt" ) - { - if ( ! args.empty() ) KIG_FILTER_PARSE_ERROR; - if ( obj.data.size() != 2 ) KIG_FILTER_PARSE_ERROR; - - switch ( obj.specialAppearanceSwitch ) - { - case 0: - { - obj.thick -= 1; - break; - } - case 2: - { - obj.thick += 1; - break; - } - case 3: - { - obj.thick += 1; - ps = 1; - break; - } - case 4: - { - obj.thick += 2; - ps = 4; - break; - } - } - // different sizes for points.. - obj.thick *= 2; - - oc = fact->fixedPointCalcer( Coordinate( obj.data[0], obj.data[1] ) ); - } - else if ( obj.type == "Cir" ) - { - if ( args.size() == 1 ) - { - if ( obj.data.size() != 1 ) KIG_FILTER_PARSE_ERROR; - ObjectConstCalcer* radc = - new ObjectConstCalcer( new DoubleImp( obj.data[0] ) ); - args.push_back( radc ); - oc = new ObjectTypeCalcer( CircleBPRType::instance(), args ); - } - else if ( args.size() == 2 ) - { - if ( ! obj.data.empty() ) KIG_FILTER_PARSE_ERROR; - oc = new ObjectTypeCalcer( CircleBCPType::instance(), args ); - } - else KIG_FILTER_PARSE_ERROR; - } - else if ( obj.type == "Line" || obj.type == "Ray" || obj.type == "Seg" || - obj.type == "Vec" ) - { - if ( args.size() == 1 ) - { - if ( obj.data.size() != 2 ) KIG_FILTER_PARSE_ERROR; - Coordinate vect( obj.data[0], obj.data[1] ); - ObjectConstCalcer* vectorcalcer = - new ObjectConstCalcer( new VectorImp( Coordinate( 0, 0 ), vect ) ); - args.push_back( vectorcalcer ); - ObjectTypeCalcer* secondpoint = - new ObjectTypeCalcer( TranslatedType::instance(), args ); - secondpoint->calc( *ret ); - args[1] = secondpoint; - } - if ( args.size() != 2 ) KIG_FILTER_PARSE_ERROR; - const ObjectType* t = 0; - if ( obj.type == "Line" ) t = LineABType::instance(); - else if ( obj.type == "Ray" ) t = RayABType::instance(); - else if ( obj.type == "Seg" ) t = SegmentABType::instance(); - else if ( obj.type == "Vec" ) t = VectorType::instance(); - else assert( t ); - oc = new ObjectTypeCalcer( t, args ); - } - else if ( obj.type == "Pt/" ) - { - // different sizes for points.. - obj.thick *= 2; - if ( args.size() != 1 || obj.data.size() != 2 ) - KIG_FILTER_PARSE_ERROR; - ObjectCalcer* parent = args[0]; - if ( !parent->imp()->inherits( CurveImp::stype() ) ) - KIG_FILTER_PARSE_ERROR; - const CurveImp* curve = static_cast( parent->imp() ); - Coordinate pt = Coordinate( obj.data[0], obj.data[1] ); - double param = curve->getParam( pt, *ret ); - args.push_back( new ObjectConstCalcer( new DoubleImp( param ) ) ); - oc = new ObjectTypeCalcer( ConstrainedPointType::instance(), args ); - } - else if ( obj.type == "Perp" || obj.type == "Par" ) - { - if ( args.size() != 2 || obj.data.size() != 0 ) - KIG_FILTER_PARSE_ERROR; - const ObjectType* t = 0; - if ( obj.type == "Perp" ) t = LinePerpendLPType::instance(); - else if ( obj.type == "Par" ) t = LineParallelLPType::instance(); - else assert( false ); - oc = new ObjectTypeCalcer( t, args ); - } - else if ( obj.type == "Arc" ) - { - if ( args.size() != 3 || ! obj.data.empty() ) - KIG_FILTER_PARSE_ERROR; - oc = new ObjectTypeCalcer( ArcBTPType::instance(), args ); - } - else if ( obj.type == "Con" ) - { - if ( args.size() != 5 || !obj.data.empty() ) - KIG_FILTER_PARSE_ERROR; - oc = new ObjectTypeCalcer( ConicB5PType::instance(), args ); - } - else if ( obj.type == "Mid" ) - { - if ( args.size() == 2 ) - { - ObjectCalcer* c = - new ObjectTypeCalcer( SegmentABType::instance(), args ); - c->calc( *ret ); - args.clear(); - args.push_back( c ); - } - // midpoint -> this can be the midpoint of a segment, two - // points, or a vector... - if ( args.size() != 1 || !obj.data.empty() ) - KIG_FILTER_PARSE_ERROR; - ObjectCalcer* parent = args[0]; - if ( parent->imp()->inherits( SegmentImp::stype() ) ) - oc = fact->propertyObjectCalcer( parent, "mid-point" ) ; - else if ( parent->imp()->inherits( VectorImp::stype() ) ) - oc = fact->propertyObjectCalcer( parent, "vect-mid-point" ); - else KIG_FILTER_PARSE_ERROR; - } - else if ( obj.type == "PBiss" ) - { - if ( args.size() == 2 ) - { - ObjectCalcer* c = - new ObjectTypeCalcer( SegmentABType::instance(), args ); - c->calc( *ret ); - args.clear(); - args.push_back( c ); - } - if ( args.size() != 1 || !obj.data.empty() ) - KIG_FILTER_PARSE_ERROR; - ObjectCalcer* parent = args[0]; - ObjectCalcer* midpoint = 0; - if ( parent->imp()->inherits( SegmentImp::stype() ) ) - midpoint = fact->propertyObjectCalcer( parent, "mid-point" ) ; -// else if ( parent->imp()->inherits( VectorImp::stype() ) ) -// midpoint = fact->propertyObjectCalcer( parent, "vect-mid-point" ); - else KIG_FILTER_PARSE_ERROR; - midpoint->calc( *ret ); - args.push_back( midpoint ); - oc = new ObjectTypeCalcer( LinePerpendLPType::instance(), args ); - } - else if ( obj.type == "Pol" ) - { - if ( args.size() < 3 || !obj.data.empty() ) - KIG_FILTER_PARSE_ERROR; - oc = new ObjectTypeCalcer( PolygonBNPType::instance(), args ); - } - else if ( obj.type == "Locus" ) - { - if ( args.size() != 2 || !obj.data.empty() ) - KIG_FILTER_PARSE_ERROR; - oc = fact->locusCalcer( args[0], args[1] ); - } - else if ( obj.type == "Refl" ) - { - if ( args.size() != 2 || !obj.data.empty() ) - KIG_FILTER_PARSE_ERROR; - oc = new ObjectTypeCalcer( LineReflectionType::instance(), args ); - } - else if ( obj.type == "Sym" ) - { - if ( args.size() != 2 || !obj.data.empty() ) - KIG_FILTER_PARSE_ERROR; - oc = new ObjectTypeCalcer( PointReflectionType::instance(), args ); - } - else if ( obj.type == "Tran" ) - { - if ( args.size() != 2 || !obj.data.empty() ) - KIG_FILTER_PARSE_ERROR; - oc = new ObjectTypeCalcer( TranslatedType::instance(), args ); - } - else - { - notSupported( file, i18n( "This Cabri file contains a \"%1\" object, " - "which Kig does not currently support." ).arg( TQString(obj.type) ) ); - return 0; - } - - if ( oc == 0 ) KIG_FILTER_PARSE_ERROR; - - oc->calc( *ret ); - calcers.push_back( oc ); - ObjectDrawer* d = new ObjectDrawer( obj.color, obj.thick, obj.visible, ls, ps ); - ObjectHolder* oh = new ObjectHolder( oc, d ); - holders.push_back( oh ); - - oc = 0; - } - - ret->addObjects( holders ); - ret->setGrid( false ); - ret->setAxes( false ); - return ret; -} - -KigFilterCabri* KigFilterCabri::instance() -{ - static KigFilterCabri t; - return &t; -} diff --git a/kig/filters/cabri-filter.cpp b/kig/filters/cabri-filter.cpp new file mode 100644 index 00000000..0a94f140 --- /dev/null +++ b/kig/filters/cabri-filter.cpp @@ -0,0 +1,577 @@ +/** + This file is part of Kig, a KDE program for Interactive Geometry... + 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 "cabri-filter.h" + +#include "../kig/kig_document.h" +#include "../kig/kig_part.h" +#include "../misc/coordinate.h" +#include "../objects/arc_type.h" +#include "../objects/bogus_imp.h" +#include "../objects/circle_type.h" +#include "../objects/conic_types.h" +#include "../objects/curve_imp.h" +#include "../objects/line_imp.h" +#include "../objects/line_type.h" +#include "../objects/object_calcer.h" +#include "../objects/object_drawer.h" +#include "../objects/object_factory.h" +#include "../objects/object_holder.h" +#include "../objects/other_imp.h" +#include "../objects/other_type.h" +#include "../objects/point_type.h" +#include "../objects/polygon_type.h" +#include "../objects/transform_types.h" +#include "../objects/vector_type.h" + +#include +#include +#include + +#include +#include + +/** + * a line: + * "Nr": Type, Unknown, "CN:"NumberOfParents, "VN:"Unknown + * Color, FillType, Thickness, "DS":Dots, "GT":SpecialAppearance, Visible, Fixed + * ["Const": Parents] ["Val": Constants] + * + * Nr: Simple sequential numbering of the objects in a file. + * Type: seen so far: Pt, Axes, Line, Cir + * NumberOfParents: The number of parents that will be specified in + * Parents + * Color: + * R -> red + * O -> purple + * Y -> yellow + * P -> dark purple + * V -> dark blue + * Bl -> blue + * lBl -> bright blue + * G -> bright green + * dG -> dark green + * Br -> brown + * dBr -> beige + * lGr -> light grey + * Gr -> grey + * dGr -> dark grey + * B -> black + * FillType: + * W -> not filled ( white ? ) + * all values of the Color item are valid here too.. + * Thickness: + * t -> thin + * tT -> medium + * T -> Thick + * Dots: + * a specification for how a line should be drawn ( with many + * dots, with short lines, it's a pretty generic format: the first + * number signifies the number of sequential dots to draw first, and + * the next is the sum of this first number with the number of + * spaces to leave before starting a new segment. + * SpecialAppearance: + * a number indicating some way of specially drawing an object. This + * can be modified using the "Modify Appearance" button in + * Cabri. For example, for a segment, the number indicates the + * amount of ticks to put on the segment, to indicate + * correspondances between segments.. + * Visible: + * V means visible, I means invisible + * Fixed: + * St means fix this object ( if you move one of its parents, it + * won't move ), nSt ( the default ) means don't fix this object. + * Parents: + * The numbers of the objects this object depends on + * Constants: + * Constants whose meaning depends on the type of object. E.g. for + * a point, this means first x, then y component. + */ + +struct CabriObject +{ + uint id; + TQCString type; + uint numberOfParents; + TQColor color; + TQColor fillColor; + int thick; + int lineSegLength; + int lineSegSplit; + int specialAppearanceSwitch; + bool visible; + bool fixed; + std::vector parents; + std::vector data; +}; + +KigFilterCabri::KigFilterCabri() +{ +} + +KigFilterCabri::~KigFilterCabri() +{ +} + +bool KigFilterCabri::supportMime( const TQString& mime ) +{ + // ugly hack to avoid duplicate extension ( XFig and Cabri files + // have the same .fig extension ). + return ( mime == "image/x-xfig" ) || + ( mime == "application/x-cabri" ); +} + +static TQString readLine( TQFile& file ) +{ + TQString ret; + file.readLine( ret, 10000L ); + if ( ret[ret.length() - 1] == '\n' ) + ret.truncate( ret.length() - 1 ); + if ( ret[ret.length() - 1] == '\r' ) + ret.truncate( ret.length() - 1 ); + return ret; +} + +static TQColor translatecolor( const TQString& s ) +{ + if ( s == "R" ) return TQt::red; + if ( s == "O" ) return TQt::magenta; + if ( s == "Y" ) return TQt::yellow; + if ( s == "P" ) return TQt::darkMagenta; + if ( s == "V" ) return TQt::darkBlue; + if ( s == "Bl" ) return TQt::blue; + if ( s == "lBl" ) return TQt::cyan; // TODO: bright blue + if ( s == "G" ) return TQt::green; + if ( s == "dG" ) return TQt::darkGreen; + if ( s == "Br" ) return TQColor( 165, 42, 42 ); + if ( s == "dBr" ) return TQColor( 128, 128, 0 ); + if ( s == "lGr" ) return TQt::lightGray; + if ( s == "Gr" ) return TQt::gray; + if ( s == "dGr" ) return TQt::darkGray; + if ( s == "B" ) return TQt::black; + if ( s == "W" ) return TQt::white; + + kdDebug() << k_funcinfo << "unknown color: " << s << endl; + return TQt::black; +} + +bool KigFilterCabri::readObject( TQFile& f, CabriObject& myobj ) +{ + // there are 4 lines per object in the file, so we read them all + // four now. + TQString line1, line2, line3, s; + TQString file = f.name(); + line1 = readLine( f ); + line2 = readLine( f ); + line3 = readLine( f ); + // ignore line 4, it is empty.. + s = readLine( f ); + + TQRegExp firstlinere( "^([^:]+): ([^,]+), ([^,]+), CN:([^,]*), VN:(.*)$" ); + if ( ! firstlinere.exactMatch( line1 ) ) + KIG_FILTER_PARSE_ERROR; + + bool ok; + TQString tmp; + + tmp = firstlinere.cap( 1 ); + myobj.id = tmp.toInt( &ok ); + if ( !ok ) KIG_FILTER_PARSE_ERROR; + + tmp = firstlinere.cap( 2 ); + myobj.type = tmp.latin1(); + + tmp = firstlinere.cap( 3 ); + // i have no idea what this number means.. + + tmp = firstlinere.cap( 4 ); + myobj.numberOfParents = tmp.toInt( &ok ); + if ( ! ok ) KIG_FILTER_PARSE_ERROR; + + tmp = firstlinere.cap( 5 ); + // i have no idea what this number means.. + + TQRegExp secondlinere( "^([^,]+), ([^,]+), ([^,]+), DS:([^ ]+) ([^,]+), GT:([^,]+), ([^,]+), (.*)$" ); + if ( ! secondlinere.exactMatch( line2 ) ) + KIG_FILTER_PARSE_ERROR; + + tmp = secondlinere.cap( 1 ); + myobj.color = translatecolor( tmp ); +// if ( ! color.isValid() ) KIG_FILTER_PARSE_ERROR; + + tmp = secondlinere.cap( 2 ); + myobj.fillColor = translatecolor( tmp ); +// if ( ! fillcolor.isValid() ) KIG_FILTER_PARSE_ERROR; + + tmp = secondlinere.cap( 3 ); + myobj.thick = tmp == "t" ? 1 : tmp == "tT" ? 2 : 3; + + tmp = secondlinere.cap( 4 ); + myobj.lineSegLength = tmp.toInt( &ok ); + if ( ! ok ) KIG_FILTER_PARSE_ERROR; + + tmp = secondlinere.cap( 5 ); + myobj.lineSegSplit = tmp.toInt( &ok ); + if ( ! ok ) KIG_FILTER_PARSE_ERROR; + + tmp = secondlinere.cap( 6 ); + myobj.specialAppearanceSwitch = tmp.toInt( &ok ); + if ( ! ok ) KIG_FILTER_PARSE_ERROR; + + tmp = secondlinere.cap( 7 ); + myobj.visible = tmp == "V"; + + tmp = secondlinere.cap( 8 ); + myobj.fixed = tmp == "St"; + + TQRegExp thirdlinere( "^(Const: ([^,]*),? ?)?(Val: (.*))?$" ); + if ( ! thirdlinere.exactMatch( line3 ) ) + KIG_FILTER_PARSE_ERROR; + + tmp = thirdlinere.cap( 2 ); + TQStringList parentsids = TQStringList::split( ' ', tmp ); + for ( TQStringList::iterator i = parentsids.begin(); + i != parentsids.end(); ++i ) + { + myobj.parents.push_back( ( *i ).toInt( &ok ) ); + if ( ! ok ) KIG_FILTER_PARSE_ERROR; + } + if ( myobj.parents.size() != myobj.numberOfParents ) + KIG_FILTER_PARSE_ERROR; + + tmp = thirdlinere.cap( 4 ); + TQStringList valIds = TQStringList::split( ' ', tmp ); + for ( TQStringList::iterator i = valIds.begin(); + i != valIds.end(); ++i ) + { + myobj.data.push_back( ( *i ).toDouble( &ok ) ); + if ( ! ok ) KIG_FILTER_PARSE_ERROR; + } +// kdDebug() +// << k_funcinfo << endl +// << "id = " << myobj.id << endl +// << "type = " << myobj.type << endl +// << "numberOfParents = " << myobj.numberOfParents << endl +// << "color = " << myobj.color.name() << endl +// << "fillcolor = " << myobj.fillColor.name() << endl +// << "thick = " << myobj.thick << endl +// << "lineseglength = " << myobj.lineSegLength << endl +// << "linesegsplit = " << myobj.lineSegSplit << endl +// << "specialAppearanceSwitch = " << myobj.specialAppearanceSwitch << endl +// << "visible = " << visible << endl +// << "fixed = " << myobj.fixed << endl +// << "parents =" << endl; +// for ( std::vector::iterator i = myobj.parents.begin(); i != myobj.parents.end(); ++i ) +// kdDebug() << " " << *i << endl; +// kdDebug() << "vals = " << endl; +// for ( std::vector::iterator i = myobj.data.begin(); i != myobj.data.end(); ++i ) +// kdDebug() << " " << *i << endl; + + return true; +} + +KigDocument* KigFilterCabri::load( const TQString& file ) +{ + TQFile f( file ); + if ( ! f.open( IO_ReadOnly ) ) + { + fileNotFound( file ); + return 0; + } + + KigDocument* ret = new KigDocument(); + + TQString s = readLine( f ); + TQString a = s.left( 21 ); + TQString b = s.mid( 21 ); + if( a != "FIGURE CabriII vers. " || + ( b != "DOS 1.0" && b != "MS-Windows 1.0" ) ) + { + if ( s.left( 5 ) == "#FIG " ) + { + notSupported( file, i18n( "This is an XFig file, not a Cabri figure." ) ); + return 0; + } + else + KIG_FILTER_PARSE_ERROR; + } + + // next we have: + // line 2: empty line + // line 3: window dimensions -> we don't need/use that... + // line 4: empty line + // line 5 through 8: center point + // line 9 through 12: axes + // so we skip 11 lines... + for( int i = 0; i != 11; ++i) + s = readLine( f ); + + // all Cabri files seem to at least have these center and axes... + if ( f.atEnd() ) + KIG_FILTER_PARSE_ERROR; + + std::vector holders; + std::vector calcers; + + const ObjectFactory* fact = ObjectFactory::instance(); + + std::vector args; + ObjectCalcer* oc = 0; + + while ( ! f.atEnd() ) + { + CabriObject obj; + // we do one object each iteration.. + if ( !readObject( f, obj ) ) + return 0; + +// reading linestyle + Qt::PenStyle ls = Qt::SolidLine; + if ( ( obj.lineSegLength > 1 ) && ( obj.lineSegLength < 6 ) && + ( obj.lineSegSplit > 1 ) && ( obj.lineSegSplit <= 10 ) ) + ls = Qt::DotLine; + else if ( ( obj.lineSegLength >= 6 ) && ( obj.lineSegSplit > 10 ) ) + ls = Qt::DashLine; + int ps = 0; + + args.clear(); + for ( std::vector::iterator i = obj.parents.begin(); + i != obj.parents.end(); ++i ) + args.push_back( calcers[*i-3] ); + + // two fake objects at the start ( origin and axes.. ) + if ( obj.id != calcers.size() + 3 ) KIG_FILTER_PARSE_ERROR; + oc = 0; + if ( obj.type == "Pt" ) + { + if ( ! args.empty() ) KIG_FILTER_PARSE_ERROR; + if ( obj.data.size() != 2 ) KIG_FILTER_PARSE_ERROR; + + switch ( obj.specialAppearanceSwitch ) + { + case 0: + { + obj.thick -= 1; + break; + } + case 2: + { + obj.thick += 1; + break; + } + case 3: + { + obj.thick += 1; + ps = 1; + break; + } + case 4: + { + obj.thick += 2; + ps = 4; + break; + } + } + // different sizes for points.. + obj.thick *= 2; + + oc = fact->fixedPointCalcer( Coordinate( obj.data[0], obj.data[1] ) ); + } + else if ( obj.type == "Cir" ) + { + if ( args.size() == 1 ) + { + if ( obj.data.size() != 1 ) KIG_FILTER_PARSE_ERROR; + ObjectConstCalcer* radc = + new ObjectConstCalcer( new DoubleImp( obj.data[0] ) ); + args.push_back( radc ); + oc = new ObjectTypeCalcer( CircleBPRType::instance(), args ); + } + else if ( args.size() == 2 ) + { + if ( ! obj.data.empty() ) KIG_FILTER_PARSE_ERROR; + oc = new ObjectTypeCalcer( CircleBCPType::instance(), args ); + } + else KIG_FILTER_PARSE_ERROR; + } + else if ( obj.type == "Line" || obj.type == "Ray" || obj.type == "Seg" || + obj.type == "Vec" ) + { + if ( args.size() == 1 ) + { + if ( obj.data.size() != 2 ) KIG_FILTER_PARSE_ERROR; + Coordinate vect( obj.data[0], obj.data[1] ); + ObjectConstCalcer* vectorcalcer = + new ObjectConstCalcer( new VectorImp( Coordinate( 0, 0 ), vect ) ); + args.push_back( vectorcalcer ); + ObjectTypeCalcer* secondpoint = + new ObjectTypeCalcer( TranslatedType::instance(), args ); + secondpoint->calc( *ret ); + args[1] = secondpoint; + } + if ( args.size() != 2 ) KIG_FILTER_PARSE_ERROR; + const ObjectType* t = 0; + if ( obj.type == "Line" ) t = LineABType::instance(); + else if ( obj.type == "Ray" ) t = RayABType::instance(); + else if ( obj.type == "Seg" ) t = SegmentABType::instance(); + else if ( obj.type == "Vec" ) t = VectorType::instance(); + else assert( t ); + oc = new ObjectTypeCalcer( t, args ); + } + else if ( obj.type == "Pt/" ) + { + // different sizes for points.. + obj.thick *= 2; + if ( args.size() != 1 || obj.data.size() != 2 ) + KIG_FILTER_PARSE_ERROR; + ObjectCalcer* parent = args[0]; + if ( !parent->imp()->inherits( CurveImp::stype() ) ) + KIG_FILTER_PARSE_ERROR; + const CurveImp* curve = static_cast( parent->imp() ); + Coordinate pt = Coordinate( obj.data[0], obj.data[1] ); + double param = curve->getParam( pt, *ret ); + args.push_back( new ObjectConstCalcer( new DoubleImp( param ) ) ); + oc = new ObjectTypeCalcer( ConstrainedPointType::instance(), args ); + } + else if ( obj.type == "Perp" || obj.type == "Par" ) + { + if ( args.size() != 2 || obj.data.size() != 0 ) + KIG_FILTER_PARSE_ERROR; + const ObjectType* t = 0; + if ( obj.type == "Perp" ) t = LinePerpendLPType::instance(); + else if ( obj.type == "Par" ) t = LineParallelLPType::instance(); + else assert( false ); + oc = new ObjectTypeCalcer( t, args ); + } + else if ( obj.type == "Arc" ) + { + if ( args.size() != 3 || ! obj.data.empty() ) + KIG_FILTER_PARSE_ERROR; + oc = new ObjectTypeCalcer( ArcBTPType::instance(), args ); + } + else if ( obj.type == "Con" ) + { + if ( args.size() != 5 || !obj.data.empty() ) + KIG_FILTER_PARSE_ERROR; + oc = new ObjectTypeCalcer( ConicB5PType::instance(), args ); + } + else if ( obj.type == "Mid" ) + { + if ( args.size() == 2 ) + { + ObjectCalcer* c = + new ObjectTypeCalcer( SegmentABType::instance(), args ); + c->calc( *ret ); + args.clear(); + args.push_back( c ); + } + // midpoint -> this can be the midpoint of a segment, two + // points, or a vector... + if ( args.size() != 1 || !obj.data.empty() ) + KIG_FILTER_PARSE_ERROR; + ObjectCalcer* parent = args[0]; + if ( parent->imp()->inherits( SegmentImp::stype() ) ) + oc = fact->propertyObjectCalcer( parent, "mid-point" ) ; + else if ( parent->imp()->inherits( VectorImp::stype() ) ) + oc = fact->propertyObjectCalcer( parent, "vect-mid-point" ); + else KIG_FILTER_PARSE_ERROR; + } + else if ( obj.type == "PBiss" ) + { + if ( args.size() == 2 ) + { + ObjectCalcer* c = + new ObjectTypeCalcer( SegmentABType::instance(), args ); + c->calc( *ret ); + args.clear(); + args.push_back( c ); + } + if ( args.size() != 1 || !obj.data.empty() ) + KIG_FILTER_PARSE_ERROR; + ObjectCalcer* parent = args[0]; + ObjectCalcer* midpoint = 0; + if ( parent->imp()->inherits( SegmentImp::stype() ) ) + midpoint = fact->propertyObjectCalcer( parent, "mid-point" ) ; +// else if ( parent->imp()->inherits( VectorImp::stype() ) ) +// midpoint = fact->propertyObjectCalcer( parent, "vect-mid-point" ); + else KIG_FILTER_PARSE_ERROR; + midpoint->calc( *ret ); + args.push_back( midpoint ); + oc = new ObjectTypeCalcer( LinePerpendLPType::instance(), args ); + } + else if ( obj.type == "Pol" ) + { + if ( args.size() < 3 || !obj.data.empty() ) + KIG_FILTER_PARSE_ERROR; + oc = new ObjectTypeCalcer( PolygonBNPType::instance(), args ); + } + else if ( obj.type == "Locus" ) + { + if ( args.size() != 2 || !obj.data.empty() ) + KIG_FILTER_PARSE_ERROR; + oc = fact->locusCalcer( args[0], args[1] ); + } + else if ( obj.type == "Refl" ) + { + if ( args.size() != 2 || !obj.data.empty() ) + KIG_FILTER_PARSE_ERROR; + oc = new ObjectTypeCalcer( LineReflectionType::instance(), args ); + } + else if ( obj.type == "Sym" ) + { + if ( args.size() != 2 || !obj.data.empty() ) + KIG_FILTER_PARSE_ERROR; + oc = new ObjectTypeCalcer( PointReflectionType::instance(), args ); + } + else if ( obj.type == "Tran" ) + { + if ( args.size() != 2 || !obj.data.empty() ) + KIG_FILTER_PARSE_ERROR; + oc = new ObjectTypeCalcer( TranslatedType::instance(), args ); + } + else + { + notSupported( file, i18n( "This Cabri file contains a \"%1\" object, " + "which Kig does not currently support." ).arg( TQString(obj.type) ) ); + return 0; + } + + if ( oc == 0 ) KIG_FILTER_PARSE_ERROR; + + oc->calc( *ret ); + calcers.push_back( oc ); + ObjectDrawer* d = new ObjectDrawer( obj.color, obj.thick, obj.visible, ls, ps ); + ObjectHolder* oh = new ObjectHolder( oc, d ); + holders.push_back( oh ); + + oc = 0; + } + + ret->addObjects( holders ); + ret->setGrid( false ); + ret->setAxes( false ); + return ret; +} + +KigFilterCabri* KigFilterCabri::instance() +{ + static KigFilterCabri t; + return &t; +} diff --git a/kig/filters/drgeo-filter-chooser.cc b/kig/filters/drgeo-filter-chooser.cc deleted file mode 100644 index 89250235..00000000 --- a/kig/filters/drgeo-filter-chooser.cc +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (C) 2004 Pino Toscano -// Copyright (C) 2004 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 "drgeo-filter-chooser.h" -#include "drgeo-filter-chooser.moc" - -#include -#include -#include -#include -#include - -KigFilterDrgeoChooser::KigFilterDrgeoChooser( const TQStringList& l ) - : KigFilterDrgeoChooserBase( 0, "drgeo_filter", true ) -{ - OKButton->setGuiItem( KStdGuiItem::ok() ); - CancelButton->setGuiItem( KStdGuiItem::cancel() ); - - FigureListBox->insertStringList( l ); - - connect( OKButton, TQT_SIGNAL( clicked() ), TQT_SLOT( slotOKPressed() ) ); - connect( CancelButton, TQT_SIGNAL( clicked() ), TQT_SLOT( slotCancelPressed() ) ); - connect( FigureListBox, TQT_SIGNAL( executed( TQListBoxItem* ) ), TQT_SLOT( slotExecuted( TQListBoxItem* ) ) ); -} - -void KigFilterDrgeoChooser::slotOKPressed() -{ - const int r = FigureListBox->currentItem(); - if ( r == -1 ) - { - KMessageBox::sorry( 0, i18n( "Please select a figure." ) ); - return; - } - done( r ); -} - -void KigFilterDrgeoChooser::slotCancelPressed() -{ - done( -1 ); -} - -KigFilterDrgeoChooser::~KigFilterDrgeoChooser() -{ - -} - -void KigFilterDrgeoChooser::slotExecuted( TQListBoxItem* i ) -{ - done( FigureListBox->index( i ) ); -} diff --git a/kig/filters/drgeo-filter-chooser.cpp b/kig/filters/drgeo-filter-chooser.cpp new file mode 100644 index 00000000..89250235 --- /dev/null +++ b/kig/filters/drgeo-filter-chooser.cpp @@ -0,0 +1,65 @@ +// Copyright (C) 2004 Pino Toscano +// Copyright (C) 2004 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 "drgeo-filter-chooser.h" +#include "drgeo-filter-chooser.moc" + +#include +#include +#include +#include +#include + +KigFilterDrgeoChooser::KigFilterDrgeoChooser( const TQStringList& l ) + : KigFilterDrgeoChooserBase( 0, "drgeo_filter", true ) +{ + OKButton->setGuiItem( KStdGuiItem::ok() ); + CancelButton->setGuiItem( KStdGuiItem::cancel() ); + + FigureListBox->insertStringList( l ); + + connect( OKButton, TQT_SIGNAL( clicked() ), TQT_SLOT( slotOKPressed() ) ); + connect( CancelButton, TQT_SIGNAL( clicked() ), TQT_SLOT( slotCancelPressed() ) ); + connect( FigureListBox, TQT_SIGNAL( executed( TQListBoxItem* ) ), TQT_SLOT( slotExecuted( TQListBoxItem* ) ) ); +} + +void KigFilterDrgeoChooser::slotOKPressed() +{ + const int r = FigureListBox->currentItem(); + if ( r == -1 ) + { + KMessageBox::sorry( 0, i18n( "Please select a figure." ) ); + return; + } + done( r ); +} + +void KigFilterDrgeoChooser::slotCancelPressed() +{ + done( -1 ); +} + +KigFilterDrgeoChooser::~KigFilterDrgeoChooser() +{ + +} + +void KigFilterDrgeoChooser::slotExecuted( TQListBoxItem* i ) +{ + done( FigureListBox->index( i ) ); +} diff --git a/kig/filters/drgeo-filter.cc b/kig/filters/drgeo-filter.cc deleted file mode 100644 index 9742fcf5..00000000 --- a/kig/filters/drgeo-filter.cc +++ /dev/null @@ -1,809 +0,0 @@ -// Copyright (C) 2004 Pino Toscano -// Copyright (C) 2004 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 "drgeo-filter.h" - -#include "drgeo-filter-chooser.h" -#include "filters-common.h" - -#include "../kig/kig_document.h" -#include "../kig/kig_part.h" -#include "../misc/common.h" -#include "../misc/coordinate.h" -#include "../objects/angle_type.h" -#include "../objects/arc_type.h" -#include "../objects/bogus_imp.h" -#include "../objects/circle_imp.h" -#include "../objects/circle_type.h" -#include "../objects/conic_imp.h" -#include "../objects/conic_types.h" -#include "../objects/curve_imp.h" -#include "../objects/intersection_types.h" -#include "../objects/line_imp.h" -#include "../objects/line_type.h" -#include "../objects/object_calcer.h" -#include "../objects/object_drawer.h" -#include "../objects/object_factory.h" -#include "../objects/object_holder.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_type.h" -#include "../objects/transform_types.h" -#include "../objects/vector_type.h" - -#include - -#include -#include - -#include - -#undef DRGEO_DEBUG -//#define DRGEO_DEBUG - -struct DrGeoHierarchyElement -{ - TQString id; - std::vector parents; -}; - -KigFilterDrgeo::KigFilterDrgeo() -{ -} - -KigFilterDrgeo::~KigFilterDrgeo() -{ -} - -bool KigFilterDrgeo::supportMime( const TQString& mime ) -{ - return mime == "application/x-drgeo"; -} - -KigDocument* KigFilterDrgeo::load( const TQString& file ) -{ - TQFile f( file ); - if ( ! f.open( IO_ReadOnly ) ) - { - fileNotFound( file ); - return 0; - } - - TQStringList figures; - TQDomDocument doc( "drgenius" ); - if ( !doc.setContent( &f ) ) - KIG_FILTER_PARSE_ERROR; - TQDomElement main = doc.documentElement(); - int nmacros = 0; - // reading figures... - for ( TQDomNode n = main.firstChild(); ! n.isNull(); n = n.nextSibling() ) - { - TQDomElement e = n.toElement(); - if ( e.isNull() ) continue; - else if ( e.tagName() == "drgeo" ) - figures.append( e.attribute( "name" ) ); - else if ( e.tagName() == "macro" ) - nmacros++; - } - if ( figures.isEmpty() ) { - if( nmacros > 0 ) - warning( i18n( "The Dr. Geo file \"%1\" is a macro file so it contains no " - "figures." ).arg( file ) ); - else - warning( i18n( "There are no figures in Dr. Geo file \"%1\"." ).arg( file ) ); - return 0; - } - - int nfig = figures.count(); - // no figures, no party... - if ( nfig == 0 ) - return 0; - - int myfig = 0; - - if ( nfig > 1 ) - { - // Dr. Geo file has more than 1 figure, let the user choose one... - KigFilterDrgeoChooser* c = new KigFilterDrgeoChooser( figures ); - myfig = c->exec(); - delete c; - } - -#ifdef DRGEO_DEBUG - kdDebug() << "drgeo file " << file << endl; -#endif - int curfig = -1; - - for ( TQDomNode n = main.firstChild(); ! n.isNull(); n = n.nextSibling() ) - { - TQDomElement e = n.toElement(); - if ( e.isNull() ) continue; - else if ( e.tagName() == "drgeo" ) - { - curfig += 1; - if ( curfig == myfig ) - { -#ifdef DRGEO_DEBUG - kdDebug() << "- Figure: '" << e.attribute("name") << "'" << endl; -#endif - bool grid = !e.attribute( "grid" ).isEmpty() && - ( e.attribute( "grid" ) != "False" ); - return importFigure( e.firstChild(), file, grid ); - } - } - } - - return 0; -} - -int convertDrgeoIndex( const std::vector es, const TQString myid ) -{ - for ( uint i = 0; i < es.size(); ++i ) - if ( es[i].id == myid ) - return i; - return -1; -} - -const Coordinate convertDrgeoLineParam( const double param, const LineData& line ) -{ - const double n = ( param - 0.5 ) * M_PI; - const Coordinate c = line.dir() / line.dir().length(); - const Coordinate p = line.a + tan( n ) * c; - return p; -} - -const Coordinate convertDrgeoHalflineParam( const double param, const LineData& line ) -{ - const double n = param * M_PI * 0.5; - const Coordinate c = line.dir() / line.dir().length(); - const Coordinate p = line.a + tan( n ) * c; - return p; -} - -KigDocument* KigFilterDrgeo::importFigure( TQDomNode f, const TQString& file, const bool grid ) -{ - KigDocument* ret = new KigDocument(); - - using namespace std; - std::vector elems; - int withoutid = 0; - - // 1st: fetch relationships and build an appropriate structure - for (TQDomNode a = f; ! a.isNull(); a = a.nextSibling() ) - { - TQDomElement domelem = a.toElement(); - if ( domelem.isNull() ) continue; - else - { - DrGeoHierarchyElement elem; -#ifdef DRGEO_DEBUG - kdDebug() << " * " << domelem.tagName() << "(" << domelem.attribute("type") << ")" << endl; -#endif - for ( TQDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() ) - { - TQDomElement ce = c.toElement(); - if ( ce.isNull() ) continue; - else if ( ce.tagName() == "parent" ) - elem.parents.push_back( ce.attribute( "ref" ) ); - } - TQString curid = domelem.attribute( "id" ); - elem.id = !curid.isNull() ? curid : TQString::number( withoutid++ ) ; - elems.push_back( elem ); - } - } - -#ifdef DRGEO_DEBUG - TQString x; - kdDebug() << "+++ elems" << endl; - for ( uint i = 0; i < elems.size(); ++i ) - { - x = ""; - for ( uint j = 0; j < elems[i].parents.size(); ++j ) - { - x += elems[i].parents[j] + "_"; - } - kdDebug() << " --> " << i << " - " << elems[i].id << " - " << x << endl; - } -#endif - - // 2nd: let's draw! - int curid = 0; - const ObjectFactory* fact = ObjectFactory::instance(); - std::vector holders; - std::vector holders2; - ObjectTypeCalcer* oc = 0; - ObjectCalcer* oc2 = 0; - int nignored = 0; - - // there's no need to sort the objects because it seems that DrGeo objects - // appear in the right order... so let's go! - for (TQDomNode a = f; ! a.isNull(); a = a.nextSibling() ) - { -#ifdef DRGEO_DEBUG - kdDebug() << "+++ id: " << curid << endl; -#endif - const DrGeoHierarchyElement& el = elems[curid]; - std::vector parents; - for ( uint j = 0; j < el.parents.size(); ++j ) - { - int parentid = convertDrgeoIndex( elems, el.parents[j] ); - if ( parentid == -1 ) - KIG_FILTER_PARSE_ERROR; - parents.push_back( holders[parentid-nignored]->calcer() ); - }; - TQDomElement domelem = a.toElement(); - -#ifdef DRGEO_DEBUG - if ( parents.size() > 0 ) - for ( uint j = 0; j < parents.size(); ++j ) - { - kdDebug() << "+++++++++ parent[" << j << "]: " << parents[j] << " - " - << parents[j]->imp()->type()->internalName() << endl; - } - else - kdDebug() << "+++++++++ parents: NO" << endl; - kdDebug() << "+++++++++ " << domelem.tagName() << " - " << domelem.attribute("type") << endl; -#endif - - if ( domelem.isNull() ) continue; - else if ( domelem.tagName() == "point" ) - { - TQString xs; - TQString ys; - TQString values; - for ( TQDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() ) - { - TQDomElement ce = c.toElement(); - if ( ce.isNull() ) continue; - else if ( ce.tagName() == "x" ) - xs = ce.text(); - else if ( ce.tagName() == "y" ) - ys = ce.text(); - else if ( ce.tagName() == "value" ) - values = ce.text(); - } - if ( domelem.attribute( "type" ) == "Free" ) - { - bool ok; - bool ok2; - double x = xs.toDouble( &ok ); - double y = ys.toDouble( &ok2 ); - if ( ! ( ok && ok2 ) ) - KIG_FILTER_PARSE_ERROR; - oc = fact->fixedPointCalcer( Coordinate( x, y ) ); - } - else if ( domelem.attribute( "type" ) == "Middle_2pts" ) - oc = new ObjectTypeCalcer( MidPointType::instance(), parents ); - else if ( domelem.attribute( "type" ) == "Middle_segment" ) - { - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - if ( !parents[0]->imp()->inherits( SegmentImp::stype() ) ) - KIG_FILTER_PARSE_ERROR; - ObjectPropertyCalcer* o1 = fact->propertyObjectCalcer( parents[0], "end-point-A" ); - o1->calc( *ret ); - ObjectPropertyCalcer* o2 = fact->propertyObjectCalcer( parents[0], "end-point-B" ); - o2->calc( *ret ); - std::vector args; - args.push_back( o1 ); - args.push_back( o2 ); - oc = new ObjectTypeCalcer( MidPointType::instance(), args ); - } - else if ( domelem.attribute( "type" ) == "On_curve" ) - { - bool ok3; - double value = values.toDouble( &ok3 ); - if ( ! ok3 ) - KIG_FILTER_PARSE_ERROR; - if ( ( parents[0]->imp()->inherits( CircleImp::stype() ) ) || - ( parents[0]->imp()->inherits( SegmentImp::stype() ) ) ) - oc = fact->constrainedPointCalcer( parents[0], value ); - else if ( parents[0]->imp()->inherits( LineImp::stype() ) ) - { - const LineData l = static_cast( parents[0]->imp() )->data(); - const Coordinate p = convertDrgeoLineParam( value, l ); - oc = fact->constrainedPointCalcer( parents[0], p, *ret ); - } - else if ( parents[0]->imp()->inherits( RayImp::stype() ) ) - { - const LineData l = static_cast( parents[0]->imp() )->data(); - const Coordinate p = convertDrgeoHalflineParam( value, l ); - oc = fact->constrainedPointCalcer( parents[0], p, *ret ); - } - else if ( parents[0]->imp()->inherits( ArcImp::stype() ) ) - oc = fact->constrainedPointCalcer( parents[0], 1 - value ); - else - { -// oc = fact->constrainedPointCalcer( parents[0], value ); - notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " - "which Kig does not currently support." ).arg( domelem.tagName() ).arg( - domelem.attribute( "type" ) ) ); - return 0; - } - } - else if ( domelem.attribute( "type" ) == "Intersection" ) - { - if ( ( parents[0]->imp()->inherits( AbstractLineImp::stype() ) ) && - ( parents[1]->imp()->inherits( AbstractLineImp::stype() ) ) ) - oc = new ObjectTypeCalcer( LineLineIntersectionType::instance(), parents ); - else - { - bool ok; - int which = domelem.attribute( "extra" ).toInt( &ok ); - if ( !ok ) KIG_FILTER_PARSE_ERROR; - if ( which == 1 ) which = -1; - else if ( which == 0 ) which = 1; - else KIG_FILTER_PARSE_ERROR; - std::vector args = parents; - const ObjectType* type = 0; - args.push_back( new ObjectConstCalcer( new IntImp( which ) ) ); - if ( ( parents[0]->imp()->inherits( CircleImp::stype() ) ) && - ( parents[1]->imp()->inherits( CircleImp::stype() ) ) ) - type = CircleCircleIntersectionType::instance(); - else if ( ( parents[0]->imp()->inherits( CircleImp::stype() ) && - parents[1]->imp()->inherits( AbstractLineImp::stype() ) ) || - ( parents[1]->imp()->inherits( CircleImp::stype() ) && - parents[0]->imp()->inherits( AbstractLineImp::stype() ) ) ) - type = ConicLineIntersectionType::instance(); - else if ( ( parents[0]->imp()->inherits( ArcImp::stype() ) && - parents[1]->imp()->inherits( AbstractLineImp::stype() ) ) || - ( parents[1]->imp()->inherits( ArcImp::stype() ) && - parents[0]->imp()->inherits( AbstractLineImp::stype() ) ) ) - type = ArcLineIntersectionType::instance(); - else - { - notSupported( file, i18n( "This Dr. Geo file contains an intersection type, " - "which Kig does not currently support." ) ); - return 0; - } - oc = new ObjectTypeCalcer( type, args ); - } - } - else if ( domelem.attribute( "type" ) == "Reflexion" ) - oc = new ObjectTypeCalcer( LineReflectionType::instance(), parents ); - else if ( domelem.attribute( "type" ) == "Symmetry" ) - oc = new ObjectTypeCalcer( PointReflectionType::instance(), parents ); - else if ( domelem.attribute( "type" ) == "Translation" ) - oc = new ObjectTypeCalcer( TranslatedType::instance(), parents ); - else if ( domelem.attribute( "type" ) == "Rotation" ) - oc = new ObjectTypeCalcer( RotationType::instance(), parents ); - else - { - notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " - "which Kig does not currently support." ).arg( domelem.tagName() ).arg( - domelem.attribute( "type" ) ) ); - return 0; - } -#ifdef DRGEO_DEBUG - kdDebug() << "+++++++++ oc:" << oc << endl; -#endif - } - else if( ( domelem.tagName() == "line" ) || - ( domelem.tagName() == "halfLine" ) || - ( domelem.tagName() == "segment" ) || - ( domelem.tagName() == "vector" ) || - ( domelem.tagName() == "circle" ) || - ( domelem.tagName() == "arcCircle" ) || - ( domelem.tagName() == "polygon" ) ) - { - const ObjectType* type = 0; - if ( domelem.attribute( "type" ) == "2pts" ) - { - if( domelem.tagName() == "line" ) - type = LineABType::instance(); - else if( domelem.tagName() == "halfLine" ) - type = RayABType::instance(); - else if( domelem.tagName() == "segment" ) - type = SegmentABType::instance(); - else if( domelem.tagName() == "vector" ) - type = VectorType::instance(); - else if( domelem.tagName() == "circle" ) - type = CircleBCPType::instance(); - else - { - notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " - "which Kig does not currently support." ).arg( domelem.tagName() ).arg( - domelem.attribute( "type" ) ) ); - return 0; - } - oc = new ObjectTypeCalcer( type, parents ); - } - else if( domelem.attribute( "type" ) == "3pts" ) - { - if( domelem.tagName() == "arcCircle" ) - type = ArcBTPType::instance(); - else - { - notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " - "which Kig does not currently support." ).arg( domelem.tagName() ).arg( - domelem.attribute( "type" ) ) ); - return 0; - } - oc = new ObjectTypeCalcer( type, parents ); - } - else if( domelem.attribute( "type" ) == "segment" ) - { - if( domelem.tagName() == "circle" ) - { - type = CircleBPRType::instance(); - ObjectPropertyCalcer* o = fact->propertyObjectCalcer( parents[1], "length" ); - o->calc( *ret ); - ObjectCalcer* a = parents[0]; - parents.clear(); - parents.push_back( a ); - parents.push_back( o ); - } - else - { - notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " - "which Kig does not currently support." ).arg( domelem.tagName() ).arg( - domelem.attribute( "type" ) ) ); - return 0; - } - oc = new ObjectTypeCalcer( type, parents ); - } - else if( domelem.attribute( "type" ) == "npts" ) - { - if( domelem.tagName() == "polygon" ) - { - if ( parents.size() < 3 ) KIG_FILTER_PARSE_ERROR; - type = PolygonBNPType::instance(); - } - else - { - notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " - "which Kig does not currently support." ).arg( domelem.tagName() ).arg( - domelem.attribute( "type" ) ) ); - return 0; - } - oc = new ObjectTypeCalcer( type, parents ); - } - else if ( domelem.attribute( "type" ) == "perpendicular" ) - oc = new ObjectTypeCalcer( LinePerpendLPType::instance(), parents ); - else if ( domelem.attribute( "type" ) == "parallel" ) - oc = new ObjectTypeCalcer( LineParallelLPType::instance(), parents ); - else if ( domelem.attribute( "type" ) == "Reflexion" ) - oc = new ObjectTypeCalcer( LineReflectionType::instance(), parents ); - else if ( domelem.attribute( "type" ) == "Symmetry" ) - oc = new ObjectTypeCalcer( PointReflectionType::instance(), parents ); - else if ( domelem.attribute( "type" ) == "Translation" ) - oc = new ObjectTypeCalcer( TranslatedType::instance(), parents ); - else if ( domelem.attribute( "type" ) == "Rotation" ) - oc = new ObjectTypeCalcer( RotationType::instance(), parents ); - else - { - notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " - "which Kig does not currently support." ).arg( domelem.tagName() ).arg( - domelem.attribute( "type" ) ) ); - return 0; - } -#ifdef DRGEO_DEBUG - kdDebug() << "+++++++++ oc:" << oc << endl; -#endif - } - else if( ( domelem.tagName() == "numeric" ) || - ( domelem.tagName() == "equation" ) ) - { - TQString xs; - TQString ys; - TQString value; - for ( TQDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() ) - { - TQDomElement ce = c.toElement(); - if ( ce.isNull() ) continue; - else if ( ce.tagName() == "x" ) - xs = ce.text(); - else if ( ce.tagName() == "y" ) - ys = ce.text(); - else if ( ce.tagName() == "value" ) - value = ce.text(); - } - bool ok; - bool ok2; - double x = xs.toDouble( &ok ); - double y = ys.toDouble( &ok2 ); - if ( ! ( ok && ok2 ) ) - KIG_FILTER_PARSE_ERROR; - Coordinate m( x, y ); - // types of 'numeric' - // ugly hack to show value numerics... - if ( domelem.attribute( "type" ) == "value" ) - { - bool ok3; - double dvalue = value.toDouble( &ok3 ); - if ( ok3 ) - value = TQString( "%1" ).arg( dvalue, 0, 'g', 3 ); - oc = fact->labelCalcer( value, m, false, std::vector(), *ret ); - } - else if ( domelem.attribute( "type" ) == "pt_abscissa" ) - { - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - oc = filtersConstructTextObject( m, parents[0], "coordinate-x", *ret, false ); - } - else if ( domelem.attribute( "type" ) == "pt_ordinate" ) - { - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - oc = filtersConstructTextObject( m, parents[0], "coordinate-y", *ret, false ); - } - else if ( domelem.attribute( "type" ) == "segment_length" ) - { - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - oc = filtersConstructTextObject( m, parents[0], "length", *ret, false ); - } - else if ( domelem.attribute( "type" ) == "circle_perimeter" ) - { - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - oc = filtersConstructTextObject( m, parents[0], "circumference", *ret, false ); - } - else if ( domelem.attribute( "type" ) == "arc_length" ) - { - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - oc = filtersConstructTextObject( m, parents[0], "arc-length", *ret, false ); - } - else if ( domelem.attribute( "type" ) == "distance_2pts" ) - { - if ( parents.size() != 2 ) KIG_FILTER_PARSE_ERROR; - ObjectTypeCalcer* so = new ObjectTypeCalcer( SegmentABType::instance(), parents ); - so->calc( *ret ); - oc = filtersConstructTextObject( m, so, "length", *ret, false ); - } - else if ( domelem.attribute( "type" ) == "vector_norm" ) - { - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - oc = filtersConstructTextObject( m, parents[0], "length", *ret, false ); - } - else if ( domelem.attribute( "type" ) == "vector_abscissa" ) - { - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - oc = filtersConstructTextObject( m, parents[0], "length-x", *ret, false ); - } - else if ( domelem.attribute( "type" ) == "vector_ordinate" ) - { - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - oc = filtersConstructTextObject( m, parents[0], "length-y", *ret, false ); - } - else if ( domelem.attribute( "type" ) == "slope" ) - { - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - oc = filtersConstructTextObject( m, parents[0], "slope", *ret, false ); - } - else if ( domelem.attribute( "type" ) == "distance_pt_line" ) - { - if ( parents.size() != 2 ) KIG_FILTER_PARSE_ERROR; - std::vector args; - args.push_back( parents[1] ); - args.push_back( parents[0] ); - ObjectTypeCalcer* po = new ObjectTypeCalcer( LinePerpendLPType::instance(), args ); - po->calc( *ret ); - args.clear(); - args.push_back( parents[1] ); - args.push_back( po ); - ObjectTypeCalcer* io = new ObjectTypeCalcer( LineLineIntersectionType::instance(), args ); - io->calc( *ret ); - args.clear(); - args.push_back( parents[0] ); - args.push_back( io ); - ObjectTypeCalcer* so = new ObjectTypeCalcer( SegmentABType::instance(), args ); - so->calc( *ret ); - oc = filtersConstructTextObject( m, so, "length", *ret, false ); - } - // types of 'equation' - else if ( domelem.attribute( "type" ) == "line" ) - { - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - oc = filtersConstructTextObject( m, parents[0], "equation", *ret, false ); - } - else if ( domelem.attribute( "type" ) == "circle" ) - { - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - oc = filtersConstructTextObject( m, parents[0], "simply-cartesian-equation", *ret, false ); - } - else - { - notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " - "which Kig does not currently support." ).arg( domelem.tagName() ).arg( - domelem.attribute( "type" ) ) ); - return 0; - } -#ifdef DRGEO_DEBUG - kdDebug() << "+++++++++ oc:" << oc << endl; -#endif - } - else if ( domelem.tagName() == "angle" ) - { - if ( domelem.attribute( "type" ) == "3pts" ) - { - if ( parents.size() != 3 ) KIG_FILTER_PARSE_ERROR; - oc = new ObjectTypeCalcer( HalfAngleType::instance(), parents ); - } - else - { - notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " - "which Kig does not currently support." ).arg( domelem.tagName() ).arg( - domelem.attribute( "type" ) ) ); - return 0; - } -#ifdef DRGEO_DEBUG - kdDebug() << "+++++++++ oc:" << oc << endl; -#endif - } - else if ( domelem.tagName() == "script" ) - { - TQString xs; - TQString ys; - TQString text; - for ( TQDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() ) - { - TQDomElement ce = c.toElement(); - if ( ce.isNull() ) continue; - else if ( ce.tagName() == "x" ) - xs = ce.text(); - else if ( ce.tagName() == "y" ) - ys = ce.text(); - else if ( ce.tagName() == "code" ) - text = ce.text(); - } - bool ok; - bool ok2; - double x = xs.toDouble( &ok ); - double y = ys.toDouble( &ok2 ); - if ( ! ( ok && ok2 ) ) - KIG_FILTER_PARSE_ERROR; - // since Kig doesn't support Guile scripts, it will write script's text - // in a label, so the user can freely see the code and make whatever - // he/she wants - // possible idea: construct a new script object with the parents of Guile - // one and the Guile code inserted commented... depends on a better - // handling of arguments in scripts? - if ( domelem.attribute( "type" ) == "nitems" ) - oc = fact->labelCalcer( text, Coordinate( x, y ), false, std::vector(), *ret ); - else - { - notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " - "which Kig does not currently support." ).arg( domelem.tagName() ).arg( - domelem.attribute( "type" ) ) ); - return 0; - } - } - else if ( domelem.tagName() == "locus" ) - { - if ( domelem.attribute( "type" ) == "None" ) - oc = fact->locusCalcer( parents[0], parents[1] ); - else - { - notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " - "which Kig does not currently support." ).arg( domelem.tagName() ).arg( - domelem.attribute( "type" ) ) ); - return 0; - } -#ifdef DRGEO_DEBUG - kdDebug() << "+++++++++ oc:" << oc << endl; -#endif - } - else if ( ( domelem.tagName() == "boundingBox" ) || - ( domelem.tagName() == "customUI" ) ) - { - // ignoring these elements, since they are not useful to us... - nignored++; - } - else - { -#ifdef DRGEO_DEBUG - kdDebug() << ">>>>>>>>> UNKNOWN OBJECT" << endl; -#endif - notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " - "which Kig does not currently support." ).arg( domelem.tagName() ).arg( - domelem.attribute( "type" ) ) ); - return 0; - } - curid++; - if ( oc == 0 ) - continue; - -// reading color - TQColor co( domelem.attribute( "color" ) ); - if ( ! co.isValid() ) - if ( domelem.attribute( "color" ) == "Bordeaux" ) - co.setRgb( 145, 0, 0 ); - else - co = TQt::blue; -// reading width and style -// Dashed -> the little one -// Normal -> the medium -// Thick -> the biggest one - int w = -1; - Qt::PenStyle s = Qt::SolidLine; - if ( domelem.tagName() == "point" ) - { - if ( domelem.attribute( "thickness" ) == "Normal" ) - w = 7; - else if ( domelem.attribute( "thickness" ) == "Thick" ) - w = 9; - } - else - { - if ( domelem.attribute( "thickness" ) == "Dashed" ) - s = Qt::DotLine; - if ( domelem.attribute( "thickness" ) == "Thick" ) - w = 2; - } - TQString ps = domelem.attribute( "style" ); - int pointstyle = ObjectDrawer::pointStyleFromString( ps ); -// show this object? - bool show = ( ( domelem.attribute( "masked" ) != "True" ) && - ( domelem.attribute( "masked" ) != "Alway" ) ); -// costructing the ObjectDrawer* - ObjectDrawer* d = new ObjectDrawer( co, w, show, s, pointstyle ); -// reading object name - TQString strname = domelem.attribute( "name" ); - ObjectConstCalcer* name = new ObjectConstCalcer( new StringImp( strname ) ); - -// creating the ObjectHolder* - ObjectHolder* o = new ObjectHolder( oc, d, name ); - holders.push_back( o ); -// calc() -#ifdef DRGEO_DEBUG - kdDebug() << ">>>>>>>>> calc" << endl; -#endif - holders[curid-1-nignored]->calc( *ret ); - - if ( domelem.tagName() == "point" ) - { - if ( !strname.isEmpty() ) - { - std::vector args2; - args2.push_back( o->nameCalcer() ); - oc2 = fact->attachedLabelCalcer( TQString::fromLatin1( "%1" ), oc, - static_cast( oc->imp() )->coordinate(), - false, args2, *ret ); - co = TQt::black; - } - } - else if ( domelem.tagName() == "angle" ) - { - oc2 = filtersConstructTextObject( - static_cast( holders[curid-1-nignored]->calcer()->parents()[1]->imp() )->coordinate(), - holders[curid-1-nignored]->calcer(), "angle-degrees", *ret, false ); - } - - oc = 0; - - if ( oc2 != 0 ) - { - oc2->calc( *ret ); - ObjectDrawer* d2 = new ObjectDrawer( co ); - ObjectHolder* o2 = new ObjectHolder( oc2, d2 ); - holders2.push_back( o2 ); - oc2 = 0; - } - } - - ret->addObjects( holders ); - ret->addObjects( holders2 ); - ret->setGrid( grid ); - ret->setAxes( grid ); - return ret; -} - -KigFilterDrgeo* KigFilterDrgeo::instance() -{ - static KigFilterDrgeo f; - return &f; -} diff --git a/kig/filters/drgeo-filter.cpp b/kig/filters/drgeo-filter.cpp new file mode 100644 index 00000000..9742fcf5 --- /dev/null +++ b/kig/filters/drgeo-filter.cpp @@ -0,0 +1,809 @@ +// Copyright (C) 2004 Pino Toscano +// Copyright (C) 2004 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 "drgeo-filter.h" + +#include "drgeo-filter-chooser.h" +#include "filters-common.h" + +#include "../kig/kig_document.h" +#include "../kig/kig_part.h" +#include "../misc/common.h" +#include "../misc/coordinate.h" +#include "../objects/angle_type.h" +#include "../objects/arc_type.h" +#include "../objects/bogus_imp.h" +#include "../objects/circle_imp.h" +#include "../objects/circle_type.h" +#include "../objects/conic_imp.h" +#include "../objects/conic_types.h" +#include "../objects/curve_imp.h" +#include "../objects/intersection_types.h" +#include "../objects/line_imp.h" +#include "../objects/line_type.h" +#include "../objects/object_calcer.h" +#include "../objects/object_drawer.h" +#include "../objects/object_factory.h" +#include "../objects/object_holder.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_type.h" +#include "../objects/transform_types.h" +#include "../objects/vector_type.h" + +#include + +#include +#include + +#include + +#undef DRGEO_DEBUG +//#define DRGEO_DEBUG + +struct DrGeoHierarchyElement +{ + TQString id; + std::vector parents; +}; + +KigFilterDrgeo::KigFilterDrgeo() +{ +} + +KigFilterDrgeo::~KigFilterDrgeo() +{ +} + +bool KigFilterDrgeo::supportMime( const TQString& mime ) +{ + return mime == "application/x-drgeo"; +} + +KigDocument* KigFilterDrgeo::load( const TQString& file ) +{ + TQFile f( file ); + if ( ! f.open( IO_ReadOnly ) ) + { + fileNotFound( file ); + return 0; + } + + TQStringList figures; + TQDomDocument doc( "drgenius" ); + if ( !doc.setContent( &f ) ) + KIG_FILTER_PARSE_ERROR; + TQDomElement main = doc.documentElement(); + int nmacros = 0; + // reading figures... + for ( TQDomNode n = main.firstChild(); ! n.isNull(); n = n.nextSibling() ) + { + TQDomElement e = n.toElement(); + if ( e.isNull() ) continue; + else if ( e.tagName() == "drgeo" ) + figures.append( e.attribute( "name" ) ); + else if ( e.tagName() == "macro" ) + nmacros++; + } + if ( figures.isEmpty() ) { + if( nmacros > 0 ) + warning( i18n( "The Dr. Geo file \"%1\" is a macro file so it contains no " + "figures." ).arg( file ) ); + else + warning( i18n( "There are no figures in Dr. Geo file \"%1\"." ).arg( file ) ); + return 0; + } + + int nfig = figures.count(); + // no figures, no party... + if ( nfig == 0 ) + return 0; + + int myfig = 0; + + if ( nfig > 1 ) + { + // Dr. Geo file has more than 1 figure, let the user choose one... + KigFilterDrgeoChooser* c = new KigFilterDrgeoChooser( figures ); + myfig = c->exec(); + delete c; + } + +#ifdef DRGEO_DEBUG + kdDebug() << "drgeo file " << file << endl; +#endif + int curfig = -1; + + for ( TQDomNode n = main.firstChild(); ! n.isNull(); n = n.nextSibling() ) + { + TQDomElement e = n.toElement(); + if ( e.isNull() ) continue; + else if ( e.tagName() == "drgeo" ) + { + curfig += 1; + if ( curfig == myfig ) + { +#ifdef DRGEO_DEBUG + kdDebug() << "- Figure: '" << e.attribute("name") << "'" << endl; +#endif + bool grid = !e.attribute( "grid" ).isEmpty() && + ( e.attribute( "grid" ) != "False" ); + return importFigure( e.firstChild(), file, grid ); + } + } + } + + return 0; +} + +int convertDrgeoIndex( const std::vector es, const TQString myid ) +{ + for ( uint i = 0; i < es.size(); ++i ) + if ( es[i].id == myid ) + return i; + return -1; +} + +const Coordinate convertDrgeoLineParam( const double param, const LineData& line ) +{ + const double n = ( param - 0.5 ) * M_PI; + const Coordinate c = line.dir() / line.dir().length(); + const Coordinate p = line.a + tan( n ) * c; + return p; +} + +const Coordinate convertDrgeoHalflineParam( const double param, const LineData& line ) +{ + const double n = param * M_PI * 0.5; + const Coordinate c = line.dir() / line.dir().length(); + const Coordinate p = line.a + tan( n ) * c; + return p; +} + +KigDocument* KigFilterDrgeo::importFigure( TQDomNode f, const TQString& file, const bool grid ) +{ + KigDocument* ret = new KigDocument(); + + using namespace std; + std::vector elems; + int withoutid = 0; + + // 1st: fetch relationships and build an appropriate structure + for (TQDomNode a = f; ! a.isNull(); a = a.nextSibling() ) + { + TQDomElement domelem = a.toElement(); + if ( domelem.isNull() ) continue; + else + { + DrGeoHierarchyElement elem; +#ifdef DRGEO_DEBUG + kdDebug() << " * " << domelem.tagName() << "(" << domelem.attribute("type") << ")" << endl; +#endif + for ( TQDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() ) + { + TQDomElement ce = c.toElement(); + if ( ce.isNull() ) continue; + else if ( ce.tagName() == "parent" ) + elem.parents.push_back( ce.attribute( "ref" ) ); + } + TQString curid = domelem.attribute( "id" ); + elem.id = !curid.isNull() ? curid : TQString::number( withoutid++ ) ; + elems.push_back( elem ); + } + } + +#ifdef DRGEO_DEBUG + TQString x; + kdDebug() << "+++ elems" << endl; + for ( uint i = 0; i < elems.size(); ++i ) + { + x = ""; + for ( uint j = 0; j < elems[i].parents.size(); ++j ) + { + x += elems[i].parents[j] + "_"; + } + kdDebug() << " --> " << i << " - " << elems[i].id << " - " << x << endl; + } +#endif + + // 2nd: let's draw! + int curid = 0; + const ObjectFactory* fact = ObjectFactory::instance(); + std::vector holders; + std::vector holders2; + ObjectTypeCalcer* oc = 0; + ObjectCalcer* oc2 = 0; + int nignored = 0; + + // there's no need to sort the objects because it seems that DrGeo objects + // appear in the right order... so let's go! + for (TQDomNode a = f; ! a.isNull(); a = a.nextSibling() ) + { +#ifdef DRGEO_DEBUG + kdDebug() << "+++ id: " << curid << endl; +#endif + const DrGeoHierarchyElement& el = elems[curid]; + std::vector parents; + for ( uint j = 0; j < el.parents.size(); ++j ) + { + int parentid = convertDrgeoIndex( elems, el.parents[j] ); + if ( parentid == -1 ) + KIG_FILTER_PARSE_ERROR; + parents.push_back( holders[parentid-nignored]->calcer() ); + }; + TQDomElement domelem = a.toElement(); + +#ifdef DRGEO_DEBUG + if ( parents.size() > 0 ) + for ( uint j = 0; j < parents.size(); ++j ) + { + kdDebug() << "+++++++++ parent[" << j << "]: " << parents[j] << " - " + << parents[j]->imp()->type()->internalName() << endl; + } + else + kdDebug() << "+++++++++ parents: NO" << endl; + kdDebug() << "+++++++++ " << domelem.tagName() << " - " << domelem.attribute("type") << endl; +#endif + + if ( domelem.isNull() ) continue; + else if ( domelem.tagName() == "point" ) + { + TQString xs; + TQString ys; + TQString values; + for ( TQDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() ) + { + TQDomElement ce = c.toElement(); + if ( ce.isNull() ) continue; + else if ( ce.tagName() == "x" ) + xs = ce.text(); + else if ( ce.tagName() == "y" ) + ys = ce.text(); + else if ( ce.tagName() == "value" ) + values = ce.text(); + } + if ( domelem.attribute( "type" ) == "Free" ) + { + bool ok; + bool ok2; + double x = xs.toDouble( &ok ); + double y = ys.toDouble( &ok2 ); + if ( ! ( ok && ok2 ) ) + KIG_FILTER_PARSE_ERROR; + oc = fact->fixedPointCalcer( Coordinate( x, y ) ); + } + else if ( domelem.attribute( "type" ) == "Middle_2pts" ) + oc = new ObjectTypeCalcer( MidPointType::instance(), parents ); + else if ( domelem.attribute( "type" ) == "Middle_segment" ) + { + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + if ( !parents[0]->imp()->inherits( SegmentImp::stype() ) ) + KIG_FILTER_PARSE_ERROR; + ObjectPropertyCalcer* o1 = fact->propertyObjectCalcer( parents[0], "end-point-A" ); + o1->calc( *ret ); + ObjectPropertyCalcer* o2 = fact->propertyObjectCalcer( parents[0], "end-point-B" ); + o2->calc( *ret ); + std::vector args; + args.push_back( o1 ); + args.push_back( o2 ); + oc = new ObjectTypeCalcer( MidPointType::instance(), args ); + } + else if ( domelem.attribute( "type" ) == "On_curve" ) + { + bool ok3; + double value = values.toDouble( &ok3 ); + if ( ! ok3 ) + KIG_FILTER_PARSE_ERROR; + if ( ( parents[0]->imp()->inherits( CircleImp::stype() ) ) || + ( parents[0]->imp()->inherits( SegmentImp::stype() ) ) ) + oc = fact->constrainedPointCalcer( parents[0], value ); + else if ( parents[0]->imp()->inherits( LineImp::stype() ) ) + { + const LineData l = static_cast( parents[0]->imp() )->data(); + const Coordinate p = convertDrgeoLineParam( value, l ); + oc = fact->constrainedPointCalcer( parents[0], p, *ret ); + } + else if ( parents[0]->imp()->inherits( RayImp::stype() ) ) + { + const LineData l = static_cast( parents[0]->imp() )->data(); + const Coordinate p = convertDrgeoHalflineParam( value, l ); + oc = fact->constrainedPointCalcer( parents[0], p, *ret ); + } + else if ( parents[0]->imp()->inherits( ArcImp::stype() ) ) + oc = fact->constrainedPointCalcer( parents[0], 1 - value ); + else + { +// oc = fact->constrainedPointCalcer( parents[0], value ); + notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " + "which Kig does not currently support." ).arg( domelem.tagName() ).arg( + domelem.attribute( "type" ) ) ); + return 0; + } + } + else if ( domelem.attribute( "type" ) == "Intersection" ) + { + if ( ( parents[0]->imp()->inherits( AbstractLineImp::stype() ) ) && + ( parents[1]->imp()->inherits( AbstractLineImp::stype() ) ) ) + oc = new ObjectTypeCalcer( LineLineIntersectionType::instance(), parents ); + else + { + bool ok; + int which = domelem.attribute( "extra" ).toInt( &ok ); + if ( !ok ) KIG_FILTER_PARSE_ERROR; + if ( which == 1 ) which = -1; + else if ( which == 0 ) which = 1; + else KIG_FILTER_PARSE_ERROR; + std::vector args = parents; + const ObjectType* type = 0; + args.push_back( new ObjectConstCalcer( new IntImp( which ) ) ); + if ( ( parents[0]->imp()->inherits( CircleImp::stype() ) ) && + ( parents[1]->imp()->inherits( CircleImp::stype() ) ) ) + type = CircleCircleIntersectionType::instance(); + else if ( ( parents[0]->imp()->inherits( CircleImp::stype() ) && + parents[1]->imp()->inherits( AbstractLineImp::stype() ) ) || + ( parents[1]->imp()->inherits( CircleImp::stype() ) && + parents[0]->imp()->inherits( AbstractLineImp::stype() ) ) ) + type = ConicLineIntersectionType::instance(); + else if ( ( parents[0]->imp()->inherits( ArcImp::stype() ) && + parents[1]->imp()->inherits( AbstractLineImp::stype() ) ) || + ( parents[1]->imp()->inherits( ArcImp::stype() ) && + parents[0]->imp()->inherits( AbstractLineImp::stype() ) ) ) + type = ArcLineIntersectionType::instance(); + else + { + notSupported( file, i18n( "This Dr. Geo file contains an intersection type, " + "which Kig does not currently support." ) ); + return 0; + } + oc = new ObjectTypeCalcer( type, args ); + } + } + else if ( domelem.attribute( "type" ) == "Reflexion" ) + oc = new ObjectTypeCalcer( LineReflectionType::instance(), parents ); + else if ( domelem.attribute( "type" ) == "Symmetry" ) + oc = new ObjectTypeCalcer( PointReflectionType::instance(), parents ); + else if ( domelem.attribute( "type" ) == "Translation" ) + oc = new ObjectTypeCalcer( TranslatedType::instance(), parents ); + else if ( domelem.attribute( "type" ) == "Rotation" ) + oc = new ObjectTypeCalcer( RotationType::instance(), parents ); + else + { + notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " + "which Kig does not currently support." ).arg( domelem.tagName() ).arg( + domelem.attribute( "type" ) ) ); + return 0; + } +#ifdef DRGEO_DEBUG + kdDebug() << "+++++++++ oc:" << oc << endl; +#endif + } + else if( ( domelem.tagName() == "line" ) || + ( domelem.tagName() == "halfLine" ) || + ( domelem.tagName() == "segment" ) || + ( domelem.tagName() == "vector" ) || + ( domelem.tagName() == "circle" ) || + ( domelem.tagName() == "arcCircle" ) || + ( domelem.tagName() == "polygon" ) ) + { + const ObjectType* type = 0; + if ( domelem.attribute( "type" ) == "2pts" ) + { + if( domelem.tagName() == "line" ) + type = LineABType::instance(); + else if( domelem.tagName() == "halfLine" ) + type = RayABType::instance(); + else if( domelem.tagName() == "segment" ) + type = SegmentABType::instance(); + else if( domelem.tagName() == "vector" ) + type = VectorType::instance(); + else if( domelem.tagName() == "circle" ) + type = CircleBCPType::instance(); + else + { + notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " + "which Kig does not currently support." ).arg( domelem.tagName() ).arg( + domelem.attribute( "type" ) ) ); + return 0; + } + oc = new ObjectTypeCalcer( type, parents ); + } + else if( domelem.attribute( "type" ) == "3pts" ) + { + if( domelem.tagName() == "arcCircle" ) + type = ArcBTPType::instance(); + else + { + notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " + "which Kig does not currently support." ).arg( domelem.tagName() ).arg( + domelem.attribute( "type" ) ) ); + return 0; + } + oc = new ObjectTypeCalcer( type, parents ); + } + else if( domelem.attribute( "type" ) == "segment" ) + { + if( domelem.tagName() == "circle" ) + { + type = CircleBPRType::instance(); + ObjectPropertyCalcer* o = fact->propertyObjectCalcer( parents[1], "length" ); + o->calc( *ret ); + ObjectCalcer* a = parents[0]; + parents.clear(); + parents.push_back( a ); + parents.push_back( o ); + } + else + { + notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " + "which Kig does not currently support." ).arg( domelem.tagName() ).arg( + domelem.attribute( "type" ) ) ); + return 0; + } + oc = new ObjectTypeCalcer( type, parents ); + } + else if( domelem.attribute( "type" ) == "npts" ) + { + if( domelem.tagName() == "polygon" ) + { + if ( parents.size() < 3 ) KIG_FILTER_PARSE_ERROR; + type = PolygonBNPType::instance(); + } + else + { + notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " + "which Kig does not currently support." ).arg( domelem.tagName() ).arg( + domelem.attribute( "type" ) ) ); + return 0; + } + oc = new ObjectTypeCalcer( type, parents ); + } + else if ( domelem.attribute( "type" ) == "perpendicular" ) + oc = new ObjectTypeCalcer( LinePerpendLPType::instance(), parents ); + else if ( domelem.attribute( "type" ) == "parallel" ) + oc = new ObjectTypeCalcer( LineParallelLPType::instance(), parents ); + else if ( domelem.attribute( "type" ) == "Reflexion" ) + oc = new ObjectTypeCalcer( LineReflectionType::instance(), parents ); + else if ( domelem.attribute( "type" ) == "Symmetry" ) + oc = new ObjectTypeCalcer( PointReflectionType::instance(), parents ); + else if ( domelem.attribute( "type" ) == "Translation" ) + oc = new ObjectTypeCalcer( TranslatedType::instance(), parents ); + else if ( domelem.attribute( "type" ) == "Rotation" ) + oc = new ObjectTypeCalcer( RotationType::instance(), parents ); + else + { + notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " + "which Kig does not currently support." ).arg( domelem.tagName() ).arg( + domelem.attribute( "type" ) ) ); + return 0; + } +#ifdef DRGEO_DEBUG + kdDebug() << "+++++++++ oc:" << oc << endl; +#endif + } + else if( ( domelem.tagName() == "numeric" ) || + ( domelem.tagName() == "equation" ) ) + { + TQString xs; + TQString ys; + TQString value; + for ( TQDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() ) + { + TQDomElement ce = c.toElement(); + if ( ce.isNull() ) continue; + else if ( ce.tagName() == "x" ) + xs = ce.text(); + else if ( ce.tagName() == "y" ) + ys = ce.text(); + else if ( ce.tagName() == "value" ) + value = ce.text(); + } + bool ok; + bool ok2; + double x = xs.toDouble( &ok ); + double y = ys.toDouble( &ok2 ); + if ( ! ( ok && ok2 ) ) + KIG_FILTER_PARSE_ERROR; + Coordinate m( x, y ); + // types of 'numeric' + // ugly hack to show value numerics... + if ( domelem.attribute( "type" ) == "value" ) + { + bool ok3; + double dvalue = value.toDouble( &ok3 ); + if ( ok3 ) + value = TQString( "%1" ).arg( dvalue, 0, 'g', 3 ); + oc = fact->labelCalcer( value, m, false, std::vector(), *ret ); + } + else if ( domelem.attribute( "type" ) == "pt_abscissa" ) + { + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + oc = filtersConstructTextObject( m, parents[0], "coordinate-x", *ret, false ); + } + else if ( domelem.attribute( "type" ) == "pt_ordinate" ) + { + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + oc = filtersConstructTextObject( m, parents[0], "coordinate-y", *ret, false ); + } + else if ( domelem.attribute( "type" ) == "segment_length" ) + { + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + oc = filtersConstructTextObject( m, parents[0], "length", *ret, false ); + } + else if ( domelem.attribute( "type" ) == "circle_perimeter" ) + { + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + oc = filtersConstructTextObject( m, parents[0], "circumference", *ret, false ); + } + else if ( domelem.attribute( "type" ) == "arc_length" ) + { + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + oc = filtersConstructTextObject( m, parents[0], "arc-length", *ret, false ); + } + else if ( domelem.attribute( "type" ) == "distance_2pts" ) + { + if ( parents.size() != 2 ) KIG_FILTER_PARSE_ERROR; + ObjectTypeCalcer* so = new ObjectTypeCalcer( SegmentABType::instance(), parents ); + so->calc( *ret ); + oc = filtersConstructTextObject( m, so, "length", *ret, false ); + } + else if ( domelem.attribute( "type" ) == "vector_norm" ) + { + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + oc = filtersConstructTextObject( m, parents[0], "length", *ret, false ); + } + else if ( domelem.attribute( "type" ) == "vector_abscissa" ) + { + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + oc = filtersConstructTextObject( m, parents[0], "length-x", *ret, false ); + } + else if ( domelem.attribute( "type" ) == "vector_ordinate" ) + { + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + oc = filtersConstructTextObject( m, parents[0], "length-y", *ret, false ); + } + else if ( domelem.attribute( "type" ) == "slope" ) + { + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + oc = filtersConstructTextObject( m, parents[0], "slope", *ret, false ); + } + else if ( domelem.attribute( "type" ) == "distance_pt_line" ) + { + if ( parents.size() != 2 ) KIG_FILTER_PARSE_ERROR; + std::vector args; + args.push_back( parents[1] ); + args.push_back( parents[0] ); + ObjectTypeCalcer* po = new ObjectTypeCalcer( LinePerpendLPType::instance(), args ); + po->calc( *ret ); + args.clear(); + args.push_back( parents[1] ); + args.push_back( po ); + ObjectTypeCalcer* io = new ObjectTypeCalcer( LineLineIntersectionType::instance(), args ); + io->calc( *ret ); + args.clear(); + args.push_back( parents[0] ); + args.push_back( io ); + ObjectTypeCalcer* so = new ObjectTypeCalcer( SegmentABType::instance(), args ); + so->calc( *ret ); + oc = filtersConstructTextObject( m, so, "length", *ret, false ); + } + // types of 'equation' + else if ( domelem.attribute( "type" ) == "line" ) + { + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + oc = filtersConstructTextObject( m, parents[0], "equation", *ret, false ); + } + else if ( domelem.attribute( "type" ) == "circle" ) + { + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + oc = filtersConstructTextObject( m, parents[0], "simply-cartesian-equation", *ret, false ); + } + else + { + notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " + "which Kig does not currently support." ).arg( domelem.tagName() ).arg( + domelem.attribute( "type" ) ) ); + return 0; + } +#ifdef DRGEO_DEBUG + kdDebug() << "+++++++++ oc:" << oc << endl; +#endif + } + else if ( domelem.tagName() == "angle" ) + { + if ( domelem.attribute( "type" ) == "3pts" ) + { + if ( parents.size() != 3 ) KIG_FILTER_PARSE_ERROR; + oc = new ObjectTypeCalcer( HalfAngleType::instance(), parents ); + } + else + { + notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " + "which Kig does not currently support." ).arg( domelem.tagName() ).arg( + domelem.attribute( "type" ) ) ); + return 0; + } +#ifdef DRGEO_DEBUG + kdDebug() << "+++++++++ oc:" << oc << endl; +#endif + } + else if ( domelem.tagName() == "script" ) + { + TQString xs; + TQString ys; + TQString text; + for ( TQDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() ) + { + TQDomElement ce = c.toElement(); + if ( ce.isNull() ) continue; + else if ( ce.tagName() == "x" ) + xs = ce.text(); + else if ( ce.tagName() == "y" ) + ys = ce.text(); + else if ( ce.tagName() == "code" ) + text = ce.text(); + } + bool ok; + bool ok2; + double x = xs.toDouble( &ok ); + double y = ys.toDouble( &ok2 ); + if ( ! ( ok && ok2 ) ) + KIG_FILTER_PARSE_ERROR; + // since Kig doesn't support Guile scripts, it will write script's text + // in a label, so the user can freely see the code and make whatever + // he/she wants + // possible idea: construct a new script object with the parents of Guile + // one and the Guile code inserted commented... depends on a better + // handling of arguments in scripts? + if ( domelem.attribute( "type" ) == "nitems" ) + oc = fact->labelCalcer( text, Coordinate( x, y ), false, std::vector(), *ret ); + else + { + notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " + "which Kig does not currently support." ).arg( domelem.tagName() ).arg( + domelem.attribute( "type" ) ) ); + return 0; + } + } + else if ( domelem.tagName() == "locus" ) + { + if ( domelem.attribute( "type" ) == "None" ) + oc = fact->locusCalcer( parents[0], parents[1] ); + else + { + notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " + "which Kig does not currently support." ).arg( domelem.tagName() ).arg( + domelem.attribute( "type" ) ) ); + return 0; + } +#ifdef DRGEO_DEBUG + kdDebug() << "+++++++++ oc:" << oc << endl; +#endif + } + else if ( ( domelem.tagName() == "boundingBox" ) || + ( domelem.tagName() == "customUI" ) ) + { + // ignoring these elements, since they are not useful to us... + nignored++; + } + else + { +#ifdef DRGEO_DEBUG + kdDebug() << ">>>>>>>>> UNKNOWN OBJECT" << endl; +#endif + notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, " + "which Kig does not currently support." ).arg( domelem.tagName() ).arg( + domelem.attribute( "type" ) ) ); + return 0; + } + curid++; + if ( oc == 0 ) + continue; + +// reading color + TQColor co( domelem.attribute( "color" ) ); + if ( ! co.isValid() ) + if ( domelem.attribute( "color" ) == "Bordeaux" ) + co.setRgb( 145, 0, 0 ); + else + co = TQt::blue; +// reading width and style +// Dashed -> the little one +// Normal -> the medium +// Thick -> the biggest one + int w = -1; + Qt::PenStyle s = Qt::SolidLine; + if ( domelem.tagName() == "point" ) + { + if ( domelem.attribute( "thickness" ) == "Normal" ) + w = 7; + else if ( domelem.attribute( "thickness" ) == "Thick" ) + w = 9; + } + else + { + if ( domelem.attribute( "thickness" ) == "Dashed" ) + s = Qt::DotLine; + if ( domelem.attribute( "thickness" ) == "Thick" ) + w = 2; + } + TQString ps = domelem.attribute( "style" ); + int pointstyle = ObjectDrawer::pointStyleFromString( ps ); +// show this object? + bool show = ( ( domelem.attribute( "masked" ) != "True" ) && + ( domelem.attribute( "masked" ) != "Alway" ) ); +// costructing the ObjectDrawer* + ObjectDrawer* d = new ObjectDrawer( co, w, show, s, pointstyle ); +// reading object name + TQString strname = domelem.attribute( "name" ); + ObjectConstCalcer* name = new ObjectConstCalcer( new StringImp( strname ) ); + +// creating the ObjectHolder* + ObjectHolder* o = new ObjectHolder( oc, d, name ); + holders.push_back( o ); +// calc() +#ifdef DRGEO_DEBUG + kdDebug() << ">>>>>>>>> calc" << endl; +#endif + holders[curid-1-nignored]->calc( *ret ); + + if ( domelem.tagName() == "point" ) + { + if ( !strname.isEmpty() ) + { + std::vector args2; + args2.push_back( o->nameCalcer() ); + oc2 = fact->attachedLabelCalcer( TQString::fromLatin1( "%1" ), oc, + static_cast( oc->imp() )->coordinate(), + false, args2, *ret ); + co = TQt::black; + } + } + else if ( domelem.tagName() == "angle" ) + { + oc2 = filtersConstructTextObject( + static_cast( holders[curid-1-nignored]->calcer()->parents()[1]->imp() )->coordinate(), + holders[curid-1-nignored]->calcer(), "angle-degrees", *ret, false ); + } + + oc = 0; + + if ( oc2 != 0 ) + { + oc2->calc( *ret ); + ObjectDrawer* d2 = new ObjectDrawer( co ); + ObjectHolder* o2 = new ObjectHolder( oc2, d2 ); + holders2.push_back( o2 ); + oc2 = 0; + } + } + + ret->addObjects( holders ); + ret->addObjects( holders2 ); + ret->setGrid( grid ); + ret->setAxes( grid ); + return ret; +} + +KigFilterDrgeo* KigFilterDrgeo::instance() +{ + static KigFilterDrgeo f; + return &f; +} diff --git a/kig/filters/exporter.cc b/kig/filters/exporter.cc deleted file mode 100644 index 32b25f01..00000000 --- a/kig/filters/exporter.cc +++ /dev/null @@ -1,624 +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 "exporter.h" - -#include "imageexporteroptions.h" -#include "latexexporter.h" -#include "svgexporter.h" - -#include "../kig/kig_document.h" -#include "../kig/kig_part.h" -#include "../kig/kig_view.h" -#include "../misc/common.h" -#include "../misc/kigfiledialog.h" -#include "../misc/kigpainter.h" -#include "../objects/circle_imp.h" -#include "../objects/line_imp.h" -#include "../objects/object_drawer.h" -#include "../objects/object_holder.h" -#include "../objects/object_imp.h" -#include "../objects/other_imp.h" -#include "../objects/point_imp.h" -#include "../objects/text_imp.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -// we need this for storing colors in a std::map.. -static bool operator<( const TQColor& a, const TQColor& b ) -{ - return a.rgb() < b.rgb(); -} - -class ExporterAction - : public TDEAction -{ - KigExporter* mexp; - const KigPart* mdoc; - KigWidget* mw; -public: - ExporterAction( const KigPart* doc, KigWidget* w, - TDEActionCollection* parent, KigExporter* exp ); - void slotActivated(); -}; - -ExporterAction::ExporterAction( const KigPart* doc, KigWidget* w, - TDEActionCollection* parent, KigExporter* exp ) - : TDEAction( exp->menuEntryName(), TDEShortcut(), 0, 0, parent ), - mexp( exp ), mdoc( doc ), mw( w ) -{ - TQString iconstr = exp->menuIcon(); - if ( iconstr.isEmpty() ) - return; - TDEIconLoader* l = doc->instance()->iconLoader(); - TQPixmap icon = l->loadIcon( iconstr, TDEIcon::Small, 16, TDEIcon::DefaultState, 0L, true ); - if ( !icon.isNull() ) - setIconSet( TQIconSet( icon ) ); -} - -void ExporterAction::slotActivated() -{ - mexp->run( *mdoc, *mw ); -} - -KigExporter::~KigExporter() -{ -} - -ImageExporter::~ImageExporter() -{ -} - -TQString ImageExporter::exportToStatement() const -{ - return i18n( "&Export to image" ); -} - -TQString ImageExporter::menuEntryName() const -{ - return i18n( "&Image..." ); -} - -TQString ImageExporter::menuIcon() const -{ - return "image-x-generic"; -} - -void ImageExporter::run( const KigPart& doc, KigWidget& w ) -{ - static bool kimageioRegistered = false; - if ( ! kimageioRegistered ) - { - KImageIO::registerFormats(); - kimageioRegistered = true; - } - - KigFileDialog* kfd = new KigFileDialog( - TQString(), KImageIO::pattern( KImageIO::Writing ), - i18n( "Export as Image" ), &w ); - kfd->setOptionCaption( i18n( "Image Options" ) ); - ImageExporterOptions* opts = new ImageExporterOptions( 0L, w.size() ); - kfd->setOptionsWidget( opts ); - opts->WidthInput->setValue( w.size().width() ); - opts->HeightInput->setValue( w.size().height() ); - opts->showGridCheckBox->setChecked( doc.document().grid() ); - opts->showAxesCheckBox->setChecked( doc.document().axes() ); - if ( !kfd->exec() ) - return; - - TQString filename = kfd->selectedFile(); - bool showgrid = opts->showGridCheckBox->isOn(); - bool showaxes = opts->showAxesCheckBox->isOn(); - int width = opts->WidthInput->value(); - int height = opts->HeightInput->value(); - - delete opts; - delete kfd; - - TQString type = KImageIO::type( filename ); - if ( type.isNull() ) - { - KMessageBox::sorry( &w, i18n( "Sorry, this file format is not supported." ) ); - return; - }; - - kdDebug() << k_funcinfo << type << endl; - - TQFile file( filename ); - if ( ! file.open( IO_WriteOnly ) ) - { - KMessageBox::sorry( &w, - i18n( "The file \"%1\" could not be opened. Please check if the file permissions are set correctly." ) - .arg( filename ) ); - return; - }; - - TQPixmap img( TQSize( width, height ) ); - img.fill( TQt::white ); - KigPainter p( ScreenInfo( w.screenInfo().shownRect(), img.rect() ), TQT_TQPAINTDEVICE(&img), doc.document() ); - p.setWholeWinOverlay(); - p.drawGrid( doc.document().coordinateSystem(), showgrid, showaxes ); - // FIXME: show the selections ? - p.drawObjects( doc.document().objects(), false ); - if ( ! img.save( filename, type.latin1() ) ) - { - KMessageBox::error( &w, i18n( "Sorry, something went wrong while saving to image \"%1\"" ).arg( filename ) ); - } - -} - -KigExportManager::KigExportManager() -{ - mexporters.push_back( new ImageExporter ); - // working on this one ;) - mexporters.push_back( new XFigExporter ); - mexporters.push_back( new LatexExporter ); - mexporters.push_back( new SVGExporter ); -} - -KigExportManager::~KigExportManager() -{ - for ( uint i = 0; i < mexporters.size(); ++i ) - delete mexporters[i]; -} - -void KigExportManager::addMenuAction( const KigPart* doc, KigWidget* w, - TDEActionCollection* coll ) -{ - TDEActionMenu* m = - new TDEActionMenu( i18n( "&Export To" ), coll, "file_export" ); - for ( uint i = 0; i < mexporters.size(); ++i ) - m->insert( new ExporterAction( doc, w, coll, mexporters[i] ) ); -} - -KigExportManager* KigExportManager::instance() -{ - static KigExportManager m; - return &m; -} - -XFigExporter::~XFigExporter() -{ -} - -TQString XFigExporter::exportToStatement() const -{ - return i18n( "Export to &XFig file" ); -} - - -TQString XFigExporter::menuEntryName() const -{ - return i18n( "&XFig File..." ); -} - -TQString XFigExporter::menuIcon() const -{ - return "kig_xfig"; -} - -class XFigExportImpVisitor - : public ObjectImpVisitor -{ - TQTextStream& mstream; - ObjectHolder* mcurobj; - const KigWidget& mw; - Rect msr; - std::map mcolormap; - int mnextcolorid; - int mcurcolorid; - - TQPoint convertCoord( const Coordinate& c ) - { - Coordinate ret = ( c - msr.bottomLeft() ); - ret.y = msr.height() - ret.y; -// kdDebug() << "msr: " << msr << endl -// << "ret: " << ret << endl -// << "c: " << c << endl; - ret *= 9450; - ret /= msr.width(); - return ret.toTQPoint(); - } - - void emitLine( const Coordinate& a, const Coordinate& b, int width, bool vector = false ); -public: - void visit( ObjectHolder* obj ); - void mapColor( const ObjectDrawer* obj ); - - XFigExportImpVisitor( TQTextStream& s, const KigWidget& w ) - : mstream( s ), mw( w ), msr( mw.showingRect() ), - mnextcolorid( 32 ) - { - // predefined colors in XFig.. - mcolormap[TQt::black] = 0; - mcolormap[TQt::blue] = 1; - mcolormap[TQt::green] = 2; - mcolormap[TQt::cyan] = 3; - mcolormap[TQt::red] = 4; - mcolormap[TQt::magenta] = 5; - mcolormap[TQt::yellow] = 6; - mcolormap[TQt::white] = 7; - } - void visit( const LineImp* imp ); - void visit( const PointImp* imp ); - void visit( const TextImp* imp ); - void visit( const AngleImp* imp ); - void visit( const VectorImp* imp ); - void visit( const LocusImp* imp ); - void visit( const CircleImp* imp ); - void visit( const ConicImp* imp ); - void visit( const CubicImp* imp ); - void visit( const SegmentImp* imp ); - void visit( const RayImp* imp ); - void visit( const ArcImp* imp ); -}; - -void XFigExportImpVisitor::mapColor( const ObjectDrawer* obj ) -{ - if ( ! obj->shown() ) return; - TQColor color = obj->color(); - if ( mcolormap.find( color ) == mcolormap.end() ) - { - int newcolorid = mnextcolorid++; - mstream << "0 " - << newcolorid << " " - << color.name() << "\n"; - mcolormap[color] = newcolorid; - } -} - -void XFigExportImpVisitor::visit( ObjectHolder* obj ) -{ - if ( ! obj->drawer()->shown() ) return; - assert( mcolormap.find( obj->drawer()->color() ) != mcolormap.end() ); - mcurcolorid = mcolormap[ obj->drawer()->color() ]; - mcurobj = obj; - obj->imp()->visit( this ); -} - -void XFigExportImpVisitor::visit( const LineImp* imp ) -{ - Coordinate a = imp->data().a; - Coordinate b = imp->data().b; - calcBorderPoints( a, b, msr ); - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - - if ( a != b ) - emitLine( a, b, width ); -} - -void XFigExportImpVisitor::emitLine( const Coordinate& a, const Coordinate& b, int width, bool vector ) -{ - mstream << "2 "; // polyline type; - mstream << "1 "; // polyline subtype; - mstream << "0 "; // line_style: Solid - mstream << width << " "; // thickness: *1/80 inch - mstream << mcurcolorid << " "; // pen_color: default - mstream << "7 "; // fill_color: white - mstream << "50 "; // depth: 50 - mstream << "-1 "; // pen_style: unused by XFig - mstream << "-1 "; // area_fill: no fill - mstream << "0.000 "; // style_val: the distance between dots and - // dashes in case of dotted or dashed lines.. - mstream << "0 "; // join_style: Miter - mstream << "0 "; // cap_style: Butt - mstream << "-1 "; // radius in case of an arc-box, but we're a - // polyline, so nothing here.. - if ( ! vector ) - mstream << "0 "; // forward arrow: no - else - mstream << "1 "; // forward arrow: yes - mstream << "0 "; // backward arrow: no - mstream << "2"; // a two points polyline.. - - mstream << "\n\t "; - - if ( vector ) - { - // first the arrow line in case of a vector.. - mstream << "1 " // arrow_type: closed triangle - << "1 " // arrow_style: filled with pen color.. - << "1.00 " // arrow_thickness: 1 - << "195.00 " // arrow_width - << "165.00 " // arrow_height - << "\n\t"; - } - TQPoint ca = convertCoord( a ); - TQPoint cb = convertCoord( b ); - - mstream << ca.x() << " " << ca.y() << " " << cb.x() << " " << cb.y() << "\n"; -} - -void XFigExportImpVisitor::visit( const PointImp* imp ) -{ - const TQPoint center = convertCoord( imp->coordinate() ); - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 5; - width *= 10; - - mstream << "1 " // Ellipse type - << "3 " // circle defined by radius subtype - << "0 "; // line_style: Solid - mstream << "1 " << " " // thickness: *1/80 inch - << mcurcolorid << " " // pen_color: default - << mcurcolorid << " " // fill_color: black - << "50 " // depth: 50 - << "-1 " // pen_style: unused by XFig - << "20 " // area_fill: full saturation of the fill color - << "0.000 " // style_val: the distance between dots and - // dashes in case of dotted or dashed lines.. - << "1 " // direction: always 1 - << "0.0000 " // angle: the radius of the x-axis: 0 - << center.x() << " " << center.y() << " " // the center.. - << width << " " << width << " " // radius_x and radius_y - << center.x() << " " // start_x and start_y, appear - << center.y() << " " // unused.. - << center.x() + width << " " // end_x and end_y, - << center.y() << "\n"; // appear unused too... -} - -void XFigExportImpVisitor::visit( const TextImp* imp ) -{ - TQString text = imp->text(); - TQPoint coord = convertCoord( imp->surroundingRect().bottomLeft() ); - - mstream << "4 " // text type - << "0 " // subtype: left justfied - << mcurcolorid << " " // color: black - << "50 " // depth: 50 - << "-1 " // pen style: unused - << "0 " // font: default - << "11 " // font-size: 11 - << "0 " // angle - << "0 " // font-flags: all the defaults.. - << "500 500 " // height, width: large enough.. - << coord.x() << " " // x, y - << coord.y() << " " - << text.ascii() << "\\001" // text, terminated by \001 - << "\n"; -} - -void XFigExportImpVisitor::visit( const AngleImp* ) -{ -} - -void XFigExportImpVisitor::visit( const VectorImp* imp ) -{ - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - emitLine( imp->a(), imp->b(), width, true ); -} - -void XFigExportImpVisitor::visit( const LocusImp* ) -{ - -} - -void XFigExportImpVisitor::visit( const CircleImp* imp ) -{ - const TQPoint center = convertCoord( imp->center() ); - const int radius = - ( convertCoord( imp->center() + Coordinate( imp->radius(), 0 ) ) - center ).x(); - - mstream << "1 " // Ellipse type - << "3 " // circle defined by radius subtype - << "0 "; // line_style: Solid - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - mstream << width << " " // thickness: *1/80 inch - << mcurcolorid << " " // pen_color: default - << "7 " // fill_color: white - << "50 " // depth: 50 - << "-1 " // pen_style: unused by XFig - << "-1 " // area_fill: no fill - << "0.000 " // style_val: the distance between dots and - // dashes in case of dotted or dashed lines.. - << "1 " // direction: always 1 - << "0.0000 " // angle: the radius of the x-axis: 0 - << center.x() << " " << center.y() << " " // the center.. - << radius << " " << radius << " " // radius_x and radius_y - << center.x() << " " // start_x and start_y, appear - << center.y() << " " // unused.. - << center.x() + radius << " " // end_x and end_y, - << center.y() << "\n"; // appear unused too... -} - -void XFigExportImpVisitor::visit( const ConicImp* imp ) -{ - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - if ( imp->conicType() == 1 ) - { - // an ellipse, this is good, cause this allows us to export to a - // real ellipse type.. - const ConicPolarData data = imp->polarData(); - - // gather some necessary data.. - // the angle of the x axis.. - double anglex = atan2( data.esintheta0, data.ecostheta0 ); - // the exentricity - double e = hypot( data.esintheta0, data.ecostheta0 ); - // the x radius is easy to find.. - double radiusx = data.pdimen / ( 1 - e * e ); - // the y radius is a bit harder: we first find the distance from - // the focus point to the mid point of the two focuses, this is: - double d = -e * data.pdimen / ( 1 - e * e ); - // the distance from the first focus to the intersection of the - // second axis with the conic equals radiusx: - double r = radiusx; - double radiusy = sqrt( r*r - d*d ); - - Coordinate center = data.focus1 - Coordinate( cos( anglex ), sin( anglex ) ).normalize( d ); - const TQPoint qcenter = convertCoord( center ); - const int radius_x = ( convertCoord( center + Coordinate( radiusx, 0 ) ) - - convertCoord( center ) ).x(); - const int radius_y = ( convertCoord( center + Coordinate( radiusy, 0 ) ) - - convertCoord( center ) ).x(); - const TQPoint qpoint2 = convertCoord( center + Coordinate( -sin( anglex ), cos( anglex ) ) * radiusy ); - - mstream << "1 " // ellipse type - << "1 " // subtype: ellipse defined by readii - << "0 " // line_style: Solid - << width << " " // thickness - << mcurcolorid << " " // pen_color: black - << "7 " // fill_color: white - << "50 " // depth: 50 - << "-1 " // pan_style: not used - << "-1 " // area_fill: no fill - << "0.000 " // style_val: not used - << "1 " // direction: always 1 - << anglex << " " // angle of the main axis - << qcenter.x() << " " // center - << qcenter.y() << " " - << radius_x << " " // radiuses - << radius_y << " " - << qcenter.x() << " " // start point - << qcenter.y() << " " - << qpoint2.x() << " " // end point - << qpoint2.y() << " "; - } - else return; -} - -void XFigExportImpVisitor::visit( const CubicImp* ) -{ -} - -void XFigExportImpVisitor::visit( const SegmentImp* imp ) -{ - Coordinate a = imp->data().a; - Coordinate b = imp->data().b; - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - - emitLine( a, b, width ); -} - -void XFigExportImpVisitor::visit( const RayImp* imp ) -{ - Coordinate a = imp->data().a; - Coordinate b = imp->data().b; - calcRayBorderPoints( a, b, msr ); - - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - - emitLine( a, b, width ); -} - -void XFigExportImpVisitor::visit( const ArcImp* imp ) -{ - const Coordinate center = imp->center(); - const double radius = imp->radius(); - const double startangle = imp->startAngle(); - const double endangle = startangle + imp->angle(); - const double middleangle = ( startangle + endangle ) / 2; - const Coordinate ad = Coordinate( cos( startangle ), sin( startangle ) ).normalize( radius ); - const Coordinate bd = Coordinate( cos( middleangle ), sin( middleangle ) ).normalize( radius ); - const Coordinate cd = Coordinate( cos( endangle ), sin( endangle ) ).normalize( radius ); - const TQPoint a = convertCoord( center + ad ); - const TQPoint b = convertCoord( center + bd ); - const TQPoint c = convertCoord( center + cd ); - const TQPoint cent = convertCoord( center ); - - mstream << "5 " // Ellipse type - << "1 " // subtype: open ended arc - << "0 "; // line_style: Solid - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - mstream << width << " " // thickness: *1/80 inch - << mcurcolorid << " " // pen_color: default - << "7 " // fill_color: white - << "50 " // depth: 50 - << "-1 " // pen_style: unused by XFig - << "-1 " // area_fill: no fill - << "0.000 " // style_val: the distance between dots and - // dashes in case of dotted or dashed lines.. - << "0 "; // cap_style: Butt.. - // 0 is clockwise, 1 is counterclockwise . - int direction = imp->angle() > 0 ? 1 : 0; - // direction next - mstream << direction << " " // direction.. - << "0 " // forward_arrow: no - << "0 " // backward_arrow: no - << cent.x() << " " << cent.y() << " " // the center.. - << a.x() << " " << a.y() << " " // x1, y1 - << b.x() << " " << b.y() << " " // x2, y2 - << c.x() << " " << c.y() << " " // x3, y3 - << "\n"; -} - -void XFigExporter::run( const KigPart& doc, KigWidget& w ) -{ - KigFileDialog* kfd = new KigFileDialog( - ":document", i18n( "*.fig|XFig Documents (*.fig)" ), - i18n( "Export as XFig File" ), &w ); - if ( !kfd->exec() ) - return; - - TQString file_name = kfd->selectedFile(); - - delete kfd; - - TQFile file( file_name ); - if ( ! file.open( IO_WriteOnly ) ) - { - KMessageBox::sorry( &w, i18n( "The file \"%1\" could not be opened. Please " - "check if the file permissions are set correctly." ) - .arg( file_name ) ); - return; - }; - TQTextStream stream( &file ); - stream << "#FIG 3.2\n"; - stream << "Landscape\n"; - stream << "Center\n"; - stream << "Metric\n"; - stream << "A4\n"; - stream << "100.00\n"; - stream << "Single\n"; - stream << "-2\n"; - stream << "1200 2\n"; - - std::vector os = doc.document().objects(); - XFigExportImpVisitor visitor( stream, w ); - - for ( std::vector::const_iterator i = os.begin(); - i != os.end(); ++i ) - { - visitor.mapColor( ( *i )->drawer() ); - }; - - for ( std::vector::const_iterator i = os.begin(); - i != os.end(); ++i ) - { - visitor.visit( *i ); - }; -} diff --git a/kig/filters/exporter.cpp b/kig/filters/exporter.cpp new file mode 100644 index 00000000..32b25f01 --- /dev/null +++ b/kig/filters/exporter.cpp @@ -0,0 +1,624 @@ +// 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 "exporter.h" + +#include "imageexporteroptions.h" +#include "latexexporter.h" +#include "svgexporter.h" + +#include "../kig/kig_document.h" +#include "../kig/kig_part.h" +#include "../kig/kig_view.h" +#include "../misc/common.h" +#include "../misc/kigfiledialog.h" +#include "../misc/kigpainter.h" +#include "../objects/circle_imp.h" +#include "../objects/line_imp.h" +#include "../objects/object_drawer.h" +#include "../objects/object_holder.h" +#include "../objects/object_imp.h" +#include "../objects/other_imp.h" +#include "../objects/point_imp.h" +#include "../objects/text_imp.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +// we need this for storing colors in a std::map.. +static bool operator<( const TQColor& a, const TQColor& b ) +{ + return a.rgb() < b.rgb(); +} + +class ExporterAction + : public TDEAction +{ + KigExporter* mexp; + const KigPart* mdoc; + KigWidget* mw; +public: + ExporterAction( const KigPart* doc, KigWidget* w, + TDEActionCollection* parent, KigExporter* exp ); + void slotActivated(); +}; + +ExporterAction::ExporterAction( const KigPart* doc, KigWidget* w, + TDEActionCollection* parent, KigExporter* exp ) + : TDEAction( exp->menuEntryName(), TDEShortcut(), 0, 0, parent ), + mexp( exp ), mdoc( doc ), mw( w ) +{ + TQString iconstr = exp->menuIcon(); + if ( iconstr.isEmpty() ) + return; + TDEIconLoader* l = doc->instance()->iconLoader(); + TQPixmap icon = l->loadIcon( iconstr, TDEIcon::Small, 16, TDEIcon::DefaultState, 0L, true ); + if ( !icon.isNull() ) + setIconSet( TQIconSet( icon ) ); +} + +void ExporterAction::slotActivated() +{ + mexp->run( *mdoc, *mw ); +} + +KigExporter::~KigExporter() +{ +} + +ImageExporter::~ImageExporter() +{ +} + +TQString ImageExporter::exportToStatement() const +{ + return i18n( "&Export to image" ); +} + +TQString ImageExporter::menuEntryName() const +{ + return i18n( "&Image..." ); +} + +TQString ImageExporter::menuIcon() const +{ + return "image-x-generic"; +} + +void ImageExporter::run( const KigPart& doc, KigWidget& w ) +{ + static bool kimageioRegistered = false; + if ( ! kimageioRegistered ) + { + KImageIO::registerFormats(); + kimageioRegistered = true; + } + + KigFileDialog* kfd = new KigFileDialog( + TQString(), KImageIO::pattern( KImageIO::Writing ), + i18n( "Export as Image" ), &w ); + kfd->setOptionCaption( i18n( "Image Options" ) ); + ImageExporterOptions* opts = new ImageExporterOptions( 0L, w.size() ); + kfd->setOptionsWidget( opts ); + opts->WidthInput->setValue( w.size().width() ); + opts->HeightInput->setValue( w.size().height() ); + opts->showGridCheckBox->setChecked( doc.document().grid() ); + opts->showAxesCheckBox->setChecked( doc.document().axes() ); + if ( !kfd->exec() ) + return; + + TQString filename = kfd->selectedFile(); + bool showgrid = opts->showGridCheckBox->isOn(); + bool showaxes = opts->showAxesCheckBox->isOn(); + int width = opts->WidthInput->value(); + int height = opts->HeightInput->value(); + + delete opts; + delete kfd; + + TQString type = KImageIO::type( filename ); + if ( type.isNull() ) + { + KMessageBox::sorry( &w, i18n( "Sorry, this file format is not supported." ) ); + return; + }; + + kdDebug() << k_funcinfo << type << endl; + + TQFile file( filename ); + if ( ! file.open( IO_WriteOnly ) ) + { + KMessageBox::sorry( &w, + i18n( "The file \"%1\" could not be opened. Please check if the file permissions are set correctly." ) + .arg( filename ) ); + return; + }; + + TQPixmap img( TQSize( width, height ) ); + img.fill( TQt::white ); + KigPainter p( ScreenInfo( w.screenInfo().shownRect(), img.rect() ), TQT_TQPAINTDEVICE(&img), doc.document() ); + p.setWholeWinOverlay(); + p.drawGrid( doc.document().coordinateSystem(), showgrid, showaxes ); + // FIXME: show the selections ? + p.drawObjects( doc.document().objects(), false ); + if ( ! img.save( filename, type.latin1() ) ) + { + KMessageBox::error( &w, i18n( "Sorry, something went wrong while saving to image \"%1\"" ).arg( filename ) ); + } + +} + +KigExportManager::KigExportManager() +{ + mexporters.push_back( new ImageExporter ); + // working on this one ;) + mexporters.push_back( new XFigExporter ); + mexporters.push_back( new LatexExporter ); + mexporters.push_back( new SVGExporter ); +} + +KigExportManager::~KigExportManager() +{ + for ( uint i = 0; i < mexporters.size(); ++i ) + delete mexporters[i]; +} + +void KigExportManager::addMenuAction( const KigPart* doc, KigWidget* w, + TDEActionCollection* coll ) +{ + TDEActionMenu* m = + new TDEActionMenu( i18n( "&Export To" ), coll, "file_export" ); + for ( uint i = 0; i < mexporters.size(); ++i ) + m->insert( new ExporterAction( doc, w, coll, mexporters[i] ) ); +} + +KigExportManager* KigExportManager::instance() +{ + static KigExportManager m; + return &m; +} + +XFigExporter::~XFigExporter() +{ +} + +TQString XFigExporter::exportToStatement() const +{ + return i18n( "Export to &XFig file" ); +} + + +TQString XFigExporter::menuEntryName() const +{ + return i18n( "&XFig File..." ); +} + +TQString XFigExporter::menuIcon() const +{ + return "kig_xfig"; +} + +class XFigExportImpVisitor + : public ObjectImpVisitor +{ + TQTextStream& mstream; + ObjectHolder* mcurobj; + const KigWidget& mw; + Rect msr; + std::map mcolormap; + int mnextcolorid; + int mcurcolorid; + + TQPoint convertCoord( const Coordinate& c ) + { + Coordinate ret = ( c - msr.bottomLeft() ); + ret.y = msr.height() - ret.y; +// kdDebug() << "msr: " << msr << endl +// << "ret: " << ret << endl +// << "c: " << c << endl; + ret *= 9450; + ret /= msr.width(); + return ret.toTQPoint(); + } + + void emitLine( const Coordinate& a, const Coordinate& b, int width, bool vector = false ); +public: + void visit( ObjectHolder* obj ); + void mapColor( const ObjectDrawer* obj ); + + XFigExportImpVisitor( TQTextStream& s, const KigWidget& w ) + : mstream( s ), mw( w ), msr( mw.showingRect() ), + mnextcolorid( 32 ) + { + // predefined colors in XFig.. + mcolormap[TQt::black] = 0; + mcolormap[TQt::blue] = 1; + mcolormap[TQt::green] = 2; + mcolormap[TQt::cyan] = 3; + mcolormap[TQt::red] = 4; + mcolormap[TQt::magenta] = 5; + mcolormap[TQt::yellow] = 6; + mcolormap[TQt::white] = 7; + } + void visit( const LineImp* imp ); + void visit( const PointImp* imp ); + void visit( const TextImp* imp ); + void visit( const AngleImp* imp ); + void visit( const VectorImp* imp ); + void visit( const LocusImp* imp ); + void visit( const CircleImp* imp ); + void visit( const ConicImp* imp ); + void visit( const CubicImp* imp ); + void visit( const SegmentImp* imp ); + void visit( const RayImp* imp ); + void visit( const ArcImp* imp ); +}; + +void XFigExportImpVisitor::mapColor( const ObjectDrawer* obj ) +{ + if ( ! obj->shown() ) return; + TQColor color = obj->color(); + if ( mcolormap.find( color ) == mcolormap.end() ) + { + int newcolorid = mnextcolorid++; + mstream << "0 " + << newcolorid << " " + << color.name() << "\n"; + mcolormap[color] = newcolorid; + } +} + +void XFigExportImpVisitor::visit( ObjectHolder* obj ) +{ + if ( ! obj->drawer()->shown() ) return; + assert( mcolormap.find( obj->drawer()->color() ) != mcolormap.end() ); + mcurcolorid = mcolormap[ obj->drawer()->color() ]; + mcurobj = obj; + obj->imp()->visit( this ); +} + +void XFigExportImpVisitor::visit( const LineImp* imp ) +{ + Coordinate a = imp->data().a; + Coordinate b = imp->data().b; + calcBorderPoints( a, b, msr ); + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + + if ( a != b ) + emitLine( a, b, width ); +} + +void XFigExportImpVisitor::emitLine( const Coordinate& a, const Coordinate& b, int width, bool vector ) +{ + mstream << "2 "; // polyline type; + mstream << "1 "; // polyline subtype; + mstream << "0 "; // line_style: Solid + mstream << width << " "; // thickness: *1/80 inch + mstream << mcurcolorid << " "; // pen_color: default + mstream << "7 "; // fill_color: white + mstream << "50 "; // depth: 50 + mstream << "-1 "; // pen_style: unused by XFig + mstream << "-1 "; // area_fill: no fill + mstream << "0.000 "; // style_val: the distance between dots and + // dashes in case of dotted or dashed lines.. + mstream << "0 "; // join_style: Miter + mstream << "0 "; // cap_style: Butt + mstream << "-1 "; // radius in case of an arc-box, but we're a + // polyline, so nothing here.. + if ( ! vector ) + mstream << "0 "; // forward arrow: no + else + mstream << "1 "; // forward arrow: yes + mstream << "0 "; // backward arrow: no + mstream << "2"; // a two points polyline.. + + mstream << "\n\t "; + + if ( vector ) + { + // first the arrow line in case of a vector.. + mstream << "1 " // arrow_type: closed triangle + << "1 " // arrow_style: filled with pen color.. + << "1.00 " // arrow_thickness: 1 + << "195.00 " // arrow_width + << "165.00 " // arrow_height + << "\n\t"; + } + TQPoint ca = convertCoord( a ); + TQPoint cb = convertCoord( b ); + + mstream << ca.x() << " " << ca.y() << " " << cb.x() << " " << cb.y() << "\n"; +} + +void XFigExportImpVisitor::visit( const PointImp* imp ) +{ + const TQPoint center = convertCoord( imp->coordinate() ); + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 5; + width *= 10; + + mstream << "1 " // Ellipse type + << "3 " // circle defined by radius subtype + << "0 "; // line_style: Solid + mstream << "1 " << " " // thickness: *1/80 inch + << mcurcolorid << " " // pen_color: default + << mcurcolorid << " " // fill_color: black + << "50 " // depth: 50 + << "-1 " // pen_style: unused by XFig + << "20 " // area_fill: full saturation of the fill color + << "0.000 " // style_val: the distance between dots and + // dashes in case of dotted or dashed lines.. + << "1 " // direction: always 1 + << "0.0000 " // angle: the radius of the x-axis: 0 + << center.x() << " " << center.y() << " " // the center.. + << width << " " << width << " " // radius_x and radius_y + << center.x() << " " // start_x and start_y, appear + << center.y() << " " // unused.. + << center.x() + width << " " // end_x and end_y, + << center.y() << "\n"; // appear unused too... +} + +void XFigExportImpVisitor::visit( const TextImp* imp ) +{ + TQString text = imp->text(); + TQPoint coord = convertCoord( imp->surroundingRect().bottomLeft() ); + + mstream << "4 " // text type + << "0 " // subtype: left justfied + << mcurcolorid << " " // color: black + << "50 " // depth: 50 + << "-1 " // pen style: unused + << "0 " // font: default + << "11 " // font-size: 11 + << "0 " // angle + << "0 " // font-flags: all the defaults.. + << "500 500 " // height, width: large enough.. + << coord.x() << " " // x, y + << coord.y() << " " + << text.ascii() << "\\001" // text, terminated by \001 + << "\n"; +} + +void XFigExportImpVisitor::visit( const AngleImp* ) +{ +} + +void XFigExportImpVisitor::visit( const VectorImp* imp ) +{ + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + emitLine( imp->a(), imp->b(), width, true ); +} + +void XFigExportImpVisitor::visit( const LocusImp* ) +{ + +} + +void XFigExportImpVisitor::visit( const CircleImp* imp ) +{ + const TQPoint center = convertCoord( imp->center() ); + const int radius = + ( convertCoord( imp->center() + Coordinate( imp->radius(), 0 ) ) - center ).x(); + + mstream << "1 " // Ellipse type + << "3 " // circle defined by radius subtype + << "0 "; // line_style: Solid + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + mstream << width << " " // thickness: *1/80 inch + << mcurcolorid << " " // pen_color: default + << "7 " // fill_color: white + << "50 " // depth: 50 + << "-1 " // pen_style: unused by XFig + << "-1 " // area_fill: no fill + << "0.000 " // style_val: the distance between dots and + // dashes in case of dotted or dashed lines.. + << "1 " // direction: always 1 + << "0.0000 " // angle: the radius of the x-axis: 0 + << center.x() << " " << center.y() << " " // the center.. + << radius << " " << radius << " " // radius_x and radius_y + << center.x() << " " // start_x and start_y, appear + << center.y() << " " // unused.. + << center.x() + radius << " " // end_x and end_y, + << center.y() << "\n"; // appear unused too... +} + +void XFigExportImpVisitor::visit( const ConicImp* imp ) +{ + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + if ( imp->conicType() == 1 ) + { + // an ellipse, this is good, cause this allows us to export to a + // real ellipse type.. + const ConicPolarData data = imp->polarData(); + + // gather some necessary data.. + // the angle of the x axis.. + double anglex = atan2( data.esintheta0, data.ecostheta0 ); + // the exentricity + double e = hypot( data.esintheta0, data.ecostheta0 ); + // the x radius is easy to find.. + double radiusx = data.pdimen / ( 1 - e * e ); + // the y radius is a bit harder: we first find the distance from + // the focus point to the mid point of the two focuses, this is: + double d = -e * data.pdimen / ( 1 - e * e ); + // the distance from the first focus to the intersection of the + // second axis with the conic equals radiusx: + double r = radiusx; + double radiusy = sqrt( r*r - d*d ); + + Coordinate center = data.focus1 - Coordinate( cos( anglex ), sin( anglex ) ).normalize( d ); + const TQPoint qcenter = convertCoord( center ); + const int radius_x = ( convertCoord( center + Coordinate( radiusx, 0 ) ) - + convertCoord( center ) ).x(); + const int radius_y = ( convertCoord( center + Coordinate( radiusy, 0 ) ) - + convertCoord( center ) ).x(); + const TQPoint qpoint2 = convertCoord( center + Coordinate( -sin( anglex ), cos( anglex ) ) * radiusy ); + + mstream << "1 " // ellipse type + << "1 " // subtype: ellipse defined by readii + << "0 " // line_style: Solid + << width << " " // thickness + << mcurcolorid << " " // pen_color: black + << "7 " // fill_color: white + << "50 " // depth: 50 + << "-1 " // pan_style: not used + << "-1 " // area_fill: no fill + << "0.000 " // style_val: not used + << "1 " // direction: always 1 + << anglex << " " // angle of the main axis + << qcenter.x() << " " // center + << qcenter.y() << " " + << radius_x << " " // radiuses + << radius_y << " " + << qcenter.x() << " " // start point + << qcenter.y() << " " + << qpoint2.x() << " " // end point + << qpoint2.y() << " "; + } + else return; +} + +void XFigExportImpVisitor::visit( const CubicImp* ) +{ +} + +void XFigExportImpVisitor::visit( const SegmentImp* imp ) +{ + Coordinate a = imp->data().a; + Coordinate b = imp->data().b; + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + + emitLine( a, b, width ); +} + +void XFigExportImpVisitor::visit( const RayImp* imp ) +{ + Coordinate a = imp->data().a; + Coordinate b = imp->data().b; + calcRayBorderPoints( a, b, msr ); + + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + + emitLine( a, b, width ); +} + +void XFigExportImpVisitor::visit( const ArcImp* imp ) +{ + const Coordinate center = imp->center(); + const double radius = imp->radius(); + const double startangle = imp->startAngle(); + const double endangle = startangle + imp->angle(); + const double middleangle = ( startangle + endangle ) / 2; + const Coordinate ad = Coordinate( cos( startangle ), sin( startangle ) ).normalize( radius ); + const Coordinate bd = Coordinate( cos( middleangle ), sin( middleangle ) ).normalize( radius ); + const Coordinate cd = Coordinate( cos( endangle ), sin( endangle ) ).normalize( radius ); + const TQPoint a = convertCoord( center + ad ); + const TQPoint b = convertCoord( center + bd ); + const TQPoint c = convertCoord( center + cd ); + const TQPoint cent = convertCoord( center ); + + mstream << "5 " // Ellipse type + << "1 " // subtype: open ended arc + << "0 "; // line_style: Solid + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + mstream << width << " " // thickness: *1/80 inch + << mcurcolorid << " " // pen_color: default + << "7 " // fill_color: white + << "50 " // depth: 50 + << "-1 " // pen_style: unused by XFig + << "-1 " // area_fill: no fill + << "0.000 " // style_val: the distance between dots and + // dashes in case of dotted or dashed lines.. + << "0 "; // cap_style: Butt.. + // 0 is clockwise, 1 is counterclockwise . + int direction = imp->angle() > 0 ? 1 : 0; + // direction next + mstream << direction << " " // direction.. + << "0 " // forward_arrow: no + << "0 " // backward_arrow: no + << cent.x() << " " << cent.y() << " " // the center.. + << a.x() << " " << a.y() << " " // x1, y1 + << b.x() << " " << b.y() << " " // x2, y2 + << c.x() << " " << c.y() << " " // x3, y3 + << "\n"; +} + +void XFigExporter::run( const KigPart& doc, KigWidget& w ) +{ + KigFileDialog* kfd = new KigFileDialog( + ":document", i18n( "*.fig|XFig Documents (*.fig)" ), + i18n( "Export as XFig File" ), &w ); + if ( !kfd->exec() ) + return; + + TQString file_name = kfd->selectedFile(); + + delete kfd; + + TQFile file( file_name ); + if ( ! file.open( IO_WriteOnly ) ) + { + KMessageBox::sorry( &w, i18n( "The file \"%1\" could not be opened. Please " + "check if the file permissions are set correctly." ) + .arg( file_name ) ); + return; + }; + TQTextStream stream( &file ); + stream << "#FIG 3.2\n"; + stream << "Landscape\n"; + stream << "Center\n"; + stream << "Metric\n"; + stream << "A4\n"; + stream << "100.00\n"; + stream << "Single\n"; + stream << "-2\n"; + stream << "1200 2\n"; + + std::vector os = doc.document().objects(); + XFigExportImpVisitor visitor( stream, w ); + + for ( std::vector::const_iterator i = os.begin(); + i != os.end(); ++i ) + { + visitor.mapColor( ( *i )->drawer() ); + }; + + for ( std::vector::const_iterator i = os.begin(); + i != os.end(); ++i ) + { + visitor.visit( *i ); + }; +} diff --git a/kig/filters/filter.cc b/kig/filters/filter.cc deleted file mode 100644 index 6a543430..00000000 --- a/kig/filters/filter.cc +++ /dev/null @@ -1,114 +0,0 @@ -/** - This file is part of Kig, a KDE program for Interactive Geometry... - 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 "filter.h" - -#include "kgeo-filter.h" -#include "cabri-filter.h" -#include "native-filter.h" -#include "kseg-filter.h" -#include "drgeo-filter.h" - -#include -#include - -KigFilters* KigFilters::sThis; - -KigFilter* KigFilters::find(const TQString& mime) -{ - for (vect::iterator i = mFilters.begin(); i != mFilters.end(); ++i) - { - if ((*i)->supportMime(mime)) return *i; - }; - return 0; -} - -KigFilters::KigFilters() -{ - mFilters.push_back( KigFilterKGeo::instance() ); - mFilters.push_back( KigFilterKSeg::instance() ); - mFilters.push_back( KigFilterCabri::instance() ); - mFilters.push_back( KigFilterNative::instance() ); - mFilters.push_back( KigFilterDrgeo::instance() ); -} - -KigFilters* KigFilters::instance() -{ - return sThis ? sThis : ( sThis = new KigFilters() ); -} - -KigFilter::KigFilter() -{ -} - -KigFilter::~KigFilter() -{ -} - -bool KigFilter::supportMime( const TQString& ) -{ - return false; -} - -void KigFilter::fileNotFound( const TQString& file ) const -{ - KMessageBox::sorry( 0, - i18n( "The file \"%1\" could not be opened. " - "This probably means that it does not " - "exist, or that it cannot be opened due to " - "its permissions" ).arg( file ) ); -} - -void KigFilter::parseError( const TQString& file, const TQString& explanation ) const -{ - const TQString text = - i18n( "An error was encountered while parsing the file \"%1\". It " - "cannot be opened." ).arg( file ); - const TQString title = i18n( "Parse Error" ); - - if ( explanation.isNull() ) - KMessageBox::sorry( 0, text, title ); - else - KMessageBox::detailedSorry( 0, text, explanation, title ); -} - -void KigFilter::notSupported( const TQString& file, const TQString& explanation ) const -{ - KMessageBox::detailedSorry( 0, - i18n( "Kig cannot open the file \"%1\"." ).arg( file ), - explanation, i18n( "Not Supported" ) ); -} - -void KigFilter::warning( const TQString& explanation ) const -{ - KMessageBox::information( 0, explanation ); -} - -bool KigFilters::save( const KigDocument& data, const TQString& tofile ) -{ - return KigFilterNative::instance()->save( data, tofile ); -} - -/* -bool KigFilters::save( const KigDocument& data, TQTextStream& stream ) -{ - return KigFilterNative::instance()->save( data, stream ); -} -*/ diff --git a/kig/filters/filter.cpp b/kig/filters/filter.cpp new file mode 100644 index 00000000..6a543430 --- /dev/null +++ b/kig/filters/filter.cpp @@ -0,0 +1,114 @@ +/** + This file is part of Kig, a KDE program for Interactive Geometry... + 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 "filter.h" + +#include "kgeo-filter.h" +#include "cabri-filter.h" +#include "native-filter.h" +#include "kseg-filter.h" +#include "drgeo-filter.h" + +#include +#include + +KigFilters* KigFilters::sThis; + +KigFilter* KigFilters::find(const TQString& mime) +{ + for (vect::iterator i = mFilters.begin(); i != mFilters.end(); ++i) + { + if ((*i)->supportMime(mime)) return *i; + }; + return 0; +} + +KigFilters::KigFilters() +{ + mFilters.push_back( KigFilterKGeo::instance() ); + mFilters.push_back( KigFilterKSeg::instance() ); + mFilters.push_back( KigFilterCabri::instance() ); + mFilters.push_back( KigFilterNative::instance() ); + mFilters.push_back( KigFilterDrgeo::instance() ); +} + +KigFilters* KigFilters::instance() +{ + return sThis ? sThis : ( sThis = new KigFilters() ); +} + +KigFilter::KigFilter() +{ +} + +KigFilter::~KigFilter() +{ +} + +bool KigFilter::supportMime( const TQString& ) +{ + return false; +} + +void KigFilter::fileNotFound( const TQString& file ) const +{ + KMessageBox::sorry( 0, + i18n( "The file \"%1\" could not be opened. " + "This probably means that it does not " + "exist, or that it cannot be opened due to " + "its permissions" ).arg( file ) ); +} + +void KigFilter::parseError( const TQString& file, const TQString& explanation ) const +{ + const TQString text = + i18n( "An error was encountered while parsing the file \"%1\". It " + "cannot be opened." ).arg( file ); + const TQString title = i18n( "Parse Error" ); + + if ( explanation.isNull() ) + KMessageBox::sorry( 0, text, title ); + else + KMessageBox::detailedSorry( 0, text, explanation, title ); +} + +void KigFilter::notSupported( const TQString& file, const TQString& explanation ) const +{ + KMessageBox::detailedSorry( 0, + i18n( "Kig cannot open the file \"%1\"." ).arg( file ), + explanation, i18n( "Not Supported" ) ); +} + +void KigFilter::warning( const TQString& explanation ) const +{ + KMessageBox::information( 0, explanation ); +} + +bool KigFilters::save( const KigDocument& data, const TQString& tofile ) +{ + return KigFilterNative::instance()->save( data, tofile ); +} + +/* +bool KigFilters::save( const KigDocument& data, TQTextStream& stream ) +{ + return KigFilterNative::instance()->save( data, stream ); +} +*/ diff --git a/kig/filters/filters-common.cc b/kig/filters/filters-common.cc deleted file mode 100644 index 4ba24e9f..00000000 --- a/kig/filters/filters-common.cc +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2004 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 "filters-common.h" - -#include - -#include -#include - -#include "../objects/object_calcer.h" -#include "../objects/object_factory.h" - -ObjectTypeCalcer* filtersConstructTextObject( - const Coordinate& c, ObjectCalcer* o, - const TQCString& arg, const KigDocument& doc, bool needframe ) -{ - const ObjectFactory* fact = ObjectFactory::instance(); - ObjectCalcer* propo = fact->propertyObjectCalcer( o, arg ); - propo->calc( doc ); - std::vector args; - args.push_back( propo ); - return fact->labelCalcer( TQString::fromLatin1( "%1" ), c, needframe, - args, doc ); -} diff --git a/kig/filters/filters-common.cpp b/kig/filters/filters-common.cpp new file mode 100644 index 00000000..4ba24e9f --- /dev/null +++ b/kig/filters/filters-common.cpp @@ -0,0 +1,39 @@ +// Copyright (C) 2004 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 "filters-common.h" + +#include + +#include +#include + +#include "../objects/object_calcer.h" +#include "../objects/object_factory.h" + +ObjectTypeCalcer* filtersConstructTextObject( + const Coordinate& c, ObjectCalcer* o, + const TQCString& arg, const KigDocument& doc, bool needframe ) +{ + const ObjectFactory* fact = ObjectFactory::instance(); + ObjectCalcer* propo = fact->propertyObjectCalcer( o, arg ); + propo->calc( doc ); + std::vector args; + args.push_back( propo ); + return fact->labelCalcer( TQString::fromLatin1( "%1" ), c, needframe, + args, doc ); +} diff --git a/kig/filters/imageexporteroptions.cc b/kig/filters/imageexporteroptions.cc deleted file mode 100644 index cd68a0af..00000000 --- a/kig/filters/imageexporteroptions.cc +++ /dev/null @@ -1,57 +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 "imageexporteroptions.h" -#include "imageexporteroptions.moc" - -#include -#include - -#include - -ImageExporterOptions::ImageExporterOptions( TQWidget* parent, const TQSize& s ) - : ImageExporterOptionsBase( parent, "imageexporteroptions" ), msize( s ), - minternallysettingstuff( false ) -{ - keepAspectRatio->setChecked( true ); - connect( WidthInput, TQT_SIGNAL( valueChanged( int ) ), this, TQT_SLOT( slotWidthChanged( int ) ) ); - connect( HeightInput, TQT_SIGNAL( valueChanged( int ) ), this, TQT_SLOT( slotHeightChanged( int ) ) ); -} - -ImageExporterOptions::~ImageExporterOptions() -{ -} - -void ImageExporterOptions::slotWidthChanged( int w ) -{ - if ( ! minternallysettingstuff && keepAspectRatio->isOn() ) - { - minternallysettingstuff = true; - HeightInput->setValue( w * msize.height() / msize.width() ); - minternallysettingstuff = false; - }; -} - -void ImageExporterOptions::slotHeightChanged( int h ) -{ - if ( ! minternallysettingstuff && keepAspectRatio->isOn() ) - { - minternallysettingstuff = true; - WidthInput->setValue( h * msize.width() / msize.height() ); - minternallysettingstuff = false; - }; -} diff --git a/kig/filters/imageexporteroptions.cpp b/kig/filters/imageexporteroptions.cpp new file mode 100644 index 00000000..cd68a0af --- /dev/null +++ b/kig/filters/imageexporteroptions.cpp @@ -0,0 +1,57 @@ +// 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 "imageexporteroptions.h" +#include "imageexporteroptions.moc" + +#include +#include + +#include + +ImageExporterOptions::ImageExporterOptions( TQWidget* parent, const TQSize& s ) + : ImageExporterOptionsBase( parent, "imageexporteroptions" ), msize( s ), + minternallysettingstuff( false ) +{ + keepAspectRatio->setChecked( true ); + connect( WidthInput, TQT_SIGNAL( valueChanged( int ) ), this, TQT_SLOT( slotWidthChanged( int ) ) ); + connect( HeightInput, TQT_SIGNAL( valueChanged( int ) ), this, TQT_SLOT( slotHeightChanged( int ) ) ); +} + +ImageExporterOptions::~ImageExporterOptions() +{ +} + +void ImageExporterOptions::slotWidthChanged( int w ) +{ + if ( ! minternallysettingstuff && keepAspectRatio->isOn() ) + { + minternallysettingstuff = true; + HeightInput->setValue( w * msize.height() / msize.width() ); + minternallysettingstuff = false; + }; +} + +void ImageExporterOptions::slotHeightChanged( int h ) +{ + if ( ! minternallysettingstuff && keepAspectRatio->isOn() ) + { + minternallysettingstuff = true; + WidthInput->setValue( h * msize.width() / msize.height() ); + minternallysettingstuff = false; + }; +} diff --git a/kig/filters/kgeo-filter.cc b/kig/filters/kgeo-filter.cc deleted file mode 100644 index 8849256b..00000000 --- a/kig/filters/kgeo-filter.cc +++ /dev/null @@ -1,374 +0,0 @@ -/** - This file is part of Kig, a KDE program for Interactive Geometry... - 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 "kgeo-filter.h" - -#include "kgeo-resource.h" -#include "filters-common.h" - -#include "../kig/kig_part.h" -#include "../kig/kig_document.h" -#include "../objects/angle_type.h" -#include "../objects/bogus_imp.h" -#include "../objects/circle_imp.h" -#include "../objects/circle_type.h" -#include "../objects/intersection_types.h" -#include "../objects/line_type.h" -#include "../objects/object_calcer.h" -#include "../objects/object_drawer.h" -#include "../objects/object_factory.h" -#include "../objects/object_holder.h" -#include "../objects/other_type.h" -#include "../objects/point_imp.h" -#include "../objects/point_type.h" -#include "../objects/text_type.h" -#include "../objects/transform_types.h" -#include "../objects/vector_type.h" - -#include - -#include -#include - -bool KigFilterKGeo::supportMime( const TQString& mime ) -{ - return mime == "application/x-kgeo"; -} - -KigDocument* KigFilterKGeo::load( const TQString& sFrom ) -{ - // kgeo uses a KSimpleConfig to save its contents... - KSimpleConfig config ( sFrom ); - - loadMetrics ( &config ); - return loadObjects ( sFrom, &config ); -} - -void KigFilterKGeo::loadMetrics(KSimpleConfig* c ) -{ - c->setGroup("Main"); - xMax = c->readNumEntry("XMax", 16); - yMax = c->readNumEntry("YMax", 11); - grid = c->readBoolEntry( "Grid", true ); - axes = c->readBoolEntry( "Axes", true ); - // the rest is not relevant to us (yet ?)... -} - -struct KGeoHierarchyElement -{ - int id; - std::vector parents; -}; - -static void visitElem( std::vector& ret, - const std::vector& elems, - std::vector& seen, - int i ) -{ - if ( !seen[i] ) - { - for ( uint j = 0; j < elems[i].parents.size(); ++j ) - visitElem( ret, elems, seen, elems[i].parents[j] ); - ret.push_back( elems[i] ); - seen[i] = true; - }; -} - -static std::vector sortElems( const std::vector elems ) -{ - std::vector ret; - std::vector seenElems( elems.size(), false ); - for ( uint i = 0; i < elems.size(); ++i ) - visitElem( ret, elems, seenElems, i ); - return ret; -} - -KigDocument* KigFilterKGeo::loadObjects( const TQString& file, KSimpleConfig* c ) -{ - KigDocument* ret = new KigDocument(); - - using namespace std; - - TQString group; - bool ok = true; - c->setGroup("Main"); - int number = c->readNumEntry ("Number"); - - // first we determine the parent relationships, and sort the - // elements in an order that we can be sure all of an object's - // parents will have been handled before it is handled itself.. - // ( aka topological sort of the parent relations graph.. - std::vector elems; - elems.reserve( number ); - - for ( int i = 0; i < number; ++i ) - { - KGeoHierarchyElement elem; - elem.id = i; - group.setNum( i + 1 ); - group.prepend( "Object " ); - c->setGroup( group ); - TQStrList parents; - c->readListEntry( "Parents", parents ); - elems.push_back( elem ); - for ( const char* parent = parents.first(); parent; parent = parents.next() ) - { - int parentIndex = TQString::fromLatin1( parent ).toInt( &ok ); - if ( ! ok ) KIG_FILTER_PARSE_ERROR; - if ( parentIndex != 0 ) - elems[i].parents.push_back( parentIndex - 1 ); - }; - }; - - std::vector sortedElems = sortElems( elems ); - std::vector os; - os.resize( number, 0 ); - const ObjectFactory* factory = ObjectFactory::instance(); - - // now we iterate over the elems again in the newly determined - // order.. - for ( uint i = 0; i < sortedElems.size(); ++i ) - { - const KGeoHierarchyElement& e = sortedElems[i]; - int id = e.id; - group.setNum( id + 1 ); - group.prepend( "Object " ); - c->setGroup( group ); - int objID = c->readNumEntry( "Geo" ); - - std::vector parents; - for ( uint j = 0; j < e.parents.size(); ++j ) - { - int parentid = e.parents[j]; - parents.push_back( os[parentid]->calcer() ); - }; - - ObjectCalcer* o = 0; - switch (objID) - { - case ID_point: - { - // fetch the coordinates... - TQString strX = c->readEntry("TQPointX"); - TQString strY = c->readEntry("TQPointY"); - double x = strX.toDouble(&ok); - if (!ok) KIG_FILTER_PARSE_ERROR; - double y = strY.toDouble(&ok); - if (!ok) KIG_FILTER_PARSE_ERROR; - Coordinate m( x, y ); - uint nparents = parents.size(); - if ( nparents == 0 ) - o = factory->fixedPointCalcer( m ); - else if ( nparents == 1 ) - o = factory->constrainedPointCalcer( parents[0], m, *ret ); - else - KIG_FILTER_PARSE_ERROR; - break; - } - case ID_segment: - { - o = new ObjectTypeCalcer( SegmentABType::instance(), parents ); - break; - } - case ID_circle: - { - o = new ObjectTypeCalcer( CircleBCPType::instance(), parents ); - break; - } - case ID_line: - { - o = new ObjectTypeCalcer( LineABType::instance(), parents ); - break; - } - case ID_bisection: - { - // if this is the bisection of two points, first build a segment - // between them.. - if ( parents.size() == 2 ) - { - ObjectTypeCalcer* seg = new ObjectTypeCalcer( SegmentABType::instance(), parents ); - parents.clear(); - parents.push_back( seg ); - } - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - o = factory->propertyObjectCalcer( parents[0], "mid-point" ); - break; - }; - case ID_perpendicular: - { - o = new ObjectTypeCalcer( LinePerpendLPType::instance(), parents ); - break; - } - case ID_parallel: - { - o = new ObjectTypeCalcer( LineParallelLPType::instance(), parents ); - break; - } - case ID_vector: - { - o = new ObjectTypeCalcer( VectorType::instance(), parents ); - break; - } - case ID_ray: - { - o = new ObjectTypeCalcer( RayABType::instance(), parents ); - break; - } - case ID_move: - { - o = new ObjectTypeCalcer( TranslatedType::instance(), parents ); - break; - } - case ID_mirrorPoint: - { - o = new ObjectTypeCalcer( PointReflectionType::instance(), parents ); - break; - } - case ID_pointOfConc: - { - o = new ObjectTypeCalcer( LineLineIntersectionType::instance(), parents ); - break; - } - case ID_text: - { - bool frame = c->readBoolEntry( "Frame" ); - double x = c->readDoubleNumEntry( "TextRectCenterX" ); - double y = c->readDoubleNumEntry( "TextRectCenterY" ); - TQString text = c->readEntry( "TextRectEntry" ); - double height = c->readNumEntry( "TextRectHeight" ); - double width = c->readNumEntry( "TextRectWidth" ); - // we don't want the center, but the top left.. - x -= width / 80; - y -= height / 80; - o = factory->labelCalcer( - text, Coordinate( x, y ), frame, std::vector(), *ret ); - break; - } - case ID_fixedCircle: - { - double r = c->readDoubleNumEntry( "Radius" ); - parents.push_back( new ObjectConstCalcer( new DoubleImp( r ) ) ); - o = new ObjectTypeCalcer( CircleBPRType::instance(), parents ); - break; - } - case ID_angle: - { - if ( parents.size() == 3 ) - { - ObjectTypeCalcer* ao = new ObjectTypeCalcer( AngleType::instance(), parents ); - ao->calc( *ret ); - parents.clear(); - parents.push_back( ao ); - }; - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - ObjectCalcer* angle = parents[0]; - parents.clear(); - const Coordinate c = - static_cast( angle->parents()[1]->imp() )->coordinate(); - o = filtersConstructTextObject( c, angle, "angle-degrees", *ret, true ); - break; - } - case ID_distance: - { - if ( parents.size() != 2 ) KIG_FILTER_PARSE_ERROR; - ObjectTypeCalcer* segment = new ObjectTypeCalcer( SegmentABType::instance(), parents ); - segment->calc( *ret ); - Coordinate m = ( static_cast( parents[0]->imp() )->coordinate() + - static_cast( parents[1]->imp() )->coordinate() ) / 2; - o = filtersConstructTextObject( m, segment, "length", *ret, true ); - break; - } - case ID_arc: - { - o = new ObjectTypeCalcer( AngleType::instance(), parents ); - break; - } - case ID_area: - { - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - const CircleImp* circle = static_cast( parents[0]->imp() ); - const Coordinate c = circle->center() + Coordinate( circle->radius(), 0 ); - o = filtersConstructTextObject( c, parents[0], "surface", *ret, true ); - break; - } - case ID_slope: - { - // if parents contains a segment, line, vector or whatever, we - // take its parents cause we want points.. - if ( parents.size() == 1 ) parents = parents[0]->parents(); - if ( parents.size() != 2 ) KIG_FILTER_PARSE_ERROR; - const Coordinate c = ( - static_cast( parents[0]->imp() )->coordinate() + - static_cast( parents[1]->imp() )->coordinate() ) / 2; - ObjectTypeCalcer* line = new ObjectTypeCalcer( LineABType::instance(), parents ); - line->calc( *ret ); - o = filtersConstructTextObject( c, line, "slope", *ret, true ); - break; - } - case ID_circumference: - { - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - const CircleImp* c = static_cast( parents[0]->imp() ); - const Coordinate m = c->center() + Coordinate( c->radius(), 0 ); - o = filtersConstructTextObject( m, parents[0], "circumference", *ret, true ); - break; - } - case ID_rotation: - { - // in kig, the rotated object should be last.. - ObjectCalcer* t = parents[2]; - parents[2] = parents[0]; - parents[0] = t; - o = new ObjectTypeCalcer( RotationType::instance(), parents ); - break; - } - default: - KIG_FILTER_PARSE_ERROR; - }; - - // set the color... - TQColor co = c->readColorEntry( "Color" ); - if( !co.isValid() ) - co = TQt::blue; - ObjectDrawer* d = new ObjectDrawer( co ); - - os[i] = new ObjectHolder( o, d ); - os[i]->calc( *ret ); - }; // for loop (creating KGeoHierarchyElements.. - - ret->addObjects( os ); - ret->setGrid( grid ); - ret->setAxes( axes ); - return ret; -} - -KigFilterKGeo::KigFilterKGeo() -{ -} - -KigFilterKGeo::~KigFilterKGeo() -{ -} - -KigFilterKGeo* KigFilterKGeo::instance() -{ - static KigFilterKGeo f; - return &f; -} diff --git a/kig/filters/kgeo-filter.cpp b/kig/filters/kgeo-filter.cpp new file mode 100644 index 00000000..8849256b --- /dev/null +++ b/kig/filters/kgeo-filter.cpp @@ -0,0 +1,374 @@ +/** + This file is part of Kig, a KDE program for Interactive Geometry... + 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 "kgeo-filter.h" + +#include "kgeo-resource.h" +#include "filters-common.h" + +#include "../kig/kig_part.h" +#include "../kig/kig_document.h" +#include "../objects/angle_type.h" +#include "../objects/bogus_imp.h" +#include "../objects/circle_imp.h" +#include "../objects/circle_type.h" +#include "../objects/intersection_types.h" +#include "../objects/line_type.h" +#include "../objects/object_calcer.h" +#include "../objects/object_drawer.h" +#include "../objects/object_factory.h" +#include "../objects/object_holder.h" +#include "../objects/other_type.h" +#include "../objects/point_imp.h" +#include "../objects/point_type.h" +#include "../objects/text_type.h" +#include "../objects/transform_types.h" +#include "../objects/vector_type.h" + +#include + +#include +#include + +bool KigFilterKGeo::supportMime( const TQString& mime ) +{ + return mime == "application/x-kgeo"; +} + +KigDocument* KigFilterKGeo::load( const TQString& sFrom ) +{ + // kgeo uses a KSimpleConfig to save its contents... + KSimpleConfig config ( sFrom ); + + loadMetrics ( &config ); + return loadObjects ( sFrom, &config ); +} + +void KigFilterKGeo::loadMetrics(KSimpleConfig* c ) +{ + c->setGroup("Main"); + xMax = c->readNumEntry("XMax", 16); + yMax = c->readNumEntry("YMax", 11); + grid = c->readBoolEntry( "Grid", true ); + axes = c->readBoolEntry( "Axes", true ); + // the rest is not relevant to us (yet ?)... +} + +struct KGeoHierarchyElement +{ + int id; + std::vector parents; +}; + +static void visitElem( std::vector& ret, + const std::vector& elems, + std::vector& seen, + int i ) +{ + if ( !seen[i] ) + { + for ( uint j = 0; j < elems[i].parents.size(); ++j ) + visitElem( ret, elems, seen, elems[i].parents[j] ); + ret.push_back( elems[i] ); + seen[i] = true; + }; +} + +static std::vector sortElems( const std::vector elems ) +{ + std::vector ret; + std::vector seenElems( elems.size(), false ); + for ( uint i = 0; i < elems.size(); ++i ) + visitElem( ret, elems, seenElems, i ); + return ret; +} + +KigDocument* KigFilterKGeo::loadObjects( const TQString& file, KSimpleConfig* c ) +{ + KigDocument* ret = new KigDocument(); + + using namespace std; + + TQString group; + bool ok = true; + c->setGroup("Main"); + int number = c->readNumEntry ("Number"); + + // first we determine the parent relationships, and sort the + // elements in an order that we can be sure all of an object's + // parents will have been handled before it is handled itself.. + // ( aka topological sort of the parent relations graph.. + std::vector elems; + elems.reserve( number ); + + for ( int i = 0; i < number; ++i ) + { + KGeoHierarchyElement elem; + elem.id = i; + group.setNum( i + 1 ); + group.prepend( "Object " ); + c->setGroup( group ); + TQStrList parents; + c->readListEntry( "Parents", parents ); + elems.push_back( elem ); + for ( const char* parent = parents.first(); parent; parent = parents.next() ) + { + int parentIndex = TQString::fromLatin1( parent ).toInt( &ok ); + if ( ! ok ) KIG_FILTER_PARSE_ERROR; + if ( parentIndex != 0 ) + elems[i].parents.push_back( parentIndex - 1 ); + }; + }; + + std::vector sortedElems = sortElems( elems ); + std::vector os; + os.resize( number, 0 ); + const ObjectFactory* factory = ObjectFactory::instance(); + + // now we iterate over the elems again in the newly determined + // order.. + for ( uint i = 0; i < sortedElems.size(); ++i ) + { + const KGeoHierarchyElement& e = sortedElems[i]; + int id = e.id; + group.setNum( id + 1 ); + group.prepend( "Object " ); + c->setGroup( group ); + int objID = c->readNumEntry( "Geo" ); + + std::vector parents; + for ( uint j = 0; j < e.parents.size(); ++j ) + { + int parentid = e.parents[j]; + parents.push_back( os[parentid]->calcer() ); + }; + + ObjectCalcer* o = 0; + switch (objID) + { + case ID_point: + { + // fetch the coordinates... + TQString strX = c->readEntry("TQPointX"); + TQString strY = c->readEntry("TQPointY"); + double x = strX.toDouble(&ok); + if (!ok) KIG_FILTER_PARSE_ERROR; + double y = strY.toDouble(&ok); + if (!ok) KIG_FILTER_PARSE_ERROR; + Coordinate m( x, y ); + uint nparents = parents.size(); + if ( nparents == 0 ) + o = factory->fixedPointCalcer( m ); + else if ( nparents == 1 ) + o = factory->constrainedPointCalcer( parents[0], m, *ret ); + else + KIG_FILTER_PARSE_ERROR; + break; + } + case ID_segment: + { + o = new ObjectTypeCalcer( SegmentABType::instance(), parents ); + break; + } + case ID_circle: + { + o = new ObjectTypeCalcer( CircleBCPType::instance(), parents ); + break; + } + case ID_line: + { + o = new ObjectTypeCalcer( LineABType::instance(), parents ); + break; + } + case ID_bisection: + { + // if this is the bisection of two points, first build a segment + // between them.. + if ( parents.size() == 2 ) + { + ObjectTypeCalcer* seg = new ObjectTypeCalcer( SegmentABType::instance(), parents ); + parents.clear(); + parents.push_back( seg ); + } + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + o = factory->propertyObjectCalcer( parents[0], "mid-point" ); + break; + }; + case ID_perpendicular: + { + o = new ObjectTypeCalcer( LinePerpendLPType::instance(), parents ); + break; + } + case ID_parallel: + { + o = new ObjectTypeCalcer( LineParallelLPType::instance(), parents ); + break; + } + case ID_vector: + { + o = new ObjectTypeCalcer( VectorType::instance(), parents ); + break; + } + case ID_ray: + { + o = new ObjectTypeCalcer( RayABType::instance(), parents ); + break; + } + case ID_move: + { + o = new ObjectTypeCalcer( TranslatedType::instance(), parents ); + break; + } + case ID_mirrorPoint: + { + o = new ObjectTypeCalcer( PointReflectionType::instance(), parents ); + break; + } + case ID_pointOfConc: + { + o = new ObjectTypeCalcer( LineLineIntersectionType::instance(), parents ); + break; + } + case ID_text: + { + bool frame = c->readBoolEntry( "Frame" ); + double x = c->readDoubleNumEntry( "TextRectCenterX" ); + double y = c->readDoubleNumEntry( "TextRectCenterY" ); + TQString text = c->readEntry( "TextRectEntry" ); + double height = c->readNumEntry( "TextRectHeight" ); + double width = c->readNumEntry( "TextRectWidth" ); + // we don't want the center, but the top left.. + x -= width / 80; + y -= height / 80; + o = factory->labelCalcer( + text, Coordinate( x, y ), frame, std::vector(), *ret ); + break; + } + case ID_fixedCircle: + { + double r = c->readDoubleNumEntry( "Radius" ); + parents.push_back( new ObjectConstCalcer( new DoubleImp( r ) ) ); + o = new ObjectTypeCalcer( CircleBPRType::instance(), parents ); + break; + } + case ID_angle: + { + if ( parents.size() == 3 ) + { + ObjectTypeCalcer* ao = new ObjectTypeCalcer( AngleType::instance(), parents ); + ao->calc( *ret ); + parents.clear(); + parents.push_back( ao ); + }; + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + ObjectCalcer* angle = parents[0]; + parents.clear(); + const Coordinate c = + static_cast( angle->parents()[1]->imp() )->coordinate(); + o = filtersConstructTextObject( c, angle, "angle-degrees", *ret, true ); + break; + } + case ID_distance: + { + if ( parents.size() != 2 ) KIG_FILTER_PARSE_ERROR; + ObjectTypeCalcer* segment = new ObjectTypeCalcer( SegmentABType::instance(), parents ); + segment->calc( *ret ); + Coordinate m = ( static_cast( parents[0]->imp() )->coordinate() + + static_cast( parents[1]->imp() )->coordinate() ) / 2; + o = filtersConstructTextObject( m, segment, "length", *ret, true ); + break; + } + case ID_arc: + { + o = new ObjectTypeCalcer( AngleType::instance(), parents ); + break; + } + case ID_area: + { + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + const CircleImp* circle = static_cast( parents[0]->imp() ); + const Coordinate c = circle->center() + Coordinate( circle->radius(), 0 ); + o = filtersConstructTextObject( c, parents[0], "surface", *ret, true ); + break; + } + case ID_slope: + { + // if parents contains a segment, line, vector or whatever, we + // take its parents cause we want points.. + if ( parents.size() == 1 ) parents = parents[0]->parents(); + if ( parents.size() != 2 ) KIG_FILTER_PARSE_ERROR; + const Coordinate c = ( + static_cast( parents[0]->imp() )->coordinate() + + static_cast( parents[1]->imp() )->coordinate() ) / 2; + ObjectTypeCalcer* line = new ObjectTypeCalcer( LineABType::instance(), parents ); + line->calc( *ret ); + o = filtersConstructTextObject( c, line, "slope", *ret, true ); + break; + } + case ID_circumference: + { + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + const CircleImp* c = static_cast( parents[0]->imp() ); + const Coordinate m = c->center() + Coordinate( c->radius(), 0 ); + o = filtersConstructTextObject( m, parents[0], "circumference", *ret, true ); + break; + } + case ID_rotation: + { + // in kig, the rotated object should be last.. + ObjectCalcer* t = parents[2]; + parents[2] = parents[0]; + parents[0] = t; + o = new ObjectTypeCalcer( RotationType::instance(), parents ); + break; + } + default: + KIG_FILTER_PARSE_ERROR; + }; + + // set the color... + TQColor co = c->readColorEntry( "Color" ); + if( !co.isValid() ) + co = TQt::blue; + ObjectDrawer* d = new ObjectDrawer( co ); + + os[i] = new ObjectHolder( o, d ); + os[i]->calc( *ret ); + }; // for loop (creating KGeoHierarchyElements.. + + ret->addObjects( os ); + ret->setGrid( grid ); + ret->setAxes( axes ); + return ret; +} + +KigFilterKGeo::KigFilterKGeo() +{ +} + +KigFilterKGeo::~KigFilterKGeo() +{ +} + +KigFilterKGeo* KigFilterKGeo::instance() +{ + static KigFilterKGeo f; + return &f; +} diff --git a/kig/filters/kseg-filter.cc b/kig/filters/kseg-filter.cc deleted file mode 100644 index 1567ed37..00000000 --- a/kig/filters/kseg-filter.cc +++ /dev/null @@ -1,679 +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 "kseg-filter.h" - -#include "kseg-defs.h" - -#include "../kig/kig_document.h" -#include "../kig/kig_part.h" -#include "../misc/coordinate.h" -#include "../objects/angle_type.h" -#include "../objects/arc_type.h" -#include "../objects/bogus_imp.h" -#include "../objects/circle_type.h" -#include "../objects/conic_imp.h" -#include "../objects/conic_types.h" -#include "../objects/intersection_types.h" -#include "../objects/line_imp.h" -#include "../objects/line_type.h" -#include "../objects/object_calcer.h" -#include "../objects/object_drawer.h" -#include "../objects/object_factory.h" -#include "../objects/object_holder.h" -#include "../objects/other_imp.h" -#include "../objects/other_type.h" -#include "../objects/point_imp.h" -#include "../objects/point_type.h" -#include "../objects/polygon_type.h" -#include "../objects/transform_types.h" -#include "../objects/vector_type.h" - -#include -#include -#include -#include -#include -#include - -#include - -KigFilterKSeg::KigFilterKSeg() -{ -} - -KigFilterKSeg::~KigFilterKSeg() -{ -} - -bool KigFilterKSeg::supportMime( const TQString& mime ) -{ - return mime == "application/x-kseg"; -} - -struct drawstyle -{ - TQ_INT8 pointstyle; - TQFont font; - TQPen pen; - TQBrush brush; -}; - -static Coordinate readKSegCoordinate( TQDataStream& stream ) -{ - // read the coord.. - float inx, iny; - stream >> inx >> iny; - // KSeg uses a coordinate system, where the topleft is (0,0), and - // the bottom right is the widget coordinate in the window: if the - // KSeg window had a width of 600 pixels and a height of 600, then - // the bottom right will be at (600,600). We assume a window of - // such a height here, and transform it into Kig Coordinates. This - // function is quite similar to ScreenInfo::fromScreen, and it's - // basically a simple modification of that code to floats.. - - // invert the y-axis: 0 is at the bottom ! - Coordinate t( inx, 600 - iny ); - t *= 14; - t /= 600; - return t + Coordinate( -7, -7 ); -} - -static ObjectTypeCalcer* intersectionPoint( const std::vector& parents, int which ) -{ - if ( parents.size() != 2 ) return 0; - int nlines = 0; - int nconics = 0; - int narcs = 0; - for ( int i = 0; i < 2; ++i ) - { - if ( parents[i]->imp()->inherits( AbstractLineImp::stype() ) ) ++nlines; - else if ( parents[i]->imp()->inherits( ConicImp::stype() ) ) ++nconics; - else if ( parents[i]->imp()->inherits( ArcImp::stype() ) ) ++narcs; - else return 0; - }; - if ( nlines == 2 ) - return which == -1 ? new ObjectTypeCalcer( LineLineIntersectionType::instance(), parents ) : 0; - else if ( nlines == 1 && nconics == 1 ) - { - std::vector intparents( parents ); - intparents.push_back( new ObjectConstCalcer( new IntImp( which ) ) ); - return new ObjectTypeCalcer( ConicLineIntersectionType::instance(), intparents ); - } - else if ( nlines == 0 && nconics == 2 ) - { - std::vector rparents( parents ); - rparents.push_back( new ObjectConstCalcer( new IntImp( 1 ) ) ); - rparents.push_back( new ObjectConstCalcer( new IntImp( 1 ) ) ); - rparents.push_back( new ObjectTypeCalcer( ConicRadicalType::instance(), rparents ) ); - std::vector iparents; - iparents.push_back( parents[0] ); - iparents.push_back( rparents.back() ); - iparents.push_back( new ObjectConstCalcer( new IntImp( which ) ) ); - return new ObjectTypeCalcer( ConicLineIntersectionType::instance(), iparents ); - } - else if ( nlines == 1 && narcs == 1 ) - { - std::vector intparents( parents ); - intparents.push_back( new ObjectConstCalcer( new IntImp( which ) ) ); - return new ObjectTypeCalcer( ArcLineIntersectionType::instance(), intparents ); - } - else return 0; -} - -ObjectCalcer* KigFilterKSeg::transformObject( const TQString& file, KigDocument& kigdoc, - std::vector& parents, - int subtype, bool& ok ) -{ - ok = true; - ObjectCalcer* retobj = 0; - switch( subtype ) - { - case G_TRANSLATED: - { - std::vector vectorparents( parents.begin() + 1, parents.end() ); - ObjectTypeCalcer* vector = new ObjectTypeCalcer( VectorType::instance(), vectorparents ); - vector->calc( kigdoc ); - - std::vector transparents; - transparents.push_back( parents[0] ); - transparents.push_back( vector ); - retobj = new ObjectTypeCalcer( TranslatedType::instance(), transparents ); - break; - } - case G_ROTATED: - { - std::vector angleparents( parents.begin() + 2, parents.end() ); - ObjectTypeCalcer* angle = new ObjectTypeCalcer( AngleType::instance(), angleparents ); - angle->calc( kigdoc ); - - std::vector rotparents; - rotparents.push_back( parents[0] ); - rotparents.push_back( parents[1] ); - rotparents.push_back( angle ); - retobj = new ObjectTypeCalcer( RotationType::instance(), rotparents ); - break; - } - case G_SCALED: - { - if ( parents.size() == 4 ) - { - retobj = new ObjectTypeCalcer( ScalingOverCenter2Type::instance(), parents ); - } - else - { - // TODO - notSupported( file, i18n( "This KSeg document uses a scaling " - "transformation, which Kig currently " - "cannot import." ) ); - ok = false; - return 0; - } - break; - } - case G_REFLECTED: - { - std::vector mirparents( parents.begin(), parents.end() ); - retobj = new ObjectTypeCalcer( LineReflectionType::instance(), mirparents ); - break; - } - } - - return retobj; -} - -KigDocument* KigFilterKSeg::load( const TQString& file ) -{ - TQFile ffile( file ); - if ( ! ffile.open( IO_ReadOnly ) ) - { - fileNotFound( file ); - return 0; - }; - - KigDocument* retdoc = new KigDocument(); - - TQDataStream fstream( &ffile ); - - TQString versionstring; - fstream >> versionstring; - if ( !versionstring.startsWith( "KSeg Document Version " ) ) - KIG_FILTER_PARSE_ERROR; - - TQByteArray array; - fstream >> array; - TQBuffer buf( array ); - buf.open( IO_ReadOnly ); - TQDataStream stream( &buf ); - - stream.setVersion( 3 ); - - // G_drawstyles: - short numstyles; - stream >> numstyles; - std::vector drawstyles( numstyles ); - for ( short i = 0; i < numstyles; ++i ) - { - stream >> drawstyles[i].pointstyle; - stream >> drawstyles[i].font; - stream >> drawstyles[i].pen; - stream >> drawstyles[i].brush; - }; - - std::vector ret; - std::vector ret2; - - // G_refs - unsigned int count; - stream >> count; - - ret.resize( count, 0 ); - const ObjectFactory* fact = ObjectFactory::instance(); - - // KSeg topologically sorts the objects before saving, that means we - // can read the entire file in one iteration.. - for ( uint i = 0; i < count; ++i ) - { - short styleid; - stream >> styleid; - short nparents; - stream >> nparents; - std::vector parents( nparents, 0 ); - for ( short j = 0; j < nparents; ++j ) - { - int parent; - stream >> parent; - parents[j] = ret[parent]->calcer(); - }; - - // read the object.. - short info; - stream >> info; - int type = 1 << (info & 31); - info >>= 5; - int descendtype = (info & 15); - info >>= 4; - bool visible = info & 1; - bool labelVisible = info & 2; - bool given = info & 4; - bool final = info & 8; - - // avoid g++ warnings about unused vars.. - // this doesn't really do anything.. - (void) given; - (void) final; - - drawstyle style = drawstyles[styleid]; - - if ( type == G_LOOP ) continue; - // read the label.. - TQString labeltext; - stream >> labeltext; - Coordinate relcoord = readKSegCoordinate( stream ); - // shut up gcc - (void) relcoord; - if ( type & G_CURVE ) - { - Coordinate relcurvecoord = readKSegCoordinate( stream ); - // shut up gcc - (void) relcurvecoord; - }; - - // now load the object data.. - ObjectHolder* object = 0; - ObjectCalcer* o = 0; - bool ok = true; - - TQColor color = style.pen.color(); - int width = style.pen.width(); - -/* - kdDebug() << "type: " << type << endl - << "descendtype: " << descendtype << endl - << "label: " << labeltext << endl; -//*/ - - switch ( type ) - { - case G_POINT: - { - switch( descendtype ) - { - case G_TRANSLATED: - case G_ROTATED: - case G_SCALED: - case G_REFLECTED: - { - o = transformObject( file, *retdoc, parents, descendtype, ok ); - break; - } - case G_FREE_POINT: - { - // fixed point - if ( nparents != 0 ) KIG_FILTER_PARSE_ERROR; - Coordinate c = readKSegCoordinate( stream ); - o = fact->fixedPointCalcer( c ); - break; - } - case G_CONSTRAINED_POINT: - { - // constrained point - double p; - stream >> p; - if ( nparents != 1 ) KIG_FILTER_PARSE_ERROR; - ObjectCalcer* parent = parents[0]; - assert( parent ); - o = fact->constrainedPointCalcer( parent, p ); - break; - } - case G_INTERSECTION_POINT: - { - // KSeg has somewhat weird intersection objects.. - // for all objects G_INTERSECTION_POINT gets the - // first intersection of its parents, G_INTERSECTION2_POINT - // represents the second, if present. - o = intersectionPoint( parents, -1 ); - if ( ! o ) KIG_FILTER_PARSE_ERROR; - break; - } - case G_INTERSECTION2_POINT: - { - o = intersectionPoint( parents, 1 ); - if ( ! o ) KIG_FILTER_PARSE_ERROR; - break; - } - case G_MID_POINT: - { - // midpoint of a segment.. - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - if ( !parents[0]->imp()->inherits( SegmentImp::stype() ) ) - KIG_FILTER_PARSE_ERROR; - int index = parents[0]->imp()->propertiesInternalNames().findIndex( "mid-point" ); - assert( index != -1 ); - o = new ObjectPropertyCalcer( parents[0], index ); - break; - } - default: - KIG_FILTER_PARSE_ERROR; - }; - width = style.pointstyle == SMALL_CIRCLE ? 2 : style.pointstyle == MEDIUM_CIRCLE ? 3 : 5; - color = style.brush.color(); - break; - }; - case G_SEGMENT: - { - switch( descendtype ) - { - case G_TRANSLATED: - case G_ROTATED: - case G_SCALED: - case G_REFLECTED: - { - o = transformObject( file, *retdoc, parents, descendtype, ok ); - break; - } - case G_ENDPOINTS_SEGMENT: - { - if ( nparents != 2 ) KIG_FILTER_PARSE_ERROR; - o = new ObjectTypeCalcer( SegmentABType::instance(), parents ); - break; - } - default: - KIG_FILTER_PARSE_ERROR; - } - break; - }; - case G_RAY: - { - switch( descendtype ) - { - case G_TRANSLATED: - case G_ROTATED: - case G_SCALED: - case G_REFLECTED: - { - o = transformObject( file, *retdoc, parents, descendtype, ok ); - break; - } - case G_TWOPOINTS_RAY: - { - if ( nparents != 2 ) KIG_FILTER_PARSE_ERROR; - o = new ObjectTypeCalcer( RayABType::instance(), parents ); - break; - } - case G_BISECTOR_RAY: - { - ObjectTypeCalcer* angle = new ObjectTypeCalcer( HalfAngleType::instance(), parents ); - angle->calc( *retdoc ); - o = fact->propertyObjectCalcer( angle, "angle-bisector" ); - break; - } - default: - KIG_FILTER_PARSE_ERROR; - }; - break; - }; - case G_LINE: - { - switch( descendtype ) - { - case G_TRANSLATED: - case G_ROTATED: - case G_SCALED: - case G_REFLECTED: - { - o = transformObject( file, *retdoc, parents, descendtype, ok ); - break; - } - case G_TWOPOINTS_LINE: - { - if ( nparents != 2 ) KIG_FILTER_PARSE_ERROR; - o = new ObjectTypeCalcer( LineABType::instance(), parents ); - break; - } - case G_PARALLEL_LINE: - { - if ( nparents != 2 ) KIG_FILTER_PARSE_ERROR; - o = new ObjectTypeCalcer( LineParallelLPType::instance(), parents ); - break; - } - case G_PERPENDICULAR_LINE: - { - if ( nparents != 2 ) KIG_FILTER_PARSE_ERROR; - o = new ObjectTypeCalcer( LinePerpendLPType::instance(), parents ); - break; - } - default: - KIG_FILTER_PARSE_ERROR; - }; - break; - }; - case G_CIRCLE: - { - switch( descendtype ) - { - case G_TRANSLATED: - case G_ROTATED: - case G_SCALED: - case G_REFLECTED: - { - o = transformObject( file, *retdoc, parents, descendtype, ok ); - break; - } - case G_CENTERPOINT_CIRCLE: - { - if ( nparents != 2 ) KIG_FILTER_PARSE_ERROR; - o = new ObjectTypeCalcer( CircleBCPType::instance(), parents ); - break; - } - case G_CENTERRADIUS_CIRCLE: - { - ObjectCalcer* point; - ObjectCalcer* segment; - if ( parents[0]->imp()->inherits( PointImp::stype() ) ) - { - point = parents[0]; - segment = parents[1]; - } - else - { - point = parents[1]; - segment = parents[0]; - }; - int index = segment->imp()->propertiesInternalNames().findIndex( "length" ); - if ( index == -1 ) KIG_FILTER_PARSE_ERROR; - ObjectPropertyCalcer* length = new ObjectPropertyCalcer( segment, index ); - length->calc( *retdoc ); - std::vector cparents; - cparents.push_back( point ); - cparents.push_back( length ); - o = new ObjectTypeCalcer( CircleBPRType::instance(), cparents ); - break; - } - default: - KIG_FILTER_PARSE_ERROR; - }; - break; - }; - case G_ARC: - { - switch( descendtype ) - { - case G_TRANSLATED: - case G_ROTATED: - case G_SCALED: - case G_REFLECTED: - { - o = transformObject( file, *retdoc, parents, descendtype, ok ); - break; - } - case G_THREEPOINTS_ARC: - { - if ( nparents != 3 ) KIG_FILTER_PARSE_ERROR; - o = new ObjectTypeCalcer( ArcBTPType::instance(), parents ); - break; - } - default: - KIG_FILTER_PARSE_ERROR; - } - break; - }; - case G_POLYGON: - { - switch( descendtype ) - { - case G_TRANSLATED: - case G_ROTATED: - case G_SCALED: - case G_REFLECTED: - { - o = transformObject( file, *retdoc, parents, descendtype, ok ); - break; - } - default: - { - if ( nparents < 3 ) KIG_FILTER_PARSE_ERROR; - o = new ObjectTypeCalcer( PolygonBNPType::instance(), parents ); - } - } -// default: -// KIG_FILTER_PARSE_ERROR; - break; - }; - case G_CIRCLEINTERIOR: - { - notSupported( file, i18n( "This KSeg file contains a filled circle, " - "which Kig does not currently support." ) ); - return 0; - }; - case G_ARCSECTOR: - { - notSupported( file, i18n( "This KSeg file contains an arc sector, " - "which Kig does not currently support." ) ); - return 0; - }; - case G_ARCSEGMENT: - { - notSupported( file, i18n( "This KSeg file contains an arc segment, " - "which Kig does not currently support." ) ); - return 0; - }; - case G_LOCUS: - { - switch( descendtype ) - { - case G_TRANSLATED: - case G_ROTATED: - case G_SCALED: - case G_REFLECTED: - { - o = transformObject( file, *retdoc, parents, descendtype, ok ); - break; - } - case G_OBJECT_LOCUS: - { - if ( nparents != 2 ) KIG_FILTER_PARSE_ERROR; - o = fact->locusCalcer( parents[0], parents[1] ); - break; - } - default: - KIG_FILTER_PARSE_ERROR; - } - break; - }; - case G_MEASURE: - KIG_FILTER_PARSE_ERROR; - case G_CALCULATE: - KIG_FILTER_PARSE_ERROR; - case G_ANNOTATION: - KIG_FILTER_PARSE_ERROR; - case G_LOOP: - KIG_FILTER_PARSE_ERROR; - default: - KIG_FILTER_PARSE_ERROR; - - } - - // checking if the object was correctly created - if ( ! o ) - { - if ( ok ) - KIG_FILTER_PARSE_ERROR - else - return 0; - } - - ObjectDrawer* d = new ObjectDrawer( color, width, visible, style.pen.style() ); - if ( !labeltext.isEmpty() ) - { - ObjectConstCalcer* name = new ObjectConstCalcer( new StringImp( labeltext ) ); - object = new ObjectHolder( o, d, name ); - } - else - { - object = new ObjectHolder( o, d ); - } - - assert( object ); - ret[i] = object; - object->calc( *retdoc ); - if ( !labeltext.isEmpty() && labelVisible ) - { - std::vector args2; - args2.push_back( object->nameCalcer() ); - ObjectCalcer* oc2 = fact->attachedLabelCalcer( - TQString::fromLatin1( "%1" ), object->calcer(), - static_cast( object->imp() )->coordinate(), - false, args2, *retdoc ); - oc2->calc( *retdoc ); - ObjectDrawer* d2 = new ObjectDrawer( style.pen.color() ); - ObjectHolder* o2 = new ObjectHolder( oc2, d2 ); - ret2.push_back( o2 ); - } - }; - - // selection groups ( we ignore them, but we pretend to read them - // out anyway, so we can find what comes after them.. ) - int selgroupcount; - stream >> selgroupcount; - for ( int i = 0; i < selgroupcount; ++i ) - { - TQString name; - stream >> name; - int size; - stream >> size; - for ( int i = 0; i < size; ++i ) - { - short object; - stream >> object; - (void) object; - }; - }; - - // no more data in the file.. - retdoc->addObjects( ret ); - retdoc->addObjects( ret2 ); - retdoc->setAxes( false ); - retdoc->setGrid( false ); - return retdoc; -} - -KigFilterKSeg* KigFilterKSeg::instance() -{ - static KigFilterKSeg f; - return &f; -} diff --git a/kig/filters/kseg-filter.cpp b/kig/filters/kseg-filter.cpp new file mode 100644 index 00000000..1567ed37 --- /dev/null +++ b/kig/filters/kseg-filter.cpp @@ -0,0 +1,679 @@ +// 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 "kseg-filter.h" + +#include "kseg-defs.h" + +#include "../kig/kig_document.h" +#include "../kig/kig_part.h" +#include "../misc/coordinate.h" +#include "../objects/angle_type.h" +#include "../objects/arc_type.h" +#include "../objects/bogus_imp.h" +#include "../objects/circle_type.h" +#include "../objects/conic_imp.h" +#include "../objects/conic_types.h" +#include "../objects/intersection_types.h" +#include "../objects/line_imp.h" +#include "../objects/line_type.h" +#include "../objects/object_calcer.h" +#include "../objects/object_drawer.h" +#include "../objects/object_factory.h" +#include "../objects/object_holder.h" +#include "../objects/other_imp.h" +#include "../objects/other_type.h" +#include "../objects/point_imp.h" +#include "../objects/point_type.h" +#include "../objects/polygon_type.h" +#include "../objects/transform_types.h" +#include "../objects/vector_type.h" + +#include +#include +#include +#include +#include +#include + +#include + +KigFilterKSeg::KigFilterKSeg() +{ +} + +KigFilterKSeg::~KigFilterKSeg() +{ +} + +bool KigFilterKSeg::supportMime( const TQString& mime ) +{ + return mime == "application/x-kseg"; +} + +struct drawstyle +{ + TQ_INT8 pointstyle; + TQFont font; + TQPen pen; + TQBrush brush; +}; + +static Coordinate readKSegCoordinate( TQDataStream& stream ) +{ + // read the coord.. + float inx, iny; + stream >> inx >> iny; + // KSeg uses a coordinate system, where the topleft is (0,0), and + // the bottom right is the widget coordinate in the window: if the + // KSeg window had a width of 600 pixels and a height of 600, then + // the bottom right will be at (600,600). We assume a window of + // such a height here, and transform it into Kig Coordinates. This + // function is quite similar to ScreenInfo::fromScreen, and it's + // basically a simple modification of that code to floats.. + + // invert the y-axis: 0 is at the bottom ! + Coordinate t( inx, 600 - iny ); + t *= 14; + t /= 600; + return t + Coordinate( -7, -7 ); +} + +static ObjectTypeCalcer* intersectionPoint( const std::vector& parents, int which ) +{ + if ( parents.size() != 2 ) return 0; + int nlines = 0; + int nconics = 0; + int narcs = 0; + for ( int i = 0; i < 2; ++i ) + { + if ( parents[i]->imp()->inherits( AbstractLineImp::stype() ) ) ++nlines; + else if ( parents[i]->imp()->inherits( ConicImp::stype() ) ) ++nconics; + else if ( parents[i]->imp()->inherits( ArcImp::stype() ) ) ++narcs; + else return 0; + }; + if ( nlines == 2 ) + return which == -1 ? new ObjectTypeCalcer( LineLineIntersectionType::instance(), parents ) : 0; + else if ( nlines == 1 && nconics == 1 ) + { + std::vector intparents( parents ); + intparents.push_back( new ObjectConstCalcer( new IntImp( which ) ) ); + return new ObjectTypeCalcer( ConicLineIntersectionType::instance(), intparents ); + } + else if ( nlines == 0 && nconics == 2 ) + { + std::vector rparents( parents ); + rparents.push_back( new ObjectConstCalcer( new IntImp( 1 ) ) ); + rparents.push_back( new ObjectConstCalcer( new IntImp( 1 ) ) ); + rparents.push_back( new ObjectTypeCalcer( ConicRadicalType::instance(), rparents ) ); + std::vector iparents; + iparents.push_back( parents[0] ); + iparents.push_back( rparents.back() ); + iparents.push_back( new ObjectConstCalcer( new IntImp( which ) ) ); + return new ObjectTypeCalcer( ConicLineIntersectionType::instance(), iparents ); + } + else if ( nlines == 1 && narcs == 1 ) + { + std::vector intparents( parents ); + intparents.push_back( new ObjectConstCalcer( new IntImp( which ) ) ); + return new ObjectTypeCalcer( ArcLineIntersectionType::instance(), intparents ); + } + else return 0; +} + +ObjectCalcer* KigFilterKSeg::transformObject( const TQString& file, KigDocument& kigdoc, + std::vector& parents, + int subtype, bool& ok ) +{ + ok = true; + ObjectCalcer* retobj = 0; + switch( subtype ) + { + case G_TRANSLATED: + { + std::vector vectorparents( parents.begin() + 1, parents.end() ); + ObjectTypeCalcer* vector = new ObjectTypeCalcer( VectorType::instance(), vectorparents ); + vector->calc( kigdoc ); + + std::vector transparents; + transparents.push_back( parents[0] ); + transparents.push_back( vector ); + retobj = new ObjectTypeCalcer( TranslatedType::instance(), transparents ); + break; + } + case G_ROTATED: + { + std::vector angleparents( parents.begin() + 2, parents.end() ); + ObjectTypeCalcer* angle = new ObjectTypeCalcer( AngleType::instance(), angleparents ); + angle->calc( kigdoc ); + + std::vector rotparents; + rotparents.push_back( parents[0] ); + rotparents.push_back( parents[1] ); + rotparents.push_back( angle ); + retobj = new ObjectTypeCalcer( RotationType::instance(), rotparents ); + break; + } + case G_SCALED: + { + if ( parents.size() == 4 ) + { + retobj = new ObjectTypeCalcer( ScalingOverCenter2Type::instance(), parents ); + } + else + { + // TODO + notSupported( file, i18n( "This KSeg document uses a scaling " + "transformation, which Kig currently " + "cannot import." ) ); + ok = false; + return 0; + } + break; + } + case G_REFLECTED: + { + std::vector mirparents( parents.begin(), parents.end() ); + retobj = new ObjectTypeCalcer( LineReflectionType::instance(), mirparents ); + break; + } + } + + return retobj; +} + +KigDocument* KigFilterKSeg::load( const TQString& file ) +{ + TQFile ffile( file ); + if ( ! ffile.open( IO_ReadOnly ) ) + { + fileNotFound( file ); + return 0; + }; + + KigDocument* retdoc = new KigDocument(); + + TQDataStream fstream( &ffile ); + + TQString versionstring; + fstream >> versionstring; + if ( !versionstring.startsWith( "KSeg Document Version " ) ) + KIG_FILTER_PARSE_ERROR; + + TQByteArray array; + fstream >> array; + TQBuffer buf( array ); + buf.open( IO_ReadOnly ); + TQDataStream stream( &buf ); + + stream.setVersion( 3 ); + + // G_drawstyles: + short numstyles; + stream >> numstyles; + std::vector drawstyles( numstyles ); + for ( short i = 0; i < numstyles; ++i ) + { + stream >> drawstyles[i].pointstyle; + stream >> drawstyles[i].font; + stream >> drawstyles[i].pen; + stream >> drawstyles[i].brush; + }; + + std::vector ret; + std::vector ret2; + + // G_refs + unsigned int count; + stream >> count; + + ret.resize( count, 0 ); + const ObjectFactory* fact = ObjectFactory::instance(); + + // KSeg topologically sorts the objects before saving, that means we + // can read the entire file in one iteration.. + for ( uint i = 0; i < count; ++i ) + { + short styleid; + stream >> styleid; + short nparents; + stream >> nparents; + std::vector parents( nparents, 0 ); + for ( short j = 0; j < nparents; ++j ) + { + int parent; + stream >> parent; + parents[j] = ret[parent]->calcer(); + }; + + // read the object.. + short info; + stream >> info; + int type = 1 << (info & 31); + info >>= 5; + int descendtype = (info & 15); + info >>= 4; + bool visible = info & 1; + bool labelVisible = info & 2; + bool given = info & 4; + bool final = info & 8; + + // avoid g++ warnings about unused vars.. + // this doesn't really do anything.. + (void) given; + (void) final; + + drawstyle style = drawstyles[styleid]; + + if ( type == G_LOOP ) continue; + // read the label.. + TQString labeltext; + stream >> labeltext; + Coordinate relcoord = readKSegCoordinate( stream ); + // shut up gcc + (void) relcoord; + if ( type & G_CURVE ) + { + Coordinate relcurvecoord = readKSegCoordinate( stream ); + // shut up gcc + (void) relcurvecoord; + }; + + // now load the object data.. + ObjectHolder* object = 0; + ObjectCalcer* o = 0; + bool ok = true; + + TQColor color = style.pen.color(); + int width = style.pen.width(); + +/* + kdDebug() << "type: " << type << endl + << "descendtype: " << descendtype << endl + << "label: " << labeltext << endl; +//*/ + + switch ( type ) + { + case G_POINT: + { + switch( descendtype ) + { + case G_TRANSLATED: + case G_ROTATED: + case G_SCALED: + case G_REFLECTED: + { + o = transformObject( file, *retdoc, parents, descendtype, ok ); + break; + } + case G_FREE_POINT: + { + // fixed point + if ( nparents != 0 ) KIG_FILTER_PARSE_ERROR; + Coordinate c = readKSegCoordinate( stream ); + o = fact->fixedPointCalcer( c ); + break; + } + case G_CONSTRAINED_POINT: + { + // constrained point + double p; + stream >> p; + if ( nparents != 1 ) KIG_FILTER_PARSE_ERROR; + ObjectCalcer* parent = parents[0]; + assert( parent ); + o = fact->constrainedPointCalcer( parent, p ); + break; + } + case G_INTERSECTION_POINT: + { + // KSeg has somewhat weird intersection objects.. + // for all objects G_INTERSECTION_POINT gets the + // first intersection of its parents, G_INTERSECTION2_POINT + // represents the second, if present. + o = intersectionPoint( parents, -1 ); + if ( ! o ) KIG_FILTER_PARSE_ERROR; + break; + } + case G_INTERSECTION2_POINT: + { + o = intersectionPoint( parents, 1 ); + if ( ! o ) KIG_FILTER_PARSE_ERROR; + break; + } + case G_MID_POINT: + { + // midpoint of a segment.. + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + if ( !parents[0]->imp()->inherits( SegmentImp::stype() ) ) + KIG_FILTER_PARSE_ERROR; + int index = parents[0]->imp()->propertiesInternalNames().findIndex( "mid-point" ); + assert( index != -1 ); + o = new ObjectPropertyCalcer( parents[0], index ); + break; + } + default: + KIG_FILTER_PARSE_ERROR; + }; + width = style.pointstyle == SMALL_CIRCLE ? 2 : style.pointstyle == MEDIUM_CIRCLE ? 3 : 5; + color = style.brush.color(); + break; + }; + case G_SEGMENT: + { + switch( descendtype ) + { + case G_TRANSLATED: + case G_ROTATED: + case G_SCALED: + case G_REFLECTED: + { + o = transformObject( file, *retdoc, parents, descendtype, ok ); + break; + } + case G_ENDPOINTS_SEGMENT: + { + if ( nparents != 2 ) KIG_FILTER_PARSE_ERROR; + o = new ObjectTypeCalcer( SegmentABType::instance(), parents ); + break; + } + default: + KIG_FILTER_PARSE_ERROR; + } + break; + }; + case G_RAY: + { + switch( descendtype ) + { + case G_TRANSLATED: + case G_ROTATED: + case G_SCALED: + case G_REFLECTED: + { + o = transformObject( file, *retdoc, parents, descendtype, ok ); + break; + } + case G_TWOPOINTS_RAY: + { + if ( nparents != 2 ) KIG_FILTER_PARSE_ERROR; + o = new ObjectTypeCalcer( RayABType::instance(), parents ); + break; + } + case G_BISECTOR_RAY: + { + ObjectTypeCalcer* angle = new ObjectTypeCalcer( HalfAngleType::instance(), parents ); + angle->calc( *retdoc ); + o = fact->propertyObjectCalcer( angle, "angle-bisector" ); + break; + } + default: + KIG_FILTER_PARSE_ERROR; + }; + break; + }; + case G_LINE: + { + switch( descendtype ) + { + case G_TRANSLATED: + case G_ROTATED: + case G_SCALED: + case G_REFLECTED: + { + o = transformObject( file, *retdoc, parents, descendtype, ok ); + break; + } + case G_TWOPOINTS_LINE: + { + if ( nparents != 2 ) KIG_FILTER_PARSE_ERROR; + o = new ObjectTypeCalcer( LineABType::instance(), parents ); + break; + } + case G_PARALLEL_LINE: + { + if ( nparents != 2 ) KIG_FILTER_PARSE_ERROR; + o = new ObjectTypeCalcer( LineParallelLPType::instance(), parents ); + break; + } + case G_PERPENDICULAR_LINE: + { + if ( nparents != 2 ) KIG_FILTER_PARSE_ERROR; + o = new ObjectTypeCalcer( LinePerpendLPType::instance(), parents ); + break; + } + default: + KIG_FILTER_PARSE_ERROR; + }; + break; + }; + case G_CIRCLE: + { + switch( descendtype ) + { + case G_TRANSLATED: + case G_ROTATED: + case G_SCALED: + case G_REFLECTED: + { + o = transformObject( file, *retdoc, parents, descendtype, ok ); + break; + } + case G_CENTERPOINT_CIRCLE: + { + if ( nparents != 2 ) KIG_FILTER_PARSE_ERROR; + o = new ObjectTypeCalcer( CircleBCPType::instance(), parents ); + break; + } + case G_CENTERRADIUS_CIRCLE: + { + ObjectCalcer* point; + ObjectCalcer* segment; + if ( parents[0]->imp()->inherits( PointImp::stype() ) ) + { + point = parents[0]; + segment = parents[1]; + } + else + { + point = parents[1]; + segment = parents[0]; + }; + int index = segment->imp()->propertiesInternalNames().findIndex( "length" ); + if ( index == -1 ) KIG_FILTER_PARSE_ERROR; + ObjectPropertyCalcer* length = new ObjectPropertyCalcer( segment, index ); + length->calc( *retdoc ); + std::vector cparents; + cparents.push_back( point ); + cparents.push_back( length ); + o = new ObjectTypeCalcer( CircleBPRType::instance(), cparents ); + break; + } + default: + KIG_FILTER_PARSE_ERROR; + }; + break; + }; + case G_ARC: + { + switch( descendtype ) + { + case G_TRANSLATED: + case G_ROTATED: + case G_SCALED: + case G_REFLECTED: + { + o = transformObject( file, *retdoc, parents, descendtype, ok ); + break; + } + case G_THREEPOINTS_ARC: + { + if ( nparents != 3 ) KIG_FILTER_PARSE_ERROR; + o = new ObjectTypeCalcer( ArcBTPType::instance(), parents ); + break; + } + default: + KIG_FILTER_PARSE_ERROR; + } + break; + }; + case G_POLYGON: + { + switch( descendtype ) + { + case G_TRANSLATED: + case G_ROTATED: + case G_SCALED: + case G_REFLECTED: + { + o = transformObject( file, *retdoc, parents, descendtype, ok ); + break; + } + default: + { + if ( nparents < 3 ) KIG_FILTER_PARSE_ERROR; + o = new ObjectTypeCalcer( PolygonBNPType::instance(), parents ); + } + } +// default: +// KIG_FILTER_PARSE_ERROR; + break; + }; + case G_CIRCLEINTERIOR: + { + notSupported( file, i18n( "This KSeg file contains a filled circle, " + "which Kig does not currently support." ) ); + return 0; + }; + case G_ARCSECTOR: + { + notSupported( file, i18n( "This KSeg file contains an arc sector, " + "which Kig does not currently support." ) ); + return 0; + }; + case G_ARCSEGMENT: + { + notSupported( file, i18n( "This KSeg file contains an arc segment, " + "which Kig does not currently support." ) ); + return 0; + }; + case G_LOCUS: + { + switch( descendtype ) + { + case G_TRANSLATED: + case G_ROTATED: + case G_SCALED: + case G_REFLECTED: + { + o = transformObject( file, *retdoc, parents, descendtype, ok ); + break; + } + case G_OBJECT_LOCUS: + { + if ( nparents != 2 ) KIG_FILTER_PARSE_ERROR; + o = fact->locusCalcer( parents[0], parents[1] ); + break; + } + default: + KIG_FILTER_PARSE_ERROR; + } + break; + }; + case G_MEASURE: + KIG_FILTER_PARSE_ERROR; + case G_CALCULATE: + KIG_FILTER_PARSE_ERROR; + case G_ANNOTATION: + KIG_FILTER_PARSE_ERROR; + case G_LOOP: + KIG_FILTER_PARSE_ERROR; + default: + KIG_FILTER_PARSE_ERROR; + + } + + // checking if the object was correctly created + if ( ! o ) + { + if ( ok ) + KIG_FILTER_PARSE_ERROR + else + return 0; + } + + ObjectDrawer* d = new ObjectDrawer( color, width, visible, style.pen.style() ); + if ( !labeltext.isEmpty() ) + { + ObjectConstCalcer* name = new ObjectConstCalcer( new StringImp( labeltext ) ); + object = new ObjectHolder( o, d, name ); + } + else + { + object = new ObjectHolder( o, d ); + } + + assert( object ); + ret[i] = object; + object->calc( *retdoc ); + if ( !labeltext.isEmpty() && labelVisible ) + { + std::vector args2; + args2.push_back( object->nameCalcer() ); + ObjectCalcer* oc2 = fact->attachedLabelCalcer( + TQString::fromLatin1( "%1" ), object->calcer(), + static_cast( object->imp() )->coordinate(), + false, args2, *retdoc ); + oc2->calc( *retdoc ); + ObjectDrawer* d2 = new ObjectDrawer( style.pen.color() ); + ObjectHolder* o2 = new ObjectHolder( oc2, d2 ); + ret2.push_back( o2 ); + } + }; + + // selection groups ( we ignore them, but we pretend to read them + // out anyway, so we can find what comes after them.. ) + int selgroupcount; + stream >> selgroupcount; + for ( int i = 0; i < selgroupcount; ++i ) + { + TQString name; + stream >> name; + int size; + stream >> size; + for ( int i = 0; i < size; ++i ) + { + short object; + stream >> object; + (void) object; + }; + }; + + // no more data in the file.. + retdoc->addObjects( ret ); + retdoc->addObjects( ret2 ); + retdoc->setAxes( false ); + retdoc->setGrid( false ); + return retdoc; +} + +KigFilterKSeg* KigFilterKSeg::instance() +{ + static KigFilterKSeg f; + return &f; +} diff --git a/kig/filters/latexexporter.cc b/kig/filters/latexexporter.cc deleted file mode 100644 index 622a1a49..00000000 --- a/kig/filters/latexexporter.cc +++ /dev/null @@ -1,608 +0,0 @@ -// 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 - -#include "latexexporter.h" - -#include "latexexporteroptions.h" - -#include "../kig/kig_document.h" -#include "../kig/kig_part.h" -#include "../kig/kig_view.h" -#include "../misc/common.h" -#include "../misc/goniometry.h" -#include "../misc/kigfiledialog.h" -#include "../misc/rect.h" -#include "../objects/circle_imp.h" -#include "../objects/cubic_imp.h" -#include "../objects/curve_imp.h" -#include "../objects/line_imp.h" -#include "../objects/locus_imp.h" -#include "../objects/object_drawer.h" -#include "../objects/object_holder.h" -#include "../objects/object_imp.h" -#include "../objects/other_imp.h" -#include "../objects/point_imp.h" -#include "../objects/polygon_imp.h" -#include "../objects/text_imp.h" - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#ifdef HAVE_TRUNC -#define KDE_TRUNC(a) trunc(a) -#else -#define KDE_TRUNC(a) rint(a) -#endif - -struct ColorMap { - TQColor color; - TQString name; -}; - -LatexExporter::~LatexExporter() -{ -} - -TQString LatexExporter::exportToStatement() const -{ - return i18n( "Export to &Latex..." ); -} - -TQString LatexExporter::menuEntryName() const -{ - return i18n( "&Latex..." ); -} - -TQString LatexExporter::menuIcon() const -{ - // TODO - return "text-x-tex"; -} - -class LatexExportImpVisitor - : public ObjectImpVisitor -{ - TQTextStream& mstream; - ObjectHolder* mcurobj; - const KigWidget& mw; - Rect msr; - std::vector mcolors; - TQString mcurcolorid; -public: - void visit( ObjectHolder* obj ); - void mapColor( TQColor color ); - - LatexExportImpVisitor( TQTextStream& s, const KigWidget& w ) - : mstream( s ), mw( w ), msr( mw.showingRect() ) - { - } - void visit( const LineImp* imp ); - void visit( const PointImp* imp ); - void visit( const TextImp* imp ); - void visit( const AngleImp* imp ); - void visit( const VectorImp* imp ); - void visit( const LocusImp* imp ); - void visit( const CircleImp* imp ); - void visit( const ConicImp* imp ); - void visit( const CubicImp* imp ); - void visit( const SegmentImp* imp ); - void visit( const RayImp* imp ); - void visit( const ArcImp* imp ); - void visit( const PolygonImp* imp ); - - double unit; - -private: - /** - * Converts Kig coords to pstrick coord system and sends them to stream - * using the format: (xcoord,ycoord) - */ - void emitCoord( const Coordinate& c ); - /** - * Draws a line (segment) or a vector if vector is true. - */ - void emitLine( const Coordinate& a, const Coordinate& b, const int width, - const Qt::PenStyle s, bool vector = false ); - /** - * Sends a new line character ( \n ) to stream. - */ - void newLine(); - /** - * Searches if a color is already mapped into mcolors, and returns its - * index or -1 if not found. - */ - int findColor( TQColor c ); - /** - * Use to convert a dimension "on the screen" to a dimension wrt. - * Kig coordinate system. - */ - double dimRealToCoord( int dim ); - /** - * Converts a pen style into latex style string. - */ - TQString writeStyle( Qt::PenStyle style ); - /** - * Plots a generic curve though its points calc'ed with getPoint. - */ - void plotGenericCurve( const CurveImp* imp ); -}; - -void LatexExportImpVisitor::emitCoord( const Coordinate& c ) -{ - mstream << "(" << c.x - msr.left() << "," << c.y - msr.bottom() << ")"; -} - -void LatexExportImpVisitor::emitLine( const Coordinate& a, const Coordinate& b, - const int width, const Qt::PenStyle s, - bool vector ) -{ - mstream << "\\psline[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0 - << "," << writeStyle( s ); - if ( vector ) - mstream << ",arrowscale=3,arrowinset=1.3"; - mstream << "]"; - if ( vector ) - mstream << "{->}"; - emitCoord( a ); - emitCoord( b ); - newLine(); -} - -void LatexExportImpVisitor::newLine() -{ - mstream << "\n"; -} - -int LatexExportImpVisitor::findColor( TQColor c ) -{ - for ( uint i = 0; i < mcolors.size(); ++i ) - { - if ( c == mcolors[i].color ) - return i; - } - return -1; -} - -void LatexExportImpVisitor::mapColor( TQColor color ) -{ - if ( findColor( color ) == -1 ) - { - ColorMap newcolor; - newcolor.color = color; - TQString tmpname = color.name(); - tmpname.replace( "#", "" ); - newcolor.name = tmpname; - mcolors.push_back( newcolor ); - mstream << "\\newrgbcolor{" << tmpname << "}{" - << color.red() / 255.0 << " " << color.green() / 255.0 << " " - << color.blue() / 255.0 << "}\n"; - } -} - -double LatexExportImpVisitor::dimRealToCoord( int dim ) -{ - TQRect qr( 0, 0, dim, dim ); - Rect r = mw.screenInfo().fromScreen( qr ); - return fabs( r.width() ); -} - -TQString LatexExportImpVisitor::writeStyle( Qt::PenStyle style ) -{ - TQString ret( "linestyle=" ); - if ( style == TQt::DashLine ) - ret += "dashed"; - else if ( style == TQt::DotLine ) - ret += "dotted,dotsep=2pt"; - else - ret += "solid"; - return ret; -} - -void LatexExportImpVisitor::plotGenericCurve( const CurveImp* imp ) -{ - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - - TQString prefix = TQString( "\\pscurve[linecolor=%1,linewidth=%2,%3]" ) - .arg( mcurcolorid ) - .arg( width / 100.0 ) - .arg( writeStyle( mcurobj->drawer()->style() ) ); - - std::vector< std::vector< Coordinate > > coordlist; - coordlist.push_back( std::vector< Coordinate >() ); - uint curid = 0; - - Coordinate c; - Coordinate prev = Coordinate::invalidCoord(); - for ( double i = 0.0; i <= 1.0; i += 0.005 ) - { - c = imp->getPoint( i, mw.document() ); - if ( !c.valid() ) - { - if ( coordlist[curid].size() > 0 ) - { - coordlist.push_back( std::vector< Coordinate >() ); - ++curid; - prev = Coordinate::invalidCoord(); - } - continue; - } - if ( ! ( ( fabs( c.x ) <= 1000 ) && ( fabs( c.y ) <= 1000 ) ) ) - continue; - // if there's too much distance between this coordinate and the previous - // one, then it's another piece of curve not joined with the rest - if ( prev.valid() && ( c.distance( prev ) > 4.0 ) ) - { - coordlist.push_back( std::vector< Coordinate >() ); - ++curid; - } - coordlist[curid].push_back( c ); - prev = c; - } - // special case for ellipse - if ( const ConicImp* conic = dynamic_cast< const ConicImp* >( imp ) ) - { - // if ellipse, close its path - if ( conic->conicType() == 1 && coordlist.size() == 1 && coordlist[0].size() > 1 ) - { - coordlist[0].push_back( coordlist[0][0] ); - } - } - for ( uint i = 0; i < coordlist.size(); ++i ) - { - uint s = coordlist[i].size(); - // there's no point in draw curves empty or with only one point - if ( s <= 1 ) - continue; - - mstream << prefix; - for ( uint j = 0; j < s; ++j ) - emitCoord( coordlist[i][j] ); - newLine(); - } -} - -void LatexExportImpVisitor::visit( ObjectHolder* obj ) -{ - if ( ! obj->drawer()->shown() ) - return; - const int id = findColor( obj->drawer()->color() ); - if ( id == -1 ) - return; - mcurcolorid = mcolors[id].name; - mcurobj = obj; - obj->imp()->visit( this ); -} - -void LatexExportImpVisitor::visit( const LineImp* imp ) -{ - Coordinate a = imp->data().a; - Coordinate b = imp->data().b; - calcBorderPoints( a, b, msr ); - - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - - emitLine( a, b, width, mcurobj->drawer()->style() ); -} - -void LatexExportImpVisitor::visit( const PointImp* imp ) -{ - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 5; - width /= 5; - - mstream << "\\psdots[linecolor=" << mcurcolorid - << ",dotscale=" << width << ",dotstyle="; - const int ps = mcurobj->drawer()->pointStyle(); - TQString pss( "*,fillstyle=solid,fillcolor=" + mcurcolorid ); - if ( ps == 1 ) - pss = "o,fillstyle=none"; - else if ( ps == 2 ) - pss = "square*,fillstyle=solid,fillcolor=" + mcurcolorid; - else if ( ps == 3 ) - pss = "square,fillstyle=none"; - else if ( ps == 4 ) - pss = "+,dotangle=45"; - mstream << pss << "]"; - emitCoord( imp->coordinate() ); - newLine(); -} - -void LatexExportImpVisitor::visit( const TextImp* imp ) -{ - // FIXME: support multiline texts... - mstream << "\\rput[tl]"; - emitCoord( imp->coordinate() ); - newLine(); - mstream << "{"; - newLine(); - if ( imp->hasFrame() ) - { - mstream << " \\psframebox[linecolor=c5c2c5,linewidth=0.01" - << ",fillstyle=solid,fillcolor=ffffde]" - << "{" << imp->text() << "}"; - } - else - { - mstream << imp->text(); - } - newLine(); - mstream << "}"; - newLine(); -} - -void LatexExportImpVisitor::visit( const AngleImp* imp ) -{ - const Coordinate center = imp->point(); - const double radius = dimRealToCoord( 50 ) * unit; - double startangle = imp->startAngle(); - double endangle = startangle + imp->angle(); -// if ( startangle > M_PI ) -// startangle -= 2 * M_PI; - startangle = Goniometry::convert( startangle, Goniometry::Rad, Goniometry::Deg ); -// if ( endangle > 2 * M_PI ) -// endangle -= 2 * M_PI; - endangle = Goniometry::convert( endangle, Goniometry::Rad, Goniometry::Deg ); - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - - mstream << "\\psarc[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0 - << "," << writeStyle( mcurobj->drawer()->style() ) << ",arrowscale=3,arrowinset=0]{->}"; - emitCoord( center ); - mstream << "{" << radius << "}{" << startangle << "}{" << endangle << "}"; - newLine(); -} - -void LatexExportImpVisitor::visit( const VectorImp* imp ) -{ - Coordinate a = imp->data().a; - Coordinate b = imp->data().b; - - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - - emitLine( a, b, width, mcurobj->drawer()->style(), true ); -} - -void LatexExportImpVisitor::visit( const LocusImp* imp ) -{ - plotGenericCurve( imp ); -} - -void LatexExportImpVisitor::visit( const CircleImp* imp ) -{ - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - - mstream << "\\pscircle[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0 - << "," << writeStyle( mcurobj->drawer()->style() ) << "]"; - emitCoord( imp->center() ); - mstream << "{" << imp->radius() * unit << "}"; - newLine(); -} - -void LatexExportImpVisitor::visit( const ConicImp* imp ) -{ - plotGenericCurve( imp ); -} - -void LatexExportImpVisitor::visit( const CubicImp* ) -{ - // FIXME: cubic are not drawn correctly with plotGenericCurve -// plotGenericCurve( imp ); -} - -void LatexExportImpVisitor::visit( const SegmentImp* imp ) -{ - Coordinate a = imp->data().a; - Coordinate b = imp->data().b; - - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - - emitLine( a, b, width, mcurobj->drawer()->style() ); -} - -void LatexExportImpVisitor::visit( const RayImp* imp ) -{ - Coordinate a = imp->data().a; - Coordinate b = imp->data().b; - calcRayBorderPoints( a, b, msr ); - - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - - emitLine( a, b, width, mcurobj->drawer()->style() ); -} - -void LatexExportImpVisitor::visit( const ArcImp* imp ) -{ - const Coordinate center = imp->center(); - const double radius = imp->radius() * unit; - double startangle = imp->startAngle(); - double endangle = startangle + imp->angle(); -// if ( startangle > M_PI ) -// startangle -= 2 * M_PI; - startangle = Goniometry::convert( startangle, Goniometry::Rad, Goniometry::Deg ); -// if ( endangle > M_PI ) -// endangle -= 2 * M_PI; - endangle = Goniometry::convert( endangle, Goniometry::Rad, Goniometry::Deg ); - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - - mstream << "\\psarc[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0 - << "," << writeStyle( mcurobj->drawer()->style() ) << "]"; - emitCoord( center ); - mstream << "{" << radius << "}{" << startangle << "}{" << endangle << "}"; - newLine(); -} - -void LatexExportImpVisitor::visit( const PolygonImp* imp ) -{ - int width = mcurobj->drawer()->width(); - if ( width == -1 ) width = 1; - - mstream << "\\pspolygon[linecolor=" << mcurcolorid << ",linewidth=0" - << "," << writeStyle( mcurobj->drawer()->style() ) - << ",hatchcolor=" << mcurcolorid << ",hatchwidth=0.5pt,hatchsep=0.5pt" - << ",fillcolor=" << mcurcolorid << ",fillstyle=crosshatch]"; - - std::vector pts = imp->points(); - for ( uint i = 0; i < pts.size(); i++ ) - { - emitCoord( pts[i] ); - } - newLine(); -} - -void LatexExporter::run( const KigPart& doc, KigWidget& w ) -{ - KigFileDialog* kfd = new KigFileDialog( - TQString(), i18n( "*.tex|Latex Documents (*.tex)" ), - i18n( "Export as Latex" ), &w ); - kfd->setOptionCaption( i18n( "Latex Options" ) ); - LatexExporterOptions* opts = new LatexExporterOptions( 0L ); - kfd->setOptionsWidget( opts ); - opts->showGridCheckBox->setChecked( doc.document().grid() ); - opts->showAxesCheckBox->setChecked( doc.document().axes() ); - opts->showExtraFrameCheckBox->setChecked( false ); - if ( !kfd->exec() ) - return; - - TQString file_name = kfd->selectedFile(); - bool showgrid = opts->showGridCheckBox->isOn(); - bool showaxes = opts->showAxesCheckBox->isOn(); - bool showframe = opts->showExtraFrameCheckBox->isOn(); - - delete opts; - delete kfd; - - TQFile file( file_name ); - if ( ! file.open( IO_WriteOnly ) ) - { - KMessageBox::sorry( &w, i18n( "The file \"%1\" could not be opened. Please " - "check if the file permissions are set correctly." ) - .arg( file_name ) ); - return; - }; - - TQTextStream stream( &file ); - stream << "\\documentclass[a4paper]{minimal}\n"; -// stream << "\\usepackage[latin1]{inputenc}\n"; - stream << "\\usepackage{pstricks}\n"; - stream << "\\usepackage{pst-plot}\n"; - stream << "\\author{Kig " << KIGVERSION << "}\n"; - stream << "\\begin{document}\n"; - - const double bottom = w.showingRect().bottom(); - const double left = w.showingRect().left(); - const double height = w.showingRect().height(); - const double width = w.showingRect().width(); - -/* - // TODO: calculating aspect ratio... - if ( 297 / 210 >= height / width ) - { - - } -*/ - const double tmpwidth = 15.0; - const double xunit = tmpwidth / width; - const double yunit = xunit; - - stream << "\\begin{pspicture*}(0,0)(" << tmpwidth << "," << yunit * height << ")\n"; - stream << "\\psset{xunit=" << xunit << "}\n"; - stream << "\\psset{yunit=" << yunit << "}\n"; - - std::vector os = doc.document().objects(); - LatexExportImpVisitor visitor( stream, w ); - visitor.unit = xunit; - - for ( std::vector::const_iterator i = os.begin(); - i != os.end(); ++i ) - { - if ( ! ( *i )->shown() ) continue; - visitor.mapColor( ( *i )->drawer()->color() ); - }; - visitor.mapColor( TQColor( 255, 255, 222 ) ); // ffffde - text label background - visitor.mapColor( TQColor( 197, 194, 197 ) ); // c5c2c5 - text label border line - visitor.mapColor( TQColor( 160, 160, 164 ) ); // a0a0a4 - axes color - visitor.mapColor( TQColor( 192, 192, 192 ) ); // c0c0c0 - grid color - - // extra frame - if ( showframe ) - { - stream << "\\psframe[linecolor=black,linewidth=0.02]" - << "(0,0)" - << "(" << width << "," << height << ")" - << "\n"; - } - - // grid - if ( showgrid ) - { - // vertical lines... - double startingpoint = - left - 1 + static_cast( KDE_TRUNC( left ) ); - for ( double i = startingpoint; i < width; ++i ) - { - stream << "\\psline[linecolor=c0c0c0,linewidth=0.01,linestyle=dashed]" - << "(" << i << ",0)" - << "(" << i << "," << height << ")" - << "\n"; - } - - // horizontal lines... - startingpoint = - bottom - 1 + static_cast( KDE_TRUNC( bottom ) ); - for ( double i = startingpoint; i < height; ++i ) - { - stream << "\\psline[linecolor=c0c0c0,linewidth=0.01,linestyle=dashed]" - << "(0," << i << ")" - << "(" << width << "," << i << ")" - << "\n"; - } - } - - // axes - if ( showaxes ) - { - stream << "\\psaxes[linecolor=a0a0a4,linewidth=0.03,ticks=none,arrowinset=0]{->}" - << "(" << -left << "," << -bottom << ")" - << "(0,0)" - << "(" << width << "," << height << ")" - << "\n"; - } - - for ( std::vector::const_iterator i = os.begin(); - i != os.end(); ++i ) - { - visitor.visit( *i ); - }; - - stream << "\\end{pspicture*}\n"; - stream << "\\end{document}\n"; -} diff --git a/kig/filters/latexexporter.cpp b/kig/filters/latexexporter.cpp new file mode 100644 index 00000000..622a1a49 --- /dev/null +++ b/kig/filters/latexexporter.cpp @@ -0,0 +1,608 @@ +// 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 + +#include "latexexporter.h" + +#include "latexexporteroptions.h" + +#include "../kig/kig_document.h" +#include "../kig/kig_part.h" +#include "../kig/kig_view.h" +#include "../misc/common.h" +#include "../misc/goniometry.h" +#include "../misc/kigfiledialog.h" +#include "../misc/rect.h" +#include "../objects/circle_imp.h" +#include "../objects/cubic_imp.h" +#include "../objects/curve_imp.h" +#include "../objects/line_imp.h" +#include "../objects/locus_imp.h" +#include "../objects/object_drawer.h" +#include "../objects/object_holder.h" +#include "../objects/object_imp.h" +#include "../objects/other_imp.h" +#include "../objects/point_imp.h" +#include "../objects/polygon_imp.h" +#include "../objects/text_imp.h" + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef HAVE_TRUNC +#define KDE_TRUNC(a) trunc(a) +#else +#define KDE_TRUNC(a) rint(a) +#endif + +struct ColorMap { + TQColor color; + TQString name; +}; + +LatexExporter::~LatexExporter() +{ +} + +TQString LatexExporter::exportToStatement() const +{ + return i18n( "Export to &Latex..." ); +} + +TQString LatexExporter::menuEntryName() const +{ + return i18n( "&Latex..." ); +} + +TQString LatexExporter::menuIcon() const +{ + // TODO + return "text-x-tex"; +} + +class LatexExportImpVisitor + : public ObjectImpVisitor +{ + TQTextStream& mstream; + ObjectHolder* mcurobj; + const KigWidget& mw; + Rect msr; + std::vector mcolors; + TQString mcurcolorid; +public: + void visit( ObjectHolder* obj ); + void mapColor( TQColor color ); + + LatexExportImpVisitor( TQTextStream& s, const KigWidget& w ) + : mstream( s ), mw( w ), msr( mw.showingRect() ) + { + } + void visit( const LineImp* imp ); + void visit( const PointImp* imp ); + void visit( const TextImp* imp ); + void visit( const AngleImp* imp ); + void visit( const VectorImp* imp ); + void visit( const LocusImp* imp ); + void visit( const CircleImp* imp ); + void visit( const ConicImp* imp ); + void visit( const CubicImp* imp ); + void visit( const SegmentImp* imp ); + void visit( const RayImp* imp ); + void visit( const ArcImp* imp ); + void visit( const PolygonImp* imp ); + + double unit; + +private: + /** + * Converts Kig coords to pstrick coord system and sends them to stream + * using the format: (xcoord,ycoord) + */ + void emitCoord( const Coordinate& c ); + /** + * Draws a line (segment) or a vector if vector is true. + */ + void emitLine( const Coordinate& a, const Coordinate& b, const int width, + const Qt::PenStyle s, bool vector = false ); + /** + * Sends a new line character ( \n ) to stream. + */ + void newLine(); + /** + * Searches if a color is already mapped into mcolors, and returns its + * index or -1 if not found. + */ + int findColor( TQColor c ); + /** + * Use to convert a dimension "on the screen" to a dimension wrt. + * Kig coordinate system. + */ + double dimRealToCoord( int dim ); + /** + * Converts a pen style into latex style string. + */ + TQString writeStyle( Qt::PenStyle style ); + /** + * Plots a generic curve though its points calc'ed with getPoint. + */ + void plotGenericCurve( const CurveImp* imp ); +}; + +void LatexExportImpVisitor::emitCoord( const Coordinate& c ) +{ + mstream << "(" << c.x - msr.left() << "," << c.y - msr.bottom() << ")"; +} + +void LatexExportImpVisitor::emitLine( const Coordinate& a, const Coordinate& b, + const int width, const Qt::PenStyle s, + bool vector ) +{ + mstream << "\\psline[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0 + << "," << writeStyle( s ); + if ( vector ) + mstream << ",arrowscale=3,arrowinset=1.3"; + mstream << "]"; + if ( vector ) + mstream << "{->}"; + emitCoord( a ); + emitCoord( b ); + newLine(); +} + +void LatexExportImpVisitor::newLine() +{ + mstream << "\n"; +} + +int LatexExportImpVisitor::findColor( TQColor c ) +{ + for ( uint i = 0; i < mcolors.size(); ++i ) + { + if ( c == mcolors[i].color ) + return i; + } + return -1; +} + +void LatexExportImpVisitor::mapColor( TQColor color ) +{ + if ( findColor( color ) == -1 ) + { + ColorMap newcolor; + newcolor.color = color; + TQString tmpname = color.name(); + tmpname.replace( "#", "" ); + newcolor.name = tmpname; + mcolors.push_back( newcolor ); + mstream << "\\newrgbcolor{" << tmpname << "}{" + << color.red() / 255.0 << " " << color.green() / 255.0 << " " + << color.blue() / 255.0 << "}\n"; + } +} + +double LatexExportImpVisitor::dimRealToCoord( int dim ) +{ + TQRect qr( 0, 0, dim, dim ); + Rect r = mw.screenInfo().fromScreen( qr ); + return fabs( r.width() ); +} + +TQString LatexExportImpVisitor::writeStyle( Qt::PenStyle style ) +{ + TQString ret( "linestyle=" ); + if ( style == TQt::DashLine ) + ret += "dashed"; + else if ( style == TQt::DotLine ) + ret += "dotted,dotsep=2pt"; + else + ret += "solid"; + return ret; +} + +void LatexExportImpVisitor::plotGenericCurve( const CurveImp* imp ) +{ + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + + TQString prefix = TQString( "\\pscurve[linecolor=%1,linewidth=%2,%3]" ) + .arg( mcurcolorid ) + .arg( width / 100.0 ) + .arg( writeStyle( mcurobj->drawer()->style() ) ); + + std::vector< std::vector< Coordinate > > coordlist; + coordlist.push_back( std::vector< Coordinate >() ); + uint curid = 0; + + Coordinate c; + Coordinate prev = Coordinate::invalidCoord(); + for ( double i = 0.0; i <= 1.0; i += 0.005 ) + { + c = imp->getPoint( i, mw.document() ); + if ( !c.valid() ) + { + if ( coordlist[curid].size() > 0 ) + { + coordlist.push_back( std::vector< Coordinate >() ); + ++curid; + prev = Coordinate::invalidCoord(); + } + continue; + } + if ( ! ( ( fabs( c.x ) <= 1000 ) && ( fabs( c.y ) <= 1000 ) ) ) + continue; + // if there's too much distance between this coordinate and the previous + // one, then it's another piece of curve not joined with the rest + if ( prev.valid() && ( c.distance( prev ) > 4.0 ) ) + { + coordlist.push_back( std::vector< Coordinate >() ); + ++curid; + } + coordlist[curid].push_back( c ); + prev = c; + } + // special case for ellipse + if ( const ConicImp* conic = dynamic_cast< const ConicImp* >( imp ) ) + { + // if ellipse, close its path + if ( conic->conicType() == 1 && coordlist.size() == 1 && coordlist[0].size() > 1 ) + { + coordlist[0].push_back( coordlist[0][0] ); + } + } + for ( uint i = 0; i < coordlist.size(); ++i ) + { + uint s = coordlist[i].size(); + // there's no point in draw curves empty or with only one point + if ( s <= 1 ) + continue; + + mstream << prefix; + for ( uint j = 0; j < s; ++j ) + emitCoord( coordlist[i][j] ); + newLine(); + } +} + +void LatexExportImpVisitor::visit( ObjectHolder* obj ) +{ + if ( ! obj->drawer()->shown() ) + return; + const int id = findColor( obj->drawer()->color() ); + if ( id == -1 ) + return; + mcurcolorid = mcolors[id].name; + mcurobj = obj; + obj->imp()->visit( this ); +} + +void LatexExportImpVisitor::visit( const LineImp* imp ) +{ + Coordinate a = imp->data().a; + Coordinate b = imp->data().b; + calcBorderPoints( a, b, msr ); + + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + + emitLine( a, b, width, mcurobj->drawer()->style() ); +} + +void LatexExportImpVisitor::visit( const PointImp* imp ) +{ + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 5; + width /= 5; + + mstream << "\\psdots[linecolor=" << mcurcolorid + << ",dotscale=" << width << ",dotstyle="; + const int ps = mcurobj->drawer()->pointStyle(); + TQString pss( "*,fillstyle=solid,fillcolor=" + mcurcolorid ); + if ( ps == 1 ) + pss = "o,fillstyle=none"; + else if ( ps == 2 ) + pss = "square*,fillstyle=solid,fillcolor=" + mcurcolorid; + else if ( ps == 3 ) + pss = "square,fillstyle=none"; + else if ( ps == 4 ) + pss = "+,dotangle=45"; + mstream << pss << "]"; + emitCoord( imp->coordinate() ); + newLine(); +} + +void LatexExportImpVisitor::visit( const TextImp* imp ) +{ + // FIXME: support multiline texts... + mstream << "\\rput[tl]"; + emitCoord( imp->coordinate() ); + newLine(); + mstream << "{"; + newLine(); + if ( imp->hasFrame() ) + { + mstream << " \\psframebox[linecolor=c5c2c5,linewidth=0.01" + << ",fillstyle=solid,fillcolor=ffffde]" + << "{" << imp->text() << "}"; + } + else + { + mstream << imp->text(); + } + newLine(); + mstream << "}"; + newLine(); +} + +void LatexExportImpVisitor::visit( const AngleImp* imp ) +{ + const Coordinate center = imp->point(); + const double radius = dimRealToCoord( 50 ) * unit; + double startangle = imp->startAngle(); + double endangle = startangle + imp->angle(); +// if ( startangle > M_PI ) +// startangle -= 2 * M_PI; + startangle = Goniometry::convert( startangle, Goniometry::Rad, Goniometry::Deg ); +// if ( endangle > 2 * M_PI ) +// endangle -= 2 * M_PI; + endangle = Goniometry::convert( endangle, Goniometry::Rad, Goniometry::Deg ); + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + + mstream << "\\psarc[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0 + << "," << writeStyle( mcurobj->drawer()->style() ) << ",arrowscale=3,arrowinset=0]{->}"; + emitCoord( center ); + mstream << "{" << radius << "}{" << startangle << "}{" << endangle << "}"; + newLine(); +} + +void LatexExportImpVisitor::visit( const VectorImp* imp ) +{ + Coordinate a = imp->data().a; + Coordinate b = imp->data().b; + + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + + emitLine( a, b, width, mcurobj->drawer()->style(), true ); +} + +void LatexExportImpVisitor::visit( const LocusImp* imp ) +{ + plotGenericCurve( imp ); +} + +void LatexExportImpVisitor::visit( const CircleImp* imp ) +{ + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + + mstream << "\\pscircle[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0 + << "," << writeStyle( mcurobj->drawer()->style() ) << "]"; + emitCoord( imp->center() ); + mstream << "{" << imp->radius() * unit << "}"; + newLine(); +} + +void LatexExportImpVisitor::visit( const ConicImp* imp ) +{ + plotGenericCurve( imp ); +} + +void LatexExportImpVisitor::visit( const CubicImp* ) +{ + // FIXME: cubic are not drawn correctly with plotGenericCurve +// plotGenericCurve( imp ); +} + +void LatexExportImpVisitor::visit( const SegmentImp* imp ) +{ + Coordinate a = imp->data().a; + Coordinate b = imp->data().b; + + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + + emitLine( a, b, width, mcurobj->drawer()->style() ); +} + +void LatexExportImpVisitor::visit( const RayImp* imp ) +{ + Coordinate a = imp->data().a; + Coordinate b = imp->data().b; + calcRayBorderPoints( a, b, msr ); + + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + + emitLine( a, b, width, mcurobj->drawer()->style() ); +} + +void LatexExportImpVisitor::visit( const ArcImp* imp ) +{ + const Coordinate center = imp->center(); + const double radius = imp->radius() * unit; + double startangle = imp->startAngle(); + double endangle = startangle + imp->angle(); +// if ( startangle > M_PI ) +// startangle -= 2 * M_PI; + startangle = Goniometry::convert( startangle, Goniometry::Rad, Goniometry::Deg ); +// if ( endangle > M_PI ) +// endangle -= 2 * M_PI; + endangle = Goniometry::convert( endangle, Goniometry::Rad, Goniometry::Deg ); + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + + mstream << "\\psarc[linecolor=" << mcurcolorid << ",linewidth=" << width / 100.0 + << "," << writeStyle( mcurobj->drawer()->style() ) << "]"; + emitCoord( center ); + mstream << "{" << radius << "}{" << startangle << "}{" << endangle << "}"; + newLine(); +} + +void LatexExportImpVisitor::visit( const PolygonImp* imp ) +{ + int width = mcurobj->drawer()->width(); + if ( width == -1 ) width = 1; + + mstream << "\\pspolygon[linecolor=" << mcurcolorid << ",linewidth=0" + << "," << writeStyle( mcurobj->drawer()->style() ) + << ",hatchcolor=" << mcurcolorid << ",hatchwidth=0.5pt,hatchsep=0.5pt" + << ",fillcolor=" << mcurcolorid << ",fillstyle=crosshatch]"; + + std::vector pts = imp->points(); + for ( uint i = 0; i < pts.size(); i++ ) + { + emitCoord( pts[i] ); + } + newLine(); +} + +void LatexExporter::run( const KigPart& doc, KigWidget& w ) +{ + KigFileDialog* kfd = new KigFileDialog( + TQString(), i18n( "*.tex|Latex Documents (*.tex)" ), + i18n( "Export as Latex" ), &w ); + kfd->setOptionCaption( i18n( "Latex Options" ) ); + LatexExporterOptions* opts = new LatexExporterOptions( 0L ); + kfd->setOptionsWidget( opts ); + opts->showGridCheckBox->setChecked( doc.document().grid() ); + opts->showAxesCheckBox->setChecked( doc.document().axes() ); + opts->showExtraFrameCheckBox->setChecked( false ); + if ( !kfd->exec() ) + return; + + TQString file_name = kfd->selectedFile(); + bool showgrid = opts->showGridCheckBox->isOn(); + bool showaxes = opts->showAxesCheckBox->isOn(); + bool showframe = opts->showExtraFrameCheckBox->isOn(); + + delete opts; + delete kfd; + + TQFile file( file_name ); + if ( ! file.open( IO_WriteOnly ) ) + { + KMessageBox::sorry( &w, i18n( "The file \"%1\" could not be opened. Please " + "check if the file permissions are set correctly." ) + .arg( file_name ) ); + return; + }; + + TQTextStream stream( &file ); + stream << "\\documentclass[a4paper]{minimal}\n"; +// stream << "\\usepackage[latin1]{inputenc}\n"; + stream << "\\usepackage{pstricks}\n"; + stream << "\\usepackage{pst-plot}\n"; + stream << "\\author{Kig " << KIGVERSION << "}\n"; + stream << "\\begin{document}\n"; + + const double bottom = w.showingRect().bottom(); + const double left = w.showingRect().left(); + const double height = w.showingRect().height(); + const double width = w.showingRect().width(); + +/* + // TODO: calculating aspect ratio... + if ( 297 / 210 >= height / width ) + { + + } +*/ + const double tmpwidth = 15.0; + const double xunit = tmpwidth / width; + const double yunit = xunit; + + stream << "\\begin{pspicture*}(0,0)(" << tmpwidth << "," << yunit * height << ")\n"; + stream << "\\psset{xunit=" << xunit << "}\n"; + stream << "\\psset{yunit=" << yunit << "}\n"; + + std::vector os = doc.document().objects(); + LatexExportImpVisitor visitor( stream, w ); + visitor.unit = xunit; + + for ( std::vector::const_iterator i = os.begin(); + i != os.end(); ++i ) + { + if ( ! ( *i )->shown() ) continue; + visitor.mapColor( ( *i )->drawer()->color() ); + }; + visitor.mapColor( TQColor( 255, 255, 222 ) ); // ffffde - text label background + visitor.mapColor( TQColor( 197, 194, 197 ) ); // c5c2c5 - text label border line + visitor.mapColor( TQColor( 160, 160, 164 ) ); // a0a0a4 - axes color + visitor.mapColor( TQColor( 192, 192, 192 ) ); // c0c0c0 - grid color + + // extra frame + if ( showframe ) + { + stream << "\\psframe[linecolor=black,linewidth=0.02]" + << "(0,0)" + << "(" << width << "," << height << ")" + << "\n"; + } + + // grid + if ( showgrid ) + { + // vertical lines... + double startingpoint = - left - 1 + static_cast( KDE_TRUNC( left ) ); + for ( double i = startingpoint; i < width; ++i ) + { + stream << "\\psline[linecolor=c0c0c0,linewidth=0.01,linestyle=dashed]" + << "(" << i << ",0)" + << "(" << i << "," << height << ")" + << "\n"; + } + + // horizontal lines... + startingpoint = - bottom - 1 + static_cast( KDE_TRUNC( bottom ) ); + for ( double i = startingpoint; i < height; ++i ) + { + stream << "\\psline[linecolor=c0c0c0,linewidth=0.01,linestyle=dashed]" + << "(0," << i << ")" + << "(" << width << "," << i << ")" + << "\n"; + } + } + + // axes + if ( showaxes ) + { + stream << "\\psaxes[linecolor=a0a0a4,linewidth=0.03,ticks=none,arrowinset=0]{->}" + << "(" << -left << "," << -bottom << ")" + << "(0,0)" + << "(" << width << "," << height << ")" + << "\n"; + } + + for ( std::vector::const_iterator i = os.begin(); + i != os.end(); ++i ) + { + visitor.visit( *i ); + }; + + stream << "\\end{pspicture*}\n"; + stream << "\\end{document}\n"; +} diff --git a/kig/filters/native-filter.cc b/kig/filters/native-filter.cc deleted file mode 100644 index cf6521b2..00000000 --- a/kig/filters/native-filter.cc +++ /dev/null @@ -1,747 +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 "native-filter.h" - -#include "../kig/kig_part.h" -#include "../kig/kig_document.h" -#include "../objects/bogus_imp.h" -#include "../objects/object_type.h" -#include "../objects/object_imp.h" -#include "../objects/object_calcer.h" -#include "../objects/object_drawer.h" -#include "../objects/object_holder.h" -#include "../objects/object_type_factory.h" -#include "../objects/object_imp_factory.h" -#include "../misc/calcpaths.h" -#include "../misc/coordinate_system.h" - -#include "config.h" - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -struct HierElem -{ - int id; - std::vector parents; - TQDomElement el; -}; - -static void extendVect( std::vector& vect, uint size ) -{ - if ( size > vect.size() ) - { - int osize = vect.size(); - vect.resize( size ); - for ( uint i = osize; i < size; ++i ) - vect[i].id = i+1; - }; -} - -static void visitElem( std::vector& ret, - const std::vector& elems, - std::vector& seen, - int i ) -{ - if ( !seen[i] ) - { - for ( uint j = 0; j < elems[i].parents.size(); ++j ) - visitElem( ret, elems, seen, elems[i].parents[j] - 1); - ret.push_back( elems[i] ); - seen[i] = true; - }; -} - -static std::vector sortElems( const std::vector elems ) -{ - std::vector ret; - std::vector seenElems( elems.size(), false ); - for ( uint i = 0; i < elems.size(); ++i ) - visitElem( ret, elems, seenElems, i ); - return ret; -} - -KigFilterNative::KigFilterNative() -{ -} - -KigFilterNative::~KigFilterNative() -{ -} - -bool KigFilterNative::supportMime( const TQString& mime ) -{ - return mime == "application/x-kig"; -} - -KigDocument* KigFilterNative::load( const TQString& file ) -{ - TQFile ffile( file ); - if ( ! ffile.open( IO_ReadOnly ) ) - { - fileNotFound( file ); - return 0; - }; - - TQFile kigdoc( file ); -#ifndef KIG_NO_COMPRESSED_FILES - bool iscompressed = false; - if ( !file.endsWith( ".kig", false ) ) - { - // the file is compressed, so we have to decompress it and fetch the - // kig file inside it... - iscompressed = true; - - TQString tempdir = TDEGlobal::dirs()->saveLocation( "tmp" ); - if ( tempdir.isEmpty() ) - KIG_FILTER_PARSE_ERROR; - - TQString tempname = file.section( '/', -1 ); - if ( file.endsWith( ".kigz", false ) ) - { - tempname.remove( TQRegExp( "\\.[Kk][Ii][Gg][Zz]$" ) ); - } - else - KIG_FILTER_PARSE_ERROR; - // reading compressed file - KTar* ark = new KTar( file, "application/x-gzip" ); - ark->open( IO_ReadOnly ); - const KArchiveDirectory* dir = ark->directory(); -// assert( dir ); - TQStringList entries = dir->entries(); - TQStringList kigfiles = entries.grep( TQRegExp( "\\.kig$" ) ); - if ( kigfiles.count() != 1 ) - // I throw a generic parse error here, but I should warn the user that - // this kig archive file doesn't contain one kig file (it contains no - // kig files or more than one). - KIG_FILTER_PARSE_ERROR; - const KArchiveEntry* kigz = dir->entry( kigfiles[0] ); - if ( !kigz->isFile() ) - KIG_FILTER_PARSE_ERROR; - dynamic_cast( kigz )->copyTo( tempdir ); - kdDebug() << "extracted file: " << tempdir + kigz->name() << endl - << "exists: " << TQFile::exists( tempdir + kigz->name() ) << endl; - - kigdoc.setName( tempdir + kigz->name() ); - } -#endif - - if ( !kigdoc.open( IO_ReadOnly ) ) - KIG_FILTER_PARSE_ERROR; - - TQDomDocument doc( "KigDocument" ); - if ( !doc.setContent( &kigdoc ) ) - KIG_FILTER_PARSE_ERROR; - kigdoc.close(); - -#ifndef KIG_NO_COMPRESSED_FILES - // removing temp file - if ( iscompressed ) - kigdoc.remove(); -#endif - - TQDomElement main = doc.documentElement(); - - TQString version = main.attribute( "CompatibilityVersion" ); - if ( version.isEmpty() ) version = main.attribute( "Version" ); - if ( version.isEmpty() ) version = main.attribute( "version" ); - if ( version.isEmpty() ) - KIG_FILTER_PARSE_ERROR; - - // matches 0.1, 0.2.0, 153.128.99 etc. - TQRegExp versionre( "(\\d+)\\.(\\d+)(\\.(\\d+))?" ); - if ( ! versionre.exactMatch( version ) ) - KIG_FILTER_PARSE_ERROR; - bool ok = true; - int major = versionre.cap( 1 ).toInt( &ok ); - bool ok2 = true; - int minor = versionre.cap( 2 ).toInt( &ok2 ); - if ( ! ok || ! ok2 ) - KIG_FILTER_PARSE_ERROR; - - // int minorminor = versionre.cap( 4 ).toInt( &ok ); - - // we only support 0.[0-7] and 1.0.* - if ( major > 0 || minor > 9 ) - { - notSupported( file, i18n( "This file was created by Kig version \"%1\", " - "which this version cannot open." ).arg( version ) ); - return 0; - } - else if ( major == 0 && minor <= 3 ) - { - notSupported( file, i18n( "This file was created by Kig version \"%1\".\n" - "Support for older Kig formats (pre-0.4) has been " - "removed from Kig.\n" - "You can try to open this file with an older Kig " - "version (0.4 to 0.6),\n" - "and then save it again, which will save it in the " - "new format." ).arg( version ) ); - return 0; - } - else if ( major == 0 && minor <= 6 ) - return load04( file, main ); - else - return load07( file, main ); -} - -KigDocument* KigFilterNative::load04( const TQString& file, const TQDomElement& docelem ) -{ - bool ok = true; - - KigDocument* ret = new KigDocument(); - - for ( TQDomNode n = docelem.firstChild(); ! n.isNull(); n = n.nextSibling() ) - { - TQDomElement e = n.toElement(); - if ( e.isNull() ) continue; - if ( e.tagName() == "CoordinateSystem" ) - { - const TQCString type = e.text().latin1(); - CoordinateSystem* s = CoordinateSystemFactory::build( type.data() ); - if ( ! s ) - { - warning( i18n( "This Kig file has a coordinate system " - "that this Kig version does not support.\n" - "A standard coordinate system will be used " - "instead." ) ); - } - else ret->setCoordinateSystem( s ); - } - else if ( e.tagName() == "Objects" ) - { - std::vector retcalcers; - std::vector retholders; - - // first pass: do a topological sort of the objects, to support - // randomly ordered files... - std::vector elems; - TQDomElement objectselem = e; - for ( TQDomNode o = objectselem.firstChild(); ! o.isNull(); o = o.nextSibling() ) - { - e = o.toElement(); - if ( e.isNull() ) continue; - uint id; - if ( e.tagName() == "Data" || e.tagName() == "Property" || e.tagName() == "Object" ) - { - // fetch the id - TQString tmp = e.attribute("id"); - id = tmp.toInt(&ok); - if ( !ok ) KIG_FILTER_PARSE_ERROR; - - extendVect( elems, id ); - elems[id-1].el = e; - } - else continue; - - for ( TQDomNode p = e.firstChild(); !p.isNull(); p = p.nextSibling() ) - { - TQDomElement f = p.toElement(); - if ( f.isNull() ) continue; - if ( f.tagName() == "Parent" ) - { - TQString tmp = f.attribute( "id" ); - uint pid = tmp.toInt( &ok ); - if ( ! ok ) KIG_FILTER_PARSE_ERROR; - - extendVect( elems, id ); - elems[id-1].parents.push_back( pid ); - } - } - }; - - for ( uint i = 0; i < elems.size(); ++i ) - if ( elems[i].el.isNull() ) - KIG_FILTER_PARSE_ERROR; - elems = sortElems( elems ); - - retcalcers.resize( elems.size(), 0 ); - - for ( std::vector::iterator i = elems.begin(); - i != elems.end(); ++i ) - { - TQDomElement e = i->el; - bool internal = e.attribute( "internal" ) == "true" ? true : false; - ObjectCalcer* o = 0; - if ( e.tagName() == "Data" ) - { - TQString tmp = e.attribute( "type" ); - if ( tmp.isNull() ) - KIG_FILTER_PARSE_ERROR; - TQString error; - ObjectImp* imp = ObjectImpFactory::instance()->deserialize( tmp, e, error ); - if ( ( !imp ) && !error.isEmpty() ) - { - parseError( file, error ); - return 0; - } - o = new ObjectConstCalcer( imp ); - } - else if ( e.tagName() == "Property" ) - { - TQCString propname; - for ( TQDomElement ec = e.firstChild().toElement(); !ec.isNull(); - ec = ec.nextSibling().toElement() ) - { - if ( ec.tagName() == "Property" ) - propname = ec.text().latin1(); - }; - - if ( i->parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - ObjectCalcer* parent = retcalcers[i->parents[0] -1]; - QCStringList propnames = parent->imp()->propertiesInternalNames(); - int propid = propnames.findIndex( propname ); - if ( propid == -1 ) - KIG_FILTER_PARSE_ERROR; - - o = new ObjectPropertyCalcer( parent, propid ); - } - else if ( e.tagName() == "Object" ) - { - TQString tmp = e.attribute( "type" ); - if ( tmp.isNull() ) - KIG_FILTER_PARSE_ERROR; - - const ObjectType* type = - ObjectTypeFactory::instance()->find( tmp.latin1() ); - if ( !type ) - { - notSupported( file, 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( tmp ) ); - return 0; - }; - - std::vector parents; - for ( std::vector::iterator j = i->parents.begin(); - j != i->parents.end(); ++j ) - parents.push_back( retcalcers[*j - 1] ); - - o = new ObjectTypeCalcer( type, parents ); - } - else continue; - - o->calc( *ret ); - retcalcers[i->id - 1] = o; - - if ( ! internal ) - { - TQString tmp = e.attribute( "color" ); - TQColor color( tmp ); - if ( !color.isValid() ) - KIG_FILTER_PARSE_ERROR; - - tmp = e.attribute( "shown" ); - bool shown = !( tmp == "false" || tmp == "no" ); - - tmp = e.attribute( "width" ); - int width = tmp.toInt( &ok ); - if ( ! ok ) width = -1; - - ObjectDrawer* d = new ObjectDrawer( color, width, shown ); - retholders.push_back( new ObjectHolder( o, d ) ); - } - } - ret->addObjects( retholders ); - } - else continue; // be forward-compatible.. - }; - - return ret; -} - -KigFilterNative* KigFilterNative::instance() -{ - static KigFilterNative f; - return &f; -} - -KigDocument* KigFilterNative::load07( const TQString& file, const TQDomElement& docelem ) -{ - KigDocument* ret = new KigDocument(); - - bool ok = true; - std::vector calcers; - std::vector holders; - - TQString t = docelem.attribute( "grid" ); - bool tmphide = ( t == "false" ) || ( t == "no" ) || ( t == "0" ); - ret->setGrid( !tmphide ); - t = docelem.attribute( "axes" ); - tmphide = ( t == "false" ) || ( t == "no" ) || ( t == "0" ); - ret->setAxes( !tmphide ); - - for ( TQDomElement subsectionelement = docelem.firstChild().toElement(); ! subsectionelement.isNull(); - subsectionelement = subsectionelement.nextSibling().toElement() ) - { - if ( subsectionelement.tagName() == "CoordinateSystem" ) - { - TQString tmptype = subsectionelement.text(); - // compatibility code - to support Invisible coord system... - if ( tmptype == "Invisible" ) - { - tmptype = "Euclidean"; - ret->setGrid( false ); - ret->setAxes( false ); - } - const TQCString type = tmptype.latin1(); - CoordinateSystem* s = CoordinateSystemFactory::build( type.data() ); - if ( ! s ) - { - warning( i18n( "This Kig file has a coordinate system " - "that this Kig version does not support.\n" - "A standard coordinate system will be used " - "instead." ) ); - } - else ret->setCoordinateSystem( s ); - } - else if ( subsectionelement.tagName() == "Hierarchy" ) - { - for ( TQDomElement e = subsectionelement.firstChild().toElement(); ! e.isNull(); - e = e.nextSibling().toElement() ) - { - TQString tmp = e.attribute( "id" ); - uint id = tmp.toInt( &ok ); - if ( id <= 0 ) KIG_FILTER_PARSE_ERROR; - - std::vector parents; - for ( TQDomElement parentel = e.firstChild().toElement(); ! parentel.isNull(); - parentel = parentel.nextSibling().toElement() ) - { - if ( parentel.tagName() != "Parent" ) continue; - TQString tmp = parentel.attribute( "id" ); - uint parentid = tmp.toInt( &ok ); - if ( ! ok ) KIG_FILTER_PARSE_ERROR; - if ( parentid == 0 || parentid > calcers.size() ) KIG_FILTER_PARSE_ERROR; - ObjectCalcer* parent = calcers[parentid - 1].get(); - if ( ! parent ) KIG_FILTER_PARSE_ERROR; - parents.push_back( parent ); - } - - ObjectCalcer* o = 0; - - if ( e.tagName() == "Data" ) - { - if ( !parents.empty() ) KIG_FILTER_PARSE_ERROR; - TQString tmp = e.attribute( "type" ); - TQString error; - ObjectImp* imp = ObjectImpFactory::instance()->deserialize( tmp, e, error ); - if ( ( !imp ) && !error.isEmpty() ) - { - parseError( file, error ); - return 0; - } - o = new ObjectConstCalcer( imp ); - } - else if ( e.tagName() == "Property" ) - { - if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; - TQCString propname = e.attribute( "which" ).latin1(); - - ObjectCalcer* parent = parents[0]; - int propid = parent->imp()->propertiesInternalNames().findIndex( propname ); - if ( propid == -1 ) KIG_FILTER_PARSE_ERROR; - - o = new ObjectPropertyCalcer( parent, propid ); - } - else if ( e.tagName() == "Object" ) - { - TQString tmp = e.attribute( "type" ); - const ObjectType* type = - ObjectTypeFactory::instance()->find( tmp.latin1() ); - if ( ! type ) - { - notSupported( file, 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( tmp ) ); - return 0; - } - - // mp: (I take the responsibility for this!) explanation: the usual ObjectTypeCalcer - // constructor also "sortArgs" the parents. I believe that this *must not* be done - // when loading from a saved kig file for the following reasons: - // 1. the arguments should already be in their intended order, since the file was - // saved from a working hierarchy; furthermore we actually want to restore the original - // hierarchy, not really to also fix possible problems with the original hierarchy; - // 2. calling sortArgs could have undesirable side effects in particular situations, - // since kig actually allow an ObjectType to produce different type of ObjectImp's - // it may happen that the parents of an object do not satisfy the requirements - // enforced by sortArgs (while moving around the free objects) but still be - // perfectly valid - o = new ObjectTypeCalcer( type, parents, false ); - } - else KIG_FILTER_PARSE_ERROR; - - o->calc( *ret ); - calcers.resize( id, 0 ); - calcers[id-1] = o; - } - } - else if ( subsectionelement.tagName() == "View" ) - { - for ( TQDomElement e = subsectionelement.firstChild().toElement(); ! e.isNull(); - e = e.nextSibling().toElement() ) - { - if ( e.tagName() != "Draw" ) KIG_FILTER_PARSE_ERROR; - - TQString tmp = e.attribute( "object" ); - uint id = tmp.toInt( &ok ); - if ( !ok ) KIG_FILTER_PARSE_ERROR; - if ( id <= 0 || id > calcers.size() ) - KIG_FILTER_PARSE_ERROR; - ObjectCalcer* calcer = calcers[id-1].get(); - - tmp = e.attribute( "color" ); - TQColor color( tmp ); - if ( !color.isValid() ) - KIG_FILTER_PARSE_ERROR; - - tmp = e.attribute( "shown" ); - bool shown = !( tmp == "false" || tmp == "no" ); - - tmp = e.attribute( "width" ); - int width = tmp.toInt( &ok ); - if ( ! ok ) width = -1; - - tmp = e.attribute( "style" ); - Qt::PenStyle style = ObjectDrawer::styleFromString( tmp ); - - tmp = e.attribute( "point-style" ); - int pointstyle = ObjectDrawer::pointStyleFromString( tmp ); - - ObjectConstCalcer* namecalcer = 0; - tmp = e.attribute( "namecalcer" ); - if ( tmp != "none" && !tmp.isEmpty() ) - { - int ncid = tmp.toInt( &ok ); - if ( !ok ) KIG_FILTER_PARSE_ERROR; - if ( ncid <= 0 || ncid > calcers.size() ) - KIG_FILTER_PARSE_ERROR; - if ( ! dynamic_cast( calcers[ncid-1].get() ) ) - KIG_FILTER_PARSE_ERROR; - namecalcer = static_cast( calcers[ncid-1].get() ); - } - - ObjectDrawer* drawer = new ObjectDrawer( color, width, shown, style, pointstyle ); - holders.push_back( new ObjectHolder( calcer, drawer, namecalcer ) ); - } - } - } - - ret->addObjects( holders ); - return ret; -} - -bool KigFilterNative::save07( const KigDocument& kdoc, TQTextStream& stream ) -{ - TQDomDocument doc( "KigDocument" ); - - TQDomElement docelem = doc.createElement( "KigDocument" ); - docelem.setAttribute( "Version", KIGVERSION ); - docelem.setAttribute( "CompatibilityVersion", "0.7.0" ); - docelem.setAttribute( "grid", kdoc.grid() ); - docelem.setAttribute( "axes", kdoc.axes() ); - - TQDomElement cselem = doc.createElement( "CoordinateSystem" ); - cselem.appendChild( doc.createTextNode( kdoc.coordinateSystem().type() ) ); - docelem.appendChild( cselem ); - - std::vector holders = kdoc.objects(); - std::vector calcers = getAllParents( getAllCalcers( holders ) ); - calcers = calcPath( calcers ); - - TQDomElement hierelem = doc.createElement( "Hierarchy" ); - std::map idmap; - for ( std::vector::const_iterator i = calcers.begin(); - i != calcers.end(); ++i ) - idmap[*i] = ( i - calcers.begin() ) + 1; - int id = 1; - - for ( std::vector::const_iterator i = calcers.begin(); i != calcers.end(); ++i ) - { - TQDomElement objectelem; - if ( dynamic_cast( *i ) ) - { - objectelem = doc.createElement( "Data" ); - TQString ser = - ObjectImpFactory::instance()->serialize( *(*i)->imp(), objectelem, doc ); - objectelem.setAttribute( "type", ser ); - } - else if ( dynamic_cast( *i ) ) - { - const ObjectPropertyCalcer* o = static_cast( *i ); - objectelem = doc.createElement( "Property" ); - - TQCString propname = o->parent()->imp()->propertiesInternalNames()[o->propId()]; - objectelem.setAttribute( TQString("which"), TQString(propname) ); - } - else if ( dynamic_cast( *i ) ) - { - const ObjectTypeCalcer* o = static_cast( *i ); - objectelem = doc.createElement( "Object" ); - objectelem.setAttribute( "type", o->type()->fullName() ); - } - else assert( false ); - - const std::vector parents = ( *i )->parents(); - for ( std::vector::const_iterator i = parents.begin(); i != parents.end(); ++i ) - { - std::map::const_iterator idp = idmap.find( *i ); - assert( idp != idmap.end() ); - int pid = idp->second; - TQDomElement pel = doc.createElement( "Parent" ); - pel.setAttribute( "id", pid ); - objectelem.appendChild( pel ); - } - - objectelem.setAttribute( "id", id++ ); - hierelem.appendChild( objectelem ); - } - docelem.appendChild( hierelem ); - - TQDomElement windowelem = doc.createElement( "View" ); - for ( std::vector::iterator i = holders.begin(); i != holders.end(); ++i ) - { - std::map::const_iterator idp = idmap.find( ( *i )->calcer() ); - assert( idp != idmap.end() ); - int id = idp->second; - - const ObjectDrawer* d = ( *i )->drawer(); - TQDomElement drawelem = doc.createElement( "Draw" ); - drawelem.setAttribute( "object", id ); - drawelem.setAttribute( "color", d->color().name() ); - drawelem.setAttribute( "shown", TQString::fromLatin1( d->shown() ? "true" : "false" ) ); - drawelem.setAttribute( "width", TQString::number( d->width() ) ); - drawelem.setAttribute( "style", d->styleToString() ); - drawelem.setAttribute( "point-style", d->pointStyleToString() ); - - ObjectCalcer* namecalcer = ( *i )->nameCalcer(); - if ( namecalcer ) - { - std::map::const_iterator ncp = idmap.find( namecalcer ); - assert( ncp != idmap.end() ); - int ncid = ncp->second; - drawelem.setAttribute( "namecalcer", ncid ); - } - else - { - drawelem.setAttribute( "namecalcer", "none" ); - } - - windowelem.appendChild( drawelem ); - }; - docelem.appendChild( windowelem ); - - doc.appendChild( docelem ); - stream << doc.toString(); - return true; -} - -bool KigFilterNative::save( const KigDocument& data, const TQString& file ) -{ - return save07( data, file ); -} - -bool KigFilterNative::save07( const KigDocument& data, const TQString& outfile ) -{ - // we have an empty outfile, so we have to print all to stdout - if ( outfile.isEmpty() ) - { - TQTextStream stdoutstream( stdout, IO_WriteOnly ); - return save07( data, stdoutstream ); - } -#ifndef KIG_NO_COMPRESSED_FILES - if ( !outfile.endsWith( ".kig", false ) ) - { - // the user wants to save a compressed file, so we have to save our kig - // file to a temp file and then compress it... - - TQString tempdir = TDEGlobal::dirs()->saveLocation( "tmp" ); - if ( tempdir.isEmpty() ) - return false; - - TQString tempname = outfile.section( '/', -1 ); - if ( outfile.endsWith( ".kigz", false ) ) - tempname.remove( TQRegExp( "\\.[Kk][Ii][Gg][Zz]$" ) ); - else - return false; - - TQString tmpfile = tempdir + tempname + ".kig"; - TQFile ftmpfile( tmpfile ); - if ( !ftmpfile.open( IO_WriteOnly ) ) - return false; - TQTextStream stream( &ftmpfile ); - if ( !save07( data, stream ) ) - return false; - ftmpfile.close(); - - kdDebug() << "tmp saved file: " << tmpfile << endl; - - // creating the archive and adding our file - KTar* ark = new KTar( outfile, "application/x-gzip" ); - ark->open( IO_WriteOnly ); - ark->addLocalFile( tmpfile, tempname + ".kig" ); - ark->close(); - - // finally, removing temp file - TQFile::remove( tmpfile ); - - return true; - } - else - { -#endif - TQFile file( outfile ); - if ( ! file.open( IO_WriteOnly ) ) - { - fileNotFound( outfile ); - return false; - } - TQTextStream stream( &file ); - return save07( data, stream ); -#ifndef KIG_NO_COMPRESSED_FILES - } - - // we should never reach this point... - return false; -#endif -} - -/* -bool KigFilterNative::save( const KigDocument& data, TQTextStream& stream ) -{ - return save07( data, stream ); -} -*/ diff --git a/kig/filters/native-filter.cpp b/kig/filters/native-filter.cpp new file mode 100644 index 00000000..cf6521b2 --- /dev/null +++ b/kig/filters/native-filter.cpp @@ -0,0 +1,747 @@ +// 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 "native-filter.h" + +#include "../kig/kig_part.h" +#include "../kig/kig_document.h" +#include "../objects/bogus_imp.h" +#include "../objects/object_type.h" +#include "../objects/object_imp.h" +#include "../objects/object_calcer.h" +#include "../objects/object_drawer.h" +#include "../objects/object_holder.h" +#include "../objects/object_type_factory.h" +#include "../objects/object_imp_factory.h" +#include "../misc/calcpaths.h" +#include "../misc/coordinate_system.h" + +#include "config.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +struct HierElem +{ + int id; + std::vector parents; + TQDomElement el; +}; + +static void extendVect( std::vector& vect, uint size ) +{ + if ( size > vect.size() ) + { + int osize = vect.size(); + vect.resize( size ); + for ( uint i = osize; i < size; ++i ) + vect[i].id = i+1; + }; +} + +static void visitElem( std::vector& ret, + const std::vector& elems, + std::vector& seen, + int i ) +{ + if ( !seen[i] ) + { + for ( uint j = 0; j < elems[i].parents.size(); ++j ) + visitElem( ret, elems, seen, elems[i].parents[j] - 1); + ret.push_back( elems[i] ); + seen[i] = true; + }; +} + +static std::vector sortElems( const std::vector elems ) +{ + std::vector ret; + std::vector seenElems( elems.size(), false ); + for ( uint i = 0; i < elems.size(); ++i ) + visitElem( ret, elems, seenElems, i ); + return ret; +} + +KigFilterNative::KigFilterNative() +{ +} + +KigFilterNative::~KigFilterNative() +{ +} + +bool KigFilterNative::supportMime( const TQString& mime ) +{ + return mime == "application/x-kig"; +} + +KigDocument* KigFilterNative::load( const TQString& file ) +{ + TQFile ffile( file ); + if ( ! ffile.open( IO_ReadOnly ) ) + { + fileNotFound( file ); + return 0; + }; + + TQFile kigdoc( file ); +#ifndef KIG_NO_COMPRESSED_FILES + bool iscompressed = false; + if ( !file.endsWith( ".kig", false ) ) + { + // the file is compressed, so we have to decompress it and fetch the + // kig file inside it... + iscompressed = true; + + TQString tempdir = TDEGlobal::dirs()->saveLocation( "tmp" ); + if ( tempdir.isEmpty() ) + KIG_FILTER_PARSE_ERROR; + + TQString tempname = file.section( '/', -1 ); + if ( file.endsWith( ".kigz", false ) ) + { + tempname.remove( TQRegExp( "\\.[Kk][Ii][Gg][Zz]$" ) ); + } + else + KIG_FILTER_PARSE_ERROR; + // reading compressed file + KTar* ark = new KTar( file, "application/x-gzip" ); + ark->open( IO_ReadOnly ); + const KArchiveDirectory* dir = ark->directory(); +// assert( dir ); + TQStringList entries = dir->entries(); + TQStringList kigfiles = entries.grep( TQRegExp( "\\.kig$" ) ); + if ( kigfiles.count() != 1 ) + // I throw a generic parse error here, but I should warn the user that + // this kig archive file doesn't contain one kig file (it contains no + // kig files or more than one). + KIG_FILTER_PARSE_ERROR; + const KArchiveEntry* kigz = dir->entry( kigfiles[0] ); + if ( !kigz->isFile() ) + KIG_FILTER_PARSE_ERROR; + dynamic_cast( kigz )->copyTo( tempdir ); + kdDebug() << "extracted file: " << tempdir + kigz->name() << endl + << "exists: " << TQFile::exists( tempdir + kigz->name() ) << endl; + + kigdoc.setName( tempdir + kigz->name() ); + } +#endif + + if ( !kigdoc.open( IO_ReadOnly ) ) + KIG_FILTER_PARSE_ERROR; + + TQDomDocument doc( "KigDocument" ); + if ( !doc.setContent( &kigdoc ) ) + KIG_FILTER_PARSE_ERROR; + kigdoc.close(); + +#ifndef KIG_NO_COMPRESSED_FILES + // removing temp file + if ( iscompressed ) + kigdoc.remove(); +#endif + + TQDomElement main = doc.documentElement(); + + TQString version = main.attribute( "CompatibilityVersion" ); + if ( version.isEmpty() ) version = main.attribute( "Version" ); + if ( version.isEmpty() ) version = main.attribute( "version" ); + if ( version.isEmpty() ) + KIG_FILTER_PARSE_ERROR; + + // matches 0.1, 0.2.0, 153.128.99 etc. + TQRegExp versionre( "(\\d+)\\.(\\d+)(\\.(\\d+))?" ); + if ( ! versionre.exactMatch( version ) ) + KIG_FILTER_PARSE_ERROR; + bool ok = true; + int major = versionre.cap( 1 ).toInt( &ok ); + bool ok2 = true; + int minor = versionre.cap( 2 ).toInt( &ok2 ); + if ( ! ok || ! ok2 ) + KIG_FILTER_PARSE_ERROR; + + // int minorminor = versionre.cap( 4 ).toInt( &ok ); + + // we only support 0.[0-7] and 1.0.* + if ( major > 0 || minor > 9 ) + { + notSupported( file, i18n( "This file was created by Kig version \"%1\", " + "which this version cannot open." ).arg( version ) ); + return 0; + } + else if ( major == 0 && minor <= 3 ) + { + notSupported( file, i18n( "This file was created by Kig version \"%1\".\n" + "Support for older Kig formats (pre-0.4) has been " + "removed from Kig.\n" + "You can try to open this file with an older Kig " + "version (0.4 to 0.6),\n" + "and then save it again, which will save it in the " + "new format." ).arg( version ) ); + return 0; + } + else if ( major == 0 && minor <= 6 ) + return load04( file, main ); + else + return load07( file, main ); +} + +KigDocument* KigFilterNative::load04( const TQString& file, const TQDomElement& docelem ) +{ + bool ok = true; + + KigDocument* ret = new KigDocument(); + + for ( TQDomNode n = docelem.firstChild(); ! n.isNull(); n = n.nextSibling() ) + { + TQDomElement e = n.toElement(); + if ( e.isNull() ) continue; + if ( e.tagName() == "CoordinateSystem" ) + { + const TQCString type = e.text().latin1(); + CoordinateSystem* s = CoordinateSystemFactory::build( type.data() ); + if ( ! s ) + { + warning( i18n( "This Kig file has a coordinate system " + "that this Kig version does not support.\n" + "A standard coordinate system will be used " + "instead." ) ); + } + else ret->setCoordinateSystem( s ); + } + else if ( e.tagName() == "Objects" ) + { + std::vector retcalcers; + std::vector retholders; + + // first pass: do a topological sort of the objects, to support + // randomly ordered files... + std::vector elems; + TQDomElement objectselem = e; + for ( TQDomNode o = objectselem.firstChild(); ! o.isNull(); o = o.nextSibling() ) + { + e = o.toElement(); + if ( e.isNull() ) continue; + uint id; + if ( e.tagName() == "Data" || e.tagName() == "Property" || e.tagName() == "Object" ) + { + // fetch the id + TQString tmp = e.attribute("id"); + id = tmp.toInt(&ok); + if ( !ok ) KIG_FILTER_PARSE_ERROR; + + extendVect( elems, id ); + elems[id-1].el = e; + } + else continue; + + for ( TQDomNode p = e.firstChild(); !p.isNull(); p = p.nextSibling() ) + { + TQDomElement f = p.toElement(); + if ( f.isNull() ) continue; + if ( f.tagName() == "Parent" ) + { + TQString tmp = f.attribute( "id" ); + uint pid = tmp.toInt( &ok ); + if ( ! ok ) KIG_FILTER_PARSE_ERROR; + + extendVect( elems, id ); + elems[id-1].parents.push_back( pid ); + } + } + }; + + for ( uint i = 0; i < elems.size(); ++i ) + if ( elems[i].el.isNull() ) + KIG_FILTER_PARSE_ERROR; + elems = sortElems( elems ); + + retcalcers.resize( elems.size(), 0 ); + + for ( std::vector::iterator i = elems.begin(); + i != elems.end(); ++i ) + { + TQDomElement e = i->el; + bool internal = e.attribute( "internal" ) == "true" ? true : false; + ObjectCalcer* o = 0; + if ( e.tagName() == "Data" ) + { + TQString tmp = e.attribute( "type" ); + if ( tmp.isNull() ) + KIG_FILTER_PARSE_ERROR; + TQString error; + ObjectImp* imp = ObjectImpFactory::instance()->deserialize( tmp, e, error ); + if ( ( !imp ) && !error.isEmpty() ) + { + parseError( file, error ); + return 0; + } + o = new ObjectConstCalcer( imp ); + } + else if ( e.tagName() == "Property" ) + { + TQCString propname; + for ( TQDomElement ec = e.firstChild().toElement(); !ec.isNull(); + ec = ec.nextSibling().toElement() ) + { + if ( ec.tagName() == "Property" ) + propname = ec.text().latin1(); + }; + + if ( i->parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + ObjectCalcer* parent = retcalcers[i->parents[0] -1]; + QCStringList propnames = parent->imp()->propertiesInternalNames(); + int propid = propnames.findIndex( propname ); + if ( propid == -1 ) + KIG_FILTER_PARSE_ERROR; + + o = new ObjectPropertyCalcer( parent, propid ); + } + else if ( e.tagName() == "Object" ) + { + TQString tmp = e.attribute( "type" ); + if ( tmp.isNull() ) + KIG_FILTER_PARSE_ERROR; + + const ObjectType* type = + ObjectTypeFactory::instance()->find( tmp.latin1() ); + if ( !type ) + { + notSupported( file, 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( tmp ) ); + return 0; + }; + + std::vector parents; + for ( std::vector::iterator j = i->parents.begin(); + j != i->parents.end(); ++j ) + parents.push_back( retcalcers[*j - 1] ); + + o = new ObjectTypeCalcer( type, parents ); + } + else continue; + + o->calc( *ret ); + retcalcers[i->id - 1] = o; + + if ( ! internal ) + { + TQString tmp = e.attribute( "color" ); + TQColor color( tmp ); + if ( !color.isValid() ) + KIG_FILTER_PARSE_ERROR; + + tmp = e.attribute( "shown" ); + bool shown = !( tmp == "false" || tmp == "no" ); + + tmp = e.attribute( "width" ); + int width = tmp.toInt( &ok ); + if ( ! ok ) width = -1; + + ObjectDrawer* d = new ObjectDrawer( color, width, shown ); + retholders.push_back( new ObjectHolder( o, d ) ); + } + } + ret->addObjects( retholders ); + } + else continue; // be forward-compatible.. + }; + + return ret; +} + +KigFilterNative* KigFilterNative::instance() +{ + static KigFilterNative f; + return &f; +} + +KigDocument* KigFilterNative::load07( const TQString& file, const TQDomElement& docelem ) +{ + KigDocument* ret = new KigDocument(); + + bool ok = true; + std::vector calcers; + std::vector holders; + + TQString t = docelem.attribute( "grid" ); + bool tmphide = ( t == "false" ) || ( t == "no" ) || ( t == "0" ); + ret->setGrid( !tmphide ); + t = docelem.attribute( "axes" ); + tmphide = ( t == "false" ) || ( t == "no" ) || ( t == "0" ); + ret->setAxes( !tmphide ); + + for ( TQDomElement subsectionelement = docelem.firstChild().toElement(); ! subsectionelement.isNull(); + subsectionelement = subsectionelement.nextSibling().toElement() ) + { + if ( subsectionelement.tagName() == "CoordinateSystem" ) + { + TQString tmptype = subsectionelement.text(); + // compatibility code - to support Invisible coord system... + if ( tmptype == "Invisible" ) + { + tmptype = "Euclidean"; + ret->setGrid( false ); + ret->setAxes( false ); + } + const TQCString type = tmptype.latin1(); + CoordinateSystem* s = CoordinateSystemFactory::build( type.data() ); + if ( ! s ) + { + warning( i18n( "This Kig file has a coordinate system " + "that this Kig version does not support.\n" + "A standard coordinate system will be used " + "instead." ) ); + } + else ret->setCoordinateSystem( s ); + } + else if ( subsectionelement.tagName() == "Hierarchy" ) + { + for ( TQDomElement e = subsectionelement.firstChild().toElement(); ! e.isNull(); + e = e.nextSibling().toElement() ) + { + TQString tmp = e.attribute( "id" ); + uint id = tmp.toInt( &ok ); + if ( id <= 0 ) KIG_FILTER_PARSE_ERROR; + + std::vector parents; + for ( TQDomElement parentel = e.firstChild().toElement(); ! parentel.isNull(); + parentel = parentel.nextSibling().toElement() ) + { + if ( parentel.tagName() != "Parent" ) continue; + TQString tmp = parentel.attribute( "id" ); + uint parentid = tmp.toInt( &ok ); + if ( ! ok ) KIG_FILTER_PARSE_ERROR; + if ( parentid == 0 || parentid > calcers.size() ) KIG_FILTER_PARSE_ERROR; + ObjectCalcer* parent = calcers[parentid - 1].get(); + if ( ! parent ) KIG_FILTER_PARSE_ERROR; + parents.push_back( parent ); + } + + ObjectCalcer* o = 0; + + if ( e.tagName() == "Data" ) + { + if ( !parents.empty() ) KIG_FILTER_PARSE_ERROR; + TQString tmp = e.attribute( "type" ); + TQString error; + ObjectImp* imp = ObjectImpFactory::instance()->deserialize( tmp, e, error ); + if ( ( !imp ) && !error.isEmpty() ) + { + parseError( file, error ); + return 0; + } + o = new ObjectConstCalcer( imp ); + } + else if ( e.tagName() == "Property" ) + { + if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR; + TQCString propname = e.attribute( "which" ).latin1(); + + ObjectCalcer* parent = parents[0]; + int propid = parent->imp()->propertiesInternalNames().findIndex( propname ); + if ( propid == -1 ) KIG_FILTER_PARSE_ERROR; + + o = new ObjectPropertyCalcer( parent, propid ); + } + else if ( e.tagName() == "Object" ) + { + TQString tmp = e.attribute( "type" ); + const ObjectType* type = + ObjectTypeFactory::instance()->find( tmp.latin1() ); + if ( ! type ) + { + notSupported( file, 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( tmp ) ); + return 0; + } + + // mp: (I take the responsibility for this!) explanation: the usual ObjectTypeCalcer + // constructor also "sortArgs" the parents. I believe that this *must not* be done + // when loading from a saved kig file for the following reasons: + // 1. the arguments should already be in their intended order, since the file was + // saved from a working hierarchy; furthermore we actually want to restore the original + // hierarchy, not really to also fix possible problems with the original hierarchy; + // 2. calling sortArgs could have undesirable side effects in particular situations, + // since kig actually allow an ObjectType to produce different type of ObjectImp's + // it may happen that the parents of an object do not satisfy the requirements + // enforced by sortArgs (while moving around the free objects) but still be + // perfectly valid + o = new ObjectTypeCalcer( type, parents, false ); + } + else KIG_FILTER_PARSE_ERROR; + + o->calc( *ret ); + calcers.resize( id, 0 ); + calcers[id-1] = o; + } + } + else if ( subsectionelement.tagName() == "View" ) + { + for ( TQDomElement e = subsectionelement.firstChild().toElement(); ! e.isNull(); + e = e.nextSibling().toElement() ) + { + if ( e.tagName() != "Draw" ) KIG_FILTER_PARSE_ERROR; + + TQString tmp = e.attribute( "object" ); + uint id = tmp.toInt( &ok ); + if ( !ok ) KIG_FILTER_PARSE_ERROR; + if ( id <= 0 || id > calcers.size() ) + KIG_FILTER_PARSE_ERROR; + ObjectCalcer* calcer = calcers[id-1].get(); + + tmp = e.attribute( "color" ); + TQColor color( tmp ); + if ( !color.isValid() ) + KIG_FILTER_PARSE_ERROR; + + tmp = e.attribute( "shown" ); + bool shown = !( tmp == "false" || tmp == "no" ); + + tmp = e.attribute( "width" ); + int width = tmp.toInt( &ok ); + if ( ! ok ) width = -1; + + tmp = e.attribute( "style" ); + Qt::PenStyle style = ObjectDrawer::styleFromString( tmp ); + + tmp = e.attribute( "point-style" ); + int pointstyle = ObjectDrawer::pointStyleFromString( tmp ); + + ObjectConstCalcer* namecalcer = 0; + tmp = e.attribute( "namecalcer" ); + if ( tmp != "none" && !tmp.isEmpty() ) + { + int ncid = tmp.toInt( &ok ); + if ( !ok ) KIG_FILTER_PARSE_ERROR; + if ( ncid <= 0 || ncid > calcers.size() ) + KIG_FILTER_PARSE_ERROR; + if ( ! dynamic_cast( calcers[ncid-1].get() ) ) + KIG_FILTER_PARSE_ERROR; + namecalcer = static_cast( calcers[ncid-1].get() ); + } + + ObjectDrawer* drawer = new ObjectDrawer( color, width, shown, style, pointstyle ); + holders.push_back( new ObjectHolder( calcer, drawer, namecalcer ) ); + } + } + } + + ret->addObjects( holders ); + return ret; +} + +bool KigFilterNative::save07( const KigDocument& kdoc, TQTextStream& stream ) +{ + TQDomDocument doc( "KigDocument" ); + + TQDomElement docelem = doc.createElement( "KigDocument" ); + docelem.setAttribute( "Version", KIGVERSION ); + docelem.setAttribute( "CompatibilityVersion", "0.7.0" ); + docelem.setAttribute( "grid", kdoc.grid() ); + docelem.setAttribute( "axes", kdoc.axes() ); + + TQDomElement cselem = doc.createElement( "CoordinateSystem" ); + cselem.appendChild( doc.createTextNode( kdoc.coordinateSystem().type() ) ); + docelem.appendChild( cselem ); + + std::vector holders = kdoc.objects(); + std::vector calcers = getAllParents( getAllCalcers( holders ) ); + calcers = calcPath( calcers ); + + TQDomElement hierelem = doc.createElement( "Hierarchy" ); + std::map idmap; + for ( std::vector::const_iterator i = calcers.begin(); + i != calcers.end(); ++i ) + idmap[*i] = ( i - calcers.begin() ) + 1; + int id = 1; + + for ( std::vector::const_iterator i = calcers.begin(); i != calcers.end(); ++i ) + { + TQDomElement objectelem; + if ( dynamic_cast( *i ) ) + { + objectelem = doc.createElement( "Data" ); + TQString ser = + ObjectImpFactory::instance()->serialize( *(*i)->imp(), objectelem, doc ); + objectelem.setAttribute( "type", ser ); + } + else if ( dynamic_cast( *i ) ) + { + const ObjectPropertyCalcer* o = static_cast( *i ); + objectelem = doc.createElement( "Property" ); + + TQCString propname = o->parent()->imp()->propertiesInternalNames()[o->propId()]; + objectelem.setAttribute( TQString("which"), TQString(propname) ); + } + else if ( dynamic_cast( *i ) ) + { + const ObjectTypeCalcer* o = static_cast( *i ); + objectelem = doc.createElement( "Object" ); + objectelem.setAttribute( "type", o->type()->fullName() ); + } + else assert( false ); + + const std::vector parents = ( *i )->parents(); + for ( std::vector::const_iterator i = parents.begin(); i != parents.end(); ++i ) + { + std::map::const_iterator idp = idmap.find( *i ); + assert( idp != idmap.end() ); + int pid = idp->second; + TQDomElement pel = doc.createElement( "Parent" ); + pel.setAttribute( "id", pid ); + objectelem.appendChild( pel ); + } + + objectelem.setAttribute( "id", id++ ); + hierelem.appendChild( objectelem ); + } + docelem.appendChild( hierelem ); + + TQDomElement windowelem = doc.createElement( "View" ); + for ( std::vector::iterator i = holders.begin(); i != holders.end(); ++i ) + { + std::map::const_iterator idp = idmap.find( ( *i )->calcer() ); + assert( idp != idmap.end() ); + int id = idp->second; + + const ObjectDrawer* d = ( *i )->drawer(); + TQDomElement drawelem = doc.createElement( "Draw" ); + drawelem.setAttribute( "object", id ); + drawelem.setAttribute( "color", d->color().name() ); + drawelem.setAttribute( "shown", TQString::fromLatin1( d->shown() ? "true" : "false" ) ); + drawelem.setAttribute( "width", TQString::number( d->width() ) ); + drawelem.setAttribute( "style", d->styleToString() ); + drawelem.setAttribute( "point-style", d->pointStyleToString() ); + + ObjectCalcer* namecalcer = ( *i )->nameCalcer(); + if ( namecalcer ) + { + std::map::const_iterator ncp = idmap.find( namecalcer ); + assert( ncp != idmap.end() ); + int ncid = ncp->second; + drawelem.setAttribute( "namecalcer", ncid ); + } + else + { + drawelem.setAttribute( "namecalcer", "none" ); + } + + windowelem.appendChild( drawelem ); + }; + docelem.appendChild( windowelem ); + + doc.appendChild( docelem ); + stream << doc.toString(); + return true; +} + +bool KigFilterNative::save( const KigDocument& data, const TQString& file ) +{ + return save07( data, file ); +} + +bool KigFilterNative::save07( const KigDocument& data, const TQString& outfile ) +{ + // we have an empty outfile, so we have to print all to stdout + if ( outfile.isEmpty() ) + { + TQTextStream stdoutstream( stdout, IO_WriteOnly ); + return save07( data, stdoutstream ); + } +#ifndef KIG_NO_COMPRESSED_FILES + if ( !outfile.endsWith( ".kig", false ) ) + { + // the user wants to save a compressed file, so we have to save our kig + // file to a temp file and then compress it... + + TQString tempdir = TDEGlobal::dirs()->saveLocation( "tmp" ); + if ( tempdir.isEmpty() ) + return false; + + TQString tempname = outfile.section( '/', -1 ); + if ( outfile.endsWith( ".kigz", false ) ) + tempname.remove( TQRegExp( "\\.[Kk][Ii][Gg][Zz]$" ) ); + else + return false; + + TQString tmpfile = tempdir + tempname + ".kig"; + TQFile ftmpfile( tmpfile ); + if ( !ftmpfile.open( IO_WriteOnly ) ) + return false; + TQTextStream stream( &ftmpfile ); + if ( !save07( data, stream ) ) + return false; + ftmpfile.close(); + + kdDebug() << "tmp saved file: " << tmpfile << endl; + + // creating the archive and adding our file + KTar* ark = new KTar( outfile, "application/x-gzip" ); + ark->open( IO_WriteOnly ); + ark->addLocalFile( tmpfile, tempname + ".kig" ); + ark->close(); + + // finally, removing temp file + TQFile::remove( tmpfile ); + + return true; + } + else + { +#endif + TQFile file( outfile ); + if ( ! file.open( IO_WriteOnly ) ) + { + fileNotFound( outfile ); + return false; + } + TQTextStream stream( &file ); + return save07( data, stream ); +#ifndef KIG_NO_COMPRESSED_FILES + } + + // we should never reach this point... + return false; +#endif +} + +/* +bool KigFilterNative::save( const KigDocument& data, TQTextStream& stream ) +{ + return save07( data, stream ); +} +*/ diff --git a/kig/filters/svgexporter.cc b/kig/filters/svgexporter.cc deleted file mode 100644 index 2fd53756..00000000 --- a/kig/filters/svgexporter.cc +++ /dev/null @@ -1,111 +0,0 @@ -// 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 "svgexporter.h" - -#include "svgexporteroptions.h" - -#include "../kig/kig_document.h" -#include "../kig/kig_part.h" -#include "../kig/kig_view.h" -#include "../misc/common.h" -#include "../misc/kigfiledialog.h" -#include "../misc/kigpainter.h" - -#include -#include -#include -#include - -#include -#include - -#include - -SVGExporter::~SVGExporter() -{ -} - -TQString SVGExporter::exportToStatement() const -{ - return i18n( "&Export to SVG..." ); -} - -TQString SVGExporter::menuEntryName() const -{ - return i18n( "&SVG..." ); -} - -TQString SVGExporter::menuIcon() const -{ - // TODO - return "image-svg+xml"; -} - -void SVGExporter::run( const KigPart& part, KigWidget& w ) -{ - KigFileDialog* kfd = new KigFileDialog( - TQString(), i18n( "*.svg|Scalable Vector Graphics (*.svg)" ), - i18n( "Export as SVG" ), &w ); - kfd->setOptionCaption( i18n( "SVG Options" ) ); - SVGExporterOptions* opts = new SVGExporterOptions( 0L ); - kfd->setOptionsWidget( opts ); - opts->showGridCheckBox->setChecked( part.document().grid() ); - opts->showAxesCheckBox->setChecked( part.document().axes() ); - if ( !kfd->exec() ) - return; - - TQString file_name = kfd->selectedFile(); - bool showgrid = opts->showGridCheckBox->isOn(); - bool showaxes = opts->showAxesCheckBox->isOn(); - - delete opts; - delete kfd; - - TQFile file( file_name ); - if ( ! file.open( IO_WriteOnly ) ) - { - KMessageBox::sorry( &w, i18n( "The file \"%1\" could not be opened. Please " - "check if the file permissions are set correctly." ) - .arg( file_name ) ); - return; - }; - - TQRect viewrect( w.screenInfo().viewRect() ); - TQRect r( 0, 0, viewrect.width(), viewrect.height() ); - - TQPicture pic; - pic.setBoundingRect( r ); - KigPainter* p = new KigPainter( ScreenInfo( w.screenInfo().shownRect(), viewrect ), - TQT_TQPAINTDEVICE(&pic), part.document() ); -// p->setWholeWinOverlay(); -// p->setBrushColor( TQt::white ); -// p->setBrushStyle( TQt::SolidPattern ); -// p->drawRect( r ); -// p->setBrushStyle( TQt::NoBrush ); -// p->setWholeWinOverlay(); - p->drawGrid( part.document().coordinateSystem(), showgrid, showaxes ); - p->drawObjects( part.document().objects(), false ); - - delete p; - - if ( !pic.save( file_name, "SVG" ) ) - { - KMessageBox::error( &w, i18n( "Sorry, something went wrong while saving to SVG file \"%1\"" ).arg( file_name ) ); - } - -} diff --git a/kig/filters/svgexporter.cpp b/kig/filters/svgexporter.cpp new file mode 100644 index 00000000..2fd53756 --- /dev/null +++ b/kig/filters/svgexporter.cpp @@ -0,0 +1,111 @@ +// 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 "svgexporter.h" + +#include "svgexporteroptions.h" + +#include "../kig/kig_document.h" +#include "../kig/kig_part.h" +#include "../kig/kig_view.h" +#include "../misc/common.h" +#include "../misc/kigfiledialog.h" +#include "../misc/kigpainter.h" + +#include +#include +#include +#include + +#include +#include + +#include + +SVGExporter::~SVGExporter() +{ +} + +TQString SVGExporter::exportToStatement() const +{ + return i18n( "&Export to SVG..." ); +} + +TQString SVGExporter::menuEntryName() const +{ + return i18n( "&SVG..." ); +} + +TQString SVGExporter::menuIcon() const +{ + // TODO + return "image-svg+xml"; +} + +void SVGExporter::run( const KigPart& part, KigWidget& w ) +{ + KigFileDialog* kfd = new KigFileDialog( + TQString(), i18n( "*.svg|Scalable Vector Graphics (*.svg)" ), + i18n( "Export as SVG" ), &w ); + kfd->setOptionCaption( i18n( "SVG Options" ) ); + SVGExporterOptions* opts = new SVGExporterOptions( 0L ); + kfd->setOptionsWidget( opts ); + opts->showGridCheckBox->setChecked( part.document().grid() ); + opts->showAxesCheckBox->setChecked( part.document().axes() ); + if ( !kfd->exec() ) + return; + + TQString file_name = kfd->selectedFile(); + bool showgrid = opts->showGridCheckBox->isOn(); + bool showaxes = opts->showAxesCheckBox->isOn(); + + delete opts; + delete kfd; + + TQFile file( file_name ); + if ( ! file.open( IO_WriteOnly ) ) + { + KMessageBox::sorry( &w, i18n( "The file \"%1\" could not be opened. Please " + "check if the file permissions are set correctly." ) + .arg( file_name ) ); + return; + }; + + TQRect viewrect( w.screenInfo().viewRect() ); + TQRect r( 0, 0, viewrect.width(), viewrect.height() ); + + TQPicture pic; + pic.setBoundingRect( r ); + KigPainter* p = new KigPainter( ScreenInfo( w.screenInfo().shownRect(), viewrect ), + TQT_TQPAINTDEVICE(&pic), part.document() ); +// p->setWholeWinOverlay(); +// p->setBrushColor( TQt::white ); +// p->setBrushStyle( TQt::SolidPattern ); +// p->drawRect( r ); +// p->setBrushStyle( TQt::NoBrush ); +// p->setWholeWinOverlay(); + p->drawGrid( part.document().coordinateSystem(), showgrid, showaxes ); + p->drawObjects( part.document().objects(), false ); + + delete p; + + if ( !pic.save( file_name, "SVG" ) ) + { + KMessageBox::error( &w, i18n( "Sorry, something went wrong while saving to SVG file \"%1\"" ).arg( file_name ) ); + } + +} diff --git a/kig/kig/CMakeLists.txt b/kig/kig/CMakeLists.txt index 8134f923..a1d88e24 100644 --- a/kig/kig/CMakeLists.txt +++ b/kig/kig/CMakeLists.txt @@ -17,7 +17,7 @@ link_directories( tde_add_library( kigpart STATIC_PIC AUTOMOC SOURCES - kig_document.cc + kig_document.cpp kig_part.cpp kig_view.cpp kig_commands.cpp diff --git a/kig/kig/Makefile.am b/kig/kig/Makefile.am index f01a4b29..063b1e2e 100644 --- a/kig/kig/Makefile.am +++ b/kig/kig/Makefile.am @@ -40,7 +40,7 @@ noinst_LTLIBRARIES = libkigparttemp.la # the Part's source, library search path, and link libraries libkigparttemp_la_SOURCES = \ - kig_document.cc \ + kig_document.cpp \ kig_part.cpp \ kig_view.cpp \ kig_commands.cpp diff --git a/kig/kig/kig_document.cc b/kig/kig/kig_document.cc deleted file mode 100644 index 884b41c5..00000000 --- a/kig/kig/kig_document.cc +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (C) 2004 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 "kig_document.h" - -#include "../objects/object_calcer.h" -#include "../objects/object_holder.h" -#include "../objects/point_imp.h" -#include "../objects/polygon_imp.h" -#include "../misc/coordinate_system.h" -#include "../misc/rect.h" - -#include - -KigDocument::KigDocument( std::set objects, CoordinateSystem* coordsystem, - bool showgrid, bool showaxes, bool nv ) - : mobjects( objects ), mcoordsystem( coordsystem ), mshowgrid( showgrid ), - mshowaxes( showaxes ), mnightvision( nv ) -{ -} - -const CoordinateSystem& KigDocument::coordinateSystem() const -{ - assert( mcoordsystem ); - return *mcoordsystem; -} - -const std::vector KigDocument::objects() const -{ - return std::vector( mobjects.begin(), mobjects.end() ); -} - -const std::set& KigDocument::objectsSet() const -{ - return mobjects; -} - -void KigDocument::setCoordinateSystem( CoordinateSystem* s ) -{ - delete switchCoordinateSystem( s ); -} - -CoordinateSystem* KigDocument::switchCoordinateSystem( CoordinateSystem* s ) -{ - CoordinateSystem* ret = mcoordsystem; - mcoordsystem = s; - return ret; -} - -std::vector KigDocument::whatAmIOn( const Coordinate& p, const KigWidget& w ) const -{ - std::vector ret; - std::vector curves; - std::vector fatobjects; - for ( std::set::const_iterator i = mobjects.begin(); - i != mobjects.end(); ++i ) - { - if(!(*i)->contains(p, w, mnightvision)) continue; - if ( (*i)->imp()->inherits( PointImp::stype() ) ) ret.push_back( *i ); - else - if ( !(*i)->imp()->inherits( PolygonImp::stype() ) ) curves.push_back( *i ); - else fatobjects.push_back( *i ); - }; - std::copy( curves.begin(), curves.end(), std::back_inserter( ret ) ); - std::copy( fatobjects.begin(), fatobjects.end(), std::back_inserter( ret ) ); - return ret; -} - -std::vector KigDocument::whatIsInHere( const Rect& p, const KigWidget& w ) -{ - std::vector ret; - std::vector nonpoints; - for ( std::set::const_iterator i = mobjects.begin(); - i != mobjects.end(); ++i ) - { - if(! (*i)->inRect( p, w ) ) continue; - if ( (*i)->imp()->inherits( PointImp::stype() ) ) ret.push_back( *i ); - else nonpoints.push_back( *i ); - }; - std::copy( nonpoints.begin(), nonpoints.end(), std::back_inserter( ret ) ); - return ret; -} - -Rect KigDocument::suggestedRect() const -{ - bool rectInited = false; - Rect r(0.,0.,0.,0.); - for ( std::set::const_iterator i = mobjects.begin(); - i != mobjects.end(); ++i ) - { - if ( (*i)->shown() ) - { - Rect cr = (*i)->imp()->surroundingRect(); - if ( ! cr.valid() ) continue; - if( !rectInited ) - { - r = cr; - rectInited = true; - } - else - r.eat( cr ); - }; - }; - - if ( ! rectInited ) - return Rect( -5.5, -5.5, 11., 11. ); - r.setContains( Coordinate( 0, 0 ) ); - if( r.width() == 0 ) r.setWidth( 1 ); - if( r.height() == 0 ) r.setHeight( 1 ); - Coordinate center = r.center(); - r *= 2; - r.setCenter(center); - return r; -} - -void KigDocument::addObject( ObjectHolder* o ) -{ - mobjects.insert( o ); -} - -void KigDocument::addObjects( const std::vector& os ) -{ - for ( std::vector::const_iterator i = os.begin(); - i != os.end(); ++i ) - ( *i )->calc( *this ); - std::copy( os.begin(), os.end(), std::inserter( mobjects, mobjects.begin() ) ); -} - -void KigDocument::delObject( ObjectHolder* o ) -{ - mobjects.erase( o ); -} - -void KigDocument::delObjects( const std::vector& os ) -{ - for ( std::vector::const_iterator i = os.begin(); - i != os.end(); ++i ) - mobjects.erase( *i ); -} - -KigDocument::KigDocument() - : mcoordsystem( new EuclideanCoords ) -{ - mshowgrid = true; - mshowaxes = true; - mnightvision = false; -} - -KigDocument::~KigDocument() -{ - typedef std::set s; - for ( s::iterator i = mobjects.begin(); i != mobjects.end(); ++i ) { - delete *i; - } - delete mcoordsystem; -} - -void KigDocument::setGrid( bool showgrid ) -{ - mshowgrid = showgrid; -} - -const bool KigDocument::grid() const -{ - return mshowgrid; -} - -void KigDocument::setAxes( bool showaxes ) -{ - mshowaxes = showaxes; -} - -void KigDocument::setNightVision( bool nv ) -{ - mnightvision = nv; -} - -const bool KigDocument::axes() const -{ - return mshowaxes; -} - -const bool KigDocument::getNightVision() const -{ - return mnightvision; -} diff --git a/kig/kig/kig_document.cpp b/kig/kig/kig_document.cpp new file mode 100644 index 00000000..884b41c5 --- /dev/null +++ b/kig/kig/kig_document.cpp @@ -0,0 +1,200 @@ +// Copyright (C) 2004 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 "kig_document.h" + +#include "../objects/object_calcer.h" +#include "../objects/object_holder.h" +#include "../objects/point_imp.h" +#include "../objects/polygon_imp.h" +#include "../misc/coordinate_system.h" +#include "../misc/rect.h" + +#include + +KigDocument::KigDocument( std::set objects, CoordinateSystem* coordsystem, + bool showgrid, bool showaxes, bool nv ) + : mobjects( objects ), mcoordsystem( coordsystem ), mshowgrid( showgrid ), + mshowaxes( showaxes ), mnightvision( nv ) +{ +} + +const CoordinateSystem& KigDocument::coordinateSystem() const +{ + assert( mcoordsystem ); + return *mcoordsystem; +} + +const std::vector KigDocument::objects() const +{ + return std::vector( mobjects.begin(), mobjects.end() ); +} + +const std::set& KigDocument::objectsSet() const +{ + return mobjects; +} + +void KigDocument::setCoordinateSystem( CoordinateSystem* s ) +{ + delete switchCoordinateSystem( s ); +} + +CoordinateSystem* KigDocument::switchCoordinateSystem( CoordinateSystem* s ) +{ + CoordinateSystem* ret = mcoordsystem; + mcoordsystem = s; + return ret; +} + +std::vector KigDocument::whatAmIOn( const Coordinate& p, const KigWidget& w ) const +{ + std::vector ret; + std::vector curves; + std::vector fatobjects; + for ( std::set::const_iterator i = mobjects.begin(); + i != mobjects.end(); ++i ) + { + if(!(*i)->contains(p, w, mnightvision)) continue; + if ( (*i)->imp()->inherits( PointImp::stype() ) ) ret.push_back( *i ); + else + if ( !(*i)->imp()->inherits( PolygonImp::stype() ) ) curves.push_back( *i ); + else fatobjects.push_back( *i ); + }; + std::copy( curves.begin(), curves.end(), std::back_inserter( ret ) ); + std::copy( fatobjects.begin(), fatobjects.end(), std::back_inserter( ret ) ); + return ret; +} + +std::vector KigDocument::whatIsInHere( const Rect& p, const KigWidget& w ) +{ + std::vector ret; + std::vector nonpoints; + for ( std::set::const_iterator i = mobjects.begin(); + i != mobjects.end(); ++i ) + { + if(! (*i)->inRect( p, w ) ) continue; + if ( (*i)->imp()->inherits( PointImp::stype() ) ) ret.push_back( *i ); + else nonpoints.push_back( *i ); + }; + std::copy( nonpoints.begin(), nonpoints.end(), std::back_inserter( ret ) ); + return ret; +} + +Rect KigDocument::suggestedRect() const +{ + bool rectInited = false; + Rect r(0.,0.,0.,0.); + for ( std::set::const_iterator i = mobjects.begin(); + i != mobjects.end(); ++i ) + { + if ( (*i)->shown() ) + { + Rect cr = (*i)->imp()->surroundingRect(); + if ( ! cr.valid() ) continue; + if( !rectInited ) + { + r = cr; + rectInited = true; + } + else + r.eat( cr ); + }; + }; + + if ( ! rectInited ) + return Rect( -5.5, -5.5, 11., 11. ); + r.setContains( Coordinate( 0, 0 ) ); + if( r.width() == 0 ) r.setWidth( 1 ); + if( r.height() == 0 ) r.setHeight( 1 ); + Coordinate center = r.center(); + r *= 2; + r.setCenter(center); + return r; +} + +void KigDocument::addObject( ObjectHolder* o ) +{ + mobjects.insert( o ); +} + +void KigDocument::addObjects( const std::vector& os ) +{ + for ( std::vector::const_iterator i = os.begin(); + i != os.end(); ++i ) + ( *i )->calc( *this ); + std::copy( os.begin(), os.end(), std::inserter( mobjects, mobjects.begin() ) ); +} + +void KigDocument::delObject( ObjectHolder* o ) +{ + mobjects.erase( o ); +} + +void KigDocument::delObjects( const std::vector& os ) +{ + for ( std::vector::const_iterator i = os.begin(); + i != os.end(); ++i ) + mobjects.erase( *i ); +} + +KigDocument::KigDocument() + : mcoordsystem( new EuclideanCoords ) +{ + mshowgrid = true; + mshowaxes = true; + mnightvision = false; +} + +KigDocument::~KigDocument() +{ + typedef std::set s; + for ( s::iterator i = mobjects.begin(); i != mobjects.end(); ++i ) { + delete *i; + } + delete mcoordsystem; +} + +void KigDocument::setGrid( bool showgrid ) +{ + mshowgrid = showgrid; +} + +const bool KigDocument::grid() const +{ + return mshowgrid; +} + +void KigDocument::setAxes( bool showaxes ) +{ + mshowaxes = showaxes; +} + +void KigDocument::setNightVision( bool nv ) +{ + mnightvision = nv; +} + +const bool KigDocument::axes() const +{ + return mshowaxes; +} + +const bool KigDocument::getNightVision() const +{ + return mnightvision; +} 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..." ); +//} diff --git a/kig/modes/CMakeLists.txt b/kig/modes/CMakeLists.txt index ab62086d..a6b2fb4c 100644 --- a/kig/modes/CMakeLists.txt +++ b/kig/modes/CMakeLists.txt @@ -21,18 +21,18 @@ tde_add_library( kigmodes STATIC_PIC AUTOMOC macrowizardbase.ui textlabelwizardbase.ui typesdialogbase.ui - base_mode.cc - construct_mode.cc - dragrectmode.cc - edittype.cc - label.cc + base_mode.cpp + construct_mode.cpp + dragrectmode.cpp + edittype.cpp + label.cpp linkslabel.cpp - macro.cc - macrowizard.cc - mode.cc - moving.cc - normal.cc - popup.cc - textlabelwizard.cc + macro.cpp + macrowizard.cpp + mode.cpp + moving.cpp + normal.cpp + popup.cpp + textlabelwizard.cpp typesdialog.cpp ) diff --git a/kig/modes/Makefile.am b/kig/modes/Makefile.am index 5f7518e5..76d3d773 100644 --- a/kig/modes/Makefile.am +++ b/kig/modes/Makefile.am @@ -2,21 +2,21 @@ INCLUDES=$(all_includes) noinst_LTLIBRARIES=libmodes.la libmodes_la_SOURCES= \ - base_mode.cc \ - construct_mode.cc \ - dragrectmode.cc \ - edittype.cc \ + base_mode.cpp \ + construct_mode.cpp \ + dragrectmode.cpp \ + edittype.cpp \ edittypebase.ui \ - label.cc \ + label.cpp \ linkslabel.cpp \ - macro.cc \ - macrowizard.cc \ + macro.cpp \ + macrowizard.cpp \ macrowizardbase.ui \ - mode.cc \ - moving.cc \ - normal.cc \ - popup.cc \ - textlabelwizard.cc \ + mode.cpp \ + moving.cpp \ + normal.cpp \ + popup.cpp \ + textlabelwizard.cpp \ textlabelwizardbase.ui \ typesdialog.cpp \ typesdialogbase.ui diff --git a/kig/modes/base_mode.cc b/kig/modes/base_mode.cc deleted file mode 100644 index 487eaf9e..00000000 --- a/kig/modes/base_mode.cc +++ /dev/null @@ -1,160 +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 "base_mode.h" - -#include "popup.h" - -#include "../kig/kig_view.h" -#include "../kig/kig_part.h" -#include "../kig/kig_document.h" - -#include -#include - -BaseMode::BaseMode( KigPart& d ) - : KigMode( d ) -{ -} - -BaseMode::~BaseMode() -{ -} - -void BaseMode::leftClicked( TQMouseEvent* e, KigWidget* v ) -{ - // touch screens don't send a mouseMoved event before a click event, - // apparently, so we simulate it. - mouseMoved( e, v ); - - // get rid of text still showing... - v->updateCurPix(); - v->updateWidget(); - - mplc = e->pos(); - moco = mdoc.document().whatAmIOn( v->fromScreen( mplc ), *v ); - - if( moco.empty() ) - { - // clicked on an empty spot --> we show the rectangle for - // selecting stuff... - dragRect( mplc, *v ); - } - else - { - // the user clicked on some object.. --> this could either mean - // that he/she wants to select the object or that he wants to - // start moving it. We assume nothing here, we wait till he - // either moves some 4 pixels, or till he releases his mouse - // button in leftReleased() or mouseMoved()... - }; -} - -void BaseMode::leftMouseMoved( TQMouseEvent* e, KigWidget* w ) -{ - if( !moco.empty() && ( mplc - e->pos() ).manhattanLength() > 3 ) - dragObject( moco, mplc, *w, - ( e->state() & (ShiftButton | ControlButton ) ) != 0 - ); -} - -void BaseMode::leftReleased( TQMouseEvent* e, KigWidget* v ) -{ - if( (mplc - e->pos()).manhattanLength() > 4 ) return; - - ObjectHolder* o = 0; - bool keyCtrl = ( e->state() & ControlButton ) != 0; - bool keyShift = ( e->state() & ShiftButton ) != 0; - if ( ! moco.empty() ) - { - if ( keyShift ) - { - int id = ObjectChooserPopup::getObjectFromList( e->pos(), v, moco ); - if ( id >= 0 ) - o = moco[id]; - } - else - o = moco.front(); - } - leftClickedObject( o, e->pos(), *v, keyCtrl ); -} - -void BaseMode::midClicked( TQMouseEvent* e, KigWidget* v ) -{ - // get rid of text still showing... - v->updateCurPix(); - v->updateWidget(); - - mplc = e->pos(); - moco = mdoc.document().whatAmIOn( v->fromScreen( e->pos() ), *v ); -} - -void BaseMode::midReleased( TQMouseEvent* e, KigWidget* v ) -{ - if( (e->pos() - mplc).manhattanLength() > 4 ) return; - - midClicked( mplc, *v ); -} - -void BaseMode::rightClicked( TQMouseEvent* e, KigWidget* w ) -{ - // get rid of text still showing... - w->updateCurPix(); - w->updateWidget(); - // set a normal cursor... - w->setCursor( KCursor::arrowCursor() ); - - mplc = e->pos(); - moco = mdoc.document().whatAmIOn( w->fromScreen( mplc ), *w ); - - rightClicked( moco, mplc, *w ); -} - -void BaseMode::mouseMoved( TQMouseEvent* e, KigWidget* w ) -{ - std::vector os = mdoc.document().whatAmIOn( w->fromScreen( e->pos() ), *w ); - mouseMoved( os, e->pos(), *w, e->state() & TQt::ShiftButton ); -} - -void BaseMode::dragRect( const TQPoint&, KigWidget& ) -{ -} - -void BaseMode::leftClickedObject( ObjectHolder*, const TQPoint&, - KigWidget&, bool ) -{ -} - -void BaseMode::dragObject( const std::vector&, const TQPoint&, - KigWidget&, bool ) -{ -} - -void BaseMode::enableActions() -{ - KigMode::enableActions(); -} - -std::vector BaseMode::oco() -{ - return moco; -} - -TQPoint BaseMode::pointLocation() -{ - return mplc; -} diff --git a/kig/modes/base_mode.cpp b/kig/modes/base_mode.cpp new file mode 100644 index 00000000..487eaf9e --- /dev/null +++ b/kig/modes/base_mode.cpp @@ -0,0 +1,160 @@ +// 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 "base_mode.h" + +#include "popup.h" + +#include "../kig/kig_view.h" +#include "../kig/kig_part.h" +#include "../kig/kig_document.h" + +#include +#include + +BaseMode::BaseMode( KigPart& d ) + : KigMode( d ) +{ +} + +BaseMode::~BaseMode() +{ +} + +void BaseMode::leftClicked( TQMouseEvent* e, KigWidget* v ) +{ + // touch screens don't send a mouseMoved event before a click event, + // apparently, so we simulate it. + mouseMoved( e, v ); + + // get rid of text still showing... + v->updateCurPix(); + v->updateWidget(); + + mplc = e->pos(); + moco = mdoc.document().whatAmIOn( v->fromScreen( mplc ), *v ); + + if( moco.empty() ) + { + // clicked on an empty spot --> we show the rectangle for + // selecting stuff... + dragRect( mplc, *v ); + } + else + { + // the user clicked on some object.. --> this could either mean + // that he/she wants to select the object or that he wants to + // start moving it. We assume nothing here, we wait till he + // either moves some 4 pixels, or till he releases his mouse + // button in leftReleased() or mouseMoved()... + }; +} + +void BaseMode::leftMouseMoved( TQMouseEvent* e, KigWidget* w ) +{ + if( !moco.empty() && ( mplc - e->pos() ).manhattanLength() > 3 ) + dragObject( moco, mplc, *w, + ( e->state() & (ShiftButton | ControlButton ) ) != 0 + ); +} + +void BaseMode::leftReleased( TQMouseEvent* e, KigWidget* v ) +{ + if( (mplc - e->pos()).manhattanLength() > 4 ) return; + + ObjectHolder* o = 0; + bool keyCtrl = ( e->state() & ControlButton ) != 0; + bool keyShift = ( e->state() & ShiftButton ) != 0; + if ( ! moco.empty() ) + { + if ( keyShift ) + { + int id = ObjectChooserPopup::getObjectFromList( e->pos(), v, moco ); + if ( id >= 0 ) + o = moco[id]; + } + else + o = moco.front(); + } + leftClickedObject( o, e->pos(), *v, keyCtrl ); +} + +void BaseMode::midClicked( TQMouseEvent* e, KigWidget* v ) +{ + // get rid of text still showing... + v->updateCurPix(); + v->updateWidget(); + + mplc = e->pos(); + moco = mdoc.document().whatAmIOn( v->fromScreen( e->pos() ), *v ); +} + +void BaseMode::midReleased( TQMouseEvent* e, KigWidget* v ) +{ + if( (e->pos() - mplc).manhattanLength() > 4 ) return; + + midClicked( mplc, *v ); +} + +void BaseMode::rightClicked( TQMouseEvent* e, KigWidget* w ) +{ + // get rid of text still showing... + w->updateCurPix(); + w->updateWidget(); + // set a normal cursor... + w->setCursor( KCursor::arrowCursor() ); + + mplc = e->pos(); + moco = mdoc.document().whatAmIOn( w->fromScreen( mplc ), *w ); + + rightClicked( moco, mplc, *w ); +} + +void BaseMode::mouseMoved( TQMouseEvent* e, KigWidget* w ) +{ + std::vector os = mdoc.document().whatAmIOn( w->fromScreen( e->pos() ), *w ); + mouseMoved( os, e->pos(), *w, e->state() & TQt::ShiftButton ); +} + +void BaseMode::dragRect( const TQPoint&, KigWidget& ) +{ +} + +void BaseMode::leftClickedObject( ObjectHolder*, const TQPoint&, + KigWidget&, bool ) +{ +} + +void BaseMode::dragObject( const std::vector&, const TQPoint&, + KigWidget&, bool ) +{ +} + +void BaseMode::enableActions() +{ + KigMode::enableActions(); +} + +std::vector BaseMode::oco() +{ + return moco; +} + +TQPoint BaseMode::pointLocation() +{ + return mplc; +} diff --git a/kig/modes/construct_mode.cc b/kig/modes/construct_mode.cc deleted file mode 100644 index e9c13364..00000000 --- a/kig/modes/construct_mode.cc +++ /dev/null @@ -1,572 +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 "construct_mode.h" - -#include "../objects/object_factory.h" -#include "../objects/object_drawer.h" -#include "../objects/text_type.h" -#include "../objects/text_imp.h" -#include "../objects/bogus_imp.h" -#include "../objects/point_imp.h" -#include "../misc/argsparser.h" - -#include "../kig/kig_document.h" -#include "../kig/kig_part.h" -#include "../kig/kig_view.h" -#include "../misc/object_constructor.h" -#include "../misc/coordinate_system.h" -#include "../misc/kigpainter.h" -#include "../misc/calcpaths.h" - -#include "popup.h" - -#include -#include - -#include -#include - -static void redefinePoint( ObjectTypeCalcer* mpt, const Coordinate& c, KigDocument& doc, const KigWidget& w ) -{ - ObjectFactory::instance()->redefinePoint( mpt, c, doc, w ); - mpt->calc( doc ); -} - -BaseConstructMode::BaseConstructMode( KigPart& d ) - : BaseMode( d ) -{ - mpt = ObjectFactory::instance()->fixedPointCalcer( Coordinate( 0, 0 ) ); - mpt->calc( d.document() ); - mcursor = ObjectFactory::instance()->cursorPointCalcer( Coordinate( 0, 0 ) ); - mcursor->calc( d.document() ); -// mcursorholder = new ObjectHolder( mcursor ); -} - -BaseConstructMode::~BaseConstructMode() -{ - delete mcursor; -// delete mcursorholder; -} - -void BaseConstructMode::leftReleased( TQMouseEvent* e, KigWidget* v ) -{ - if( (pointLocation() - e->pos()).manhattanLength() > 4 ) return; - - ObjectHolder* o = 0; - bool keyCtrlOrShift = ( e->state() & ( ControlButton | ShiftButton) ) != 0; - std::vector moco = oco(); - if ( ! moco.empty() ) - { - std::vector goodargs; - if ( !moco.empty() ) - { - std::vector::const_iterator it; - std::vector testargs = getCalcers( mparents ); - for ( std::vector::const_iterator i = moco.begin(); i != moco.end(); ++i ) - { - it = std::find( mparents.begin(), mparents.end(), *i ); - bool newdup = - ( it == mparents.end() ) || - isAlreadySelectedOK( testargs, it - mparents.begin() ); - if ( newdup ) - { - testargs.push_back( ( *i )->calcer() ); - if ( wantArgs( testargs, mdoc.document(), *v ) ) - goodargs.push_back( *i ); - testargs.pop_back(); - } - } - int id = ObjectChooserPopup::getObjectFromList( e->pos(), v, goodargs ); - if ( id >= 0 ) - o = goodargs[id]; - } - } - leftClickedObject( o, e->pos(), *v, keyCtrlOrShift ); - KigMode::leftReleased( e, v ); -} - -void BaseConstructMode::leftClickedObject( - ObjectHolder* o, const TQPoint& p, KigWidget& w, bool ) -{ - std::vector::iterator it = std::find( mparents.begin(), mparents.end(), o ); - std::vector nargs = getCalcers( mparents ); -// -// mp: duplicationchecked controls whether the arguments list is -// free of duplications or if a duplication is safe (asking this to -// the Constructor class through the "isAlreadySelectedOK" method). -// - bool duplicationchecked = - ( it == mparents.end() ) || - isAlreadySelectedOK( nargs, it - mparents.begin() ); - if ( o && duplicationchecked ) - { - nargs.push_back( o->calcer() ); - if ( wantArgs( nargs, mdoc.document(), w ) ) - { - selectObject( o, w ); - return; - } - } - - nargs = getCalcers( mparents ); - nargs.push_back( mpt.get() ); - if ( wantArgs( nargs, mdoc.document(), w ) ) - { - // add mpt to the document.. - ObjectHolder* n = new ObjectHolder( mpt.get() ); - mdoc.addObject( n ); - selectObject( n, w ); - // get a new mpt for our further use.. - mpt = ObjectFactory::instance()->sensiblePointCalcer( w.fromScreen( p ), mdoc.document(), w ); - mpt->calc( mdoc.document() ); - return; - } - - nargs = getCalcers( mparents ); - nargs.push_back( mcursor ); - - if ( wantArgs( nargs, mdoc.document(), w ) ) - { - // DON'T add mpt to the document.. - // the objectholder has been constructed once and for all - // when entering construction mode, and delete in the - // destructor. - ObjectHolder* n = new ObjectHolder( mcursor ); - selectObject( n, w ); - mcursor = ObjectFactory::instance()->cursorPointCalcer( w.fromScreen( p ) ); -// mcursor = ObjectFactory::instance()->sensiblePointCalcer( w.fromScreen( p ), mdoc.document(), w ); - mcursor->calc( mdoc.document() ); - delete n; - } -} - -void BaseConstructMode::midClicked( const TQPoint& p, KigWidget& w ) -{ - std::vector args = getCalcers( mparents ); - args.push_back( mpt.get() ); - if ( wantArgs( args, mdoc.document(), w ) ) - { - ObjectHolder* n = new ObjectHolder( mpt.get() ); - mdoc.addObject( n ); - - selectObject( n, w ); - - mpt = ObjectFactory::instance()->sensiblePointCalcer( w.fromScreen( p ), mdoc.document(), w ); - mpt->calc( mdoc.document() ); - } -} - -void BaseConstructMode::rightClicked( const std::vector&, const TQPoint&, KigWidget& ) -{ - // TODO ? -} - -void BaseConstructMode::mouseMoved( const std::vector& os, const TQPoint& p, - KigWidget& w, bool shiftpressed ) -{ - mdoc.emitStatusBarText( selectStatement( getCalcers( mparents ), w ) ); - - w.updateCurPix(); - KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.curPix), mdoc.document() ); - - Coordinate ncoord = w.fromScreen( p ); - if ( shiftpressed ) - ncoord = mdoc.document().coordinateSystem().snapToGrid( ncoord, w ); - - redefinePoint( mpt.get(), ncoord, mdoc.document(), w ); - mcursor->move( ncoord, mdoc.document() ); - mcursor->calc( mdoc.document() ); - - std::vector args = getCalcers( mparents ); - bool duplicationchecked = false; - std::vector goodargs; - if ( ! os.empty() ) - { - std::vector::const_iterator it; - std::vector testargs = getCalcers( mparents ); - for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) - { - it = std::find( mparents.begin(), mparents.end(), *i ); - bool newdup = - ( it == mparents.end() ) || - isAlreadySelectedOK( args, it - mparents.begin() ); - if ( newdup ) - { - testargs.push_back( ( *i )->calcer() ); - if ( wantArgs( testargs, mdoc.document(), w ) ) - goodargs.push_back( *i ); - testargs.pop_back(); - } - duplicationchecked |= newdup; - } - } - bool calcnow = ( goodargs.size() == 1 ) || ( ( goodargs.size() > 0 ) && ( goodargs.front()->imp()->inherits( PointImp::stype() ) ) ); - if ( calcnow ) - { - args.push_back( goodargs.front()->calcer() ); - } - - if ( !os.empty() && duplicationchecked && calcnow ) - { - handlePrelim( args, p, pter, w ); - - w.setCursor( KCursor::handCursor() ); - } - else - { - std::vector args = getCalcers( mparents ); - args.push_back( mpt.get() ); - std::vector argscursor = getCalcers( mparents ); - argscursor.push_back( mcursor ); - bool text = true; - if ( wantArgs( args, mdoc.document(), w ) ) - { - ObjectDrawer d; - d.draw( *mpt->imp(), pter, true ); - - handlePrelim( args, p, pter, w ); - - w.setCursor( KCursor::handCursor() ); - } - else if ( wantArgs( argscursor, mdoc.document(), w ) ) - { - ObjectDrawer d; -// d.draw( *mcursor->imp(), pter, true ); - - handlePrelim( argscursor, p, pter, w ); - - w.setCursor( KCursor::crossCursor() ); - } - else - { - w.setCursor( KCursor::arrowCursor() ); - text = false; - } - if ( !text && ( goodargs.size() > 1 ) ) - { - TQString strwhich = i18n( "Which object?" ); - mdoc.emitStatusBarText( strwhich ); - - TQPoint textloc = p; - textloc.setX( textloc.x() + 15 ); - pter.drawTextStd( textloc, strwhich ); - - w.setCursor( KCursor::handCursor() ); - } - } - w.updateWidget( pter.overlay() ); -} - -void BaseConstructMode::selectObject( ObjectHolder* o, KigWidget& w ) -{ - mparents.push_back( o ); - std::vector args = getCalcers( mparents ); - - if ( wantArgs( args, mdoc.document(), w ) == ArgsParser::Complete ) - { - handleArgs( args, w ); - }; - - w.redrawScreen( mparents ); -} - -PointConstructMode::PointConstructMode( KigPart& d ) - : BaseMode( d ) -{ - // we add the data objects to the document cause - // ObjectFactory::redefinePoint does that too, and this way, we can - // depend on them already being known by the doc when we add the - // mpt.. - mpt = ObjectFactory::instance()->fixedPointCalcer( Coordinate() ); - mpt->calc( d.document() ); - - mdoc.emitStatusBarText( i18n( "Click the location where you want to place the new point, or the curve that you want to attach it to..." ) ); -} - -PointConstructMode::~PointConstructMode() -{ -} - -void PointConstructMode::leftClickedObject( - ObjectHolder*, const TQPoint&, KigWidget& w, bool ) -{ - mdoc.addObject( new ObjectHolder( mpt.get() ) ); - w.redrawScreen( std::vector() ); - - mdoc.emitStatusBarText( TQString() ); - mdoc.doneMode( this ); -} - -void PointConstructMode::midClicked( const TQPoint& p, KigWidget& w ) -{ - leftClickedObject( 0, p, w, true ); -} - -void PointConstructMode::rightClicked( const std::vector&, const TQPoint&, - KigWidget& ) -{ - // TODO ? -} - -void PointConstructMode::mouseMoved( - const std::vector&, - const TQPoint& p, - KigWidget& w, - bool shiftpressed ) -{ - w.updateCurPix(); - KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.curPix), mdoc.document() ); - - Coordinate ncoord = w.fromScreen( p ); - if ( shiftpressed ) - ncoord = mdoc.document().coordinateSystem().snapToGrid( ncoord, w ); - - redefinePoint( mpt.get(), ncoord, mdoc.document(), w ); - - ObjectDrawer d; - d.draw( *mpt->imp(), pter, true ); - w.setCursor( KCursor::blankCursor() ); - - w.updateWidget( pter.overlay() ); -} - -void BaseConstructMode::enableActions() -{ - BaseMode::enableActions(); - - mdoc.aCancelConstruction->setEnabled( true ); -} - -void BaseConstructMode::cancelConstruction() -{ - finish(); -} - -void PointConstructMode::enableActions() -{ - BaseMode::enableActions(); - - mdoc.aCancelConstruction->setEnabled( true ); -} - -void PointConstructMode::cancelConstruction() -{ - mdoc.doneMode( this ); -} - -void BaseConstructMode::selectObjects( const std::vector& os, KigWidget& w ) -{ - for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) - { - std::vector args = getCalcers( mparents ); - assert( wantArgs( args, mdoc.document(), w ) != ArgsParser::Complete ); - selectObject( *i, w ); - }; -} - -void ConstructMode::handlePrelim( const std::vector& args, const TQPoint& p, KigPainter& pter, KigWidget& w ) -{ - // set the text next to the arrow cursor like in modes/normal.cc - TQPoint textloc = p; - textloc.setX( textloc.x() + 15 ); - - mctor->handlePrelim( pter, args, mdoc.document(), w ); - - TQString o = mctor->useText( *args.back(), args, mdoc.document(), w ); - pter.drawTextStd( textloc, o ); -} - -int ConstructMode::isAlreadySelectedOK( const std::vector& os, - const int& pos ) -{ - return mctor->isAlreadySelectedOK( os, pos ); -} - -int ConstructMode::wantArgs( const std::vector& os, KigDocument& d, KigWidget& w ) -{ - return mctor->wantArgs( os, d, w ); -} - -void BaseConstructMode::finish() -{ - mdoc.doneMode( this ); -} - -ConstructMode::ConstructMode( KigPart& d, const ObjectConstructor* ctor ) - : BaseConstructMode( d ), mctor( ctor ) -{ -} - -ConstructMode::~ConstructMode() -{ -} - -// does a test result have a frame by default ? -static const bool test_has_frame_dflt = true; - -void TestConstructMode::handlePrelim( const std::vector& os, const TQPoint& p, KigPainter& pter, KigWidget& w ) -{ - Args args; - std::transform( os.begin(), os.end(), std::back_inserter( args ), - std::mem_fun( &ObjectCalcer::imp ) ); - - // usetext - TQString usetext = i18n( mtype->argsParser().usetext( args.back(), args ).c_str() ); - TQPoint textloc = p; - textloc.setX( textloc.x() + 15 ); - pter.drawTextStd( textloc, usetext ); - - // test result - ObjectImp* data = mtype->calc( args, mdoc.document() ); - if ( ! data->valid() ) return; - assert( data->inherits( TestResultImp::stype() ) ); - TQString outputtext = static_cast( data )->data(); - TextImp ti( outputtext, w.fromScreen( p + TQPoint( - 40, 30 ) ), test_has_frame_dflt ); - ti.draw( pter ); - - delete data; -} - -TestConstructMode::TestConstructMode( KigPart& d, const ArgsParserObjectType* type ) - : BaseConstructMode( d ), mtype( type ) -{ -} - -TestConstructMode::~TestConstructMode() -{ -} - -void ConstructMode::handleArgs( const std::vector& args, KigWidget& w ) -{ - mctor->handleArgs( args, mdoc, w ); - finish(); -} - -int TestConstructMode::isAlreadySelectedOK( const std::vector&, - const int& ) -{ - return false; -} - -int TestConstructMode::wantArgs( const std::vector& os, KigDocument&, KigWidget& ) -{ - return mtype->argsParser().check( os ); -} - -void TestConstructMode::handleArgs( const std::vector& args, KigWidget& ) -{ - mresult = new ObjectTypeCalcer( mtype, args ); - mresult->calc( mdoc.document() ); - mdoc.emitStatusBarText( i18n( "Now select the location for the result label." ) ); -} - -void TestConstructMode::leftClickedObject( ObjectHolder* o, const TQPoint& p, - KigWidget& w, bool ctrlOrShiftDown ) -{ - if ( mresult ) { - TQPoint qloc = p + TQPoint( -40, 0 ); - Coordinate loc = w.fromScreen( qloc ); - - std::vector parents; - parents.push_back( new ObjectConstCalcer( new IntImp( test_has_frame_dflt ) ) ); - parents.push_back( new ObjectConstCalcer( new PointImp( loc ) ) ); - parents.push_back( new ObjectConstCalcer( new StringImp( TQString::fromLatin1( "%1" ) ) ) ); - assert( mresult->imp()->inherits( TestResultImp::stype() ) ); - parents.push_back( - new ObjectPropertyCalcer( - mresult.get(), mresult->imp()->propertiesInternalNames().findIndex( "test-result" ) ) ); - parents.back()->calc( mdoc.document() ); - - ObjectCalcer* ret = new ObjectTypeCalcer( TextType::instance(), parents ); - ret->calc( mdoc.document() ); - mdoc.addObject( new ObjectHolder( ret ) ); - - w.unsetCursor(); - mdoc.emitStatusBarText( TQString() ); - - finish(); - } - else - BaseConstructMode::leftClickedObject( o, p, w, ctrlOrShiftDown ); -} - -void TestConstructMode::midClicked( const TQPoint& p, KigWidget& w ) -{ - if ( mresult ) { - // nothing to be done here, really - } - else - BaseConstructMode::midClicked( p, w ); -} - -void TestConstructMode::rightClicked( const std::vector& oco, const TQPoint& p, KigWidget& w ) -{ - if ( mresult ) { - // nothing to be done here, really - } - else - BaseConstructMode::rightClicked( oco, p, w ); -} - -void TestConstructMode::mouseMoved( const std::vector& os, const TQPoint& p, KigWidget& w, bool shiftPressed ) -{ - if ( mresult ) { - w.setCursor( KCursor::blankCursor() ); - - w.updateCurPix(); - KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.curPix), mdoc.document() ); - - TQPoint qloc = p + TQPoint( -40, 0 ); - Coordinate loc = w.fromScreen( qloc ); - assert( dynamic_cast( mresult->imp() ) ); - TextImp ti( static_cast( mresult->imp() )->data(), loc, test_has_frame_dflt ); - ObjectDrawer d; - d.draw( ti, pter, false ); - - - w.updateWidget( pter.overlay() ); - } - else - BaseConstructMode::mouseMoved( os, p, w, shiftPressed ); -} - -TQString ConstructMode::selectStatement( const std::vector& args, const KigWidget& w ) -{ - return mctor->selectStatement( args, mdoc.document(), w ); -} - -TQString TestConstructMode::selectStatement( const std::vector& sel, const KigWidget& ) -{ - using namespace std; - Args args; - transform( sel.begin(), sel.end(), back_inserter( args ), mem_fun( &ObjectCalcer::imp ) ); - - std::string ret = mtype->argsParser().selectStatement( args ); - if ( ret.empty() ) return TQString(); - return i18n( ret.c_str() ); -} - -void PointConstructMode::redrawScreen( KigWidget* w ) -{ - w->redrawScreen( std::vector() ); -} - -void BaseConstructMode::redrawScreen( KigWidget* w ) -{ - w->redrawScreen( std::vector() ); -} diff --git a/kig/modes/construct_mode.cpp b/kig/modes/construct_mode.cpp new file mode 100644 index 00000000..02bb98fc --- /dev/null +++ b/kig/modes/construct_mode.cpp @@ -0,0 +1,572 @@ +// 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 "construct_mode.h" + +#include "../objects/object_factory.h" +#include "../objects/object_drawer.h" +#include "../objects/text_type.h" +#include "../objects/text_imp.h" +#include "../objects/bogus_imp.h" +#include "../objects/point_imp.h" +#include "../misc/argsparser.h" + +#include "../kig/kig_document.h" +#include "../kig/kig_part.h" +#include "../kig/kig_view.h" +#include "../misc/object_constructor.h" +#include "../misc/coordinate_system.h" +#include "../misc/kigpainter.h" +#include "../misc/calcpaths.h" + +#include "popup.h" + +#include +#include + +#include +#include + +static void redefinePoint( ObjectTypeCalcer* mpt, const Coordinate& c, KigDocument& doc, const KigWidget& w ) +{ + ObjectFactory::instance()->redefinePoint( mpt, c, doc, w ); + mpt->calc( doc ); +} + +BaseConstructMode::BaseConstructMode( KigPart& d ) + : BaseMode( d ) +{ + mpt = ObjectFactory::instance()->fixedPointCalcer( Coordinate( 0, 0 ) ); + mpt->calc( d.document() ); + mcursor = ObjectFactory::instance()->cursorPointCalcer( Coordinate( 0, 0 ) ); + mcursor->calc( d.document() ); +// mcursorholder = new ObjectHolder( mcursor ); +} + +BaseConstructMode::~BaseConstructMode() +{ + delete mcursor; +// delete mcursorholder; +} + +void BaseConstructMode::leftReleased( TQMouseEvent* e, KigWidget* v ) +{ + if( (pointLocation() - e->pos()).manhattanLength() > 4 ) return; + + ObjectHolder* o = 0; + bool keyCtrlOrShift = ( e->state() & ( ControlButton | ShiftButton) ) != 0; + std::vector moco = oco(); + if ( ! moco.empty() ) + { + std::vector goodargs; + if ( !moco.empty() ) + { + std::vector::const_iterator it; + std::vector testargs = getCalcers( mparents ); + for ( std::vector::const_iterator i = moco.begin(); i != moco.end(); ++i ) + { + it = std::find( mparents.begin(), mparents.end(), *i ); + bool newdup = + ( it == mparents.end() ) || + isAlreadySelectedOK( testargs, it - mparents.begin() ); + if ( newdup ) + { + testargs.push_back( ( *i )->calcer() ); + if ( wantArgs( testargs, mdoc.document(), *v ) ) + goodargs.push_back( *i ); + testargs.pop_back(); + } + } + int id = ObjectChooserPopup::getObjectFromList( e->pos(), v, goodargs ); + if ( id >= 0 ) + o = goodargs[id]; + } + } + leftClickedObject( o, e->pos(), *v, keyCtrlOrShift ); + KigMode::leftReleased( e, v ); +} + +void BaseConstructMode::leftClickedObject( + ObjectHolder* o, const TQPoint& p, KigWidget& w, bool ) +{ + std::vector::iterator it = std::find( mparents.begin(), mparents.end(), o ); + std::vector nargs = getCalcers( mparents ); +// +// mp: duplicationchecked controls whether the arguments list is +// free of duplications or if a duplication is safe (asking this to +// the Constructor class through the "isAlreadySelectedOK" method). +// + bool duplicationchecked = + ( it == mparents.end() ) || + isAlreadySelectedOK( nargs, it - mparents.begin() ); + if ( o && duplicationchecked ) + { + nargs.push_back( o->calcer() ); + if ( wantArgs( nargs, mdoc.document(), w ) ) + { + selectObject( o, w ); + return; + } + } + + nargs = getCalcers( mparents ); + nargs.push_back( mpt.get() ); + if ( wantArgs( nargs, mdoc.document(), w ) ) + { + // add mpt to the document.. + ObjectHolder* n = new ObjectHolder( mpt.get() ); + mdoc.addObject( n ); + selectObject( n, w ); + // get a new mpt for our further use.. + mpt = ObjectFactory::instance()->sensiblePointCalcer( w.fromScreen( p ), mdoc.document(), w ); + mpt->calc( mdoc.document() ); + return; + } + + nargs = getCalcers( mparents ); + nargs.push_back( mcursor ); + + if ( wantArgs( nargs, mdoc.document(), w ) ) + { + // DON'T add mpt to the document.. + // the objectholder has been constructed once and for all + // when entering construction mode, and delete in the + // destructor. + ObjectHolder* n = new ObjectHolder( mcursor ); + selectObject( n, w ); + mcursor = ObjectFactory::instance()->cursorPointCalcer( w.fromScreen( p ) ); +// mcursor = ObjectFactory::instance()->sensiblePointCalcer( w.fromScreen( p ), mdoc.document(), w ); + mcursor->calc( mdoc.document() ); + delete n; + } +} + +void BaseConstructMode::midClicked( const TQPoint& p, KigWidget& w ) +{ + std::vector args = getCalcers( mparents ); + args.push_back( mpt.get() ); + if ( wantArgs( args, mdoc.document(), w ) ) + { + ObjectHolder* n = new ObjectHolder( mpt.get() ); + mdoc.addObject( n ); + + selectObject( n, w ); + + mpt = ObjectFactory::instance()->sensiblePointCalcer( w.fromScreen( p ), mdoc.document(), w ); + mpt->calc( mdoc.document() ); + } +} + +void BaseConstructMode::rightClicked( const std::vector&, const TQPoint&, KigWidget& ) +{ + // TODO ? +} + +void BaseConstructMode::mouseMoved( const std::vector& os, const TQPoint& p, + KigWidget& w, bool shiftpressed ) +{ + mdoc.emitStatusBarText( selectStatement( getCalcers( mparents ), w ) ); + + w.updateCurPix(); + KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.curPix), mdoc.document() ); + + Coordinate ncoord = w.fromScreen( p ); + if ( shiftpressed ) + ncoord = mdoc.document().coordinateSystem().snapToGrid( ncoord, w ); + + redefinePoint( mpt.get(), ncoord, mdoc.document(), w ); + mcursor->move( ncoord, mdoc.document() ); + mcursor->calc( mdoc.document() ); + + std::vector args = getCalcers( mparents ); + bool duplicationchecked = false; + std::vector goodargs; + if ( ! os.empty() ) + { + std::vector::const_iterator it; + std::vector testargs = getCalcers( mparents ); + for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) + { + it = std::find( mparents.begin(), mparents.end(), *i ); + bool newdup = + ( it == mparents.end() ) || + isAlreadySelectedOK( args, it - mparents.begin() ); + if ( newdup ) + { + testargs.push_back( ( *i )->calcer() ); + if ( wantArgs( testargs, mdoc.document(), w ) ) + goodargs.push_back( *i ); + testargs.pop_back(); + } + duplicationchecked |= newdup; + } + } + bool calcnow = ( goodargs.size() == 1 ) || ( ( goodargs.size() > 0 ) && ( goodargs.front()->imp()->inherits( PointImp::stype() ) ) ); + if ( calcnow ) + { + args.push_back( goodargs.front()->calcer() ); + } + + if ( !os.empty() && duplicationchecked && calcnow ) + { + handlePrelim( args, p, pter, w ); + + w.setCursor( KCursor::handCursor() ); + } + else + { + std::vector args = getCalcers( mparents ); + args.push_back( mpt.get() ); + std::vector argscursor = getCalcers( mparents ); + argscursor.push_back( mcursor ); + bool text = true; + if ( wantArgs( args, mdoc.document(), w ) ) + { + ObjectDrawer d; + d.draw( *mpt->imp(), pter, true ); + + handlePrelim( args, p, pter, w ); + + w.setCursor( KCursor::handCursor() ); + } + else if ( wantArgs( argscursor, mdoc.document(), w ) ) + { + ObjectDrawer d; +// d.draw( *mcursor->imp(), pter, true ); + + handlePrelim( argscursor, p, pter, w ); + + w.setCursor( KCursor::crossCursor() ); + } + else + { + w.setCursor( KCursor::arrowCursor() ); + text = false; + } + if ( !text && ( goodargs.size() > 1 ) ) + { + TQString strwhich = i18n( "Which object?" ); + mdoc.emitStatusBarText( strwhich ); + + TQPoint textloc = p; + textloc.setX( textloc.x() + 15 ); + pter.drawTextStd( textloc, strwhich ); + + w.setCursor( KCursor::handCursor() ); + } + } + w.updateWidget( pter.overlay() ); +} + +void BaseConstructMode::selectObject( ObjectHolder* o, KigWidget& w ) +{ + mparents.push_back( o ); + std::vector args = getCalcers( mparents ); + + if ( wantArgs( args, mdoc.document(), w ) == ArgsParser::Complete ) + { + handleArgs( args, w ); + }; + + w.redrawScreen( mparents ); +} + +PointConstructMode::PointConstructMode( KigPart& d ) + : BaseMode( d ) +{ + // we add the data objects to the document cause + // ObjectFactory::redefinePoint does that too, and this way, we can + // depend on them already being known by the doc when we add the + // mpt.. + mpt = ObjectFactory::instance()->fixedPointCalcer( Coordinate() ); + mpt->calc( d.document() ); + + mdoc.emitStatusBarText( i18n( "Click the location where you want to place the new point, or the curve that you want to attach it to..." ) ); +} + +PointConstructMode::~PointConstructMode() +{ +} + +void PointConstructMode::leftClickedObject( + ObjectHolder*, const TQPoint&, KigWidget& w, bool ) +{ + mdoc.addObject( new ObjectHolder( mpt.get() ) ); + w.redrawScreen( std::vector() ); + + mdoc.emitStatusBarText( TQString() ); + mdoc.doneMode( this ); +} + +void PointConstructMode::midClicked( const TQPoint& p, KigWidget& w ) +{ + leftClickedObject( 0, p, w, true ); +} + +void PointConstructMode::rightClicked( const std::vector&, const TQPoint&, + KigWidget& ) +{ + // TODO ? +} + +void PointConstructMode::mouseMoved( + const std::vector&, + const TQPoint& p, + KigWidget& w, + bool shiftpressed ) +{ + w.updateCurPix(); + KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.curPix), mdoc.document() ); + + Coordinate ncoord = w.fromScreen( p ); + if ( shiftpressed ) + ncoord = mdoc.document().coordinateSystem().snapToGrid( ncoord, w ); + + redefinePoint( mpt.get(), ncoord, mdoc.document(), w ); + + ObjectDrawer d; + d.draw( *mpt->imp(), pter, true ); + w.setCursor( KCursor::blankCursor() ); + + w.updateWidget( pter.overlay() ); +} + +void BaseConstructMode::enableActions() +{ + BaseMode::enableActions(); + + mdoc.aCancelConstruction->setEnabled( true ); +} + +void BaseConstructMode::cancelConstruction() +{ + finish(); +} + +void PointConstructMode::enableActions() +{ + BaseMode::enableActions(); + + mdoc.aCancelConstruction->setEnabled( true ); +} + +void PointConstructMode::cancelConstruction() +{ + mdoc.doneMode( this ); +} + +void BaseConstructMode::selectObjects( const std::vector& os, KigWidget& w ) +{ + for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) + { + std::vector args = getCalcers( mparents ); + assert( wantArgs( args, mdoc.document(), w ) != ArgsParser::Complete ); + selectObject( *i, w ); + }; +} + +void ConstructMode::handlePrelim( const std::vector& args, const TQPoint& p, KigPainter& pter, KigWidget& w ) +{ + // set the text next to the arrow cursor like in modes/normal.cpp + TQPoint textloc = p; + textloc.setX( textloc.x() + 15 ); + + mctor->handlePrelim( pter, args, mdoc.document(), w ); + + TQString o = mctor->useText( *args.back(), args, mdoc.document(), w ); + pter.drawTextStd( textloc, o ); +} + +int ConstructMode::isAlreadySelectedOK( const std::vector& os, + const int& pos ) +{ + return mctor->isAlreadySelectedOK( os, pos ); +} + +int ConstructMode::wantArgs( const std::vector& os, KigDocument& d, KigWidget& w ) +{ + return mctor->wantArgs( os, d, w ); +} + +void BaseConstructMode::finish() +{ + mdoc.doneMode( this ); +} + +ConstructMode::ConstructMode( KigPart& d, const ObjectConstructor* ctor ) + : BaseConstructMode( d ), mctor( ctor ) +{ +} + +ConstructMode::~ConstructMode() +{ +} + +// does a test result have a frame by default ? +static const bool test_has_frame_dflt = true; + +void TestConstructMode::handlePrelim( const std::vector& os, const TQPoint& p, KigPainter& pter, KigWidget& w ) +{ + Args args; + std::transform( os.begin(), os.end(), std::back_inserter( args ), + std::mem_fun( &ObjectCalcer::imp ) ); + + // usetext + TQString usetext = i18n( mtype->argsParser().usetext( args.back(), args ).c_str() ); + TQPoint textloc = p; + textloc.setX( textloc.x() + 15 ); + pter.drawTextStd( textloc, usetext ); + + // test result + ObjectImp* data = mtype->calc( args, mdoc.document() ); + if ( ! data->valid() ) return; + assert( data->inherits( TestResultImp::stype() ) ); + TQString outputtext = static_cast( data )->data(); + TextImp ti( outputtext, w.fromScreen( p + TQPoint( - 40, 30 ) ), test_has_frame_dflt ); + ti.draw( pter ); + + delete data; +} + +TestConstructMode::TestConstructMode( KigPart& d, const ArgsParserObjectType* type ) + : BaseConstructMode( d ), mtype( type ) +{ +} + +TestConstructMode::~TestConstructMode() +{ +} + +void ConstructMode::handleArgs( const std::vector& args, KigWidget& w ) +{ + mctor->handleArgs( args, mdoc, w ); + finish(); +} + +int TestConstructMode::isAlreadySelectedOK( const std::vector&, + const int& ) +{ + return false; +} + +int TestConstructMode::wantArgs( const std::vector& os, KigDocument&, KigWidget& ) +{ + return mtype->argsParser().check( os ); +} + +void TestConstructMode::handleArgs( const std::vector& args, KigWidget& ) +{ + mresult = new ObjectTypeCalcer( mtype, args ); + mresult->calc( mdoc.document() ); + mdoc.emitStatusBarText( i18n( "Now select the location for the result label." ) ); +} + +void TestConstructMode::leftClickedObject( ObjectHolder* o, const TQPoint& p, + KigWidget& w, bool ctrlOrShiftDown ) +{ + if ( mresult ) { + TQPoint qloc = p + TQPoint( -40, 0 ); + Coordinate loc = w.fromScreen( qloc ); + + std::vector parents; + parents.push_back( new ObjectConstCalcer( new IntImp( test_has_frame_dflt ) ) ); + parents.push_back( new ObjectConstCalcer( new PointImp( loc ) ) ); + parents.push_back( new ObjectConstCalcer( new StringImp( TQString::fromLatin1( "%1" ) ) ) ); + assert( mresult->imp()->inherits( TestResultImp::stype() ) ); + parents.push_back( + new ObjectPropertyCalcer( + mresult.get(), mresult->imp()->propertiesInternalNames().findIndex( "test-result" ) ) ); + parents.back()->calc( mdoc.document() ); + + ObjectCalcer* ret = new ObjectTypeCalcer( TextType::instance(), parents ); + ret->calc( mdoc.document() ); + mdoc.addObject( new ObjectHolder( ret ) ); + + w.unsetCursor(); + mdoc.emitStatusBarText( TQString() ); + + finish(); + } + else + BaseConstructMode::leftClickedObject( o, p, w, ctrlOrShiftDown ); +} + +void TestConstructMode::midClicked( const TQPoint& p, KigWidget& w ) +{ + if ( mresult ) { + // nothing to be done here, really + } + else + BaseConstructMode::midClicked( p, w ); +} + +void TestConstructMode::rightClicked( const std::vector& oco, const TQPoint& p, KigWidget& w ) +{ + if ( mresult ) { + // nothing to be done here, really + } + else + BaseConstructMode::rightClicked( oco, p, w ); +} + +void TestConstructMode::mouseMoved( const std::vector& os, const TQPoint& p, KigWidget& w, bool shiftPressed ) +{ + if ( mresult ) { + w.setCursor( KCursor::blankCursor() ); + + w.updateCurPix(); + KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.curPix), mdoc.document() ); + + TQPoint qloc = p + TQPoint( -40, 0 ); + Coordinate loc = w.fromScreen( qloc ); + assert( dynamic_cast( mresult->imp() ) ); + TextImp ti( static_cast( mresult->imp() )->data(), loc, test_has_frame_dflt ); + ObjectDrawer d; + d.draw( ti, pter, false ); + + + w.updateWidget( pter.overlay() ); + } + else + BaseConstructMode::mouseMoved( os, p, w, shiftPressed ); +} + +TQString ConstructMode::selectStatement( const std::vector& args, const KigWidget& w ) +{ + return mctor->selectStatement( args, mdoc.document(), w ); +} + +TQString TestConstructMode::selectStatement( const std::vector& sel, const KigWidget& ) +{ + using namespace std; + Args args; + transform( sel.begin(), sel.end(), back_inserter( args ), mem_fun( &ObjectCalcer::imp ) ); + + std::string ret = mtype->argsParser().selectStatement( args ); + if ( ret.empty() ) return TQString(); + return i18n( ret.c_str() ); +} + +void PointConstructMode::redrawScreen( KigWidget* w ) +{ + w->redrawScreen( std::vector() ); +} + +void BaseConstructMode::redrawScreen( KigWidget* w ) +{ + w->redrawScreen( std::vector() ); +} diff --git a/kig/modes/dragrectmode.cc b/kig/modes/dragrectmode.cc deleted file mode 100644 index 29b00886..00000000 --- a/kig/modes/dragrectmode.cc +++ /dev/null @@ -1,180 +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 "dragrectmode.h" - -#include "../kig/kig_document.h" -#include "../kig/kig_part.h" -#include "../kig/kig_view.h" -#include "../misc/kigpainter.h" - -#include -#include -#include - -DragRectMode::DragRectMode( const TQPoint& start, KigPart& d, KigWidget& w ) - : KigMode( d ), mstart( start ), mnc( true ), mstartselected( true ), - mcancelled( false ) -{ - moved( start, w ); -} - -DragRectMode::DragRectMode( KigPart& d, KigWidget& w ) - : KigMode( d ), mnc( true ), mstartselected( false ), - mcancelled( false ) -{ - w.updateCurPix(); - w.updateWidget(); -} - -void DragRectMode::moved( const TQPoint& p, KigWidget& w ) -{ - // update the rect... - w.updateCurPix(); - std::vector overlay; - if ( mstartselected ) - { - KigPainter pt( w.screenInfo(), TQT_TQPAINTDEVICE(&w.curPix), mdoc.document() ); - pt.drawFilledRect( TQRect( p, mstart ) ); - overlay = pt.overlay(); - }; - w.updateWidget( overlay ); -} - -void DragRectMode::released( const TQPoint& p, KigWidget& w, bool nc ) -{ - if ( mstartselected ) - { - mrect = w.fromScreen( TQRect( mstart, p ) ); - mret = mdoc.document().whatIsInHere( mrect, w ); - mnc = nc; - - mdoc.doneMode( this ); - }; -} - -void DragRectMode::enableActions() -{ - KigMode::enableActions(); - - mdoc.aCancelConstruction->setEnabled( true ); -} - -std::vector DragRectMode::ret() const -{ - return mret; -} - -bool DragRectMode::needClear() const -{ - return mnc; -} - -void DragRectMode::moved( TQMouseEvent* e, KigWidget& w ) -{ - moved( e->pos(), w ); -} - -void DragRectMode::released( TQMouseEvent* e, KigWidget& w ) -{ - released( e->pos(), w, ! ( e->state() & ( ControlButton | ShiftButton ) ) ); -} - -DragRectMode::~DragRectMode() -{ -} - -void DragRectMode::mouseMoved( TQMouseEvent* e, KigWidget* w ) -{ - moved( e, *w ); -} - -void DragRectMode::leftMouseMoved( TQMouseEvent* e, KigWidget* w ) -{ - moved( e, *w ); -} - -void DragRectMode::midMouseMoved( TQMouseEvent* e, KigWidget* w ) -{ - moved( e, *w ); -} - -void DragRectMode::rightMouseMoved( TQMouseEvent* e, KigWidget* w ) -{ - moved( e, *w ); -} - -void DragRectMode::leftReleased( TQMouseEvent* e, KigWidget* w ) -{ - released( e, *w ); -} - -void DragRectMode::midReleased( TQMouseEvent* e, KigWidget* w ) -{ - released( e, *w ); -} - -void DragRectMode::rightReleased( TQMouseEvent* e, KigWidget* w ) -{ - released( e, *w ); -} - -Rect DragRectMode::rect() const -{ - return mrect; -} - -void DragRectMode::clicked( const TQMouseEvent* e, KigWidget& w ) -{ - clicked( e->pos(), w ); -} - -void DragRectMode::leftClicked( TQMouseEvent* e, KigWidget* w ) -{ - clicked( e, *w ); -} - -void DragRectMode::midClicked( TQMouseEvent* e, KigWidget* w ) -{ - clicked( e, *w ); -} - -void DragRectMode::rightClicked( TQMouseEvent* e, KigWidget* w ) -{ - clicked( e, *w ); -} - -void DragRectMode::clicked( const TQPoint& p, KigWidget& ) -{ - if ( !mstartselected ) - { - mstartselected = true; - mstart = p; - }; -} - -bool DragRectMode::cancelled() const -{ - return mcancelled; -} - -void DragRectMode::cancelConstruction() -{ - mcancelled = true; - mdoc.doneMode( this ); -} - diff --git a/kig/modes/dragrectmode.cpp b/kig/modes/dragrectmode.cpp new file mode 100644 index 00000000..29b00886 --- /dev/null +++ b/kig/modes/dragrectmode.cpp @@ -0,0 +1,180 @@ +// 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 "dragrectmode.h" + +#include "../kig/kig_document.h" +#include "../kig/kig_part.h" +#include "../kig/kig_view.h" +#include "../misc/kigpainter.h" + +#include +#include +#include + +DragRectMode::DragRectMode( const TQPoint& start, KigPart& d, KigWidget& w ) + : KigMode( d ), mstart( start ), mnc( true ), mstartselected( true ), + mcancelled( false ) +{ + moved( start, w ); +} + +DragRectMode::DragRectMode( KigPart& d, KigWidget& w ) + : KigMode( d ), mnc( true ), mstartselected( false ), + mcancelled( false ) +{ + w.updateCurPix(); + w.updateWidget(); +} + +void DragRectMode::moved( const TQPoint& p, KigWidget& w ) +{ + // update the rect... + w.updateCurPix(); + std::vector overlay; + if ( mstartselected ) + { + KigPainter pt( w.screenInfo(), TQT_TQPAINTDEVICE(&w.curPix), mdoc.document() ); + pt.drawFilledRect( TQRect( p, mstart ) ); + overlay = pt.overlay(); + }; + w.updateWidget( overlay ); +} + +void DragRectMode::released( const TQPoint& p, KigWidget& w, bool nc ) +{ + if ( mstartselected ) + { + mrect = w.fromScreen( TQRect( mstart, p ) ); + mret = mdoc.document().whatIsInHere( mrect, w ); + mnc = nc; + + mdoc.doneMode( this ); + }; +} + +void DragRectMode::enableActions() +{ + KigMode::enableActions(); + + mdoc.aCancelConstruction->setEnabled( true ); +} + +std::vector DragRectMode::ret() const +{ + return mret; +} + +bool DragRectMode::needClear() const +{ + return mnc; +} + +void DragRectMode::moved( TQMouseEvent* e, KigWidget& w ) +{ + moved( e->pos(), w ); +} + +void DragRectMode::released( TQMouseEvent* e, KigWidget& w ) +{ + released( e->pos(), w, ! ( e->state() & ( ControlButton | ShiftButton ) ) ); +} + +DragRectMode::~DragRectMode() +{ +} + +void DragRectMode::mouseMoved( TQMouseEvent* e, KigWidget* w ) +{ + moved( e, *w ); +} + +void DragRectMode::leftMouseMoved( TQMouseEvent* e, KigWidget* w ) +{ + moved( e, *w ); +} + +void DragRectMode::midMouseMoved( TQMouseEvent* e, KigWidget* w ) +{ + moved( e, *w ); +} + +void DragRectMode::rightMouseMoved( TQMouseEvent* e, KigWidget* w ) +{ + moved( e, *w ); +} + +void DragRectMode::leftReleased( TQMouseEvent* e, KigWidget* w ) +{ + released( e, *w ); +} + +void DragRectMode::midReleased( TQMouseEvent* e, KigWidget* w ) +{ + released( e, *w ); +} + +void DragRectMode::rightReleased( TQMouseEvent* e, KigWidget* w ) +{ + released( e, *w ); +} + +Rect DragRectMode::rect() const +{ + return mrect; +} + +void DragRectMode::clicked( const TQMouseEvent* e, KigWidget& w ) +{ + clicked( e->pos(), w ); +} + +void DragRectMode::leftClicked( TQMouseEvent* e, KigWidget* w ) +{ + clicked( e, *w ); +} + +void DragRectMode::midClicked( TQMouseEvent* e, KigWidget* w ) +{ + clicked( e, *w ); +} + +void DragRectMode::rightClicked( TQMouseEvent* e, KigWidget* w ) +{ + clicked( e, *w ); +} + +void DragRectMode::clicked( const TQPoint& p, KigWidget& ) +{ + if ( !mstartselected ) + { + mstartselected = true; + mstart = p; + }; +} + +bool DragRectMode::cancelled() const +{ + return mcancelled; +} + +void DragRectMode::cancelConstruction() +{ + mcancelled = true; + mdoc.doneMode( this ); +} + diff --git a/kig/modes/edittype.cc b/kig/modes/edittype.cc deleted file mode 100644 index 00686392..00000000 --- a/kig/modes/edittype.cc +++ /dev/null @@ -1,107 +0,0 @@ -/** - 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 "edittype.h" -#include "edittype.moc" - -#include -#include -#include -#include -#include -#include -#include - -EditType::EditType( TQWidget* parent, TQString name, TQString desc, TQString icon ) - : EditTypeBase( parent, "edittype", true ), mname( name ), mdesc( desc ), micon( icon ) -{ - // improving GUI look'n'feel... - buttonHelp->setGuiItem( KStdGuiItem::help() ); - buttonOk->setGuiItem( KStdGuiItem::ok() ); - buttonCancel->setGuiItem( KStdGuiItem::cancel() ); - - editName->setText( mname ); - editDescription->setText( mdesc ); - typeIcon->setIcon( !micon.isEmpty() ? micon : "gear" ); -} - -EditType::~EditType() -{ -} - -void EditType::helpSlot() -{ - kapp->invokeHelp( TQString::fromLatin1( "working-with-types" ), - TQString::fromLatin1( "kig" ) ); -} - -void EditType::okSlot() -{ - TQString tmp = editName->text(); - if ( tmp.isEmpty() ) - { - KMessageBox::information( this, i18n( "The name of the macro can not be empty." ) ); - return; - } - - bool namechanged = false; - bool descchanged = false; - bool iconchanged = false; - if ( tmp != mname ) - { - mname = tmp; - namechanged = true; - } - tmp = editDescription->text(); - if ( tmp != mdesc ) - { - mdesc = tmp; - descchanged = true; - } - tmp = typeIcon->icon(); - if ( tmp != micon ) - { - micon = tmp; - iconchanged = true; - } - done( namechanged || descchanged || iconchanged ); -} - -void EditType::cancelSlot() -{ - done( 0 ); -} - -const TQString EditType::name() const -{ - return mname; -} - -const TQString EditType::description() const -{ - return mdesc; -} - -const TQString EditType::icon() const -{ - return micon; -} diff --git a/kig/modes/edittype.cpp b/kig/modes/edittype.cpp new file mode 100644 index 00000000..00686392 --- /dev/null +++ b/kig/modes/edittype.cpp @@ -0,0 +1,107 @@ +/** + 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 "edittype.h" +#include "edittype.moc" + +#include +#include +#include +#include +#include +#include +#include + +EditType::EditType( TQWidget* parent, TQString name, TQString desc, TQString icon ) + : EditTypeBase( parent, "edittype", true ), mname( name ), mdesc( desc ), micon( icon ) +{ + // improving GUI look'n'feel... + buttonHelp->setGuiItem( KStdGuiItem::help() ); + buttonOk->setGuiItem( KStdGuiItem::ok() ); + buttonCancel->setGuiItem( KStdGuiItem::cancel() ); + + editName->setText( mname ); + editDescription->setText( mdesc ); + typeIcon->setIcon( !micon.isEmpty() ? micon : "gear" ); +} + +EditType::~EditType() +{ +} + +void EditType::helpSlot() +{ + kapp->invokeHelp( TQString::fromLatin1( "working-with-types" ), + TQString::fromLatin1( "kig" ) ); +} + +void EditType::okSlot() +{ + TQString tmp = editName->text(); + if ( tmp.isEmpty() ) + { + KMessageBox::information( this, i18n( "The name of the macro can not be empty." ) ); + return; + } + + bool namechanged = false; + bool descchanged = false; + bool iconchanged = false; + if ( tmp != mname ) + { + mname = tmp; + namechanged = true; + } + tmp = editDescription->text(); + if ( tmp != mdesc ) + { + mdesc = tmp; + descchanged = true; + } + tmp = typeIcon->icon(); + if ( tmp != micon ) + { + micon = tmp; + iconchanged = true; + } + done( namechanged || descchanged || iconchanged ); +} + +void EditType::cancelSlot() +{ + done( 0 ); +} + +const TQString EditType::name() const +{ + return mname; +} + +const TQString EditType::description() const +{ + return mdesc; +} + +const TQString EditType::icon() const +{ + return micon; +} diff --git a/kig/modes/label.cc b/kig/modes/label.cc deleted file mode 100644 index 12f0d57c..00000000 --- a/kig/modes/label.cc +++ /dev/null @@ -1,589 +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 "label.h" -#include "normal.h" - -#include "textlabelwizard.h" -#include "linkslabel.h" - -#include "../kig/kig_commands.h" -#include "../kig/kig_document.h" -#include "../kig/kig_part.h" -#include "../kig/kig_view.h" -#include "../misc/common.h" -#include "../misc/kigpainter.h" -#include "../objects/bogus_imp.h" -#include "../objects/curve_imp.h" -#include "../objects/object_factory.h" -#include "../objects/point_imp.h" -#include "../objects/text_imp.h" -#include "../objects/text_type.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -class TextLabelModeBase::Private -{ -public: - // point last clicked.. - TQPoint plc; - // the currently selected coordinate - Coordinate mcoord; - // the possible parent object that defines the location of the label.. - ObjectCalcer* locationparent; - - // the text is only kept in the text input widget, not here - // TQString mtext; - - // the property objects we'll be using as args, we keep a reference - // to them in the args object, and keep a pointer to them ( or 0 ) - // in the correct order in args ( separately, because we can't use - // the order of the parents of a ReferenceObject, and certainly - // can't give 0 as a parent.. - argvect args; - - // if we're ReallySelectingArgs, then this var points to the arg - // we're currently selecting... - int mwaaws; - - // last percent count... - uint lpc; - - TextLabelWizard* wiz; - - // What Are We Doing - wawdtype mwawd; -}; - -TextLabelModeBase::~TextLabelModeBase() -{ - delete d->wiz; - delete d; -} - -TextLabelModeBase::TextLabelModeBase( KigPart& doc ) - : KigMode( doc ), d( new Private ) -{ - d->locationparent = 0; - d->lpc = 0; - d->mwawd = SelectingLocation; - d->wiz = new TextLabelWizard( doc.widget(), this ); -} - -void TextLabelModeBase::leftClicked( TQMouseEvent* e, KigWidget* ) -{ - d->plc = e->pos(); - switch( d->mwawd ) - { - case RequestingText: - case SelectingArgs: - d->wiz->raise(); - d->wiz->setActiveWindow(); - break; - default: - break; - }; -} - -void TextLabelModeBase::leftReleased( TQMouseEvent* e, KigWidget* v ) -{ - switch( d->mwawd ) - { - case SelectingLocation: - { - if ( ( d->plc - e->pos() ).manhattanLength() > 4 ) return; - setCoordinate( v->fromScreen( d->plc ) ); - break; - } - case RequestingText: - case SelectingArgs: - d->wiz->raise(); - d->wiz->setActiveWindow(); - break; - case ReallySelectingArgs: - { - if ( ( d->plc - e->pos() ).manhattanLength() > 4 ) break; - std::vector os = mdoc.document().whatAmIOn( v->fromScreen( d->plc ), *v ); - if ( os.empty() ) break; - ObjectHolder* o = os[0]; - TQPopupMenu* p = new TQPopupMenu( v, "text_label_select_arg_popup" ); - p->insertItem( i18n( "Name" ), 0 ); - QCStringList l = o->imp()->properties(); - assert( l.size() == o->imp()->numberOfProperties() ); - for ( int i = 0; static_cast( i ) < l.size(); ++i ) - { - TQString s = i18n( l[i] ); - const char* iconfile = o->imp()->iconForProperty( i ); - int t; - if ( iconfile && *iconfile ) - { - TQPixmap pix = mdoc.instance()->iconLoader()->loadIcon( iconfile, TDEIcon::User ); - t = p->insertItem( TQIconSet( pix ), s, i + 1 ); - } - else - { - t = p->insertItem( s, i + 1 ); - }; - assert( t == i + 1 ); - }; - int result = p->exec( v->mapToGlobal( d->plc ) ); - ObjectCalcer::shared_ptr argcalcer; - if ( result == -1 ) break; - else if ( result == 0 ) - { - argcalcer = o->nameCalcer(); - if ( !argcalcer ) - { - ObjectConstCalcer* c = new ObjectConstCalcer( new StringImp( i18n( "" ) ) ); - o->setNameCalcer( c ); - argcalcer = c; - } - } - else - { - assert( static_cast( result ) < l.size() + 1 ); - argcalcer = new ObjectPropertyCalcer( o->calcer(), result - 1 ); - } - d->args[d->mwaaws] = argcalcer.get(); - argcalcer->calc( mdoc.document() ); - - updateLinksLabel(); - updateWiz(); - break; - } - default: - assert( false ); - break; - }; -} - -void TextLabelModeBase::killMode() -{ - mdoc.doneMode( this ); -} - -void TextLabelModeBase::cancelConstruction() -{ - killMode(); -} - -void TextLabelModeBase::enableActions() -{ - KigMode::enableActions(); - - mdoc.aCancelConstruction->setEnabled( true ); -} - -void TextLabelModeBase::mouseMoved( TQMouseEvent* e, KigWidget* w ) -{ - if ( d->mwawd == ReallySelectingArgs ) - { - std::vector os = mdoc.document().whatAmIOn( w->fromScreen( e->pos() ), *w ); - if ( !os.empty() ) w->setCursor( KCursor::handCursor() ); - else w->setCursor( KCursor::arrowCursor() ); - } - else if ( d->mwawd == SelectingLocation ) - { - std::vector os = mdoc.document().whatAmIOn( w->fromScreen( e->pos() ), *w ); - bool attachable = false; - d->locationparent = 0; - for ( std::vector::iterator i = os.begin(); i != os.end(); ++i ) - { - if( (*i)->imp()->attachPoint().valid() || - (*i)->imp()->inherits( PointImp::stype() ) || - (*i)->imp()->inherits( CurveImp::stype() ) ) - { - attachable = true; - d->locationparent = (*i)->calcer(); - break; - }; - }; - w->updateCurPix(); - if ( attachable ) - { - w->setCursor( KCursor::handCursor() ); - TQString s = d->locationparent->imp()->type()->attachToThisStatement(); - mdoc.emitStatusBarText( s ); - - KigPainter p( w->screenInfo(), TQT_TQPAINTDEVICE(&w->curPix), mdoc.document() ); - - // set the text next to the arrow cursor - TQPoint point = e->pos(); - point.setX(point.x()+15); - - p.drawTextStd( point, s ); - w->updateWidget( p.overlay() ); - } - else - { - w->setCursor( KCursor::crossCursor() ); - mdoc.emitStatusBarText( 0 ); - w->updateWidget(); - }; - } -} - -void TextLabelModeBase::enterTextPageEntered() -{ -} - -void TextLabelModeBase::selectArgumentsPageEntered() -{ - updateLinksLabel(); -} - -void TextLabelModeBase::cancelPressed() -{ - cancelConstruction(); -} - -static uint percentCount( const TQString& s ) -{ -// TQRegExp re( TQString::fromUtf8( "%[0-9]" ) ); - TQRegExp re( TQString::fromUtf8( "%[\\d]+" ) ); - int offset = 0; - uint percentcount = 0; - while ( ( offset = re.search( s, offset ) ) != -1 ) - { - ++percentcount; - offset += re.matchedLength(); - }; - return percentcount; -} - -void TextLabelModeBase::finishPressed() -{ - bool needframe = d->wiz->needFrameCheckBox->isChecked(); - TQString s = d->wiz->labelTextInput->text(); - - assert( percentCount( s ) == d->args.size() ); - if ( d->wiz->currentPage() == d->wiz->enter_text_page ) - assert( d->args.size() == 0 ); - - bool finished = true; - for ( argvect::iterator i = d->args.begin(); i != d->args.end(); ++i ) - finished &= ( *i != 0 ); - - if ( ! finished ) - KMessageBox::sorry( mdoc.widget(), - i18n( "There are '%n' parts in the text that you have not selected a " - "value for. Please remove them or select enough arguments." ) ); - else - { - finish( d->mcoord, s, d->args, needframe, d->locationparent ); - killMode(); - }; -} - -void TextLabelModeBase::updateWiz() -{ - TQString s = d->wiz->labelTextInput->text(); - uint percentcount = percentCount( s ); - if ( d->lpc > percentcount ) - { - d->args = argvect( d->args.begin(), d->args.begin() + percentcount ); - } - else if ( d->lpc < percentcount ) - { - d->args.resize( percentcount, 0 ); - }; - - if ( percentcount == 0 && ! s.isEmpty() ) - { - d->wiz->setNextEnabled( d->wiz->enter_text_page, false ); - d->wiz->setFinishEnabled( d->wiz->enter_text_page, true ); - d->wiz->setAppropriate( d->wiz->select_arguments_page, false ); - } - else - { - d->wiz->setAppropriate( d->wiz->select_arguments_page, !s.isEmpty() ); - d->wiz->setNextEnabled( d->wiz->enter_text_page, ! s.isEmpty() ); - d->wiz->setFinishEnabled( d->wiz->enter_text_page, false ); - bool finished = true; - for ( argvect::iterator i = d->args.begin(); i != d->args.end(); ++i ) - finished &= ( *i != 0 ); - assert( percentCount( s ) == d->args.size() ); - - d->wiz->setFinishEnabled( d->wiz->select_arguments_page, finished ); - }; - - d->lpc = percentcount; -} - -void TextLabelModeBase::labelTextChanged() -{ - updateWiz(); -} - -void TextLabelModeBase::updateLinksLabel() -{ - LinksLabel::LinksLabelEditBuf buf = d->wiz->myCustomWidget1->startEdit(); - TQString s = d->wiz->labelTextInput->text(); -// TQRegExp re( "%[0-9]" ); - TQRegExp re( "%[\\d]+" ); - int prevpos = 0; - int pos = 0; - uint count = 0; - // we split up the string into text and "links" - while ( ( pos = re.search( s, pos ) ) != -1 ) - { - // prevpos is the first character after the last match, pos is the - // first char of the current match.. - if ( prevpos != pos ) - { - // there is a text part between the previous and the current - // "link"... - assert( prevpos < pos ); - // fetch the text part... - TQString subs = s.mid( prevpos, pos - prevpos ); - // and add it... - d->wiz->myCustomWidget1->addText( subs, buf ); - }; - // we always need a link part... - TQString linktext( "%1" ); - assert( count < d->args.size() ); - if ( d->args[count] ) - { - // if the user has already selected a property, then we show its - // value... - d->args[count]->imp()->fillInNextEscape( linktext, mdoc.document() ); - } - else - // otherwise, we show a stub... - linktext = i18n( "argument %1" ).arg( count + 1 ); - - d->wiz->myCustomWidget1->addLink( linktext, buf ); - // set pos and prevpos to the next char after the last match, so - // we don't enter infinite loops... -// pos += 2; - pos += re.matchedLength(); - prevpos = pos; - ++count; - }; - - if ( static_cast( prevpos ) != s.length() ) - d->wiz->myCustomWidget1->addText( s.mid( prevpos ), buf ); - - d->wiz->myCustomWidget1->applyEdit( buf ); - d->wiz->relayoutArgsPage(); - - d->wiz->resize( d->wiz->size() ); -} - -void TextLabelModeBase::linkClicked( int i ) -{ - mdoc.widget()->setActiveWindow(); - mdoc.widget()->raise(); - - assert( d->args.size() >= static_cast( i + 1 ) ); - - d->mwawd = ReallySelectingArgs; - d->mwaaws = i; - - mdoc.emitStatusBarText( i18n( "Selecting argument %1" ).arg( i + 1 ) ); -} - -void TextLabelModeBase::redrawScreen( KigWidget* w ) -{ - w->redrawScreen( std::vector() ); - w->updateScrollBars(); -} - -void TextLabelModeBase::setCoordinate( const Coordinate& coord ) -{ - d->mcoord = coord; - if ( d->mwawd == SelectingLocation ) - { - d->mwawd = RequestingText; - updateWiz(); - d->wiz->show(); - // shouldn't be necessary, but seems to be anyway.. :( - updateWiz(); - }; -} - -void TextLabelModeBase::setText( const TQString& s ) -{ - d->wiz->labelTextInput->setText( s ); -} - -void TextLabelModeBase::setPropertyObjects( const argvect& props ) -{ - d->args = props; - for ( argvect::iterator i = d->args.begin(); i != d->args.end(); ++i ) - (*i)->calc( mdoc.document() ); -} - -TextLabelConstructionMode::TextLabelConstructionMode( KigPart& d ) - : TextLabelModeBase( d ) -{ -} - -TextLabelConstructionMode::~TextLabelConstructionMode() -{ -} - -void TextLabelConstructionMode::finish( - const Coordinate& coord, const TQString& s, - const argvect& props, bool needframe, - ObjectCalcer* locationparent ) -{ - std::vector args; - for ( argvect::const_iterator i = props.begin(); - i != props.end(); ++i ) - args.push_back( i->get() ); - - ObjectHolder* label = 0; - if ( locationparent ) - label = ObjectFactory::instance()->attachedLabel( s, locationparent, coord, needframe, args, mdoc.document() ); - else - label = ObjectFactory::instance()->label( s, coord, needframe, args, mdoc.document() ); - mdoc.addObject( label ); -} - -TextLabelRedefineMode::TextLabelRedefineMode( KigPart& d, ObjectTypeCalcer* label ) - : TextLabelModeBase( d ), mlabel( label ) -{ - assert( label->imp()->inherits( TextImp::stype() ) ); - std::vector parents = label->parents(); - assert( parents.size() >= 3 ); - std::vector firstthree( parents.begin(), parents.begin() + 3 ); - std::vector rest( parents.begin() + 3, parents.end() ); - firstthree = TextType::instance()->argParser().parse( firstthree ); - - assert( firstthree[0]->imp()->inherits( IntImp::stype() ) ); - assert( firstthree[1]->imp()->inherits( PointImp::stype() ) ); - assert( firstthree[2]->imp()->inherits( StringImp::stype() ) ); - - bool frame = static_cast( firstthree[0]->imp() )->data() != 0; - Coordinate coord = static_cast( firstthree[1]->imp() )->coordinate(); - TQString text = static_cast( firstthree[2]->imp() )->data(); - - // don't set it, let the user redefine it.. -// setCoordinate( coord ); - setText( text ); - setFrame( frame ); - - argvect v; - for ( uint i = 0; i < rest.size(); ++i ) - { - v.push_back( rest[i] ); - }; - assert( v.size() == rest.size() ); - - setPropertyObjects( v ); -} - -TextLabelRedefineMode::~TextLabelRedefineMode() -{ -} - -void TextLabelRedefineMode::finish( - const Coordinate& coord, const TQString& s, - const argvect& props, bool needframe, - ObjectCalcer* locationparent ) -{ - std::vector parents = mlabel->parents(); - assert( parents.size() >= 3 ); - std::vector firstthree( parents.begin(), parents.begin() + 3 ); - std::vector rest( parents.begin() + 3, parents.end() ); - firstthree = TextType::instance()->argParser().parse( firstthree ); - - KigCommand* kc = new KigCommand( mdoc, i18n( "Change Label" ) ); - MonitorDataObjects mon( firstthree ); - - assert( firstthree[0]->imp()->inherits( IntImp::stype() ) ); - assert( firstthree[1]->imp()->inherits( PointImp::stype() ) ); - assert( firstthree[2]->imp()->inherits( StringImp::stype() ) ); - - assert( dynamic_cast( firstthree[0] ) ); - assert( dynamic_cast( firstthree[2] ) ); - static_cast( firstthree[0] )->setImp( new IntImp( needframe ? 1 : 0 ) ); - - // we don't do this, because - // 1 this isn't necessarily a DataObject, we also support it to be a - // user-known point, or an internal constrained point.. - // 2 we don't know that we don't want it to become a user-known - // point or an internal constrained point, instead of a - // DataObject.. - // static_cast( firstthree[1] )->setImp( new PointImp( - // coord ) ); - - static_cast( firstthree[2] )->setImp( new StringImp( s ) ); - mon.finish( kc ); - - std::vector oldparents = mlabel->parents(); - std::vector p; - for ( argvect::const_iterator i = props.begin(); - i != props.end(); ++i ) - p.push_back( i->get() ); - for ( std::vector::iterator i = p.begin(); - i != p.end(); ++i ) - ( *i )->calc( mdoc.document() ); - - std::vector np = firstthree; - /* - * take advantage of the method "getAttachPoint" that should - * do all the work; it is also used when creating a new label - */ - np[1] = ObjectFactory::instance()->getAttachPoint( locationparent, coord, mdoc.document() ); - -/* this is the old code, just in case... */ -// if ( locationparent && locationparent->imp()->inherits( CurveImp::stype() ) ) -// { -// double param = static_cast( locationparent->imp() )->getParam( coord, mdoc.document() ); -// np[1] = ObjectFactory::instance()->constrainedPointCalcer( locationparent, param ); -// np[1]->calc( mdoc.document() ); -// } -// else if ( locationparent ) -// { -// assert( locationparent->imp()->inherits( PointImp::stype() ) ); -// np[1] = locationparent; -// } -// else -// np[1] = new ObjectConstCalcer( new PointImp( coord ) ); - - copy( p.begin(), p.end(), back_inserter( np ) ); - - kc->addTask( - new ChangeParentsAndTypeTask( - mlabel, np, TextType::instance() ) ); - - mdoc.history()->addCommand( kc ); -} - -void TextLabelModeBase::setFrame( bool f ) -{ - d->wiz->needFrameCheckBox->setChecked( f ); -} - -void TextLabelModeBase::setLocationParent( ObjectCalcer* o ) -{ - d->locationparent = o; -} diff --git a/kig/modes/label.cpp b/kig/modes/label.cpp new file mode 100644 index 00000000..12f0d57c --- /dev/null +++ b/kig/modes/label.cpp @@ -0,0 +1,589 @@ +// 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 "label.h" +#include "normal.h" + +#include "textlabelwizard.h" +#include "linkslabel.h" + +#include "../kig/kig_commands.h" +#include "../kig/kig_document.h" +#include "../kig/kig_part.h" +#include "../kig/kig_view.h" +#include "../misc/common.h" +#include "../misc/kigpainter.h" +#include "../objects/bogus_imp.h" +#include "../objects/curve_imp.h" +#include "../objects/object_factory.h" +#include "../objects/point_imp.h" +#include "../objects/text_imp.h" +#include "../objects/text_type.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +class TextLabelModeBase::Private +{ +public: + // point last clicked.. + TQPoint plc; + // the currently selected coordinate + Coordinate mcoord; + // the possible parent object that defines the location of the label.. + ObjectCalcer* locationparent; + + // the text is only kept in the text input widget, not here + // TQString mtext; + + // the property objects we'll be using as args, we keep a reference + // to them in the args object, and keep a pointer to them ( or 0 ) + // in the correct order in args ( separately, because we can't use + // the order of the parents of a ReferenceObject, and certainly + // can't give 0 as a parent.. + argvect args; + + // if we're ReallySelectingArgs, then this var points to the arg + // we're currently selecting... + int mwaaws; + + // last percent count... + uint lpc; + + TextLabelWizard* wiz; + + // What Are We Doing + wawdtype mwawd; +}; + +TextLabelModeBase::~TextLabelModeBase() +{ + delete d->wiz; + delete d; +} + +TextLabelModeBase::TextLabelModeBase( KigPart& doc ) + : KigMode( doc ), d( new Private ) +{ + d->locationparent = 0; + d->lpc = 0; + d->mwawd = SelectingLocation; + d->wiz = new TextLabelWizard( doc.widget(), this ); +} + +void TextLabelModeBase::leftClicked( TQMouseEvent* e, KigWidget* ) +{ + d->plc = e->pos(); + switch( d->mwawd ) + { + case RequestingText: + case SelectingArgs: + d->wiz->raise(); + d->wiz->setActiveWindow(); + break; + default: + break; + }; +} + +void TextLabelModeBase::leftReleased( TQMouseEvent* e, KigWidget* v ) +{ + switch( d->mwawd ) + { + case SelectingLocation: + { + if ( ( d->plc - e->pos() ).manhattanLength() > 4 ) return; + setCoordinate( v->fromScreen( d->plc ) ); + break; + } + case RequestingText: + case SelectingArgs: + d->wiz->raise(); + d->wiz->setActiveWindow(); + break; + case ReallySelectingArgs: + { + if ( ( d->plc - e->pos() ).manhattanLength() > 4 ) break; + std::vector os = mdoc.document().whatAmIOn( v->fromScreen( d->plc ), *v ); + if ( os.empty() ) break; + ObjectHolder* o = os[0]; + TQPopupMenu* p = new TQPopupMenu( v, "text_label_select_arg_popup" ); + p->insertItem( i18n( "Name" ), 0 ); + QCStringList l = o->imp()->properties(); + assert( l.size() == o->imp()->numberOfProperties() ); + for ( int i = 0; static_cast( i ) < l.size(); ++i ) + { + TQString s = i18n( l[i] ); + const char* iconfile = o->imp()->iconForProperty( i ); + int t; + if ( iconfile && *iconfile ) + { + TQPixmap pix = mdoc.instance()->iconLoader()->loadIcon( iconfile, TDEIcon::User ); + t = p->insertItem( TQIconSet( pix ), s, i + 1 ); + } + else + { + t = p->insertItem( s, i + 1 ); + }; + assert( t == i + 1 ); + }; + int result = p->exec( v->mapToGlobal( d->plc ) ); + ObjectCalcer::shared_ptr argcalcer; + if ( result == -1 ) break; + else if ( result == 0 ) + { + argcalcer = o->nameCalcer(); + if ( !argcalcer ) + { + ObjectConstCalcer* c = new ObjectConstCalcer( new StringImp( i18n( "" ) ) ); + o->setNameCalcer( c ); + argcalcer = c; + } + } + else + { + assert( static_cast( result ) < l.size() + 1 ); + argcalcer = new ObjectPropertyCalcer( o->calcer(), result - 1 ); + } + d->args[d->mwaaws] = argcalcer.get(); + argcalcer->calc( mdoc.document() ); + + updateLinksLabel(); + updateWiz(); + break; + } + default: + assert( false ); + break; + }; +} + +void TextLabelModeBase::killMode() +{ + mdoc.doneMode( this ); +} + +void TextLabelModeBase::cancelConstruction() +{ + killMode(); +} + +void TextLabelModeBase::enableActions() +{ + KigMode::enableActions(); + + mdoc.aCancelConstruction->setEnabled( true ); +} + +void TextLabelModeBase::mouseMoved( TQMouseEvent* e, KigWidget* w ) +{ + if ( d->mwawd == ReallySelectingArgs ) + { + std::vector os = mdoc.document().whatAmIOn( w->fromScreen( e->pos() ), *w ); + if ( !os.empty() ) w->setCursor( KCursor::handCursor() ); + else w->setCursor( KCursor::arrowCursor() ); + } + else if ( d->mwawd == SelectingLocation ) + { + std::vector os = mdoc.document().whatAmIOn( w->fromScreen( e->pos() ), *w ); + bool attachable = false; + d->locationparent = 0; + for ( std::vector::iterator i = os.begin(); i != os.end(); ++i ) + { + if( (*i)->imp()->attachPoint().valid() || + (*i)->imp()->inherits( PointImp::stype() ) || + (*i)->imp()->inherits( CurveImp::stype() ) ) + { + attachable = true; + d->locationparent = (*i)->calcer(); + break; + }; + }; + w->updateCurPix(); + if ( attachable ) + { + w->setCursor( KCursor::handCursor() ); + TQString s = d->locationparent->imp()->type()->attachToThisStatement(); + mdoc.emitStatusBarText( s ); + + KigPainter p( w->screenInfo(), TQT_TQPAINTDEVICE(&w->curPix), mdoc.document() ); + + // set the text next to the arrow cursor + TQPoint point = e->pos(); + point.setX(point.x()+15); + + p.drawTextStd( point, s ); + w->updateWidget( p.overlay() ); + } + else + { + w->setCursor( KCursor::crossCursor() ); + mdoc.emitStatusBarText( 0 ); + w->updateWidget(); + }; + } +} + +void TextLabelModeBase::enterTextPageEntered() +{ +} + +void TextLabelModeBase::selectArgumentsPageEntered() +{ + updateLinksLabel(); +} + +void TextLabelModeBase::cancelPressed() +{ + cancelConstruction(); +} + +static uint percentCount( const TQString& s ) +{ +// TQRegExp re( TQString::fromUtf8( "%[0-9]" ) ); + TQRegExp re( TQString::fromUtf8( "%[\\d]+" ) ); + int offset = 0; + uint percentcount = 0; + while ( ( offset = re.search( s, offset ) ) != -1 ) + { + ++percentcount; + offset += re.matchedLength(); + }; + return percentcount; +} + +void TextLabelModeBase::finishPressed() +{ + bool needframe = d->wiz->needFrameCheckBox->isChecked(); + TQString s = d->wiz->labelTextInput->text(); + + assert( percentCount( s ) == d->args.size() ); + if ( d->wiz->currentPage() == d->wiz->enter_text_page ) + assert( d->args.size() == 0 ); + + bool finished = true; + for ( argvect::iterator i = d->args.begin(); i != d->args.end(); ++i ) + finished &= ( *i != 0 ); + + if ( ! finished ) + KMessageBox::sorry( mdoc.widget(), + i18n( "There are '%n' parts in the text that you have not selected a " + "value for. Please remove them or select enough arguments." ) ); + else + { + finish( d->mcoord, s, d->args, needframe, d->locationparent ); + killMode(); + }; +} + +void TextLabelModeBase::updateWiz() +{ + TQString s = d->wiz->labelTextInput->text(); + uint percentcount = percentCount( s ); + if ( d->lpc > percentcount ) + { + d->args = argvect( d->args.begin(), d->args.begin() + percentcount ); + } + else if ( d->lpc < percentcount ) + { + d->args.resize( percentcount, 0 ); + }; + + if ( percentcount == 0 && ! s.isEmpty() ) + { + d->wiz->setNextEnabled( d->wiz->enter_text_page, false ); + d->wiz->setFinishEnabled( d->wiz->enter_text_page, true ); + d->wiz->setAppropriate( d->wiz->select_arguments_page, false ); + } + else + { + d->wiz->setAppropriate( d->wiz->select_arguments_page, !s.isEmpty() ); + d->wiz->setNextEnabled( d->wiz->enter_text_page, ! s.isEmpty() ); + d->wiz->setFinishEnabled( d->wiz->enter_text_page, false ); + bool finished = true; + for ( argvect::iterator i = d->args.begin(); i != d->args.end(); ++i ) + finished &= ( *i != 0 ); + assert( percentCount( s ) == d->args.size() ); + + d->wiz->setFinishEnabled( d->wiz->select_arguments_page, finished ); + }; + + d->lpc = percentcount; +} + +void TextLabelModeBase::labelTextChanged() +{ + updateWiz(); +} + +void TextLabelModeBase::updateLinksLabel() +{ + LinksLabel::LinksLabelEditBuf buf = d->wiz->myCustomWidget1->startEdit(); + TQString s = d->wiz->labelTextInput->text(); +// TQRegExp re( "%[0-9]" ); + TQRegExp re( "%[\\d]+" ); + int prevpos = 0; + int pos = 0; + uint count = 0; + // we split up the string into text and "links" + while ( ( pos = re.search( s, pos ) ) != -1 ) + { + // prevpos is the first character after the last match, pos is the + // first char of the current match.. + if ( prevpos != pos ) + { + // there is a text part between the previous and the current + // "link"... + assert( prevpos < pos ); + // fetch the text part... + TQString subs = s.mid( prevpos, pos - prevpos ); + // and add it... + d->wiz->myCustomWidget1->addText( subs, buf ); + }; + // we always need a link part... + TQString linktext( "%1" ); + assert( count < d->args.size() ); + if ( d->args[count] ) + { + // if the user has already selected a property, then we show its + // value... + d->args[count]->imp()->fillInNextEscape( linktext, mdoc.document() ); + } + else + // otherwise, we show a stub... + linktext = i18n( "argument %1" ).arg( count + 1 ); + + d->wiz->myCustomWidget1->addLink( linktext, buf ); + // set pos and prevpos to the next char after the last match, so + // we don't enter infinite loops... +// pos += 2; + pos += re.matchedLength(); + prevpos = pos; + ++count; + }; + + if ( static_cast( prevpos ) != s.length() ) + d->wiz->myCustomWidget1->addText( s.mid( prevpos ), buf ); + + d->wiz->myCustomWidget1->applyEdit( buf ); + d->wiz->relayoutArgsPage(); + + d->wiz->resize( d->wiz->size() ); +} + +void TextLabelModeBase::linkClicked( int i ) +{ + mdoc.widget()->setActiveWindow(); + mdoc.widget()->raise(); + + assert( d->args.size() >= static_cast( i + 1 ) ); + + d->mwawd = ReallySelectingArgs; + d->mwaaws = i; + + mdoc.emitStatusBarText( i18n( "Selecting argument %1" ).arg( i + 1 ) ); +} + +void TextLabelModeBase::redrawScreen( KigWidget* w ) +{ + w->redrawScreen( std::vector() ); + w->updateScrollBars(); +} + +void TextLabelModeBase::setCoordinate( const Coordinate& coord ) +{ + d->mcoord = coord; + if ( d->mwawd == SelectingLocation ) + { + d->mwawd = RequestingText; + updateWiz(); + d->wiz->show(); + // shouldn't be necessary, but seems to be anyway.. :( + updateWiz(); + }; +} + +void TextLabelModeBase::setText( const TQString& s ) +{ + d->wiz->labelTextInput->setText( s ); +} + +void TextLabelModeBase::setPropertyObjects( const argvect& props ) +{ + d->args = props; + for ( argvect::iterator i = d->args.begin(); i != d->args.end(); ++i ) + (*i)->calc( mdoc.document() ); +} + +TextLabelConstructionMode::TextLabelConstructionMode( KigPart& d ) + : TextLabelModeBase( d ) +{ +} + +TextLabelConstructionMode::~TextLabelConstructionMode() +{ +} + +void TextLabelConstructionMode::finish( + const Coordinate& coord, const TQString& s, + const argvect& props, bool needframe, + ObjectCalcer* locationparent ) +{ + std::vector args; + for ( argvect::const_iterator i = props.begin(); + i != props.end(); ++i ) + args.push_back( i->get() ); + + ObjectHolder* label = 0; + if ( locationparent ) + label = ObjectFactory::instance()->attachedLabel( s, locationparent, coord, needframe, args, mdoc.document() ); + else + label = ObjectFactory::instance()->label( s, coord, needframe, args, mdoc.document() ); + mdoc.addObject( label ); +} + +TextLabelRedefineMode::TextLabelRedefineMode( KigPart& d, ObjectTypeCalcer* label ) + : TextLabelModeBase( d ), mlabel( label ) +{ + assert( label->imp()->inherits( TextImp::stype() ) ); + std::vector parents = label->parents(); + assert( parents.size() >= 3 ); + std::vector firstthree( parents.begin(), parents.begin() + 3 ); + std::vector rest( parents.begin() + 3, parents.end() ); + firstthree = TextType::instance()->argParser().parse( firstthree ); + + assert( firstthree[0]->imp()->inherits( IntImp::stype() ) ); + assert( firstthree[1]->imp()->inherits( PointImp::stype() ) ); + assert( firstthree[2]->imp()->inherits( StringImp::stype() ) ); + + bool frame = static_cast( firstthree[0]->imp() )->data() != 0; + Coordinate coord = static_cast( firstthree[1]->imp() )->coordinate(); + TQString text = static_cast( firstthree[2]->imp() )->data(); + + // don't set it, let the user redefine it.. +// setCoordinate( coord ); + setText( text ); + setFrame( frame ); + + argvect v; + for ( uint i = 0; i < rest.size(); ++i ) + { + v.push_back( rest[i] ); + }; + assert( v.size() == rest.size() ); + + setPropertyObjects( v ); +} + +TextLabelRedefineMode::~TextLabelRedefineMode() +{ +} + +void TextLabelRedefineMode::finish( + const Coordinate& coord, const TQString& s, + const argvect& props, bool needframe, + ObjectCalcer* locationparent ) +{ + std::vector parents = mlabel->parents(); + assert( parents.size() >= 3 ); + std::vector firstthree( parents.begin(), parents.begin() + 3 ); + std::vector rest( parents.begin() + 3, parents.end() ); + firstthree = TextType::instance()->argParser().parse( firstthree ); + + KigCommand* kc = new KigCommand( mdoc, i18n( "Change Label" ) ); + MonitorDataObjects mon( firstthree ); + + assert( firstthree[0]->imp()->inherits( IntImp::stype() ) ); + assert( firstthree[1]->imp()->inherits( PointImp::stype() ) ); + assert( firstthree[2]->imp()->inherits( StringImp::stype() ) ); + + assert( dynamic_cast( firstthree[0] ) ); + assert( dynamic_cast( firstthree[2] ) ); + static_cast( firstthree[0] )->setImp( new IntImp( needframe ? 1 : 0 ) ); + + // we don't do this, because + // 1 this isn't necessarily a DataObject, we also support it to be a + // user-known point, or an internal constrained point.. + // 2 we don't know that we don't want it to become a user-known + // point or an internal constrained point, instead of a + // DataObject.. + // static_cast( firstthree[1] )->setImp( new PointImp( + // coord ) ); + + static_cast( firstthree[2] )->setImp( new StringImp( s ) ); + mon.finish( kc ); + + std::vector oldparents = mlabel->parents(); + std::vector p; + for ( argvect::const_iterator i = props.begin(); + i != props.end(); ++i ) + p.push_back( i->get() ); + for ( std::vector::iterator i = p.begin(); + i != p.end(); ++i ) + ( *i )->calc( mdoc.document() ); + + std::vector np = firstthree; + /* + * take advantage of the method "getAttachPoint" that should + * do all the work; it is also used when creating a new label + */ + np[1] = ObjectFactory::instance()->getAttachPoint( locationparent, coord, mdoc.document() ); + +/* this is the old code, just in case... */ +// if ( locationparent && locationparent->imp()->inherits( CurveImp::stype() ) ) +// { +// double param = static_cast( locationparent->imp() )->getParam( coord, mdoc.document() ); +// np[1] = ObjectFactory::instance()->constrainedPointCalcer( locationparent, param ); +// np[1]->calc( mdoc.document() ); +// } +// else if ( locationparent ) +// { +// assert( locationparent->imp()->inherits( PointImp::stype() ) ); +// np[1] = locationparent; +// } +// else +// np[1] = new ObjectConstCalcer( new PointImp( coord ) ); + + copy( p.begin(), p.end(), back_inserter( np ) ); + + kc->addTask( + new ChangeParentsAndTypeTask( + mlabel, np, TextType::instance() ) ); + + mdoc.history()->addCommand( kc ); +} + +void TextLabelModeBase::setFrame( bool f ) +{ + d->wiz->needFrameCheckBox->setChecked( f ); +} + +void TextLabelModeBase::setLocationParent( ObjectCalcer* o ) +{ + d->locationparent = o; +} diff --git a/kig/modes/macro.cc b/kig/modes/macro.cc deleted file mode 100644 index 8fe16b4d..00000000 --- a/kig/modes/macro.cc +++ /dev/null @@ -1,245 +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 "macro.h" - -#include "macrowizard.h" -#include "dragrectmode.h" -#include "../kig/kig_part.h" -#include "../kig/kig_view.h" -#include "../misc/kigpainter.h" -#include "../misc/object_constructor.h" -#include "../misc/lists.h" -#include "../misc/guiaction.h" -#include "../objects/object_imp.h" - -#include -#include -#include -#include - -#include -#include - -using namespace std; - -DefineMacroMode::DefineMacroMode( KigPart& d ) - : BaseMode( d ) -{ - mwizard = new MacroWizard( d.widget(), this ); - mwizard->show(); - updateNexts(); -} - -DefineMacroMode::~DefineMacroMode() -{ - delete mwizard; -} - -void DefineMacroMode::abandonMacro() -{ - mdoc.doneMode( this ); -} - -void DefineMacroMode::updateNexts() -{ - mwizard->setNextEnabled( mwizard->mpgiven, - !mgiven.empty() ); - mwizard->setNextEnabled( mwizard->mpfinal, - !mfinal.empty() ); - mwizard->setFinishEnabled( - mwizard->mpname, - !mwizard->KLineEdit2->text().isEmpty() - ); -} - -void DefineMacroMode::enableActions() -{ - KigMode::enableActions(); - // we don't enable any actions... -} - -void DefineMacroMode::givenPageEntered() -{ - std::vector given( mgiven.begin(), mgiven.end() ); - static_cast( mdoc.widget() )->realWidget()->redrawScreen( given ); - updateNexts(); -} - -void DefineMacroMode::finalPageEntered() -{ - std::vector final( mfinal.begin(), mfinal.end() ); - static_cast( mdoc.widget() )->realWidget()->redrawScreen( final ); - - updateNexts(); -} - -void DefineMacroMode::namePageEntered() -{ - ObjectCalcer* (ObjectHolder::*memfun)() = &ObjectHolder::calcer; - std::vector given; - std::transform( mgiven.begin(), mgiven.end(), - std::back_inserter( given ), - std::mem_fun( memfun ) ); - std::vector final; - std::transform( mfinal.begin(), mfinal.end(), - std::back_inserter( final ), - std::mem_fun( memfun ) ); - ObjectHierarchy hier( given, final ); - if ( hier.resultDoesNotDependOnGiven() ) - { - KMessageBox::sorry( mwizard, - i18n( "One of the result objects you selected " - "cannot be calculated from the given objects. " - "Kig cannot calculate this macro because of this. " - "Please press Back, and construct the objects " - "in the correct order..." ) ); - mwizard->back(); - } - else if( !hier.allGivenObjectsUsed() ) - { - KMessageBox::sorry( mwizard, - i18n( "One of the given objects is not used in the " - "calculation of the resultant objects. This " - "probably means you are expecting Kig to do " - "something impossible. Please check the " - "macro and try again." ) ); - mwizard->back(); - } - - static_cast( mdoc.widget() )->realWidget()->redrawScreen( std::vector() ); - - updateNexts(); -} - -void DefineMacroMode::finishPressed() -{ - ObjectCalcer* (ObjectHolder::*memfun)() = &ObjectHolder::calcer; - std::vector given; - std::transform( mgiven.begin(), mgiven.end(), - std::back_inserter( given ), - std::mem_fun( memfun ) ); - std::vector final; - std::transform( mfinal.begin(), mfinal.end(), - std::back_inserter( final ), - std::mem_fun( memfun ) ); - ObjectHierarchy hier( given, final ); - MacroConstructor* ctor = - new MacroConstructor( hier, - mwizard->KLineEdit2->text(), - mwizard->KLineEdit1->text() ); - ConstructibleAction* act = new ConstructibleAction( ctor, 0 ); - MacroList::instance()->add( new Macro( act, ctor ) ); - - abandonMacro(); -} - -void DefineMacroMode::cancelPressed() -{ - abandonMacro(); -} - -void DefineMacroMode::macroNameChanged() -{ - mwizard->setFinishEnabled( - mwizard->mpname, - !mwizard->KLineEdit2->text().isEmpty() - ); -} - -void DefineMacroMode::dragRect( const TQPoint& p, KigWidget& w ) -{ - if ( mwizard->currentPage() == mwizard->mpname ) return; - std::vector* objs = mwizard->currentPage() == mwizard->mpgiven ? &mgiven : &mfinal; - DragRectMode dm( p, mdoc, w ); - mdoc.runMode( &dm ); - KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.stillPix), mdoc.document() ); - if ( ! dm.cancelled() ) - { - std::vector ret = dm.ret(); - if ( dm.needClear() ) - { - pter.drawObjects( objs->begin(), objs->end(), false ); - objs->clear(); - } - - std::copy( ret.begin(), ret.end(), std::back_inserter( *objs ) ); - pter.drawObjects( objs->begin(), objs->end(), true ); - }; - w.updateCurPix( pter.overlay() ); - w.updateWidget(); - - updateNexts(); -} - -void DefineMacroMode::leftClickedObject( ObjectHolder* o, const TQPoint&, - KigWidget& w, bool ) -{ - if ( mwizard->currentPage() == mwizard->mpname ) return; - std::vector* objs = mwizard->currentPage() == mwizard->mpgiven ? &mgiven : &mfinal; - std::vector::iterator iter = std::find( objs->begin(), objs->end(), o ); - bool isselected = ( iter != objs->end() ); - if ( isselected ) objs->erase( iter ); - else objs->push_back( o ); - - KigPainter p( w.screenInfo(), TQT_TQPAINTDEVICE(&w.stillPix), mdoc.document() ); - p.drawObject( o, !isselected ); - w.updateCurPix( p.overlay() ); - w.updateWidget(); - - updateNexts(); -} - -void DefineMacroMode::mouseMoved( const std::vector& os, const TQPoint& pt, KigWidget& w, bool ) -{ - w.updateCurPix(); - - if ( os.empty() ) - { - w.setCursor( KCursor::arrowCursor() ); - mdoc.emitStatusBarText( 0 ); - w.updateWidget(); - } - else - { - // the cursor is over an object, show object type next to cursor - // and set statusbar text - - w.setCursor( KCursor::handCursor() ); - TQString selectstat = os.front()->selectStatement(); - - // statusbar text - mdoc.emitStatusBarText( selectstat ); - KigPainter p( w.screenInfo(), TQT_TQPAINTDEVICE(&w.curPix), mdoc.document() ); - - // set the text next to the arrow cursor - TQPoint point = pt; - point.setX(point.x()+15); - - p.drawTextStd( point, selectstat ); - w.updateWidget( p.overlay() ); - } -} - -void DefineMacroMode::rightClicked( const std::vector&, const TQPoint&, KigWidget& ) -{ -} - -void DefineMacroMode::midClicked( const TQPoint&, KigWidget& ) -{ -} - diff --git a/kig/modes/macro.cpp b/kig/modes/macro.cpp new file mode 100644 index 00000000..8fe16b4d --- /dev/null +++ b/kig/modes/macro.cpp @@ -0,0 +1,245 @@ +// 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 "macro.h" + +#include "macrowizard.h" +#include "dragrectmode.h" +#include "../kig/kig_part.h" +#include "../kig/kig_view.h" +#include "../misc/kigpainter.h" +#include "../misc/object_constructor.h" +#include "../misc/lists.h" +#include "../misc/guiaction.h" +#include "../objects/object_imp.h" + +#include +#include +#include +#include + +#include +#include + +using namespace std; + +DefineMacroMode::DefineMacroMode( KigPart& d ) + : BaseMode( d ) +{ + mwizard = new MacroWizard( d.widget(), this ); + mwizard->show(); + updateNexts(); +} + +DefineMacroMode::~DefineMacroMode() +{ + delete mwizard; +} + +void DefineMacroMode::abandonMacro() +{ + mdoc.doneMode( this ); +} + +void DefineMacroMode::updateNexts() +{ + mwizard->setNextEnabled( mwizard->mpgiven, + !mgiven.empty() ); + mwizard->setNextEnabled( mwizard->mpfinal, + !mfinal.empty() ); + mwizard->setFinishEnabled( + mwizard->mpname, + !mwizard->KLineEdit2->text().isEmpty() + ); +} + +void DefineMacroMode::enableActions() +{ + KigMode::enableActions(); + // we don't enable any actions... +} + +void DefineMacroMode::givenPageEntered() +{ + std::vector given( mgiven.begin(), mgiven.end() ); + static_cast( mdoc.widget() )->realWidget()->redrawScreen( given ); + updateNexts(); +} + +void DefineMacroMode::finalPageEntered() +{ + std::vector final( mfinal.begin(), mfinal.end() ); + static_cast( mdoc.widget() )->realWidget()->redrawScreen( final ); + + updateNexts(); +} + +void DefineMacroMode::namePageEntered() +{ + ObjectCalcer* (ObjectHolder::*memfun)() = &ObjectHolder::calcer; + std::vector given; + std::transform( mgiven.begin(), mgiven.end(), + std::back_inserter( given ), + std::mem_fun( memfun ) ); + std::vector final; + std::transform( mfinal.begin(), mfinal.end(), + std::back_inserter( final ), + std::mem_fun( memfun ) ); + ObjectHierarchy hier( given, final ); + if ( hier.resultDoesNotDependOnGiven() ) + { + KMessageBox::sorry( mwizard, + i18n( "One of the result objects you selected " + "cannot be calculated from the given objects. " + "Kig cannot calculate this macro because of this. " + "Please press Back, and construct the objects " + "in the correct order..." ) ); + mwizard->back(); + } + else if( !hier.allGivenObjectsUsed() ) + { + KMessageBox::sorry( mwizard, + i18n( "One of the given objects is not used in the " + "calculation of the resultant objects. This " + "probably means you are expecting Kig to do " + "something impossible. Please check the " + "macro and try again." ) ); + mwizard->back(); + } + + static_cast( mdoc.widget() )->realWidget()->redrawScreen( std::vector() ); + + updateNexts(); +} + +void DefineMacroMode::finishPressed() +{ + ObjectCalcer* (ObjectHolder::*memfun)() = &ObjectHolder::calcer; + std::vector given; + std::transform( mgiven.begin(), mgiven.end(), + std::back_inserter( given ), + std::mem_fun( memfun ) ); + std::vector final; + std::transform( mfinal.begin(), mfinal.end(), + std::back_inserter( final ), + std::mem_fun( memfun ) ); + ObjectHierarchy hier( given, final ); + MacroConstructor* ctor = + new MacroConstructor( hier, + mwizard->KLineEdit2->text(), + mwizard->KLineEdit1->text() ); + ConstructibleAction* act = new ConstructibleAction( ctor, 0 ); + MacroList::instance()->add( new Macro( act, ctor ) ); + + abandonMacro(); +} + +void DefineMacroMode::cancelPressed() +{ + abandonMacro(); +} + +void DefineMacroMode::macroNameChanged() +{ + mwizard->setFinishEnabled( + mwizard->mpname, + !mwizard->KLineEdit2->text().isEmpty() + ); +} + +void DefineMacroMode::dragRect( const TQPoint& p, KigWidget& w ) +{ + if ( mwizard->currentPage() == mwizard->mpname ) return; + std::vector* objs = mwizard->currentPage() == mwizard->mpgiven ? &mgiven : &mfinal; + DragRectMode dm( p, mdoc, w ); + mdoc.runMode( &dm ); + KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.stillPix), mdoc.document() ); + if ( ! dm.cancelled() ) + { + std::vector ret = dm.ret(); + if ( dm.needClear() ) + { + pter.drawObjects( objs->begin(), objs->end(), false ); + objs->clear(); + } + + std::copy( ret.begin(), ret.end(), std::back_inserter( *objs ) ); + pter.drawObjects( objs->begin(), objs->end(), true ); + }; + w.updateCurPix( pter.overlay() ); + w.updateWidget(); + + updateNexts(); +} + +void DefineMacroMode::leftClickedObject( ObjectHolder* o, const TQPoint&, + KigWidget& w, bool ) +{ + if ( mwizard->currentPage() == mwizard->mpname ) return; + std::vector* objs = mwizard->currentPage() == mwizard->mpgiven ? &mgiven : &mfinal; + std::vector::iterator iter = std::find( objs->begin(), objs->end(), o ); + bool isselected = ( iter != objs->end() ); + if ( isselected ) objs->erase( iter ); + else objs->push_back( o ); + + KigPainter p( w.screenInfo(), TQT_TQPAINTDEVICE(&w.stillPix), mdoc.document() ); + p.drawObject( o, !isselected ); + w.updateCurPix( p.overlay() ); + w.updateWidget(); + + updateNexts(); +} + +void DefineMacroMode::mouseMoved( const std::vector& os, const TQPoint& pt, KigWidget& w, bool ) +{ + w.updateCurPix(); + + if ( os.empty() ) + { + w.setCursor( KCursor::arrowCursor() ); + mdoc.emitStatusBarText( 0 ); + w.updateWidget(); + } + else + { + // the cursor is over an object, show object type next to cursor + // and set statusbar text + + w.setCursor( KCursor::handCursor() ); + TQString selectstat = os.front()->selectStatement(); + + // statusbar text + mdoc.emitStatusBarText( selectstat ); + KigPainter p( w.screenInfo(), TQT_TQPAINTDEVICE(&w.curPix), mdoc.document() ); + + // set the text next to the arrow cursor + TQPoint point = pt; + point.setX(point.x()+15); + + p.drawTextStd( point, selectstat ); + w.updateWidget( p.overlay() ); + } +} + +void DefineMacroMode::rightClicked( const std::vector&, const TQPoint&, KigWidget& ) +{ +} + +void DefineMacroMode::midClicked( const TQPoint&, KigWidget& ) +{ +} + diff --git a/kig/modes/macrowizard.cc b/kig/modes/macrowizard.cc deleted file mode 100644 index c6b8f36c..00000000 --- a/kig/modes/macrowizard.cc +++ /dev/null @@ -1,90 +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 "macrowizard.h" -#include "macrowizard.moc" - -#include "macro.h" - -#include -#include -#include - -MacroWizard::MacroWizard( TQWidget* parent, DefineMacroMode* m ) - : MacroWizardBase( parent, "Define Macro Wizard", false ), mmode( m ) -{ - connect( KLineEdit2, TQT_SIGNAL( textChanged( const TQString& ) ), - this, TQT_SLOT( nameTextChanged( const TQString& ) ) ); - connect( this, TQT_SIGNAL( helpClicked() ), this, - TQT_SLOT( slotHelpClicked() ) ); -} - -MacroWizard::~MacroWizard() -{ -} - -void MacroWizard::back() -{ - if ( currentPage() == mpfinal ) - { - // currentPage() is not yet updated when we get here, so this - // means that the page about to be shown is actually mpgiven... - mmode->givenPageEntered(); - } - else if ( currentPage() == mpname ) - { - mmode->finalPageEntered(); - } - MacroWizardBase::back(); -} - -void MacroWizard::next() -{ - if ( currentPage() == mpgiven ) - { - // currentPage() is not yet updated when we get here, so this - // means that the page about to be shown is actually mpfinal... - mmode->finalPageEntered(); - } - else if ( currentPage() == mpfinal ) - { - mmode->namePageEntered(); - } - MacroWizardBase::next(); -} - -void MacroWizard::reject() -{ - MacroWizardBase::reject(); - mmode->cancelPressed(); -} - -void MacroWizard::nameTextChanged( const TQString& ) -{ - mmode->macroNameChanged(); -} - -void MacroWizard::accept() -{ - mmode->finishPressed(); -} - -void MacroWizard::slotHelpClicked() -{ - kapp->invokeHelp( TQString::fromLatin1( "defining-macros"), - TQString::fromLatin1( "kig" ) ); -} diff --git a/kig/modes/macrowizard.cpp b/kig/modes/macrowizard.cpp new file mode 100644 index 00000000..c6b8f36c --- /dev/null +++ b/kig/modes/macrowizard.cpp @@ -0,0 +1,90 @@ +// 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 "macrowizard.h" +#include "macrowizard.moc" + +#include "macro.h" + +#include +#include +#include + +MacroWizard::MacroWizard( TQWidget* parent, DefineMacroMode* m ) + : MacroWizardBase( parent, "Define Macro Wizard", false ), mmode( m ) +{ + connect( KLineEdit2, TQT_SIGNAL( textChanged( const TQString& ) ), + this, TQT_SLOT( nameTextChanged( const TQString& ) ) ); + connect( this, TQT_SIGNAL( helpClicked() ), this, + TQT_SLOT( slotHelpClicked() ) ); +} + +MacroWizard::~MacroWizard() +{ +} + +void MacroWizard::back() +{ + if ( currentPage() == mpfinal ) + { + // currentPage() is not yet updated when we get here, so this + // means that the page about to be shown is actually mpgiven... + mmode->givenPageEntered(); + } + else if ( currentPage() == mpname ) + { + mmode->finalPageEntered(); + } + MacroWizardBase::back(); +} + +void MacroWizard::next() +{ + if ( currentPage() == mpgiven ) + { + // currentPage() is not yet updated when we get here, so this + // means that the page about to be shown is actually mpfinal... + mmode->finalPageEntered(); + } + else if ( currentPage() == mpfinal ) + { + mmode->namePageEntered(); + } + MacroWizardBase::next(); +} + +void MacroWizard::reject() +{ + MacroWizardBase::reject(); + mmode->cancelPressed(); +} + +void MacroWizard::nameTextChanged( const TQString& ) +{ + mmode->macroNameChanged(); +} + +void MacroWizard::accept() +{ + mmode->finishPressed(); +} + +void MacroWizard::slotHelpClicked() +{ + kapp->invokeHelp( TQString::fromLatin1( "defining-macros"), + TQString::fromLatin1( "kig" ) ); +} diff --git a/kig/modes/mode.cc b/kig/modes/mode.cc deleted file mode 100644 index dbc6f7d6..00000000 --- a/kig/modes/mode.cc +++ /dev/null @@ -1,133 +0,0 @@ -/** - This file is part of Kig, a KDE program for Interactive Geometry... - 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 "mode.h" - -#include "../kig/kig_part.h" - -#include - -void KigMode::enableActions() -{ - mdoc.enableConstructActions( false ); - mdoc.aSelectAll->setEnabled( false ); - mdoc.aDeselectAll->setEnabled( false ); - mdoc.aInvertSelection->setEnabled( false ); - mdoc.aCancelConstruction->setEnabled( false ); - mdoc.aConfigureTypes->setEnabled( false ); - mdoc.aDeleteObjects->setEnabled( false ); - mdoc.aShowHidden->setEnabled( false ); - mdoc.aNewMacro->setEnabled( false ); - mdoc.action( "edit_undo" )->setEnabled( false ); - mdoc.action( "edit_redo" )->setEnabled( false ); -} - -KigMode::~KigMode() -{ -} - -KigMode::KigMode( KigPart& d ) - : mdoc( d ) -{ -} - -void KigMode::leftClicked( TQMouseEvent*, KigWidget* ) -{ -} - -void KigMode::leftMouseMoved( TQMouseEvent*, KigWidget* ) -{ -} - -void KigMode::leftReleased( TQMouseEvent*, KigWidget* ) -{ - /* insist disabling the undo button to avoid crashes */ - mdoc.action( "edit_undo" )->setEnabled( false ); - mdoc.action( "edit_redo" )->setEnabled( false ); -} - -void KigMode::midClicked( TQMouseEvent*, KigWidget* ) -{ -} - -void KigMode::midMouseMoved( TQMouseEvent*, KigWidget* ) -{ -} - -void KigMode::midReleased( TQMouseEvent*, KigWidget* ) -{ -} - -void KigMode::rightClicked( TQMouseEvent*, KigWidget* ) -{ -} - -void KigMode::rightMouseMoved( TQMouseEvent*, KigWidget* ) -{ -} - -void KigMode::rightReleased( TQMouseEvent*, KigWidget* ) -{ -} - -void KigMode::mouseMoved( TQMouseEvent*, KigWidget* ) -{ -} - -void KigMode::cancelConstruction() -{ -} - -void KigMode::deleteObjects() -{ -} - -void KigMode::showHidden() -{ -} - -void KigMode::newMacro() -{ -} - -void KigMode::editTypes() -{ -} - -void KigMode::redrawScreen( KigWidget* ) -{ -} - -StdConstructionMode* KigMode::toStdConstructionMode() -{ - return 0; -} - -void KigMode::selectAll() -{ -} - -void KigMode::deselectAll() -{ -} - -void KigMode::invertSelection() -{ -} diff --git a/kig/modes/mode.cpp b/kig/modes/mode.cpp new file mode 100644 index 00000000..dbc6f7d6 --- /dev/null +++ b/kig/modes/mode.cpp @@ -0,0 +1,133 @@ +/** + This file is part of Kig, a KDE program for Interactive Geometry... + 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 "mode.h" + +#include "../kig/kig_part.h" + +#include + +void KigMode::enableActions() +{ + mdoc.enableConstructActions( false ); + mdoc.aSelectAll->setEnabled( false ); + mdoc.aDeselectAll->setEnabled( false ); + mdoc.aInvertSelection->setEnabled( false ); + mdoc.aCancelConstruction->setEnabled( false ); + mdoc.aConfigureTypes->setEnabled( false ); + mdoc.aDeleteObjects->setEnabled( false ); + mdoc.aShowHidden->setEnabled( false ); + mdoc.aNewMacro->setEnabled( false ); + mdoc.action( "edit_undo" )->setEnabled( false ); + mdoc.action( "edit_redo" )->setEnabled( false ); +} + +KigMode::~KigMode() +{ +} + +KigMode::KigMode( KigPart& d ) + : mdoc( d ) +{ +} + +void KigMode::leftClicked( TQMouseEvent*, KigWidget* ) +{ +} + +void KigMode::leftMouseMoved( TQMouseEvent*, KigWidget* ) +{ +} + +void KigMode::leftReleased( TQMouseEvent*, KigWidget* ) +{ + /* insist disabling the undo button to avoid crashes */ + mdoc.action( "edit_undo" )->setEnabled( false ); + mdoc.action( "edit_redo" )->setEnabled( false ); +} + +void KigMode::midClicked( TQMouseEvent*, KigWidget* ) +{ +} + +void KigMode::midMouseMoved( TQMouseEvent*, KigWidget* ) +{ +} + +void KigMode::midReleased( TQMouseEvent*, KigWidget* ) +{ +} + +void KigMode::rightClicked( TQMouseEvent*, KigWidget* ) +{ +} + +void KigMode::rightMouseMoved( TQMouseEvent*, KigWidget* ) +{ +} + +void KigMode::rightReleased( TQMouseEvent*, KigWidget* ) +{ +} + +void KigMode::mouseMoved( TQMouseEvent*, KigWidget* ) +{ +} + +void KigMode::cancelConstruction() +{ +} + +void KigMode::deleteObjects() +{ +} + +void KigMode::showHidden() +{ +} + +void KigMode::newMacro() +{ +} + +void KigMode::editTypes() +{ +} + +void KigMode::redrawScreen( KigWidget* ) +{ +} + +StdConstructionMode* KigMode::toStdConstructionMode() +{ + return 0; +} + +void KigMode::selectAll() +{ +} + +void KigMode::deselectAll() +{ +} + +void KigMode::invertSelection() +{ +} diff --git a/kig/modes/moving.cc b/kig/modes/moving.cc deleted file mode 100644 index 593c7077..00000000 --- a/kig/modes/moving.cc +++ /dev/null @@ -1,245 +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 "moving.h" - -#include "normal.h" - -#include "../objects/object_imp.h" -#include "../objects/object_factory.h" -#include "../kig/kig_document.h" -#include "../kig/kig_part.h" -#include "../kig/kig_view.h" -#include "../kig/kig_commands.h" -#include "../misc/kigpainter.h" -#include "../misc/calcpaths.h" -#include "../misc/coordinate_system.h" - -#include - -#include -#include -#include - -void MovingModeBase::initScreen( const std::vector& in ) -{ - mcalcable = in; - std::set calcableset( mcalcable.begin(), mcalcable.end() ); - - // don't try to move objects that have been deleted from the - // document or internal objects that the user is not aware of.. - std::vector docobjs = mdoc.document().objects(); - for ( std::vector::iterator i = docobjs.begin(); - i != docobjs.end(); ++i ) - if ( calcableset.find( ( *i )->calcer() ) != calcableset.end() ) - mdrawable.push_back( *i ); - - std::set docobjsset( docobjs.begin(), docobjs.end() ); - std::set drawableset( mdrawable.begin(), mdrawable.end() ); - std::set notmovingobjs; - std::set_difference( docobjsset.begin(), docobjsset.end(), drawableset.begin(), drawableset.end(), - std::inserter( notmovingobjs, notmovingobjs.begin() ) ); - - mview.clearStillPix(); - KigPainter p( mview.screenInfo(), TQT_TQPAINTDEVICE(&mview.stillPix), mdoc.document() ); - p.drawGrid( mdoc.document().coordinateSystem(), mdoc.document().grid(), - mdoc.document().axes() ); - p.drawObjects( notmovingobjs.begin(), notmovingobjs.end(), false ); - mview.updateCurPix(); - - KigPainter p2( mview.screenInfo(), TQT_TQPAINTDEVICE(&mview.curPix), mdoc.document() ); - p2.drawObjects( drawableset.begin(), drawableset.end(), true ); -} - -void MovingModeBase::leftReleased( TQMouseEvent*, KigWidget* v ) -{ - // clean up after ourselves: - for ( std::vector::iterator i = mcalcable.begin(); - i != mcalcable.end(); ++i ) - ( *i )->calc( mdoc.document() ); - stopMove(); - mdoc.setModified( true ); - - // refresh the screen: - v->redrawScreen( std::vector() ); - v->updateScrollBars(); - - mdoc.doneMode( this ); -} - -void MovingModeBase::mouseMoved( TQMouseEvent* e, KigWidget* v ) -{ - v->updateCurPix(); - Coordinate c = v->fromScreen( e->pos() ); - - bool snaptogrid = e->state() & TQt::ShiftButton; - moveTo( c, snaptogrid ); - for ( std::vector::iterator i = mcalcable.begin(); - i != mcalcable.end(); ++i ) - ( *i )->calc( mdoc.document() ); - KigPainter p( v->screenInfo(), TQT_TQPAINTDEVICE(&v->curPix), mdoc.document() ); - // TODO: only draw the explicitly moving objects as selected, the - // other ones as deselected.. Needs some support from the - // subclasses.. - p.drawObjects( mdrawable, true ); - v->updateWidget( p.overlay() ); - v->updateScrollBars(); -} - -class MovingMode::Private -{ -public: - // explicitly moving objects: these are the objects that the user - // requested to move... - std::vector emo; - // point where we started moving.. - Coordinate pwwsm; - MonitorDataObjects* mon; - // we keep a map from the emo objects to their reference location. - // This is the location that they claim to be at before moving - // starts, and we use it as a reference point to determine where - // they should move next.. - std::map refmap; -}; - -MovingMode::MovingMode( const std::vector& os, const Coordinate& c, - KigWidget& v, KigPart& doc ) - : MovingModeBase( doc, v ), d( new Private ) -{ - d->pwwsm = c; - std::vector emo; - std::set objs; - for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) - if ( (*i)->canMove() ) - { - emo.push_back( ( *i )->calcer() ); - d->refmap[( *i )->calcer()] = (*i)->moveReferencePoint(); - objs.insert( ( *i )->calcer() ); - std::vector parents = ( *i )->calcer()->movableParents(); - objs.insert( parents.begin(), parents.end() ); - }; - - emo = calcPath( emo ); - for ( std::vector::const_iterator i = emo.begin(); i != emo.end(); ++i ) - if ( !isChild( *i, d->emo ) ) - d->emo.push_back( *i ); - - d->mon = new MonitorDataObjects( std::vector( objs.begin(),objs.end() ) ); - - std::set tmp = objs; - for ( std::set::const_iterator i = tmp.begin(); i != tmp.end(); ++i ) - { - std::set children = getAllChildren(*i); - objs.insert( children.begin(), children.end() ); - } - - initScreen( calcPath( std::vector( objs.begin(), objs.end() ) ) ); -} - -void MovingMode::stopMove() -{ - TQString text = d->emo.size() == 1 ? - d->emo[0]->imp()->type()->moveAStatement() : - i18n( "Move %1 Objects" ).arg( d->emo.size() ); - KigCommand* mc = new KigCommand( mdoc, text ); - d->mon->finish( mc ); - mdoc.history()->addCommand( mc ); -} - -void MovingMode::moveTo( const Coordinate& o, bool snaptogrid ) -{ - for( std::vector::iterator i = d->emo.begin(); i != d->emo.end(); ++i ) - { - assert( d->refmap.find( *i ) != d->refmap.end() ); - Coordinate nc = d->refmap[*i] + ( o - d->pwwsm ); - if ( snaptogrid ) nc = mdoc.document().coordinateSystem().snapToGrid( nc, mview ); - (*i)->move( nc, mdoc.document() ); - }; -} - -PointRedefineMode::PointRedefineMode( ObjectHolder* p, KigPart& d, KigWidget& v ) - : MovingModeBase( d, v ), mp( p ), mmon( 0 ) -{ - assert( dynamic_cast( p->calcer() ) ); - moldtype = static_cast( p->calcer() )->type(); - std::vector oldparents = p->calcer()->parents(); - std::copy( oldparents.begin(), oldparents.end(), std::back_inserter( moldparents ) ); - - std::vector parents = getAllParents( mp->calcer() ); - mmon = new MonitorDataObjects( parents ); - std::vector moving = parents; - std::set children = getAllChildren( mp->calcer() ); - std::copy( children.begin(), children.end(), std::back_inserter( moving ) ); - initScreen( moving ); -} - -void PointRedefineMode::moveTo( const Coordinate& o, bool snaptogrid ) -{ - Coordinate realo = - snaptogrid ? mdoc.document().coordinateSystem().snapToGrid( o, mview ) : o; - ObjectFactory::instance()->redefinePoint( - static_cast( mp->calcer() ), realo, mdoc.document(), mview ); -} - -PointRedefineMode::~PointRedefineMode() -{ -} - -MovingModeBase::MovingModeBase( KigPart& doc, KigWidget& v ) - : KigMode( doc ), mview( v ) -{ -} - -MovingModeBase::~MovingModeBase() -{ -} - -void MovingModeBase::leftMouseMoved( TQMouseEvent* e, KigWidget* v ) -{ - mouseMoved( e, v ); -} - -MovingMode::~MovingMode() -{ - delete d->mon; - delete d; -} - -void PointRedefineMode::stopMove() -{ - assert( dynamic_cast( mp->calcer() ) ); - ObjectTypeCalcer* mpcalc = static_cast( mp->calcer() ); - - std::vector newparents = mpcalc->parents(); - std::vector newparentsref( - newparents.begin(), newparents.end() ); - const ObjectType* newtype = mpcalc->type(); - - std::vector oldparents; - for( std::vector::iterator i = moldparents.begin(); - i != moldparents.end(); ++i ) - oldparents.push_back( i->get() ); - mpcalc->setType( moldtype ); - mpcalc->setParents( oldparents ); - mp->calc( mdoc.document() ); - - KigCommand* command = new KigCommand( mdoc, i18n( "Redefine Point" ) ); - command->addTask( - new ChangeParentsAndTypeTask( mpcalc, newparents, newtype ) ); - mmon->finish( command ); - mdoc.history()->addCommand( command ); -} diff --git a/kig/modes/moving.cpp b/kig/modes/moving.cpp new file mode 100644 index 00000000..593c7077 --- /dev/null +++ b/kig/modes/moving.cpp @@ -0,0 +1,245 @@ +// 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 "moving.h" + +#include "normal.h" + +#include "../objects/object_imp.h" +#include "../objects/object_factory.h" +#include "../kig/kig_document.h" +#include "../kig/kig_part.h" +#include "../kig/kig_view.h" +#include "../kig/kig_commands.h" +#include "../misc/kigpainter.h" +#include "../misc/calcpaths.h" +#include "../misc/coordinate_system.h" + +#include + +#include +#include +#include + +void MovingModeBase::initScreen( const std::vector& in ) +{ + mcalcable = in; + std::set calcableset( mcalcable.begin(), mcalcable.end() ); + + // don't try to move objects that have been deleted from the + // document or internal objects that the user is not aware of.. + std::vector docobjs = mdoc.document().objects(); + for ( std::vector::iterator i = docobjs.begin(); + i != docobjs.end(); ++i ) + if ( calcableset.find( ( *i )->calcer() ) != calcableset.end() ) + mdrawable.push_back( *i ); + + std::set docobjsset( docobjs.begin(), docobjs.end() ); + std::set drawableset( mdrawable.begin(), mdrawable.end() ); + std::set notmovingobjs; + std::set_difference( docobjsset.begin(), docobjsset.end(), drawableset.begin(), drawableset.end(), + std::inserter( notmovingobjs, notmovingobjs.begin() ) ); + + mview.clearStillPix(); + KigPainter p( mview.screenInfo(), TQT_TQPAINTDEVICE(&mview.stillPix), mdoc.document() ); + p.drawGrid( mdoc.document().coordinateSystem(), mdoc.document().grid(), + mdoc.document().axes() ); + p.drawObjects( notmovingobjs.begin(), notmovingobjs.end(), false ); + mview.updateCurPix(); + + KigPainter p2( mview.screenInfo(), TQT_TQPAINTDEVICE(&mview.curPix), mdoc.document() ); + p2.drawObjects( drawableset.begin(), drawableset.end(), true ); +} + +void MovingModeBase::leftReleased( TQMouseEvent*, KigWidget* v ) +{ + // clean up after ourselves: + for ( std::vector::iterator i = mcalcable.begin(); + i != mcalcable.end(); ++i ) + ( *i )->calc( mdoc.document() ); + stopMove(); + mdoc.setModified( true ); + + // refresh the screen: + v->redrawScreen( std::vector() ); + v->updateScrollBars(); + + mdoc.doneMode( this ); +} + +void MovingModeBase::mouseMoved( TQMouseEvent* e, KigWidget* v ) +{ + v->updateCurPix(); + Coordinate c = v->fromScreen( e->pos() ); + + bool snaptogrid = e->state() & TQt::ShiftButton; + moveTo( c, snaptogrid ); + for ( std::vector::iterator i = mcalcable.begin(); + i != mcalcable.end(); ++i ) + ( *i )->calc( mdoc.document() ); + KigPainter p( v->screenInfo(), TQT_TQPAINTDEVICE(&v->curPix), mdoc.document() ); + // TODO: only draw the explicitly moving objects as selected, the + // other ones as deselected.. Needs some support from the + // subclasses.. + p.drawObjects( mdrawable, true ); + v->updateWidget( p.overlay() ); + v->updateScrollBars(); +} + +class MovingMode::Private +{ +public: + // explicitly moving objects: these are the objects that the user + // requested to move... + std::vector emo; + // point where we started moving.. + Coordinate pwwsm; + MonitorDataObjects* mon; + // we keep a map from the emo objects to their reference location. + // This is the location that they claim to be at before moving + // starts, and we use it as a reference point to determine where + // they should move next.. + std::map refmap; +}; + +MovingMode::MovingMode( const std::vector& os, const Coordinate& c, + KigWidget& v, KigPart& doc ) + : MovingModeBase( doc, v ), d( new Private ) +{ + d->pwwsm = c; + std::vector emo; + std::set objs; + for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) + if ( (*i)->canMove() ) + { + emo.push_back( ( *i )->calcer() ); + d->refmap[( *i )->calcer()] = (*i)->moveReferencePoint(); + objs.insert( ( *i )->calcer() ); + std::vector parents = ( *i )->calcer()->movableParents(); + objs.insert( parents.begin(), parents.end() ); + }; + + emo = calcPath( emo ); + for ( std::vector::const_iterator i = emo.begin(); i != emo.end(); ++i ) + if ( !isChild( *i, d->emo ) ) + d->emo.push_back( *i ); + + d->mon = new MonitorDataObjects( std::vector( objs.begin(),objs.end() ) ); + + std::set tmp = objs; + for ( std::set::const_iterator i = tmp.begin(); i != tmp.end(); ++i ) + { + std::set children = getAllChildren(*i); + objs.insert( children.begin(), children.end() ); + } + + initScreen( calcPath( std::vector( objs.begin(), objs.end() ) ) ); +} + +void MovingMode::stopMove() +{ + TQString text = d->emo.size() == 1 ? + d->emo[0]->imp()->type()->moveAStatement() : + i18n( "Move %1 Objects" ).arg( d->emo.size() ); + KigCommand* mc = new KigCommand( mdoc, text ); + d->mon->finish( mc ); + mdoc.history()->addCommand( mc ); +} + +void MovingMode::moveTo( const Coordinate& o, bool snaptogrid ) +{ + for( std::vector::iterator i = d->emo.begin(); i != d->emo.end(); ++i ) + { + assert( d->refmap.find( *i ) != d->refmap.end() ); + Coordinate nc = d->refmap[*i] + ( o - d->pwwsm ); + if ( snaptogrid ) nc = mdoc.document().coordinateSystem().snapToGrid( nc, mview ); + (*i)->move( nc, mdoc.document() ); + }; +} + +PointRedefineMode::PointRedefineMode( ObjectHolder* p, KigPart& d, KigWidget& v ) + : MovingModeBase( d, v ), mp( p ), mmon( 0 ) +{ + assert( dynamic_cast( p->calcer() ) ); + moldtype = static_cast( p->calcer() )->type(); + std::vector oldparents = p->calcer()->parents(); + std::copy( oldparents.begin(), oldparents.end(), std::back_inserter( moldparents ) ); + + std::vector parents = getAllParents( mp->calcer() ); + mmon = new MonitorDataObjects( parents ); + std::vector moving = parents; + std::set children = getAllChildren( mp->calcer() ); + std::copy( children.begin(), children.end(), std::back_inserter( moving ) ); + initScreen( moving ); +} + +void PointRedefineMode::moveTo( const Coordinate& o, bool snaptogrid ) +{ + Coordinate realo = + snaptogrid ? mdoc.document().coordinateSystem().snapToGrid( o, mview ) : o; + ObjectFactory::instance()->redefinePoint( + static_cast( mp->calcer() ), realo, mdoc.document(), mview ); +} + +PointRedefineMode::~PointRedefineMode() +{ +} + +MovingModeBase::MovingModeBase( KigPart& doc, KigWidget& v ) + : KigMode( doc ), mview( v ) +{ +} + +MovingModeBase::~MovingModeBase() +{ +} + +void MovingModeBase::leftMouseMoved( TQMouseEvent* e, KigWidget* v ) +{ + mouseMoved( e, v ); +} + +MovingMode::~MovingMode() +{ + delete d->mon; + delete d; +} + +void PointRedefineMode::stopMove() +{ + assert( dynamic_cast( mp->calcer() ) ); + ObjectTypeCalcer* mpcalc = static_cast( mp->calcer() ); + + std::vector newparents = mpcalc->parents(); + std::vector newparentsref( + newparents.begin(), newparents.end() ); + const ObjectType* newtype = mpcalc->type(); + + std::vector oldparents; + for( std::vector::iterator i = moldparents.begin(); + i != moldparents.end(); ++i ) + oldparents.push_back( i->get() ); + mpcalc->setType( moldtype ); + mpcalc->setParents( oldparents ); + mp->calc( mdoc.document() ); + + KigCommand* command = new KigCommand( mdoc, i18n( "Redefine Point" ) ); + command->addTask( + new ChangeParentsAndTypeTask( mpcalc, newparents, newtype ) ); + mmon->finish( command ); + mdoc.history()->addCommand( command ); +} diff --git a/kig/modes/normal.cc b/kig/modes/normal.cc deleted file mode 100644 index 9a30c213..00000000 --- a/kig/modes/normal.cc +++ /dev/null @@ -1,306 +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 "normal.h" - -#include "../kig/kig_view.h" -#include "../kig/kig_part.h" -#include "../kig/kig_document.h" -#include "../kig/kig_commands.h" -#include "../objects/object_factory.h" -#include "../objects/object_imp.h" -#include "../objects/object_drawer.h" -#include "../misc/kigpainter.h" -#include "popup.h" -#include "moving.h" -#include "macro.h" -#include "dragrectmode.h" -#include "typesdialog.h" - -#include -#include -#include -#include - -#include -#include - -using namespace std; - -void NormalMode::enableActions() -{ - KigMode::enableActions(); - mdoc.enableConstructActions( true ); - mdoc.aSelectAll->setEnabled( true ); - mdoc.aDeselectAll->setEnabled( true ); - mdoc.aInvertSelection->setEnabled( true ); - mdoc.aDeleteObjects->setEnabled( true ); - mdoc.aShowHidden->setEnabled( true ); - mdoc.aNewMacro->setEnabled( true ); - mdoc.aConfigureTypes->setEnabled( true ); - mdoc.history()->updateActions(); -} - -void NormalMode::deleteObjects() -{ - std::vector sel( sos.begin(), sos.end() ); - mdoc.delObjects( sel ); - sos.clear(); -} - -void NormalMode::selectObject( ObjectHolder* o ) -{ - sos.insert( o ); -} - -void NormalMode::selectObjects( const std::vector& os ) -{ - // hehe, don't you love this c++ stuff ;) - std::for_each( os.begin(), os.end(), - std::bind1st( - std::mem_fun( &NormalMode::selectObject ), this ) ); -} - -void NormalMode::unselectObject( ObjectHolder* o ) -{ - sos.erase( o ); -} - -void NormalMode::clearSelection() -{ - sos.clear(); -} - -// KigDocumentPopup* NormalMode::popup( KigDocument* ) -// { -// return 0; -// } - -void NormalMode::showHidden() -{ - mdoc.showObjects( mdoc.document().objects() ); -} - -void NormalMode::newMacro() -{ - DefineMacroMode m( mdoc ); - mdoc.runMode( &m ); -} - -void NormalMode::redrawScreen( KigWidget* w ) -{ - // unselect removed objects.. - std::vector nsos; - const std::set docobjs = mdoc.document().objectsSet(); - std::set_intersection( docobjs.begin(), docobjs.end(), sos.begin(), sos.end(), - std::back_inserter( nsos ) ); - sos = std::set( nsos.begin(), nsos.end() ); - w->redrawScreen( nsos, true ); - w->updateScrollBars(); -} - -void NormalMode::editTypes() -{ - TypesDialog d( mdoc.widget(), mdoc ); - d.exec(); -} - -NormalMode::NormalMode( KigPart& d ) - : BaseMode( d ) -{ -} - -NormalMode::~NormalMode() -{ -} - -void NormalMode::dragRect( const TQPoint& p, KigWidget& w ) -{ - DragRectMode d( p, mdoc, w ); - mdoc.runMode( &d ); - - KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.stillPix), mdoc.document() ); - - if ( ! d.cancelled() ) - { - std::vector sel = d.ret(); - - if ( d.needClear() ) - { - pter.drawObjects( sos.begin(), sos.end(), false ); - clearSelection(); - }; - - selectObjects( sel ); - pter.drawObjects( sel, true ); - }; - - w.updateCurPix( pter.overlay() ); - w.updateWidget(); -} - -void NormalMode::dragObject( const std::vector& oco, const TQPoint& pco, - KigWidget& w, bool ctrlOrShiftDown ) -{ - // first determine what to move... - if( sos.find( oco.front() ) == sos.end() ) - { - // the user clicked on something that is currently not - // selected... --> we select it, taking the Ctrl- and - // Shift-buttons into account... - if ( !ctrlOrShiftDown ) clearSelection(); - selectObject(oco.front()); - } - - std::vector sosv( sos.begin(), sos.end() ); - MovingMode m( sosv, w.fromScreen( pco ), w, mdoc ); - mdoc.runMode( &m ); -} - -void NormalMode::leftClickedObject( ObjectHolder* o, const TQPoint&, - KigWidget& w, bool ctrlOrShiftDown ) -{ - KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.stillPix), mdoc.document() ); - - if ( ! o ) - { - pter.drawObjects( sos.begin(), sos.end(), false ); - clearSelection(); - } - else if( sos.find( o ) == sos.end() ) - { - // clicked on an object that wasn't selected.... - if (!ctrlOrShiftDown) - { - pter.drawObjects( sos.begin(), sos.end(), false ); - clearSelection(); - }; - pter.drawObject( o, true ); - selectObject( o ); - } - else - { - // clicked on an object that was selected.... - pter.drawObject( o, false ); - unselectObject( o ); - }; - w.updateCurPix( pter.overlay() ); - w.updateWidget(); -} - -void NormalMode::midClicked( const TQPoint& p, KigWidget& w ) -{ - ObjectHolder* pto = ObjectFactory::instance()->sensiblePoint( w.fromScreen( p ), mdoc.document(), w ); - pto->calc( mdoc.document() ); - mdoc.addObject( pto ); - - // refresh the screen... - // not necessary, done by addObjects, which calls NormalMode::redrawScreen.. -// w.redrawScreen(); -// w.updateScrollBars(); -} - -void NormalMode::rightClicked( const std::vector& os, - const TQPoint& plc, - KigWidget& w ) -{ - // saving the current cursor position - TQPoint pt = TQCursor::pos(); - if( !os.empty() ) - { - ObjectHolder* o = 0; - int id = ObjectChooserPopup::getObjectFromList( pt, &w, os ); - if ( id >= 0 ) - o = os[id]; - else - return; - if( sos.find( o ) == sos.end() ) - { - clearSelection(); - selectObject( o ); - }; - // show a popup menu... - std::vector sosv( sos.begin(), sos.end() ); - NormalModePopupObjects p( mdoc, w, *this, sosv, plc ); - p.exec( pt ); - } - else - { - NormalModePopupObjects p( mdoc, w, *this, std::vector(), plc ); - p.exec( pt ); - }; -} - -void NormalMode::mouseMoved( const std::vector& os, - const TQPoint& plc, - KigWidget& w, - bool ) -{ - w.updateCurPix(); - if( os.empty() ) - { - w.setCursor( KCursor::arrowCursor() ); - mdoc.emitStatusBarText( 0 ); - w.updateWidget(); - } - else - { - // the cursor is over an object, show object type next to cursor - // and set statusbar text - - w.setCursor( KCursor::handCursor() ); - - int id = ObjectChooserPopup::getObjectFromList( plc, &w, os, false ); - TQString stat = id == 0 ? os.front()->selectStatement() : i18n( "Which object?" ); - - // statusbar text - mdoc.emitStatusBarText( stat ); - KigPainter p( w.screenInfo(), TQT_TQPAINTDEVICE(&w.curPix), mdoc.document() ); - - // set the text next to the arrow cursor - TQPoint point = plc; - point.setX(point.x()+15); - - p.drawTextStd( point, stat ); - w.updateWidget( p.overlay() ); - }; -} - -void NormalMode::selectAll() -{ - const std::vector os = mdoc.document().objects(); - selectObjects( os ); - mdoc.redrawScreen(); -} - -void NormalMode::deselectAll() -{ - clearSelection(); - mdoc.redrawScreen(); -} - -void NormalMode::invertSelection() -{ - std::vector os = mdoc.document().objects(); - std::set oldsel = sos; - clearSelection(); - for ( std::vector::const_iterator i = os.begin(); - i != os.end(); ++i ) - if ( oldsel.find( *i ) == oldsel.end() ) - sos.insert( *i ); - mdoc.redrawScreen(); -} diff --git a/kig/modes/normal.cpp b/kig/modes/normal.cpp new file mode 100644 index 00000000..9a30c213 --- /dev/null +++ b/kig/modes/normal.cpp @@ -0,0 +1,306 @@ +// 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 "normal.h" + +#include "../kig/kig_view.h" +#include "../kig/kig_part.h" +#include "../kig/kig_document.h" +#include "../kig/kig_commands.h" +#include "../objects/object_factory.h" +#include "../objects/object_imp.h" +#include "../objects/object_drawer.h" +#include "../misc/kigpainter.h" +#include "popup.h" +#include "moving.h" +#include "macro.h" +#include "dragrectmode.h" +#include "typesdialog.h" + +#include +#include +#include +#include + +#include +#include + +using namespace std; + +void NormalMode::enableActions() +{ + KigMode::enableActions(); + mdoc.enableConstructActions( true ); + mdoc.aSelectAll->setEnabled( true ); + mdoc.aDeselectAll->setEnabled( true ); + mdoc.aInvertSelection->setEnabled( true ); + mdoc.aDeleteObjects->setEnabled( true ); + mdoc.aShowHidden->setEnabled( true ); + mdoc.aNewMacro->setEnabled( true ); + mdoc.aConfigureTypes->setEnabled( true ); + mdoc.history()->updateActions(); +} + +void NormalMode::deleteObjects() +{ + std::vector sel( sos.begin(), sos.end() ); + mdoc.delObjects( sel ); + sos.clear(); +} + +void NormalMode::selectObject( ObjectHolder* o ) +{ + sos.insert( o ); +} + +void NormalMode::selectObjects( const std::vector& os ) +{ + // hehe, don't you love this c++ stuff ;) + std::for_each( os.begin(), os.end(), + std::bind1st( + std::mem_fun( &NormalMode::selectObject ), this ) ); +} + +void NormalMode::unselectObject( ObjectHolder* o ) +{ + sos.erase( o ); +} + +void NormalMode::clearSelection() +{ + sos.clear(); +} + +// KigDocumentPopup* NormalMode::popup( KigDocument* ) +// { +// return 0; +// } + +void NormalMode::showHidden() +{ + mdoc.showObjects( mdoc.document().objects() ); +} + +void NormalMode::newMacro() +{ + DefineMacroMode m( mdoc ); + mdoc.runMode( &m ); +} + +void NormalMode::redrawScreen( KigWidget* w ) +{ + // unselect removed objects.. + std::vector nsos; + const std::set docobjs = mdoc.document().objectsSet(); + std::set_intersection( docobjs.begin(), docobjs.end(), sos.begin(), sos.end(), + std::back_inserter( nsos ) ); + sos = std::set( nsos.begin(), nsos.end() ); + w->redrawScreen( nsos, true ); + w->updateScrollBars(); +} + +void NormalMode::editTypes() +{ + TypesDialog d( mdoc.widget(), mdoc ); + d.exec(); +} + +NormalMode::NormalMode( KigPart& d ) + : BaseMode( d ) +{ +} + +NormalMode::~NormalMode() +{ +} + +void NormalMode::dragRect( const TQPoint& p, KigWidget& w ) +{ + DragRectMode d( p, mdoc, w ); + mdoc.runMode( &d ); + + KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.stillPix), mdoc.document() ); + + if ( ! d.cancelled() ) + { + std::vector sel = d.ret(); + + if ( d.needClear() ) + { + pter.drawObjects( sos.begin(), sos.end(), false ); + clearSelection(); + }; + + selectObjects( sel ); + pter.drawObjects( sel, true ); + }; + + w.updateCurPix( pter.overlay() ); + w.updateWidget(); +} + +void NormalMode::dragObject( const std::vector& oco, const TQPoint& pco, + KigWidget& w, bool ctrlOrShiftDown ) +{ + // first determine what to move... + if( sos.find( oco.front() ) == sos.end() ) + { + // the user clicked on something that is currently not + // selected... --> we select it, taking the Ctrl- and + // Shift-buttons into account... + if ( !ctrlOrShiftDown ) clearSelection(); + selectObject(oco.front()); + } + + std::vector sosv( sos.begin(), sos.end() ); + MovingMode m( sosv, w.fromScreen( pco ), w, mdoc ); + mdoc.runMode( &m ); +} + +void NormalMode::leftClickedObject( ObjectHolder* o, const TQPoint&, + KigWidget& w, bool ctrlOrShiftDown ) +{ + KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.stillPix), mdoc.document() ); + + if ( ! o ) + { + pter.drawObjects( sos.begin(), sos.end(), false ); + clearSelection(); + } + else if( sos.find( o ) == sos.end() ) + { + // clicked on an object that wasn't selected.... + if (!ctrlOrShiftDown) + { + pter.drawObjects( sos.begin(), sos.end(), false ); + clearSelection(); + }; + pter.drawObject( o, true ); + selectObject( o ); + } + else + { + // clicked on an object that was selected.... + pter.drawObject( o, false ); + unselectObject( o ); + }; + w.updateCurPix( pter.overlay() ); + w.updateWidget(); +} + +void NormalMode::midClicked( const TQPoint& p, KigWidget& w ) +{ + ObjectHolder* pto = ObjectFactory::instance()->sensiblePoint( w.fromScreen( p ), mdoc.document(), w ); + pto->calc( mdoc.document() ); + mdoc.addObject( pto ); + + // refresh the screen... + // not necessary, done by addObjects, which calls NormalMode::redrawScreen.. +// w.redrawScreen(); +// w.updateScrollBars(); +} + +void NormalMode::rightClicked( const std::vector& os, + const TQPoint& plc, + KigWidget& w ) +{ + // saving the current cursor position + TQPoint pt = TQCursor::pos(); + if( !os.empty() ) + { + ObjectHolder* o = 0; + int id = ObjectChooserPopup::getObjectFromList( pt, &w, os ); + if ( id >= 0 ) + o = os[id]; + else + return; + if( sos.find( o ) == sos.end() ) + { + clearSelection(); + selectObject( o ); + }; + // show a popup menu... + std::vector sosv( sos.begin(), sos.end() ); + NormalModePopupObjects p( mdoc, w, *this, sosv, plc ); + p.exec( pt ); + } + else + { + NormalModePopupObjects p( mdoc, w, *this, std::vector(), plc ); + p.exec( pt ); + }; +} + +void NormalMode::mouseMoved( const std::vector& os, + const TQPoint& plc, + KigWidget& w, + bool ) +{ + w.updateCurPix(); + if( os.empty() ) + { + w.setCursor( KCursor::arrowCursor() ); + mdoc.emitStatusBarText( 0 ); + w.updateWidget(); + } + else + { + // the cursor is over an object, show object type next to cursor + // and set statusbar text + + w.setCursor( KCursor::handCursor() ); + + int id = ObjectChooserPopup::getObjectFromList( plc, &w, os, false ); + TQString stat = id == 0 ? os.front()->selectStatement() : i18n( "Which object?" ); + + // statusbar text + mdoc.emitStatusBarText( stat ); + KigPainter p( w.screenInfo(), TQT_TQPAINTDEVICE(&w.curPix), mdoc.document() ); + + // set the text next to the arrow cursor + TQPoint point = plc; + point.setX(point.x()+15); + + p.drawTextStd( point, stat ); + w.updateWidget( p.overlay() ); + }; +} + +void NormalMode::selectAll() +{ + const std::vector os = mdoc.document().objects(); + selectObjects( os ); + mdoc.redrawScreen(); +} + +void NormalMode::deselectAll() +{ + clearSelection(); + mdoc.redrawScreen(); +} + +void NormalMode::invertSelection() +{ + std::vector os = mdoc.document().objects(); + std::set oldsel = sos; + clearSelection(); + for ( std::vector::const_iterator i = os.begin(); + i != os.end(); ++i ) + if ( oldsel.find( *i ) == oldsel.end() ) + sos.insert( *i ); + mdoc.redrawScreen(); +} diff --git a/kig/modes/popup.cc b/kig/modes/popup.cc deleted file mode 100644 index 05dc5d24..00000000 --- a/kig/modes/popup.cc +++ /dev/null @@ -1,1200 +0,0 @@ -/** - This file is part of Kig, a KDE program for Interactive Geometry... - 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 "popup.h" -#include "popup.moc" - -#include "../kig/kig_part.h" -#include "../kig/kig_document.h" -#include "../kig/kig_view.h" -#include "../kig/kig_commands.h" -#include "../objects/object_imp.h" -#include "../objects/object_drawer.h" -#include "../objects/bogus_imp.h" -#include "../objects/point_imp.h" -#include "../objects/line_imp.h" -#include "../objects/other_type.h" -#include "../objects/object_factory.h" -#include "../objects/polygon_imp.h" -#include "../objects/text_imp.h" -#include "../misc/lists.h" -#include "../misc/argsparser.h" -#include "../misc/kigpainter.h" -#include "../misc/coordinate_system.h" -#include "../misc/object_constructor.h" -#include "construct_mode.h" -#include "normal.h" -#include "moving.h" - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#if KDE_IS_VERSION( 3, 1, 90 ) -#include -#else -#include -#endif - -#include - -using namespace std; - -class NormalModePopupObjects; - -/** - * This class is an abstract class. Its role is to fill up the - * NormalModePopupObjects with useful actions.. - */ -class PopupActionProvider -{ -public: - virtual ~PopupActionProvider(); - /** - * add all your entries to menu menu in popup popup. Set nextfree - * to the next free index.. - */ - virtual void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ) = 0; - /** - * try to execute the id'th action you added to menu menu in popup - * popup ( first is 0 ). Return true if this action does indeed - * belong to you ( is not greater than the number of actions you - * added ). Else return false, and subtract the number of actions - * you added from id. This requires you to keep a record of how - * much actions you added ( unless it's a fixed number, of course - * ). - */ - virtual bool executeAction( int menu, int& id, const std::vector& os, - NormalModePopupObjects& popup, - KigPart& doc, KigWidget& w, NormalMode& m ) = 0; -}; - -class BuiltinObjectActionsProvider - : public PopupActionProvider -{ -public: - void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ); - bool executeAction( int menu, int& id, const std::vector& os, - NormalModePopupObjects& popup, - KigPart& doc, KigWidget& w, NormalMode& m ); -}; - -class NameObjectActionsProvider - : public PopupActionProvider -{ -public: - void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ); - bool executeAction( int menu, int& id, const std::vector& os, - NormalModePopupObjects& popup, - KigPart& doc, KigWidget& w, NormalMode& m ); -}; - -class BuiltinDocumentActionsProvider - : public PopupActionProvider -{ - int mnumberofcoordsystems; - bool misfullscreen; -public: - void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ); - bool executeAction( int menu, int& id, const std::vector& os, - NormalModePopupObjects& popup, - KigPart& doc, KigWidget& w, NormalMode& m ); -}; - -class ObjectConstructorActionsProvider - : public PopupActionProvider -{ - std::vector mctors[NormalModePopupObjects::NumberOfMenus]; -public: - void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ); - bool executeAction( int menu, int& id, const std::vector& os, - NormalModePopupObjects& popup, - KigPart& doc, KigWidget& w, NormalMode& m ); -}; - -class PropertiesActionsProvider - : public PopupActionProvider -{ - // we don't really need NumberOfMenus vectors, but this is the - // easiest way to do it, and I'm too lazy to do it properly ;) - std::vector mprops[NormalModePopupObjects::NumberOfMenus]; -public: - void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ); - bool executeAction( int menu, int& id, const std::vector& os, - NormalModePopupObjects& popup, - KigPart& doc, KigWidget& w, NormalMode& m ); -}; - -class ObjectTypeActionsProvider - : public PopupActionProvider -{ - int mnoa; -public: - void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ); - bool executeAction( int menu, int& id, const std::vector& os, - NormalModePopupObjects& popup, - KigPart& doc, KigWidget& w, NormalMode& m ); -}; - -#ifdef KIG_ENABLE_PYTHON_SCRIPTING -#include "../scripting/script-common.h" -#include "../scripting/script_mode.h" -#include "../scripting/python_type.h" - -class ScriptActionsProvider - : public PopupActionProvider -{ - int mns; -public: - void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ); - bool executeAction( int menu, int& id, const std::vector& os, - NormalModePopupObjects& popup, - KigPart& doc, KigWidget& w, NormalMode& m ); -}; -#endif - -NormalModePopupObjects::NormalModePopupObjects( KigPart& part, - KigWidget& view, - NormalMode& mode, - const std::vector& objs, - const TQPoint& plc ) - : TDEPopupMenu( &view ), mplc( plc ), mpart( part ), mview( view ), mobjs( objs ), - mmode( mode ), monlylabels( false ) -{ - bool empty = objs.empty(); - bool single = objs.size() == 1; - connect( this, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( toplevelMenuSlot( int ) ) ); - - TQString title; - if ( empty ) - title = i18n( "Kig Document" ); - else if ( single ) - { - if ( !objs[0]->name().isNull() ) - title = TQString::fromLatin1( "%1 %2" ).arg( objs[0]->imp()->type()->translatedName() ).arg( objs[0]->name() ); - else - title = objs[0]->imp()->type()->translatedName(); - } - else - title = i18n( "%1 Objects" ).arg( objs.size() ); - insertTitle( title, 1 ); - - if ( !empty ) - { - monlylabels = true; - uint i = 0; - while ( i < objs.size() && monlylabels ) - { - monlylabels &= objs[i]->imp()->inherits( TextImp::stype() ); - ++i; - } - } - - if ( empty ) - { - // provides some diverse stuff like "unhide all", set coordinate - // system etc. - mproviders.push_back( new BuiltinDocumentActionsProvider() ); - }; - // construct an object using these objects and start constructing an - // object using these objects - mproviders.push_back( new ObjectConstructorActionsProvider() ); - if ( single ) - mproviders.push_back( new NameObjectActionsProvider() ); - if ( ! empty ) - { - // stuff like hide, show, delete, set size, set color.. - mproviders.push_back( new BuiltinObjectActionsProvider() ); - // show property as text label -> show menu - // and construct property's as objects -> construct menu - mproviders.push_back( new PropertiesActionsProvider() ); - // stuff like "redefine point" for a fixed or constrained point.. - mproviders.push_back( new ObjectTypeActionsProvider() ); - } -#ifdef KIG_ENABLE_PYTHON_SCRIPTING - // script action.. - mproviders.push_back( new ScriptActionsProvider() ); -#endif - - for ( uint i = 0; i < NumberOfMenus; ++i ) - mmenus[i] = new TQPopupMenu( this ); - - connect( mmenus[TransformMenu], TQT_SIGNAL( activated( int ) ), - this, TQT_SLOT( transformMenuSlot( int ) ) ); - connect( mmenus[TestMenu], TQT_SIGNAL( activated( int ) ), - this, TQT_SLOT( testMenuSlot( int ) ) ); - connect( mmenus[ConstructMenu], TQT_SIGNAL( activated( int ) ), - this, TQT_SLOT( constructMenuSlot( int ) ) ); - connect( mmenus[StartMenu], TQT_SIGNAL( activated( int ) ), - this, TQT_SLOT( startMenuSlot( int ) ) ); - connect( mmenus[ShowMenu], TQT_SIGNAL( activated( int ) ), - this, TQT_SLOT( showMenuSlot( int ) ) ); - connect( mmenus[SetColorMenu], TQT_SIGNAL( activated( int ) ), - this, TQT_SLOT( setColorMenuSlot( int ) ) ); - connect( mmenus[SetSizeMenu], TQT_SIGNAL( activated( int ) ), - this, TQT_SLOT( setSizeMenuSlot( int ) ) ); - connect( mmenus[SetStyleMenu], TQT_SIGNAL( activated( int ) ), - this, TQT_SLOT( setStyleMenuSlot( int ) ) ); - connect( mmenus[SetCoordinateSystemMenu], TQT_SIGNAL( activated( int ) ), - this, TQT_SLOT( setCoordinateSystemMenuSlot( int ) ) ); - - for ( int i = 0; i <= NumberOfMenus; ++i ) - { - int nextfree = 10; - for ( uint j = 0; j < mproviders.size(); ++j ) - mproviders[j]->fillUpMenu( *this, i, nextfree ); - }; - static const TQString menunames[NumberOfMenus] = - { - i18n( "&Transform" ), - i18n( "T&est" ), - i18n( "Const&ruct" ), - i18n( "&Start" ), - i18n( "Add Te&xt Label" ), - i18n( "Set Co&lor" ), - i18n( "Set &Pen Width" ), - i18n( "Set St&yle" ), - TQString(), - i18n( "Set Coordinate S&ystem" ) - }; - static const TQString menuicons[NumberOfMenus] = - { - "centralsymmetry", - "test", - TQString(), - "launch", - "kig_text", - "color_fill", -// "colorize", - "sizer", - "paintbrush", - TQString(), - TQString() - }; - int index = 1; - for ( int i = 0; i < NumberOfMenus; ++i ) - { - if ( mmenus[i]->count() == 0 ) continue; - if ( menuicons[i].isNull() ) - insertItem( menunames[i], mmenus[i], i, index++ ); - else - { - TDEIconLoader* l = part.instance()->iconLoader(); - TQPixmap icon = l->loadIcon( menuicons[i], TDEIcon::Small, 22, TDEIcon::DefaultState, 0L, true ); - insertItem( TQIconSet( icon ), menunames[i], mmenus[i], i, index++ ); - } - }; -} - -void NormalModePopupObjects::testMenuSlot( int i ) -{ - activateAction( TestMenu, i ); -} - -void NormalModePopupObjects::transformMenuSlot( int i ) -{ - activateAction( TransformMenu, i ); -} - -void NormalModePopupObjects::constructMenuSlot( int i ) -{ - activateAction( ConstructMenu, i ); -} - -void NormalModePopupObjects::startMenuSlot( int i ) -{ - activateAction( StartMenu, i ); -} - -void NormalModePopupObjects::showMenuSlot( int i ) -{ - activateAction( ShowMenu, i ); -} - -void NormalModePopupObjects::toplevelMenuSlot( int i ) -{ - activateAction( ToplevelMenu, i ); -} - -void NormalModePopupObjects::activateAction( int menu, int action ) -{ - bool done = false; - // we need action - 10 cause we called fillUpMenu with nextfree set - // to 10 initially.. - action -= 10; - for ( uint i = 0; ! done && i < mproviders.size(); ++i ) - done = mproviders[i]->executeAction( menu, action, mobjs, *this, mpart, mview, mmode ); -} - -NormalModePopupObjects::~NormalModePopupObjects() -{ - delete_all ( mproviders.begin(), mproviders.end() ); -} - -static const TQColor* colors[] = -{ - &TQt::blue, - &TQt::black, - &TQt::gray, - &TQt::red, - &TQt::green, - &TQt::cyan, - &TQt::yellow, - &TQt::darkRed -}; -static const int numberofcolors = sizeof( colors ) / sizeof( TQColor* ); - -void BuiltinObjectActionsProvider::fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ) -{ - if ( menu == NormalModePopupObjects::ToplevelMenu ) - { - TDEIconLoader* l = popup.part().instance()->iconLoader(); - std::vector os = popup.objects(); - - /* - * mp: we want the "show" action to be visible only - * if we selected only one object (to be conservative) - * and if that object is currently hidden. - * conversely for one hidden object we don't want - * the "hide" action to be inserted. - * in any case we have a fixed 'id' associated - * with the two actions. - */ - - if ( os.size() > 1 || os.front()->shown() ) - { - popup.addAction( menu, i18n( "&Hide" ), nextfree ); - } - if ( os.size() == 1 && !os.front()->shown() ) - { - popup.addAction( menu, i18n( "&Show" ), nextfree+1 ); - } - nextfree += 2; - TQPixmap p = l->loadIcon( "move", TDEIcon::Toolbar ); - popup.addAction( menu, p, i18n( "&Move" ), nextfree++ ); - p = l->loadIcon( "edit-delete", TDEIcon::Toolbar ); - popup.addAction( menu, p, i18n( "&Delete" ), nextfree++ ); - } - else if ( menu == NormalModePopupObjects::SetColorMenu ) - { - TQPixmap p( 50, 20 ); - for( const TQColor** c = colors; c < colors + numberofcolors; ++c ) - { - p.fill( **c ); - popup.addAction( menu, p, nextfree++ ); - } - popup.addAction( menu, i18n( "&Custom Color" ), nextfree++ ); - } - else if ( menu == NormalModePopupObjects::SetSizeMenu && !popup.onlyLabels() ) - { - bool point = true; - bool samecolor = true; - std::vector os = popup.objects(); - TQColor color = os.front()->drawer()->color(); - for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) - { - if ( ! (*i)->imp()->inherits( PointImp::stype() ) ) - point = false; - if ( (*i)->drawer()->color() != color ) samecolor = false; - }; - if ( ! samecolor ) color = TQt::blue; - TQPixmap p( point ? 20 : 50, 20 ); - for ( int i = 1; i < 8; ++i ) - { - p.fill( popup.eraseColor() ); - TQPainter ptr( &p ); - ptr.setPen( TQPen( color, 1 ) ); - ptr.setBrush( TQBrush( color, TQt::SolidPattern ) ); - if ( point ) - { - int size = 2*i; - TQRect r( ( 20 - size ) / 2, ( 20 - size ) / 2, size, size ); - ptr.drawEllipse( r ); - } - else - { - ptr.setPen( TQPen( color, -1 + 2*i ) ); - ptr.drawLine( TQPoint( 0, 10 ), TQPoint( 50, 10 ) ); - }; - ptr.end(); - popup.addAction( menu, p, nextfree++ ); - }; - } - else if ( menu == NormalModePopupObjects::SetStyleMenu && !popup.onlyLabels() ) - { - bool samecolor = true; - int npoints = 0; - int nothers = 0; - std::vector os = popup.objects(); - TQColor color = os.front()->drawer()->color(); - for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) - { - if ( (*i)->imp()->inherits( PointImp::stype() ) ) - npoints++; - else - nothers++; - if ( (*i)->drawer()->color() != color ) samecolor = false; - }; - bool point = ( npoints > nothers ); - if ( ! samecolor ) color = TQt::blue; - if ( point ) - for ( int i = 0; i < 5; ++i ) - { - TQPixmap p( 20, 20 ); - p.fill( popup.eraseColor() ); - ScreenInfo si( Rect( -1, -1, 2, 2 ), p.rect() ); - KigPainter ptr( si, TQT_TQPAINTDEVICE(&p), popup.part().document(), false ); - PointImp pt( Coordinate( 0, 0 ) ); - ObjectDrawer d( color, -1, true, Qt::SolidLine, i ); - d.draw( pt, ptr, false ); - popup.addAction( menu, p, nextfree++ ); - } - else - { - Qt::PenStyle penstyles[] = {Qt::SolidLine, Qt::DashLine, Qt::DashDotLine, Qt::DashDotDotLine, Qt::DotLine}; - for ( int i = 0; i < (int) ( sizeof( penstyles ) / sizeof( Qt::PenStyle ) ); ++i ) - { - TQPixmap p( 50, 20 ); - p.fill( popup.eraseColor() ); - ScreenInfo si( Rect( -2.5, -1, 5, 2 ), p.rect() ); - KigPainter ptr( si, TQT_TQPAINTDEVICE(&p), popup.part().document(), false ); - LineImp line( Coordinate( -1, 0 ), Coordinate( 1, 0 ) ); - Qt::PenStyle ps = penstyles[i]; - ObjectDrawer d( color, -1, true, ps, 1 ); - d.draw( line, ptr, false ); - popup.addAction( menu, p, nextfree++ ); - }; - } - } -} - -void NameObjectActionsProvider::fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ) -{ - if ( menu == NormalModePopupObjects::ToplevelMenu ) - { - popup.addAction( menu, i18n( "Set &Name..." ), nextfree++ ); - } - else if ( menu == NormalModePopupObjects::ShowMenu ) - { - popup.addAction( menu, i18n( "&Name" ), nextfree++ ); - } -} - -static void addNameLabel( ObjectCalcer* object, ObjectCalcer* namecalcer, const Coordinate& loc, KigPart& doc ) -{ - std::vector args; - args.push_back( namecalcer ); - const bool namelabelneedsframe = false; - ObjectCalcer* attachto = 0; - if ( object->imp()->inherits( PointImp::stype() ) || - object->imp()->attachPoint().valid() || - object->imp()->inherits( CurveImp::stype() ) ) - attachto = object; - ObjectHolder* label = ObjectFactory::instance()->attachedLabel( - TQString::fromLatin1( "%1" ), attachto, loc, namelabelneedsframe, args, doc.document() ); - doc.addObject( label ); -} - -bool NameObjectActionsProvider::executeAction( - int menu, int& id, const std::vector& os, NormalModePopupObjects& popup, - KigPart& doc, KigWidget& w, NormalMode& ) -{ - if ( menu == NormalModePopupObjects::ToplevelMenu ) - { - if ( id >= 1 ) - { - id -= 1; - return false; - } - assert( os.size() == 1 ); - TQString name = os[0]->name(); - bool ok; - TQRegExp re( ".*" ); - TQRegExpValidator* rev = new TQRegExpValidator( re, &doc ); - TQString caption = i18n( "Set Object Name" ); - TQString label = i18n( "Set Name of this Object:" ); -#if KDE_IS_VERSION( 3, 1, 90 ) - name = KInputDialog::getText( caption, label, name, &ok, &w, 0, rev ); -#else - name = KLineEditDlg::getText( caption, label, name, &ok, &w, rev ); -#endif - if ( ok ) - { - bool justadded = false; - ObjectCalcer* namecalcer = os[0]->nameCalcer(); - if ( !namecalcer ) - { - justadded = true; - ObjectConstCalcer* c = new ObjectConstCalcer( new StringImp( i18n( "" ) ) ); - os[0]->setNameCalcer( c ); - namecalcer = c; - } - assert( dynamic_cast( namecalcer ) ); - ObjectConstCalcer* cnamecalcer = static_cast( os[0]->nameCalcer() ); - MonitorDataObjects mon( cnamecalcer ); - cnamecalcer->setImp( new StringImp( name ) ); - KigCommand* kc = new KigCommand( doc, i18n( "Set Object Name" ) ); - mon.finish( kc ); - doc.history()->addCommand( kc ); - - // if we just added the name, we add a label to show it to the user. - if ( justadded ) - addNameLabel( os[0]->calcer(), namecalcer, -// w.fromScreen( w.mapFromGlobal( popup.mapToGlobal( TQPoint( 5, 0 ) ) ) ), - w.fromScreen( popup.plc() ), - doc ); - } - return true; - } - else if ( menu == NormalModePopupObjects::ShowMenu ) - { - if ( id >= 1 ) - { - id -= 1; - return false; - } - assert( os.size() == 1 ); - ObjectCalcer* namecalcer = os[0]->nameCalcer(); - if ( !namecalcer ) - { - ObjectConstCalcer* c = new ObjectConstCalcer( new StringImp( i18n( "" ) ) ); - os[0]->setNameCalcer( c ); - namecalcer = c; - } - addNameLabel( os[0]->calcer(), namecalcer, -// w.fromScreen( w.mapFromGlobal( popup.mapToGlobal( TQPoint( 5, 0 ) ) ) ), doc ); - w.fromScreen( popup.plc() ), doc ); - return true; - } - else - { - return false; - } -} - -bool BuiltinObjectActionsProvider::executeAction( - int menu, int& id, const std::vector& os, NormalModePopupObjects& popup, - KigPart& doc, KigWidget& w, NormalMode& mode ) -{ - if ( menu == NormalModePopupObjects::ToplevelMenu ) - { - if ( id > 3 ) - { - id -= 4; - return false; - }; - switch( id ) - { - case 0: - // hide the objects.. - doc.hideObjects( os ); - break; - case 1: - // show the objects.. - doc.showObjects( os ); - break; - case 2: - { - // move - TQCursor::setPos( popup.mapToGlobal( TQPoint( 0, 0 ) ) ); - TQPoint p = w.mapFromGlobal( TQCursor::pos() ); - Coordinate c = w.fromScreen( p ); - MovingMode m( os, c, w, doc ); - doc.runMode( &m ); - // in this case, we return, cause we don't want objects to be - // unselected... ( or maybe we do ? ) - return true; - } - case 3: - // delete - doc.delObjects( os ); - break; - default: assert( false ); - }; - mode.clearSelection(); - return true; - } - else if ( menu == NormalModePopupObjects::SetColorMenu ) - { - if ( id >= numberofcolors + 1 ) - { - id -= numberofcolors + 1; - return false; - }; - TQColor color; - if ( id < numberofcolors ) - color = *colors[id]; - else - { - if ( os.size() == 1 ) - color = os.front()->drawer()->color(); - int result = KColorDialog::getColor( color, &w ); - if ( result != KColorDialog::Accepted ) return true; - } - KigCommand* kc = new KigCommand( doc, i18n( "Change Object Color" ) ); - assert( color.isValid() ); - for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) - kc->addTask( new ChangeObjectDrawerTask( *i, ( *i )->drawer()->getCopyColor( color ) ) ); - doc.history()->addCommand( kc ); - mode.clearSelection(); - return true; - } - else if ( menu == NormalModePopupObjects::SetSizeMenu ) - { - if ( id >= 7 ) - { - id -= 7; - return false; - }; - - KigCommand* kc = new KigCommand( doc, i18n( "Change Object Width" ) ); - for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) - kc->addTask( new ChangeObjectDrawerTask( *i, ( *i )->drawer()->getCopyWidth( 1 + 2 * id ) ) ); - doc.history()->addCommand( kc ); - mode.clearSelection(); - return true; - } - else if ( menu == NormalModePopupObjects::SetStyleMenu ) - { - int npoints = 0; - int nothers = 0; - for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) - { - if ( (*i)->imp()->inherits( PointImp::stype() ) ) - npoints++; - else - nothers++; - }; - bool point = ( npoints > nothers ); - int max = point ? 5 : 5; - if ( id >= max ) - { - id -= max; - return false; - }; - - if ( point ) - { - KigCommand* kc = new KigCommand( doc, i18n( "Change Point Style" ) ); - for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) - if ( (*i)->imp()->inherits( PointImp::stype() ) ) - kc->addTask( new ChangeObjectDrawerTask( *i, ( *i )->drawer()->getCopyPointStyle( id ) ) ); - doc.history()->addCommand( kc ); - mode.clearSelection(); - return true; - } - else - { - Qt::PenStyle penstyles[] = {Qt::SolidLine, Qt::DashLine, Qt::DashDotLine, Qt::DashDotDotLine, Qt::DotLine}; - assert( id < (int)( sizeof( penstyles ) / sizeof( Qt::PenStyle ) ) ); - Qt::PenStyle p = penstyles[id]; - KigCommand* kc = new KigCommand( doc, i18n( "Change Object Style" ) ); - for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) - if ( ! (*i)->imp()->inherits( PointImp::stype() ) ) - kc->addTask( new ChangeObjectDrawerTask( *i, ( *i )->drawer()->getCopyStyle( p ) ) ); - doc.history()->addCommand( kc ); - mode.clearSelection(); - } - return true; - } - else return false; -} - -void ObjectConstructorActionsProvider::fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ) -{ - const KigDocument& d = popup.part().document(); - const KigWidget& v = popup.widget(); - typedef ObjectConstructorList::vectype vectype; - vectype vec = ObjectConstructorList::instance()->constructors(); - - for ( vectype::iterator i = vec.begin(); i != vec.end(); ++i ) - { - bool add = false; - if ( popup.objects().empty() ) - { - add = menu == NormalModePopupObjects::StartMenu && ! (*i)->isTransform() && ! (*i)->isTest(); - } - else - { - int ret = (*i)->wantArgs( getCalcers( popup.objects() ), d, v ); - if ( ret == ArgsParser::Invalid ) continue; - if ( (*i)->isTransform() && popup.objects().size() == 1 ) add = menu == NormalModePopupObjects::TransformMenu; - else if ( (*i)->isTest() ) add = menu == NormalModePopupObjects::TestMenu; - else if ( ( *i )->isIntersection() ) add = menu == NormalModePopupObjects::ToplevelMenu; - else if ( ret == ArgsParser::Complete ) add = menu == NormalModePopupObjects::ConstructMenu; - else add = menu == NormalModePopupObjects::StartMenu; - }; - if ( add ) - { - TQCString iconfile = (*i)->iconFileName(); - if ( !iconfile.isEmpty() && !iconfile.isNull() ) - { - TQPixmap icon = popup.part().instance()->iconLoader()->loadIcon( iconfile, TDEIcon::Toolbar, 22, TDEIcon::DefaultState, 0L, true ); - popup.addAction( menu, icon, (*i)->descriptiveName(), nextfree++ ); - } - else - popup.addAction( menu, (*i)->descriptiveName(), nextfree++ ); - mctors[menu].push_back( *i ); - } - }; -} - -bool ObjectConstructorActionsProvider::executeAction( - int menu, int& id, const std::vector& os, - NormalModePopupObjects&, - KigPart& doc, KigWidget& w, NormalMode& m ) -{ - if ( (uint) id >= mctors[menu].size() ) - { - id -= mctors[menu].size(); - return false; - } - - ObjectConstructor* ctor = mctors[menu][id]; - std::vector osc = getCalcers( os ); - if ( ! os.empty() && ctor->wantArgs( osc, doc.document(), w ) == ArgsParser::Complete ) - { - ctor->handleArgs( osc, doc, w ); - m.clearSelection(); - } - else - { - BaseConstructMode* mode = ctor->constructMode( doc ); - mode->selectObjects( os, w ); - doc.runMode( mode ); - delete mode; - }; - return true; -} - -void NormalModePopupObjects::addAction( int menu, const TQPixmap& pix, int id ) -{ - TQPopupMenu* m = 0; - if ( menu == ToplevelMenu ) m = this; - else m = mmenus[menu]; - int ret = m->insertItem( pix, id ); - assert( ret == id ); - // pretend to use this var.. - (void) ret; -} - -void NormalModePopupObjects::setColorMenuSlot( int i ) -{ - activateAction( SetColorMenu, i ); -} - -void NormalModePopupObjects::setSizeMenuSlot( int i ) -{ - activateAction( SetSizeMenu, i ); -} - -void NormalModePopupObjects::setStyleMenuSlot( int i ) -{ - activateAction( SetStyleMenu, i ); -} - -void NormalModePopupObjects::setCoordinateSystemMenuSlot( int i ) -{ - activateAction( SetCoordinateSystemMenu, i ); -} - -void NormalModePopupObjects::addAction( int menu, const TQPixmap& icon, const TQString& name, int id ) -{ - TQPopupMenu* m = 0; - if ( menu == ToplevelMenu ) m = this; - else m = mmenus[menu]; - int ret = m->insertItem( TQIconSet( icon ), name, id ); - assert( ret == id ); - // pretend to use this var.. - (void)ret; -} - -void NormalModePopupObjects::addAction( int menu, const TQString& name, int id ) -{ - TQPopupMenu* m = 0; - if ( menu == ToplevelMenu ) m = this; - else m = mmenus[menu]; - int ret = m->insertItem( name, id ); - assert( ret == id ); - // pretend to use this var.. - (void)ret; -} - -PopupActionProvider::~PopupActionProvider() -{ -} - -void PropertiesActionsProvider::fillUpMenu( NormalModePopupObjects& popup, - int menu, int& nextfree ) -{ - if ( popup.objects().size() != 1 ) return; - ObjectHolder* o = popup.objects()[0]; - uint np = o->imp()->numberOfProperties(); - if ( menu != NormalModePopupObjects::ConstructMenu && - menu != NormalModePopupObjects::ShowMenu ) return; - for ( uint i = 0; i < np; ++i ) - { - ObjectImp* prop = o->imp()->property( i, popup.part().document() ); - const char* iconfile = o->imp()->iconForProperty( i ); - bool add = true; - if ( menu == NormalModePopupObjects::ConstructMenu ) - { - // we don't want imp's like DoubleImp, since we can't show them - // anyway.. - add &= ! prop->inherits( BogusImp::stype() ); - // we don't want to construct PointImp's coordinate property, - // since it would construct a point at the same place as its - // parent.. - add &= ! ( o->imp()->inherits( PointImp::stype() ) && - prop->inherits( PointImp::stype() ) ); - } - else if ( menu == NormalModePopupObjects::ShowMenu ) - add &= prop->canFillInNextEscape(); - if ( add ) - { - if ( iconfile && *iconfile ) - { - TQPixmap pix = popup.part().instance()->iconLoader()->loadIcon( iconfile, TDEIcon::Toolbar, 22, TDEIcon::DefaultState, 0L, true ); - popup.addAction( menu, pix, i18n( o->imp()->properties()[i] ), nextfree++ ); - } - else - { - popup.addAction( menu, i18n( o->imp()->properties()[i] ), nextfree++ ); - }; - mprops[menu-1].push_back( i ); - }; - delete prop; - }; -} - -bool PropertiesActionsProvider::executeAction( - int menu, int& id, const std::vector& os, - NormalModePopupObjects& popup, - KigPart& doc, KigWidget& w, NormalMode& ) -{ - if ( menu != NormalModePopupObjects::ConstructMenu && - menu != NormalModePopupObjects::ShowMenu ) - return false; - if ( (uint) id >= mprops[menu - 1].size() ) - { - id -= mprops[menu - 1].size(); - return false; - } - int propid = mprops[menu-1][id]; - assert( os.size() == 1 ); - ObjectHolder* parent = os[0]; - if ( menu == NormalModePopupObjects::ShowMenu ) - { - std::vector args; - args.push_back( new ObjectPropertyCalcer( parent->calcer(), propid ) ); - args.back()->calc( doc.document() ); -// TODO: recover the cursor position somehow... the following does not work -// in general... -// Coordinate c = w.fromScreen( w.mapFromGlobal( popup.mapToGlobal( TQPoint( 5, 0 ) ) ) ); -// mp: it seems that we have no idea where to position the label, -// btw what's the meaning of (5,0)? let the -// attach method decide what to do... (passing an invalidCoord) -// /////// Coordinate c = Coordinate::invalidCoord(); - Coordinate c = w.fromScreen( popup.plc() ); - ObjectHolder* label = ObjectFactory::instance()->attachedLabel( - TQString::fromLatin1( "%1" ), parent->calcer(), c, - false, args, doc.document() ); - doc.addObject( label ); - } - else - { - ObjectHolder* h = new ObjectHolder( - new ObjectPropertyCalcer( parent->calcer(), propid ) ); - h->calc( doc.document() ); - doc.addObject( h ); - }; - return true; -} - -void ObjectTypeActionsProvider::fillUpMenu( - NormalModePopupObjects& popup, int menu, int& nextfree ) -{ - if ( popup.objects().size() != 1 ) return; - if ( menu != NormalModePopupObjects::ToplevelMenu ) return; - ObjectHolder* to = popup.objects()[0]; - ObjectTypeCalcer* c = dynamic_cast( to->calcer() ); - if ( ! c ) return; - const ObjectType* t = c->type(); - - TQStringList l = t->specialActions(); - mnoa = l.count(); - for ( int i = 0; i < mnoa; ++i ) - popup.addAction( menu, l[i], nextfree++ ); -} - -bool ObjectTypeActionsProvider::executeAction( - int menu, int& id, const std::vector& os, - NormalModePopupObjects&, - KigPart& doc, KigWidget& w, NormalMode& m ) -{ - if ( menu != NormalModePopupObjects::ToplevelMenu ) return false; - if ( id >= mnoa ) - { - id -= mnoa; - return false; - } - assert( os.size() == 1 ); - ObjectTypeCalcer* oc = dynamic_cast( os[0]->calcer() ); - assert( oc ); - - oc->type()->executeAction( id, *os[0], *oc, doc, w, m ); - return true; -} - -void BuiltinDocumentActionsProvider::fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ) -{ - if ( menu == NormalModePopupObjects::ToplevelMenu ) - { - popup.addAction( menu, i18n( "U&nhide All" ), nextfree++ ); - popup.part().action( "view_zoom_in" )->plug( &popup ); - popup.part().action( "view_zoom_out" )->plug( &popup ); - popup.part().action( "fullscreen" )->plug( &popup ); - nextfree += 3; - } - else if ( menu == NormalModePopupObjects::SetCoordinateSystemMenu ) - { - int idoffset = nextfree; - TQStringList l = CoordinateSystemFactory::names(); - mnumberofcoordsystems = l.count(); - for ( uint i = 0; i < l.count(); ++i ) - popup.addAction( menu, l[i], nextfree++ ); - int current = popup.part().document().coordinateSystem().id(); - popup.setChecked( menu, idoffset + current, true ); - } -} - -bool BuiltinDocumentActionsProvider::executeAction( - int menu, int& id, const std::vector&, - NormalModePopupObjects&, - KigPart& doc, KigWidget&, NormalMode& m ) -{ - if ( menu == NormalModePopupObjects::ToplevelMenu ) - { - kdDebug() << "id: " << id << endl; - if ( id == 0 ) - { - doc.showHidden(); - m.clearSelection(); - return true; - } - id -= 1; - return false; - } - else if ( menu == NormalModePopupObjects::SetCoordinateSystemMenu ) - { - if ( id >= mnumberofcoordsystems ) - { - id -= mnumberofcoordsystems; - return false; - }; - CoordinateSystem* sys = CoordinateSystemFactory::build( id ); - assert( sys ); - doc.history()->addCommand( KigCommand::changeCoordSystemCommand( doc, sys ) ); - m.clearSelection(); - return true; - } - else return false; -} - -void NormalModePopupObjects::setChecked( int menu, int n, bool checked ) -{ - mmenus[menu]->setItemChecked( n, checked ); -} - -#ifdef KIG_ENABLE_PYTHON_SCRIPTING -/** - * this is a local function that looks for a python script associated - * to a clicked object - */ -static ObjectTypeCalcer* getPythonExecuteTypeFromCalcer( ObjectCalcer* o ) -{ - ObjectTypeCalcer* oc = dynamic_cast( o ); - if ( !oc ) return 0; - const PythonExecuteType* pythonexec = dynamic_cast( oc->type() ); - if ( pythonexec ) return oc; - - return 0; -} - -void ScriptActionsProvider::fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ) -{ - if ( menu == NormalModePopupObjects::StartMenu ) - { - TDEIconLoader* l = popup.part().instance()->iconLoader(); - TQPixmap p = l->loadIcon( ScriptType::icon( ScriptType::Python ), TDEIcon::Toolbar, 22, TDEIcon::DefaultState, 0L, true ); - popup.addAction( menu, p, i18n( "Python Script" ), nextfree++ ); - mns++; - } - else if ( menu == NormalModePopupObjects::ToplevelMenu ) - { - if ( !popup.objects().empty() && - getPythonExecuteTypeFromCalcer( popup.objects().front()->calcer() ) ) - { - popup.addAction( menu, i18n( "Edit Script..." ), nextfree ); - } - nextfree++; - } -} - -bool ScriptActionsProvider::executeAction( - int menu, int& id, const std::vector& os, - NormalModePopupObjects&, KigPart& doc, KigWidget& w, NormalMode& mode ) -{ - if ( menu == NormalModePopupObjects::StartMenu ) - { - if ( id == 0 ) - { - ScriptCreationMode m( doc ); - m.setScriptType( ScriptType::Python ); - if ( os.size() > 0 ) - { - mode.clearSelection(); - m.addArgs( os, w ); - m.goToCodePage(); - } - doc.runMode( &m ); - return true; - } - else - { - id -= mns; - } - } - else if ( menu == NormalModePopupObjects::ToplevelMenu ) - { - if ( id == 0 ) - { - ObjectTypeCalcer* oc = getPythonExecuteTypeFromCalcer( os.front()->calcer() ); - if ( oc ) - { - ScriptEditMode m( oc, doc ); - m.setScriptType( ScriptType::Python ); - doc.runMode( &m ); - } - return true; - } - else - { - id -= 1; - } - } - - return false; -} -#endif - -int ObjectChooserPopup::getObjectFromList( const TQPoint& p, KigWidget* w, - const std::vector& objs, - bool givepopup ) -{ - int size = objs.size(); - - // no objects - if ( size == 0 ) - return -1; - - int id = -1; - - int numpoints = 0; - int numpolygons = 0; - int numothers = 0; - - for ( std::vector::const_iterator i = objs.begin(); - i != objs.end(); ++i ) - { - if ( (*i)->imp()->inherits( PointImp::stype() ) ) numpoints++; - else if ( (*i)->imp()->inherits( PolygonImp::stype() ) ) numpolygons++; - else numothers++; - } - - // simply cases: - // - only 1 point ( and eventually other objects ) - // - no points and an object which is not a polygon - // - only one object - // FIXME: we assume that our objects are sorted ( points, others, polygons )! - if ( ( numpoints == 1 ) || - ( ( numpoints == 0 ) && ( numothers == 1 ) ) || - ( size == 1 ) ) - id = 0; - else - { - if ( givepopup ) - { - ObjectChooserPopup* ppp = new ObjectChooserPopup( p, *w, objs ); - ppp->exec( TQCursor::pos() ); - - id = ppp->mselected; - - delete ppp; - ppp = 0; - } - else - { - // we don't want to show a popup to the user, so let's give a - // value > 0 to indicate that it's not the first - id = 1; - } - } -// kdDebug() << "numpoints: " << numpoints << endl -// << "numothers: " << numothers << endl -// << "numpolygons: " << numpolygons << endl -// << "id: " << id << endl; - - return id; -} - -ObjectChooserPopup::ObjectChooserPopup( const TQPoint& p, KigWidget& view, - const std::vector& objs ) - : TDEPopupMenu(), mplc( p ), mview( view ), mobjs( objs ), mselected( -1 ) -{ - for ( uint i = 0; i < mobjs.size(); i++ ) - { - insertItem( !mobjs[i]->name().isEmpty() - ? TQString::fromLatin1( "%1 %2" ).arg( mobjs[i]->imp()->type()->translatedName() ).arg( mobjs[i]->name() ) - : mobjs[i]->imp()->type()->translatedName(), - i ); - } - - connect( this, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( actionActivatedSlot( int ) ) ); -} - -ObjectChooserPopup::~ObjectChooserPopup() -{ -} - -void ObjectChooserPopup::actionActivatedSlot( int which ) -{ - mselected = which; -} diff --git a/kig/modes/popup.cpp b/kig/modes/popup.cpp new file mode 100644 index 00000000..05dc5d24 --- /dev/null +++ b/kig/modes/popup.cpp @@ -0,0 +1,1200 @@ +/** + This file is part of Kig, a KDE program for Interactive Geometry... + 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 "popup.h" +#include "popup.moc" + +#include "../kig/kig_part.h" +#include "../kig/kig_document.h" +#include "../kig/kig_view.h" +#include "../kig/kig_commands.h" +#include "../objects/object_imp.h" +#include "../objects/object_drawer.h" +#include "../objects/bogus_imp.h" +#include "../objects/point_imp.h" +#include "../objects/line_imp.h" +#include "../objects/other_type.h" +#include "../objects/object_factory.h" +#include "../objects/polygon_imp.h" +#include "../objects/text_imp.h" +#include "../misc/lists.h" +#include "../misc/argsparser.h" +#include "../misc/kigpainter.h" +#include "../misc/coordinate_system.h" +#include "../misc/object_constructor.h" +#include "construct_mode.h" +#include "normal.h" +#include "moving.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#if KDE_IS_VERSION( 3, 1, 90 ) +#include +#else +#include +#endif + +#include + +using namespace std; + +class NormalModePopupObjects; + +/** + * This class is an abstract class. Its role is to fill up the + * NormalModePopupObjects with useful actions.. + */ +class PopupActionProvider +{ +public: + virtual ~PopupActionProvider(); + /** + * add all your entries to menu menu in popup popup. Set nextfree + * to the next free index.. + */ + virtual void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ) = 0; + /** + * try to execute the id'th action you added to menu menu in popup + * popup ( first is 0 ). Return true if this action does indeed + * belong to you ( is not greater than the number of actions you + * added ). Else return false, and subtract the number of actions + * you added from id. This requires you to keep a record of how + * much actions you added ( unless it's a fixed number, of course + * ). + */ + virtual bool executeAction( int menu, int& id, const std::vector& os, + NormalModePopupObjects& popup, + KigPart& doc, KigWidget& w, NormalMode& m ) = 0; +}; + +class BuiltinObjectActionsProvider + : public PopupActionProvider +{ +public: + void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ); + bool executeAction( int menu, int& id, const std::vector& os, + NormalModePopupObjects& popup, + KigPart& doc, KigWidget& w, NormalMode& m ); +}; + +class NameObjectActionsProvider + : public PopupActionProvider +{ +public: + void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ); + bool executeAction( int menu, int& id, const std::vector& os, + NormalModePopupObjects& popup, + KigPart& doc, KigWidget& w, NormalMode& m ); +}; + +class BuiltinDocumentActionsProvider + : public PopupActionProvider +{ + int mnumberofcoordsystems; + bool misfullscreen; +public: + void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ); + bool executeAction( int menu, int& id, const std::vector& os, + NormalModePopupObjects& popup, + KigPart& doc, KigWidget& w, NormalMode& m ); +}; + +class ObjectConstructorActionsProvider + : public PopupActionProvider +{ + std::vector mctors[NormalModePopupObjects::NumberOfMenus]; +public: + void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ); + bool executeAction( int menu, int& id, const std::vector& os, + NormalModePopupObjects& popup, + KigPart& doc, KigWidget& w, NormalMode& m ); +}; + +class PropertiesActionsProvider + : public PopupActionProvider +{ + // we don't really need NumberOfMenus vectors, but this is the + // easiest way to do it, and I'm too lazy to do it properly ;) + std::vector mprops[NormalModePopupObjects::NumberOfMenus]; +public: + void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ); + bool executeAction( int menu, int& id, const std::vector& os, + NormalModePopupObjects& popup, + KigPart& doc, KigWidget& w, NormalMode& m ); +}; + +class ObjectTypeActionsProvider + : public PopupActionProvider +{ + int mnoa; +public: + void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ); + bool executeAction( int menu, int& id, const std::vector& os, + NormalModePopupObjects& popup, + KigPart& doc, KigWidget& w, NormalMode& m ); +}; + +#ifdef KIG_ENABLE_PYTHON_SCRIPTING +#include "../scripting/script-common.h" +#include "../scripting/script_mode.h" +#include "../scripting/python_type.h" + +class ScriptActionsProvider + : public PopupActionProvider +{ + int mns; +public: + void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ); + bool executeAction( int menu, int& id, const std::vector& os, + NormalModePopupObjects& popup, + KigPart& doc, KigWidget& w, NormalMode& m ); +}; +#endif + +NormalModePopupObjects::NormalModePopupObjects( KigPart& part, + KigWidget& view, + NormalMode& mode, + const std::vector& objs, + const TQPoint& plc ) + : TDEPopupMenu( &view ), mplc( plc ), mpart( part ), mview( view ), mobjs( objs ), + mmode( mode ), monlylabels( false ) +{ + bool empty = objs.empty(); + bool single = objs.size() == 1; + connect( this, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( toplevelMenuSlot( int ) ) ); + + TQString title; + if ( empty ) + title = i18n( "Kig Document" ); + else if ( single ) + { + if ( !objs[0]->name().isNull() ) + title = TQString::fromLatin1( "%1 %2" ).arg( objs[0]->imp()->type()->translatedName() ).arg( objs[0]->name() ); + else + title = objs[0]->imp()->type()->translatedName(); + } + else + title = i18n( "%1 Objects" ).arg( objs.size() ); + insertTitle( title, 1 ); + + if ( !empty ) + { + monlylabels = true; + uint i = 0; + while ( i < objs.size() && monlylabels ) + { + monlylabels &= objs[i]->imp()->inherits( TextImp::stype() ); + ++i; + } + } + + if ( empty ) + { + // provides some diverse stuff like "unhide all", set coordinate + // system etc. + mproviders.push_back( new BuiltinDocumentActionsProvider() ); + }; + // construct an object using these objects and start constructing an + // object using these objects + mproviders.push_back( new ObjectConstructorActionsProvider() ); + if ( single ) + mproviders.push_back( new NameObjectActionsProvider() ); + if ( ! empty ) + { + // stuff like hide, show, delete, set size, set color.. + mproviders.push_back( new BuiltinObjectActionsProvider() ); + // show property as text label -> show menu + // and construct property's as objects -> construct menu + mproviders.push_back( new PropertiesActionsProvider() ); + // stuff like "redefine point" for a fixed or constrained point.. + mproviders.push_back( new ObjectTypeActionsProvider() ); + } +#ifdef KIG_ENABLE_PYTHON_SCRIPTING + // script action.. + mproviders.push_back( new ScriptActionsProvider() ); +#endif + + for ( uint i = 0; i < NumberOfMenus; ++i ) + mmenus[i] = new TQPopupMenu( this ); + + connect( mmenus[TransformMenu], TQT_SIGNAL( activated( int ) ), + this, TQT_SLOT( transformMenuSlot( int ) ) ); + connect( mmenus[TestMenu], TQT_SIGNAL( activated( int ) ), + this, TQT_SLOT( testMenuSlot( int ) ) ); + connect( mmenus[ConstructMenu], TQT_SIGNAL( activated( int ) ), + this, TQT_SLOT( constructMenuSlot( int ) ) ); + connect( mmenus[StartMenu], TQT_SIGNAL( activated( int ) ), + this, TQT_SLOT( startMenuSlot( int ) ) ); + connect( mmenus[ShowMenu], TQT_SIGNAL( activated( int ) ), + this, TQT_SLOT( showMenuSlot( int ) ) ); + connect( mmenus[SetColorMenu], TQT_SIGNAL( activated( int ) ), + this, TQT_SLOT( setColorMenuSlot( int ) ) ); + connect( mmenus[SetSizeMenu], TQT_SIGNAL( activated( int ) ), + this, TQT_SLOT( setSizeMenuSlot( int ) ) ); + connect( mmenus[SetStyleMenu], TQT_SIGNAL( activated( int ) ), + this, TQT_SLOT( setStyleMenuSlot( int ) ) ); + connect( mmenus[SetCoordinateSystemMenu], TQT_SIGNAL( activated( int ) ), + this, TQT_SLOT( setCoordinateSystemMenuSlot( int ) ) ); + + for ( int i = 0; i <= NumberOfMenus; ++i ) + { + int nextfree = 10; + for ( uint j = 0; j < mproviders.size(); ++j ) + mproviders[j]->fillUpMenu( *this, i, nextfree ); + }; + static const TQString menunames[NumberOfMenus] = + { + i18n( "&Transform" ), + i18n( "T&est" ), + i18n( "Const&ruct" ), + i18n( "&Start" ), + i18n( "Add Te&xt Label" ), + i18n( "Set Co&lor" ), + i18n( "Set &Pen Width" ), + i18n( "Set St&yle" ), + TQString(), + i18n( "Set Coordinate S&ystem" ) + }; + static const TQString menuicons[NumberOfMenus] = + { + "centralsymmetry", + "test", + TQString(), + "launch", + "kig_text", + "color_fill", +// "colorize", + "sizer", + "paintbrush", + TQString(), + TQString() + }; + int index = 1; + for ( int i = 0; i < NumberOfMenus; ++i ) + { + if ( mmenus[i]->count() == 0 ) continue; + if ( menuicons[i].isNull() ) + insertItem( menunames[i], mmenus[i], i, index++ ); + else + { + TDEIconLoader* l = part.instance()->iconLoader(); + TQPixmap icon = l->loadIcon( menuicons[i], TDEIcon::Small, 22, TDEIcon::DefaultState, 0L, true ); + insertItem( TQIconSet( icon ), menunames[i], mmenus[i], i, index++ ); + } + }; +} + +void NormalModePopupObjects::testMenuSlot( int i ) +{ + activateAction( TestMenu, i ); +} + +void NormalModePopupObjects::transformMenuSlot( int i ) +{ + activateAction( TransformMenu, i ); +} + +void NormalModePopupObjects::constructMenuSlot( int i ) +{ + activateAction( ConstructMenu, i ); +} + +void NormalModePopupObjects::startMenuSlot( int i ) +{ + activateAction( StartMenu, i ); +} + +void NormalModePopupObjects::showMenuSlot( int i ) +{ + activateAction( ShowMenu, i ); +} + +void NormalModePopupObjects::toplevelMenuSlot( int i ) +{ + activateAction( ToplevelMenu, i ); +} + +void NormalModePopupObjects::activateAction( int menu, int action ) +{ + bool done = false; + // we need action - 10 cause we called fillUpMenu with nextfree set + // to 10 initially.. + action -= 10; + for ( uint i = 0; ! done && i < mproviders.size(); ++i ) + done = mproviders[i]->executeAction( menu, action, mobjs, *this, mpart, mview, mmode ); +} + +NormalModePopupObjects::~NormalModePopupObjects() +{ + delete_all ( mproviders.begin(), mproviders.end() ); +} + +static const TQColor* colors[] = +{ + &TQt::blue, + &TQt::black, + &TQt::gray, + &TQt::red, + &TQt::green, + &TQt::cyan, + &TQt::yellow, + &TQt::darkRed +}; +static const int numberofcolors = sizeof( colors ) / sizeof( TQColor* ); + +void BuiltinObjectActionsProvider::fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ) +{ + if ( menu == NormalModePopupObjects::ToplevelMenu ) + { + TDEIconLoader* l = popup.part().instance()->iconLoader(); + std::vector os = popup.objects(); + + /* + * mp: we want the "show" action to be visible only + * if we selected only one object (to be conservative) + * and if that object is currently hidden. + * conversely for one hidden object we don't want + * the "hide" action to be inserted. + * in any case we have a fixed 'id' associated + * with the two actions. + */ + + if ( os.size() > 1 || os.front()->shown() ) + { + popup.addAction( menu, i18n( "&Hide" ), nextfree ); + } + if ( os.size() == 1 && !os.front()->shown() ) + { + popup.addAction( menu, i18n( "&Show" ), nextfree+1 ); + } + nextfree += 2; + TQPixmap p = l->loadIcon( "move", TDEIcon::Toolbar ); + popup.addAction( menu, p, i18n( "&Move" ), nextfree++ ); + p = l->loadIcon( "edit-delete", TDEIcon::Toolbar ); + popup.addAction( menu, p, i18n( "&Delete" ), nextfree++ ); + } + else if ( menu == NormalModePopupObjects::SetColorMenu ) + { + TQPixmap p( 50, 20 ); + for( const TQColor** c = colors; c < colors + numberofcolors; ++c ) + { + p.fill( **c ); + popup.addAction( menu, p, nextfree++ ); + } + popup.addAction( menu, i18n( "&Custom Color" ), nextfree++ ); + } + else if ( menu == NormalModePopupObjects::SetSizeMenu && !popup.onlyLabels() ) + { + bool point = true; + bool samecolor = true; + std::vector os = popup.objects(); + TQColor color = os.front()->drawer()->color(); + for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) + { + if ( ! (*i)->imp()->inherits( PointImp::stype() ) ) + point = false; + if ( (*i)->drawer()->color() != color ) samecolor = false; + }; + if ( ! samecolor ) color = TQt::blue; + TQPixmap p( point ? 20 : 50, 20 ); + for ( int i = 1; i < 8; ++i ) + { + p.fill( popup.eraseColor() ); + TQPainter ptr( &p ); + ptr.setPen( TQPen( color, 1 ) ); + ptr.setBrush( TQBrush( color, TQt::SolidPattern ) ); + if ( point ) + { + int size = 2*i; + TQRect r( ( 20 - size ) / 2, ( 20 - size ) / 2, size, size ); + ptr.drawEllipse( r ); + } + else + { + ptr.setPen( TQPen( color, -1 + 2*i ) ); + ptr.drawLine( TQPoint( 0, 10 ), TQPoint( 50, 10 ) ); + }; + ptr.end(); + popup.addAction( menu, p, nextfree++ ); + }; + } + else if ( menu == NormalModePopupObjects::SetStyleMenu && !popup.onlyLabels() ) + { + bool samecolor = true; + int npoints = 0; + int nothers = 0; + std::vector os = popup.objects(); + TQColor color = os.front()->drawer()->color(); + for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) + { + if ( (*i)->imp()->inherits( PointImp::stype() ) ) + npoints++; + else + nothers++; + if ( (*i)->drawer()->color() != color ) samecolor = false; + }; + bool point = ( npoints > nothers ); + if ( ! samecolor ) color = TQt::blue; + if ( point ) + for ( int i = 0; i < 5; ++i ) + { + TQPixmap p( 20, 20 ); + p.fill( popup.eraseColor() ); + ScreenInfo si( Rect( -1, -1, 2, 2 ), p.rect() ); + KigPainter ptr( si, TQT_TQPAINTDEVICE(&p), popup.part().document(), false ); + PointImp pt( Coordinate( 0, 0 ) ); + ObjectDrawer d( color, -1, true, Qt::SolidLine, i ); + d.draw( pt, ptr, false ); + popup.addAction( menu, p, nextfree++ ); + } + else + { + Qt::PenStyle penstyles[] = {Qt::SolidLine, Qt::DashLine, Qt::DashDotLine, Qt::DashDotDotLine, Qt::DotLine}; + for ( int i = 0; i < (int) ( sizeof( penstyles ) / sizeof( Qt::PenStyle ) ); ++i ) + { + TQPixmap p( 50, 20 ); + p.fill( popup.eraseColor() ); + ScreenInfo si( Rect( -2.5, -1, 5, 2 ), p.rect() ); + KigPainter ptr( si, TQT_TQPAINTDEVICE(&p), popup.part().document(), false ); + LineImp line( Coordinate( -1, 0 ), Coordinate( 1, 0 ) ); + Qt::PenStyle ps = penstyles[i]; + ObjectDrawer d( color, -1, true, ps, 1 ); + d.draw( line, ptr, false ); + popup.addAction( menu, p, nextfree++ ); + }; + } + } +} + +void NameObjectActionsProvider::fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ) +{ + if ( menu == NormalModePopupObjects::ToplevelMenu ) + { + popup.addAction( menu, i18n( "Set &Name..." ), nextfree++ ); + } + else if ( menu == NormalModePopupObjects::ShowMenu ) + { + popup.addAction( menu, i18n( "&Name" ), nextfree++ ); + } +} + +static void addNameLabel( ObjectCalcer* object, ObjectCalcer* namecalcer, const Coordinate& loc, KigPart& doc ) +{ + std::vector args; + args.push_back( namecalcer ); + const bool namelabelneedsframe = false; + ObjectCalcer* attachto = 0; + if ( object->imp()->inherits( PointImp::stype() ) || + object->imp()->attachPoint().valid() || + object->imp()->inherits( CurveImp::stype() ) ) + attachto = object; + ObjectHolder* label = ObjectFactory::instance()->attachedLabel( + TQString::fromLatin1( "%1" ), attachto, loc, namelabelneedsframe, args, doc.document() ); + doc.addObject( label ); +} + +bool NameObjectActionsProvider::executeAction( + int menu, int& id, const std::vector& os, NormalModePopupObjects& popup, + KigPart& doc, KigWidget& w, NormalMode& ) +{ + if ( menu == NormalModePopupObjects::ToplevelMenu ) + { + if ( id >= 1 ) + { + id -= 1; + return false; + } + assert( os.size() == 1 ); + TQString name = os[0]->name(); + bool ok; + TQRegExp re( ".*" ); + TQRegExpValidator* rev = new TQRegExpValidator( re, &doc ); + TQString caption = i18n( "Set Object Name" ); + TQString label = i18n( "Set Name of this Object:" ); +#if KDE_IS_VERSION( 3, 1, 90 ) + name = KInputDialog::getText( caption, label, name, &ok, &w, 0, rev ); +#else + name = KLineEditDlg::getText( caption, label, name, &ok, &w, rev ); +#endif + if ( ok ) + { + bool justadded = false; + ObjectCalcer* namecalcer = os[0]->nameCalcer(); + if ( !namecalcer ) + { + justadded = true; + ObjectConstCalcer* c = new ObjectConstCalcer( new StringImp( i18n( "" ) ) ); + os[0]->setNameCalcer( c ); + namecalcer = c; + } + assert( dynamic_cast( namecalcer ) ); + ObjectConstCalcer* cnamecalcer = static_cast( os[0]->nameCalcer() ); + MonitorDataObjects mon( cnamecalcer ); + cnamecalcer->setImp( new StringImp( name ) ); + KigCommand* kc = new KigCommand( doc, i18n( "Set Object Name" ) ); + mon.finish( kc ); + doc.history()->addCommand( kc ); + + // if we just added the name, we add a label to show it to the user. + if ( justadded ) + addNameLabel( os[0]->calcer(), namecalcer, +// w.fromScreen( w.mapFromGlobal( popup.mapToGlobal( TQPoint( 5, 0 ) ) ) ), + w.fromScreen( popup.plc() ), + doc ); + } + return true; + } + else if ( menu == NormalModePopupObjects::ShowMenu ) + { + if ( id >= 1 ) + { + id -= 1; + return false; + } + assert( os.size() == 1 ); + ObjectCalcer* namecalcer = os[0]->nameCalcer(); + if ( !namecalcer ) + { + ObjectConstCalcer* c = new ObjectConstCalcer( new StringImp( i18n( "" ) ) ); + os[0]->setNameCalcer( c ); + namecalcer = c; + } + addNameLabel( os[0]->calcer(), namecalcer, +// w.fromScreen( w.mapFromGlobal( popup.mapToGlobal( TQPoint( 5, 0 ) ) ) ), doc ); + w.fromScreen( popup.plc() ), doc ); + return true; + } + else + { + return false; + } +} + +bool BuiltinObjectActionsProvider::executeAction( + int menu, int& id, const std::vector& os, NormalModePopupObjects& popup, + KigPart& doc, KigWidget& w, NormalMode& mode ) +{ + if ( menu == NormalModePopupObjects::ToplevelMenu ) + { + if ( id > 3 ) + { + id -= 4; + return false; + }; + switch( id ) + { + case 0: + // hide the objects.. + doc.hideObjects( os ); + break; + case 1: + // show the objects.. + doc.showObjects( os ); + break; + case 2: + { + // move + TQCursor::setPos( popup.mapToGlobal( TQPoint( 0, 0 ) ) ); + TQPoint p = w.mapFromGlobal( TQCursor::pos() ); + Coordinate c = w.fromScreen( p ); + MovingMode m( os, c, w, doc ); + doc.runMode( &m ); + // in this case, we return, cause we don't want objects to be + // unselected... ( or maybe we do ? ) + return true; + } + case 3: + // delete + doc.delObjects( os ); + break; + default: assert( false ); + }; + mode.clearSelection(); + return true; + } + else if ( menu == NormalModePopupObjects::SetColorMenu ) + { + if ( id >= numberofcolors + 1 ) + { + id -= numberofcolors + 1; + return false; + }; + TQColor color; + if ( id < numberofcolors ) + color = *colors[id]; + else + { + if ( os.size() == 1 ) + color = os.front()->drawer()->color(); + int result = KColorDialog::getColor( color, &w ); + if ( result != KColorDialog::Accepted ) return true; + } + KigCommand* kc = new KigCommand( doc, i18n( "Change Object Color" ) ); + assert( color.isValid() ); + for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) + kc->addTask( new ChangeObjectDrawerTask( *i, ( *i )->drawer()->getCopyColor( color ) ) ); + doc.history()->addCommand( kc ); + mode.clearSelection(); + return true; + } + else if ( menu == NormalModePopupObjects::SetSizeMenu ) + { + if ( id >= 7 ) + { + id -= 7; + return false; + }; + + KigCommand* kc = new KigCommand( doc, i18n( "Change Object Width" ) ); + for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) + kc->addTask( new ChangeObjectDrawerTask( *i, ( *i )->drawer()->getCopyWidth( 1 + 2 * id ) ) ); + doc.history()->addCommand( kc ); + mode.clearSelection(); + return true; + } + else if ( menu == NormalModePopupObjects::SetStyleMenu ) + { + int npoints = 0; + int nothers = 0; + for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) + { + if ( (*i)->imp()->inherits( PointImp::stype() ) ) + npoints++; + else + nothers++; + }; + bool point = ( npoints > nothers ); + int max = point ? 5 : 5; + if ( id >= max ) + { + id -= max; + return false; + }; + + if ( point ) + { + KigCommand* kc = new KigCommand( doc, i18n( "Change Point Style" ) ); + for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) + if ( (*i)->imp()->inherits( PointImp::stype() ) ) + kc->addTask( new ChangeObjectDrawerTask( *i, ( *i )->drawer()->getCopyPointStyle( id ) ) ); + doc.history()->addCommand( kc ); + mode.clearSelection(); + return true; + } + else + { + Qt::PenStyle penstyles[] = {Qt::SolidLine, Qt::DashLine, Qt::DashDotLine, Qt::DashDotDotLine, Qt::DotLine}; + assert( id < (int)( sizeof( penstyles ) / sizeof( Qt::PenStyle ) ) ); + Qt::PenStyle p = penstyles[id]; + KigCommand* kc = new KigCommand( doc, i18n( "Change Object Style" ) ); + for ( std::vector::const_iterator i = os.begin(); i != os.end(); ++i ) + if ( ! (*i)->imp()->inherits( PointImp::stype() ) ) + kc->addTask( new ChangeObjectDrawerTask( *i, ( *i )->drawer()->getCopyStyle( p ) ) ); + doc.history()->addCommand( kc ); + mode.clearSelection(); + } + return true; + } + else return false; +} + +void ObjectConstructorActionsProvider::fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ) +{ + const KigDocument& d = popup.part().document(); + const KigWidget& v = popup.widget(); + typedef ObjectConstructorList::vectype vectype; + vectype vec = ObjectConstructorList::instance()->constructors(); + + for ( vectype::iterator i = vec.begin(); i != vec.end(); ++i ) + { + bool add = false; + if ( popup.objects().empty() ) + { + add = menu == NormalModePopupObjects::StartMenu && ! (*i)->isTransform() && ! (*i)->isTest(); + } + else + { + int ret = (*i)->wantArgs( getCalcers( popup.objects() ), d, v ); + if ( ret == ArgsParser::Invalid ) continue; + if ( (*i)->isTransform() && popup.objects().size() == 1 ) add = menu == NormalModePopupObjects::TransformMenu; + else if ( (*i)->isTest() ) add = menu == NormalModePopupObjects::TestMenu; + else if ( ( *i )->isIntersection() ) add = menu == NormalModePopupObjects::ToplevelMenu; + else if ( ret == ArgsParser::Complete ) add = menu == NormalModePopupObjects::ConstructMenu; + else add = menu == NormalModePopupObjects::StartMenu; + }; + if ( add ) + { + TQCString iconfile = (*i)->iconFileName(); + if ( !iconfile.isEmpty() && !iconfile.isNull() ) + { + TQPixmap icon = popup.part().instance()->iconLoader()->loadIcon( iconfile, TDEIcon::Toolbar, 22, TDEIcon::DefaultState, 0L, true ); + popup.addAction( menu, icon, (*i)->descriptiveName(), nextfree++ ); + } + else + popup.addAction( menu, (*i)->descriptiveName(), nextfree++ ); + mctors[menu].push_back( *i ); + } + }; +} + +bool ObjectConstructorActionsProvider::executeAction( + int menu, int& id, const std::vector& os, + NormalModePopupObjects&, + KigPart& doc, KigWidget& w, NormalMode& m ) +{ + if ( (uint) id >= mctors[menu].size() ) + { + id -= mctors[menu].size(); + return false; + } + + ObjectConstructor* ctor = mctors[menu][id]; + std::vector osc = getCalcers( os ); + if ( ! os.empty() && ctor->wantArgs( osc, doc.document(), w ) == ArgsParser::Complete ) + { + ctor->handleArgs( osc, doc, w ); + m.clearSelection(); + } + else + { + BaseConstructMode* mode = ctor->constructMode( doc ); + mode->selectObjects( os, w ); + doc.runMode( mode ); + delete mode; + }; + return true; +} + +void NormalModePopupObjects::addAction( int menu, const TQPixmap& pix, int id ) +{ + TQPopupMenu* m = 0; + if ( menu == ToplevelMenu ) m = this; + else m = mmenus[menu]; + int ret = m->insertItem( pix, id ); + assert( ret == id ); + // pretend to use this var.. + (void) ret; +} + +void NormalModePopupObjects::setColorMenuSlot( int i ) +{ + activateAction( SetColorMenu, i ); +} + +void NormalModePopupObjects::setSizeMenuSlot( int i ) +{ + activateAction( SetSizeMenu, i ); +} + +void NormalModePopupObjects::setStyleMenuSlot( int i ) +{ + activateAction( SetStyleMenu, i ); +} + +void NormalModePopupObjects::setCoordinateSystemMenuSlot( int i ) +{ + activateAction( SetCoordinateSystemMenu, i ); +} + +void NormalModePopupObjects::addAction( int menu, const TQPixmap& icon, const TQString& name, int id ) +{ + TQPopupMenu* m = 0; + if ( menu == ToplevelMenu ) m = this; + else m = mmenus[menu]; + int ret = m->insertItem( TQIconSet( icon ), name, id ); + assert( ret == id ); + // pretend to use this var.. + (void)ret; +} + +void NormalModePopupObjects::addAction( int menu, const TQString& name, int id ) +{ + TQPopupMenu* m = 0; + if ( menu == ToplevelMenu ) m = this; + else m = mmenus[menu]; + int ret = m->insertItem( name, id ); + assert( ret == id ); + // pretend to use this var.. + (void)ret; +} + +PopupActionProvider::~PopupActionProvider() +{ +} + +void PropertiesActionsProvider::fillUpMenu( NormalModePopupObjects& popup, + int menu, int& nextfree ) +{ + if ( popup.objects().size() != 1 ) return; + ObjectHolder* o = popup.objects()[0]; + uint np = o->imp()->numberOfProperties(); + if ( menu != NormalModePopupObjects::ConstructMenu && + menu != NormalModePopupObjects::ShowMenu ) return; + for ( uint i = 0; i < np; ++i ) + { + ObjectImp* prop = o->imp()->property( i, popup.part().document() ); + const char* iconfile = o->imp()->iconForProperty( i ); + bool add = true; + if ( menu == NormalModePopupObjects::ConstructMenu ) + { + // we don't want imp's like DoubleImp, since we can't show them + // anyway.. + add &= ! prop->inherits( BogusImp::stype() ); + // we don't want to construct PointImp's coordinate property, + // since it would construct a point at the same place as its + // parent.. + add &= ! ( o->imp()->inherits( PointImp::stype() ) && + prop->inherits( PointImp::stype() ) ); + } + else if ( menu == NormalModePopupObjects::ShowMenu ) + add &= prop->canFillInNextEscape(); + if ( add ) + { + if ( iconfile && *iconfile ) + { + TQPixmap pix = popup.part().instance()->iconLoader()->loadIcon( iconfile, TDEIcon::Toolbar, 22, TDEIcon::DefaultState, 0L, true ); + popup.addAction( menu, pix, i18n( o->imp()->properties()[i] ), nextfree++ ); + } + else + { + popup.addAction( menu, i18n( o->imp()->properties()[i] ), nextfree++ ); + }; + mprops[menu-1].push_back( i ); + }; + delete prop; + }; +} + +bool PropertiesActionsProvider::executeAction( + int menu, int& id, const std::vector& os, + NormalModePopupObjects& popup, + KigPart& doc, KigWidget& w, NormalMode& ) +{ + if ( menu != NormalModePopupObjects::ConstructMenu && + menu != NormalModePopupObjects::ShowMenu ) + return false; + if ( (uint) id >= mprops[menu - 1].size() ) + { + id -= mprops[menu - 1].size(); + return false; + } + int propid = mprops[menu-1][id]; + assert( os.size() == 1 ); + ObjectHolder* parent = os[0]; + if ( menu == NormalModePopupObjects::ShowMenu ) + { + std::vector args; + args.push_back( new ObjectPropertyCalcer( parent->calcer(), propid ) ); + args.back()->calc( doc.document() ); +// TODO: recover the cursor position somehow... the following does not work +// in general... +// Coordinate c = w.fromScreen( w.mapFromGlobal( popup.mapToGlobal( TQPoint( 5, 0 ) ) ) ); +// mp: it seems that we have no idea where to position the label, +// btw what's the meaning of (5,0)? let the +// attach method decide what to do... (passing an invalidCoord) +// /////// Coordinate c = Coordinate::invalidCoord(); + Coordinate c = w.fromScreen( popup.plc() ); + ObjectHolder* label = ObjectFactory::instance()->attachedLabel( + TQString::fromLatin1( "%1" ), parent->calcer(), c, + false, args, doc.document() ); + doc.addObject( label ); + } + else + { + ObjectHolder* h = new ObjectHolder( + new ObjectPropertyCalcer( parent->calcer(), propid ) ); + h->calc( doc.document() ); + doc.addObject( h ); + }; + return true; +} + +void ObjectTypeActionsProvider::fillUpMenu( + NormalModePopupObjects& popup, int menu, int& nextfree ) +{ + if ( popup.objects().size() != 1 ) return; + if ( menu != NormalModePopupObjects::ToplevelMenu ) return; + ObjectHolder* to = popup.objects()[0]; + ObjectTypeCalcer* c = dynamic_cast( to->calcer() ); + if ( ! c ) return; + const ObjectType* t = c->type(); + + TQStringList l = t->specialActions(); + mnoa = l.count(); + for ( int i = 0; i < mnoa; ++i ) + popup.addAction( menu, l[i], nextfree++ ); +} + +bool ObjectTypeActionsProvider::executeAction( + int menu, int& id, const std::vector& os, + NormalModePopupObjects&, + KigPart& doc, KigWidget& w, NormalMode& m ) +{ + if ( menu != NormalModePopupObjects::ToplevelMenu ) return false; + if ( id >= mnoa ) + { + id -= mnoa; + return false; + } + assert( os.size() == 1 ); + ObjectTypeCalcer* oc = dynamic_cast( os[0]->calcer() ); + assert( oc ); + + oc->type()->executeAction( id, *os[0], *oc, doc, w, m ); + return true; +} + +void BuiltinDocumentActionsProvider::fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ) +{ + if ( menu == NormalModePopupObjects::ToplevelMenu ) + { + popup.addAction( menu, i18n( "U&nhide All" ), nextfree++ ); + popup.part().action( "view_zoom_in" )->plug( &popup ); + popup.part().action( "view_zoom_out" )->plug( &popup ); + popup.part().action( "fullscreen" )->plug( &popup ); + nextfree += 3; + } + else if ( menu == NormalModePopupObjects::SetCoordinateSystemMenu ) + { + int idoffset = nextfree; + TQStringList l = CoordinateSystemFactory::names(); + mnumberofcoordsystems = l.count(); + for ( uint i = 0; i < l.count(); ++i ) + popup.addAction( menu, l[i], nextfree++ ); + int current = popup.part().document().coordinateSystem().id(); + popup.setChecked( menu, idoffset + current, true ); + } +} + +bool BuiltinDocumentActionsProvider::executeAction( + int menu, int& id, const std::vector&, + NormalModePopupObjects&, + KigPart& doc, KigWidget&, NormalMode& m ) +{ + if ( menu == NormalModePopupObjects::ToplevelMenu ) + { + kdDebug() << "id: " << id << endl; + if ( id == 0 ) + { + doc.showHidden(); + m.clearSelection(); + return true; + } + id -= 1; + return false; + } + else if ( menu == NormalModePopupObjects::SetCoordinateSystemMenu ) + { + if ( id >= mnumberofcoordsystems ) + { + id -= mnumberofcoordsystems; + return false; + }; + CoordinateSystem* sys = CoordinateSystemFactory::build( id ); + assert( sys ); + doc.history()->addCommand( KigCommand::changeCoordSystemCommand( doc, sys ) ); + m.clearSelection(); + return true; + } + else return false; +} + +void NormalModePopupObjects::setChecked( int menu, int n, bool checked ) +{ + mmenus[menu]->setItemChecked( n, checked ); +} + +#ifdef KIG_ENABLE_PYTHON_SCRIPTING +/** + * this is a local function that looks for a python script associated + * to a clicked object + */ +static ObjectTypeCalcer* getPythonExecuteTypeFromCalcer( ObjectCalcer* o ) +{ + ObjectTypeCalcer* oc = dynamic_cast( o ); + if ( !oc ) return 0; + const PythonExecuteType* pythonexec = dynamic_cast( oc->type() ); + if ( pythonexec ) return oc; + + return 0; +} + +void ScriptActionsProvider::fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ) +{ + if ( menu == NormalModePopupObjects::StartMenu ) + { + TDEIconLoader* l = popup.part().instance()->iconLoader(); + TQPixmap p = l->loadIcon( ScriptType::icon( ScriptType::Python ), TDEIcon::Toolbar, 22, TDEIcon::DefaultState, 0L, true ); + popup.addAction( menu, p, i18n( "Python Script" ), nextfree++ ); + mns++; + } + else if ( menu == NormalModePopupObjects::ToplevelMenu ) + { + if ( !popup.objects().empty() && + getPythonExecuteTypeFromCalcer( popup.objects().front()->calcer() ) ) + { + popup.addAction( menu, i18n( "Edit Script..." ), nextfree ); + } + nextfree++; + } +} + +bool ScriptActionsProvider::executeAction( + int menu, int& id, const std::vector& os, + NormalModePopupObjects&, KigPart& doc, KigWidget& w, NormalMode& mode ) +{ + if ( menu == NormalModePopupObjects::StartMenu ) + { + if ( id == 0 ) + { + ScriptCreationMode m( doc ); + m.setScriptType( ScriptType::Python ); + if ( os.size() > 0 ) + { + mode.clearSelection(); + m.addArgs( os, w ); + m.goToCodePage(); + } + doc.runMode( &m ); + return true; + } + else + { + id -= mns; + } + } + else if ( menu == NormalModePopupObjects::ToplevelMenu ) + { + if ( id == 0 ) + { + ObjectTypeCalcer* oc = getPythonExecuteTypeFromCalcer( os.front()->calcer() ); + if ( oc ) + { + ScriptEditMode m( oc, doc ); + m.setScriptType( ScriptType::Python ); + doc.runMode( &m ); + } + return true; + } + else + { + id -= 1; + } + } + + return false; +} +#endif + +int ObjectChooserPopup::getObjectFromList( const TQPoint& p, KigWidget* w, + const std::vector& objs, + bool givepopup ) +{ + int size = objs.size(); + + // no objects + if ( size == 0 ) + return -1; + + int id = -1; + + int numpoints = 0; + int numpolygons = 0; + int numothers = 0; + + for ( std::vector::const_iterator i = objs.begin(); + i != objs.end(); ++i ) + { + if ( (*i)->imp()->inherits( PointImp::stype() ) ) numpoints++; + else if ( (*i)->imp()->inherits( PolygonImp::stype() ) ) numpolygons++; + else numothers++; + } + + // simply cases: + // - only 1 point ( and eventually other objects ) + // - no points and an object which is not a polygon + // - only one object + // FIXME: we assume that our objects are sorted ( points, others, polygons )! + if ( ( numpoints == 1 ) || + ( ( numpoints == 0 ) && ( numothers == 1 ) ) || + ( size == 1 ) ) + id = 0; + else + { + if ( givepopup ) + { + ObjectChooserPopup* ppp = new ObjectChooserPopup( p, *w, objs ); + ppp->exec( TQCursor::pos() ); + + id = ppp->mselected; + + delete ppp; + ppp = 0; + } + else + { + // we don't want to show a popup to the user, so let's give a + // value > 0 to indicate that it's not the first + id = 1; + } + } +// kdDebug() << "numpoints: " << numpoints << endl +// << "numothers: " << numothers << endl +// << "numpolygons: " << numpolygons << endl +// << "id: " << id << endl; + + return id; +} + +ObjectChooserPopup::ObjectChooserPopup( const TQPoint& p, KigWidget& view, + const std::vector& objs ) + : TDEPopupMenu(), mplc( p ), mview( view ), mobjs( objs ), mselected( -1 ) +{ + for ( uint i = 0; i < mobjs.size(); i++ ) + { + insertItem( !mobjs[i]->name().isEmpty() + ? TQString::fromLatin1( "%1 %2" ).arg( mobjs[i]->imp()->type()->translatedName() ).arg( mobjs[i]->name() ) + : mobjs[i]->imp()->type()->translatedName(), + i ); + } + + connect( this, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( actionActivatedSlot( int ) ) ); +} + +ObjectChooserPopup::~ObjectChooserPopup() +{ +} + +void ObjectChooserPopup::actionActivatedSlot( int which ) +{ + mselected = which; +} diff --git a/kig/modes/textlabelwizard.cc b/kig/modes/textlabelwizard.cc deleted file mode 100644 index c92068de..00000000 --- a/kig/modes/textlabelwizard.cc +++ /dev/null @@ -1,95 +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 "textlabelwizard.h" -#include "textlabelwizard.moc" - -#include "label.h" -#include "linkslabel.h" - -#include -#include - -#include - -TextLabelWizard::TextLabelWizard( TQWidget* parent, TextLabelModeBase* mode ) - : TextLabelWizardBase( parent, "TextLabelWizard", false ), mmode( mode ) -{ - connect( labelTextInput, TQT_SIGNAL( textChanged() ), - TQT_SLOT( textChanged() ) ); - connect( myCustomWidget1, TQT_SIGNAL( linkClicked( int ) ), - TQT_SLOT( linkClicked( int ) ) ); - connect( this, TQT_SIGNAL( helpClicked() ), - this, TQT_SLOT( slotHelpClicked() ) ); - labelTextInput->setFocus(); -} - -TextLabelWizard::~TextLabelWizard() -{ -} - -void TextLabelWizard::back() -{ - if ( currentPage() == select_arguments_page ) - { - mmode->enterTextPageEntered(); - } - TextLabelWizardBase::back(); -} - -void TextLabelWizard::next() -{ - if ( currentPage() == enter_text_page ) - { - mmode->selectArgumentsPageEntered(); - } - TextLabelWizardBase::next(); -} - -void TextLabelWizard::reject() -{ - TextLabelWizardBase::reject(); - mmode->cancelPressed(); -} - -void TextLabelWizard::accept() -{ - mmode->finishPressed(); -} - -void TextLabelWizard::textChanged() -{ - mmode->labelTextChanged(); -} - -void TextLabelWizard::linkClicked( int which ) -{ - mmode->linkClicked( which ); -} - -void TextLabelWizard::relayoutArgsPage() -{ - select_arguments_pageLayout->activate(); - repaint(); -} - -void TextLabelWizard::slotHelpClicked() -{ - kapp->invokeHelp( TQString::fromLatin1( "text-labels" ), - TQString::fromLatin1( "kig" ) ); -} - diff --git a/kig/modes/textlabelwizard.cpp b/kig/modes/textlabelwizard.cpp new file mode 100644 index 00000000..c92068de --- /dev/null +++ b/kig/modes/textlabelwizard.cpp @@ -0,0 +1,95 @@ +// 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 "textlabelwizard.h" +#include "textlabelwizard.moc" + +#include "label.h" +#include "linkslabel.h" + +#include +#include + +#include + +TextLabelWizard::TextLabelWizard( TQWidget* parent, TextLabelModeBase* mode ) + : TextLabelWizardBase( parent, "TextLabelWizard", false ), mmode( mode ) +{ + connect( labelTextInput, TQT_SIGNAL( textChanged() ), + TQT_SLOT( textChanged() ) ); + connect( myCustomWidget1, TQT_SIGNAL( linkClicked( int ) ), + TQT_SLOT( linkClicked( int ) ) ); + connect( this, TQT_SIGNAL( helpClicked() ), + this, TQT_SLOT( slotHelpClicked() ) ); + labelTextInput->setFocus(); +} + +TextLabelWizard::~TextLabelWizard() +{ +} + +void TextLabelWizard::back() +{ + if ( currentPage() == select_arguments_page ) + { + mmode->enterTextPageEntered(); + } + TextLabelWizardBase::back(); +} + +void TextLabelWizard::next() +{ + if ( currentPage() == enter_text_page ) + { + mmode->selectArgumentsPageEntered(); + } + TextLabelWizardBase::next(); +} + +void TextLabelWizard::reject() +{ + TextLabelWizardBase::reject(); + mmode->cancelPressed(); +} + +void TextLabelWizard::accept() +{ + mmode->finishPressed(); +} + +void TextLabelWizard::textChanged() +{ + mmode->labelTextChanged(); +} + +void TextLabelWizard::linkClicked( int which ) +{ + mmode->linkClicked( which ); +} + +void TextLabelWizard::relayoutArgsPage() +{ + select_arguments_pageLayout->activate(); + repaint(); +} + +void TextLabelWizard::slotHelpClicked() +{ + kapp->invokeHelp( TQString::fromLatin1( "text-labels" ), + TQString::fromLatin1( "kig" ) ); +} + diff --git a/kig/objects/CMakeLists.txt b/kig/objects/CMakeLists.txt index 80157665..7bde2dde 100644 --- a/kig/objects/CMakeLists.txt +++ b/kig/objects/CMakeLists.txt @@ -17,42 +17,42 @@ link_directories( tde_add_library( kigobjects STATIC_PIC AUTOMOC SOURCES - angle_type.cc - arc_type.cc - base_type.cc - bogus_imp.cc - circle_imp.cc - circle_type.cc - polygon_type.cc - common.cc - conic_imp.cc - conic_types.cc - cubic_imp.cc - cubic_type.cc - curve_imp.cc - intersection_types.cc - inversion_type.cc - line_imp.cc - line_type.cc - locus_imp.cc - object_calcer.cc - object_drawer.cc - object_factory.cc - object_holder.cc - object_imp.cc - object_imp_factory.cc - object_type.cc - object_type_factory.cc - other_imp.cc - other_type.cc - point_imp.cc - point_type.cc - polygon_imp.cc - tangent_type.cc - centerofcurvature_type.cc - tests_type.cc - text_imp.cc - text_type.cc - transform_types.cc - vector_type.cc + angle_type.cpp + arc_type.cpp + base_type.cpp + bogus_imp.cpp + circle_imp.cpp + circle_type.cpp + polygon_type.cpp + common.cpp + conic_imp.cpp + conic_types.cpp + cubic_imp.cpp + cubic_type.cpp + curve_imp.cpp + intersection_types.cpp + inversion_type.cpp + line_imp.cpp + line_type.cpp + locus_imp.cpp + object_calcer.cpp + object_drawer.cpp + object_factory.cpp + object_holder.cpp + object_imp.cpp + object_imp_factory.cpp + object_type.cpp + object_type_factory.cpp + other_imp.cpp + other_type.cpp + point_imp.cpp + point_type.cpp + polygon_imp.cpp + tangent_type.cpp + centerofcurvature_type.cpp + tests_type.cpp + text_imp.cpp + text_type.cpp + transform_types.cpp + vector_type.cpp ) diff --git a/kig/objects/Makefile.am b/kig/objects/Makefile.am index 21a02c6f..383fb35f 100644 --- a/kig/objects/Makefile.am +++ b/kig/objects/Makefile.am @@ -39,43 +39,43 @@ noinst_HEADERS=\ transform_types.h \ vector_type.h libobjects_la_SOURCES=\ - angle_type.cc \ - arc_type.cc \ - base_type.cc \ - bogus_imp.cc \ - circle_imp.cc \ - circle_type.cc \ - polygon_type.cc \ - common.cc \ - conic_imp.cc \ - conic_types.cc \ - cubic_imp.cc \ - cubic_type.cc \ - curve_imp.cc \ - intersection_types.cc \ - inversion_type.cc \ - line_imp.cc \ - line_type.cc \ - locus_imp.cc \ - object_calcer.cc \ - object_drawer.cc \ - object_factory.cc \ - object_holder.cc \ - object_imp.cc \ - object_imp_factory.cc \ - object_type.cc \ - object_type_factory.cc \ - other_imp.cc \ - other_type.cc \ - point_imp.cc \ - point_type.cc \ - polygon_imp.cc \ - tangent_type.cc \ - centerofcurvature_type.cc \ - tests_type.cc \ - text_imp.cc \ - text_type.cc \ - transform_types.cc \ - vector_type.cc + angle_type.cpp \ + arc_type.cpp \ + base_type.cpp \ + bogus_imp.cpp \ + circle_imp.cpp \ + circle_type.cpp \ + polygon_type.cpp \ + common.cpp \ + conic_imp.cpp \ + conic_types.cpp \ + cubic_imp.cpp \ + cubic_type.cpp \ + curve_imp.cpp \ + intersection_types.cpp \ + inversion_type.cpp \ + line_imp.cpp \ + line_type.cpp \ + locus_imp.cpp \ + object_calcer.cpp \ + object_drawer.cpp \ + object_factory.cpp \ + object_holder.cpp \ + object_imp.cpp \ + object_imp_factory.cpp \ + object_type.cpp \ + object_type_factory.cpp \ + other_imp.cpp \ + other_type.cpp \ + point_imp.cpp \ + point_type.cpp \ + polygon_imp.cpp \ + tangent_type.cpp \ + centerofcurvature_type.cpp \ + tests_type.cpp \ + text_imp.cpp \ + text_type.cpp \ + transform_types.cpp \ + vector_type.cpp libobjects_la_LIBADD=-lm METASOURCES=AUTO diff --git a/kig/objects/angle_type.cc b/kig/objects/angle_type.cc deleted file mode 100644 index 7b86411b..00000000 --- a/kig/objects/angle_type.cc +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright (C) 2003 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 "angle_type.h" - -#include "bogus_imp.h" -#include "other_imp.h" -#include "point_imp.h" -#include "../misc/calcpaths.h" -#include "../misc/common.h" -#include "../misc/goniometry.h" -#include "../misc/kiginputdialog.h" -#include "../kig/kig_commands.h" -#include "../kig/kig_part.h" -#include "../kig/kig_view.h" - -#include -#include -#include - -#include - -static const char* constructanglethroughpoint = - I18N_NOOP( "Construct an angle through this point" ); - -static const ArgsParser::spec argsspecAngle[] = -{ - { PointImp::stype(), constructanglethroughpoint, - I18N_NOOP( "Select a point that the first half-line of the angle should go through..." ), true }, - { PointImp::stype(), I18N_NOOP( "Construct an angle at this point" ), - I18N_NOOP( "Select the point to construct the angle in..." ), true }, - { PointImp::stype(), constructanglethroughpoint, - I18N_NOOP( "Select a point that the second half-line of the angle should go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( AngleType ) - -AngleType::AngleType() - : ArgsParserObjectType( "Angle", argsspecAngle, 3 ) -{ -} - -AngleType::~AngleType() -{ -} - -const AngleType* AngleType::instance() -{ - static const AngleType t; - return &t; -} - -ObjectImp* AngleType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; - - std::vector points; - for ( uint i = 0; i < parents.size(); ++i ) - points.push_back( - static_cast( parents[i] )->coordinate() ); - - Coordinate lvect = points[0] - points[1]; - Coordinate rvect; - if ( points.size() == 3 ) - rvect = points[2] - points[1]; - else - { - rvect = lvect.orthogonal(); - } - - double startangle = atan2( lvect.y, lvect.x ); - double endangle = atan2( rvect.y, rvect.x ); - double anglelength = endangle - startangle; - if ( anglelength < 0 ) anglelength += 2* M_PI; - if ( startangle < 0 ) startangle += 2*M_PI; - - return new AngleImp( points[1], startangle, anglelength ); -} - -const ObjectImpType* AngleType::resultId() const -{ - return AngleImp::stype(); -} - -TQStringList AngleType::specialActions() const -{ - TQStringList ret; - ret << i18n( "Set Si&ze" ); - return ret; -} - -void AngleType::executeAction( - int i, ObjectHolder&, ObjectTypeCalcer& t, - KigPart& d, KigWidget& w, NormalMode& ) const -{ - assert( i == 0 ); - // pretend to use this var.. - (void) i; - - std::vector parents = t.parents(); - - assert( margsparser.checkArgs( parents ) ); - - Coordinate a = static_cast( parents[0]->imp() )->coordinate(); - Coordinate b = static_cast( parents[1]->imp() )->coordinate(); - Coordinate c = static_cast( parents[2]->imp() )->coordinate(); - - Coordinate lvect = a - b; - Coordinate rvect = c - b; - - double startangle = atan2( lvect.y, lvect.x ); - double endangle = atan2( rvect.y, rvect.x ); - double anglelength = endangle - startangle; - if ( anglelength < 0 ) anglelength += 2* M_PI; - if ( startangle < 0 ) startangle += 2*M_PI; - - Goniometry go( anglelength, Goniometry::Rad ); - go.convertTo( Goniometry::Deg ); - - bool ok; - Goniometry newsize = KigInputDialog::getAngle( &w, &ok, go ); - if ( !ok ) - return; - newsize.convertTo( Goniometry::Rad ); - - double newcangle = startangle + newsize.value(); - Coordinate cdir( cos( newcangle ), sin( newcangle ) ); - Coordinate nc = b + cdir.normalize( rvect.length() ); - - MonitorDataObjects mon( getAllParents( parents ) ); - parents[2]->move( nc, d.document() ); - KigCommand* kc = new KigCommand( d, i18n( "Resize Angle" ) ); - mon.finish( kc ); - d.history()->addCommand( kc ); -} - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( HalfAngleType ) - -HalfAngleType::HalfAngleType() - : ArgsParserObjectType( "HalfAngle", argsspecAngle, 3 ) -{ -} - -HalfAngleType::~HalfAngleType() -{ -} - -const HalfAngleType* HalfAngleType::instance() -{ - static const HalfAngleType t; - return &t; -} - -ObjectImp* HalfAngleType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; - - std::vector points; - for ( uint i = 0; i < parents.size(); ++i ) - points.push_back( - static_cast( parents[i] )->coordinate() ); - - Coordinate lvect = points[0] - points[1]; - Coordinate rvect; - if ( points.size() == 3 ) - rvect = points[2] - points[1]; - else - { - rvect = lvect.orthogonal(); - } - - double startangle = atan2( lvect.y, lvect.x ); - double endangle = atan2( rvect.y, rvect.x ); - double anglelength = endangle - startangle; - if ( anglelength < 0 ) anglelength += 2 * M_PI; - if ( startangle < 0 ) startangle += 2 * M_PI; - - if ( anglelength > M_PI ) - { - startangle += anglelength; - anglelength = 2 * M_PI - anglelength; - if ( startangle > 2 * M_PI ) startangle -= 2 * M_PI; - if ( anglelength < 0 ) anglelength += 2 * M_PI; - } - - return new AngleImp( points[1], startangle, anglelength ); -} - -const ObjectImpType* HalfAngleType::resultId() const -{ - return AngleImp::stype(); -} - diff --git a/kig/objects/angle_type.cpp b/kig/objects/angle_type.cpp new file mode 100644 index 00000000..7b86411b --- /dev/null +++ b/kig/objects/angle_type.cpp @@ -0,0 +1,208 @@ +// Copyright (C) 2003 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 "angle_type.h" + +#include "bogus_imp.h" +#include "other_imp.h" +#include "point_imp.h" +#include "../misc/calcpaths.h" +#include "../misc/common.h" +#include "../misc/goniometry.h" +#include "../misc/kiginputdialog.h" +#include "../kig/kig_commands.h" +#include "../kig/kig_part.h" +#include "../kig/kig_view.h" + +#include +#include +#include + +#include + +static const char* constructanglethroughpoint = + I18N_NOOP( "Construct an angle through this point" ); + +static const ArgsParser::spec argsspecAngle[] = +{ + { PointImp::stype(), constructanglethroughpoint, + I18N_NOOP( "Select a point that the first half-line of the angle should go through..." ), true }, + { PointImp::stype(), I18N_NOOP( "Construct an angle at this point" ), + I18N_NOOP( "Select the point to construct the angle in..." ), true }, + { PointImp::stype(), constructanglethroughpoint, + I18N_NOOP( "Select a point that the second half-line of the angle should go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( AngleType ) + +AngleType::AngleType() + : ArgsParserObjectType( "Angle", argsspecAngle, 3 ) +{ +} + +AngleType::~AngleType() +{ +} + +const AngleType* AngleType::instance() +{ + static const AngleType t; + return &t; +} + +ObjectImp* AngleType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; + + std::vector points; + for ( uint i = 0; i < parents.size(); ++i ) + points.push_back( + static_cast( parents[i] )->coordinate() ); + + Coordinate lvect = points[0] - points[1]; + Coordinate rvect; + if ( points.size() == 3 ) + rvect = points[2] - points[1]; + else + { + rvect = lvect.orthogonal(); + } + + double startangle = atan2( lvect.y, lvect.x ); + double endangle = atan2( rvect.y, rvect.x ); + double anglelength = endangle - startangle; + if ( anglelength < 0 ) anglelength += 2* M_PI; + if ( startangle < 0 ) startangle += 2*M_PI; + + return new AngleImp( points[1], startangle, anglelength ); +} + +const ObjectImpType* AngleType::resultId() const +{ + return AngleImp::stype(); +} + +TQStringList AngleType::specialActions() const +{ + TQStringList ret; + ret << i18n( "Set Si&ze" ); + return ret; +} + +void AngleType::executeAction( + int i, ObjectHolder&, ObjectTypeCalcer& t, + KigPart& d, KigWidget& w, NormalMode& ) const +{ + assert( i == 0 ); + // pretend to use this var.. + (void) i; + + std::vector parents = t.parents(); + + assert( margsparser.checkArgs( parents ) ); + + Coordinate a = static_cast( parents[0]->imp() )->coordinate(); + Coordinate b = static_cast( parents[1]->imp() )->coordinate(); + Coordinate c = static_cast( parents[2]->imp() )->coordinate(); + + Coordinate lvect = a - b; + Coordinate rvect = c - b; + + double startangle = atan2( lvect.y, lvect.x ); + double endangle = atan2( rvect.y, rvect.x ); + double anglelength = endangle - startangle; + if ( anglelength < 0 ) anglelength += 2* M_PI; + if ( startangle < 0 ) startangle += 2*M_PI; + + Goniometry go( anglelength, Goniometry::Rad ); + go.convertTo( Goniometry::Deg ); + + bool ok; + Goniometry newsize = KigInputDialog::getAngle( &w, &ok, go ); + if ( !ok ) + return; + newsize.convertTo( Goniometry::Rad ); + + double newcangle = startangle + newsize.value(); + Coordinate cdir( cos( newcangle ), sin( newcangle ) ); + Coordinate nc = b + cdir.normalize( rvect.length() ); + + MonitorDataObjects mon( getAllParents( parents ) ); + parents[2]->move( nc, d.document() ); + KigCommand* kc = new KigCommand( d, i18n( "Resize Angle" ) ); + mon.finish( kc ); + d.history()->addCommand( kc ); +} + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( HalfAngleType ) + +HalfAngleType::HalfAngleType() + : ArgsParserObjectType( "HalfAngle", argsspecAngle, 3 ) +{ +} + +HalfAngleType::~HalfAngleType() +{ +} + +const HalfAngleType* HalfAngleType::instance() +{ + static const HalfAngleType t; + return &t; +} + +ObjectImp* HalfAngleType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; + + std::vector points; + for ( uint i = 0; i < parents.size(); ++i ) + points.push_back( + static_cast( parents[i] )->coordinate() ); + + Coordinate lvect = points[0] - points[1]; + Coordinate rvect; + if ( points.size() == 3 ) + rvect = points[2] - points[1]; + else + { + rvect = lvect.orthogonal(); + } + + double startangle = atan2( lvect.y, lvect.x ); + double endangle = atan2( rvect.y, rvect.x ); + double anglelength = endangle - startangle; + if ( anglelength < 0 ) anglelength += 2 * M_PI; + if ( startangle < 0 ) startangle += 2 * M_PI; + + if ( anglelength > M_PI ) + { + startangle += anglelength; + anglelength = 2 * M_PI - anglelength; + if ( startangle > 2 * M_PI ) startangle -= 2 * M_PI; + if ( anglelength < 0 ) anglelength += 2 * M_PI; + } + + return new AngleImp( points[1], startangle, anglelength ); +} + +const ObjectImpType* HalfAngleType::resultId() const +{ + return AngleImp::stype(); +} + diff --git a/kig/objects/arc_type.cc b/kig/objects/arc_type.cc deleted file mode 100644 index 59d38054..00000000 --- a/kig/objects/arc_type.cc +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (C) 2003-2004 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 "arc_type.h" - -#include "bogus_imp.h" -#include "other_imp.h" -#include "point_imp.h" -#include "line_imp.h" -#include "locus_imp.h" - -#include "../misc/common.h" -#include "../misc/calcpaths.h" -#include "../misc/goniometry.h" -#include "../kig/kig_part.h" -#include "../kig/kig_view.h" -#include "../kig/kig_commands.h" - -#include -#include -#include - -using std::find; - -#include - -static const char constructarcstartingstat[] = I18N_NOOP( "Construct an arc starting at this point" ); - -static const ArgsParser::spec argsspecArcBTP[] = -{ - { PointImp::stype(), constructarcstartingstat, - I18N_NOOP( "Select the start point of the new arc..." ), true }, - { PointImp::stype(), I18N_NOOP( "Construct an arc through this point" ), - I18N_NOOP( "Select a point for the new arc to go through..." ), true }, - { PointImp::stype(), I18N_NOOP( "Construct an arc ending at this point" ), - I18N_NOOP( "Select the end point of the new arc..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ArcBTPType ) - -ArcBTPType::ArcBTPType() - : ArgsParserObjectType( "ArcBTP", argsspecArcBTP, 3 ) -{ -} - -ArcBTPType::~ArcBTPType() -{ -} - -const ArcBTPType* ArcBTPType::instance() -{ - static const ArcBTPType t; - return &t; -} - -ObjectImp* ArcBTPType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args, 2 ) ) - return new InvalidImp; - - const Coordinate a = - static_cast( args[0] )->coordinate(); - const Coordinate b = - static_cast( args[1] )->coordinate(); - Coordinate center; - double angle = 0.; - double startangle = 0.; - if ( args.size() == 3 ) - { - Coordinate c = static_cast( args[2] )->coordinate(); - center = calcCenter( a, b, c ); - if ( ! center.valid() ) return new InvalidImp; - Coordinate ad = a - center; - Coordinate bd = b - center; - Coordinate cd = c - center; - double anglea = atan2( ad.y, ad.x ); - double angleb = atan2( bd.y, bd.x ); - double anglec = atan2( cd.y, cd.x ); - - // anglea should be smaller than anglec - if ( anglea > anglec ) - { - double t = anglea; - anglea = anglec; - anglec = t; - }; - if ( angleb > anglec || angleb < anglea ) - { - startangle = anglec; - angle = 2 * M_PI + anglea - startangle; - } - else - { - startangle = anglea; - angle = anglec - anglea; - }; - } - else - { - // find a center and angles that look natural.. - center = (b+a)/2 + .6*(b-a).orthogonal(); - Coordinate bd = b - center; - Coordinate ad = a - center; - startangle = atan2( ad.y, ad.x ); - double halfangle = atan2( bd.y, bd.x ) - startangle; - if ( halfangle < - M_PI ) halfangle += 2*M_PI; - angle = 2 * halfangle; - }; - - double radius = ( a - center ).length(); - return new ArcImp( center, radius, startangle, angle ); -} - -const ObjectImpType* ArcBTPType::impRequirement( const ObjectImp*, const Args& ) const -{ - return PointImp::stype(); -} - -bool ArcBTPType::inherits( int type ) const -{ - return Parent::inherits( type ); -} - -const ObjectImpType* ArcBTPType::resultId() const -{ - return ArcImp::stype(); -} - -static const ArgsParser::spec argsspecArcBCPA[] = -{ - { PointImp::stype(), I18N_NOOP( "Construct an arc with this center" ), - I18N_NOOP( "Select the center of the new arc..." ), true }, - { PointImp::stype(), constructarcstartingstat, - I18N_NOOP( "Select the start point of the new arc..." ), true }, - { AngleImp::stype(), I18N_NOOP( "Construct an arc with this angle" ), - I18N_NOOP( "Select the angle of the new arc..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ArcBCPAType ) - -ArcBCPAType::ArcBCPAType() - : ArgsParserObjectType( "ArcBCPA", argsspecArcBCPA, 3 ) -{ -} - -ArcBCPAType::~ArcBCPAType() -{ -} - -const ArcBCPAType* ArcBCPAType::instance() -{ - static const ArcBCPAType t; - return &t; -} - -ObjectImp* ArcBCPAType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) - return new InvalidImp; - - const Coordinate center = static_cast( args[0] )->coordinate(); - const Coordinate p = static_cast( args[1] )->coordinate(); - const AngleImp* a = static_cast( args[2] ); - const double angle = a->angle(); - const Coordinate dir = p - center; - const double startangle = atan2( dir.y, dir.x ); - const double radius = center.distance( p ); - - return new ArcImp( center, radius, startangle, angle ); -} - -const ObjectImpType* ArcBCPAType::impRequirement( const ObjectImp*, const Args& ) const -{ - return PointImp::stype(); -} - -bool ArcBCPAType::inherits( int type ) const -{ - return Parent::inherits( type ); -} - -const ObjectImpType* ArcBCPAType::resultId() const -{ - return ArcImp::stype(); -} diff --git a/kig/objects/arc_type.cpp b/kig/objects/arc_type.cpp new file mode 100644 index 00000000..59d38054 --- /dev/null +++ b/kig/objects/arc_type.cpp @@ -0,0 +1,199 @@ +// Copyright (C) 2003-2004 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 "arc_type.h" + +#include "bogus_imp.h" +#include "other_imp.h" +#include "point_imp.h" +#include "line_imp.h" +#include "locus_imp.h" + +#include "../misc/common.h" +#include "../misc/calcpaths.h" +#include "../misc/goniometry.h" +#include "../kig/kig_part.h" +#include "../kig/kig_view.h" +#include "../kig/kig_commands.h" + +#include +#include +#include + +using std::find; + +#include + +static const char constructarcstartingstat[] = I18N_NOOP( "Construct an arc starting at this point" ); + +static const ArgsParser::spec argsspecArcBTP[] = +{ + { PointImp::stype(), constructarcstartingstat, + I18N_NOOP( "Select the start point of the new arc..." ), true }, + { PointImp::stype(), I18N_NOOP( "Construct an arc through this point" ), + I18N_NOOP( "Select a point for the new arc to go through..." ), true }, + { PointImp::stype(), I18N_NOOP( "Construct an arc ending at this point" ), + I18N_NOOP( "Select the end point of the new arc..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ArcBTPType ) + +ArcBTPType::ArcBTPType() + : ArgsParserObjectType( "ArcBTP", argsspecArcBTP, 3 ) +{ +} + +ArcBTPType::~ArcBTPType() +{ +} + +const ArcBTPType* ArcBTPType::instance() +{ + static const ArcBTPType t; + return &t; +} + +ObjectImp* ArcBTPType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args, 2 ) ) + return new InvalidImp; + + const Coordinate a = + static_cast( args[0] )->coordinate(); + const Coordinate b = + static_cast( args[1] )->coordinate(); + Coordinate center; + double angle = 0.; + double startangle = 0.; + if ( args.size() == 3 ) + { + Coordinate c = static_cast( args[2] )->coordinate(); + center = calcCenter( a, b, c ); + if ( ! center.valid() ) return new InvalidImp; + Coordinate ad = a - center; + Coordinate bd = b - center; + Coordinate cd = c - center; + double anglea = atan2( ad.y, ad.x ); + double angleb = atan2( bd.y, bd.x ); + double anglec = atan2( cd.y, cd.x ); + + // anglea should be smaller than anglec + if ( anglea > anglec ) + { + double t = anglea; + anglea = anglec; + anglec = t; + }; + if ( angleb > anglec || angleb < anglea ) + { + startangle = anglec; + angle = 2 * M_PI + anglea - startangle; + } + else + { + startangle = anglea; + angle = anglec - anglea; + }; + } + else + { + // find a center and angles that look natural.. + center = (b+a)/2 + .6*(b-a).orthogonal(); + Coordinate bd = b - center; + Coordinate ad = a - center; + startangle = atan2( ad.y, ad.x ); + double halfangle = atan2( bd.y, bd.x ) - startangle; + if ( halfangle < - M_PI ) halfangle += 2*M_PI; + angle = 2 * halfangle; + }; + + double radius = ( a - center ).length(); + return new ArcImp( center, radius, startangle, angle ); +} + +const ObjectImpType* ArcBTPType::impRequirement( const ObjectImp*, const Args& ) const +{ + return PointImp::stype(); +} + +bool ArcBTPType::inherits( int type ) const +{ + return Parent::inherits( type ); +} + +const ObjectImpType* ArcBTPType::resultId() const +{ + return ArcImp::stype(); +} + +static const ArgsParser::spec argsspecArcBCPA[] = +{ + { PointImp::stype(), I18N_NOOP( "Construct an arc with this center" ), + I18N_NOOP( "Select the center of the new arc..." ), true }, + { PointImp::stype(), constructarcstartingstat, + I18N_NOOP( "Select the start point of the new arc..." ), true }, + { AngleImp::stype(), I18N_NOOP( "Construct an arc with this angle" ), + I18N_NOOP( "Select the angle of the new arc..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ArcBCPAType ) + +ArcBCPAType::ArcBCPAType() + : ArgsParserObjectType( "ArcBCPA", argsspecArcBCPA, 3 ) +{ +} + +ArcBCPAType::~ArcBCPAType() +{ +} + +const ArcBCPAType* ArcBCPAType::instance() +{ + static const ArcBCPAType t; + return &t; +} + +ObjectImp* ArcBCPAType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) + return new InvalidImp; + + const Coordinate center = static_cast( args[0] )->coordinate(); + const Coordinate p = static_cast( args[1] )->coordinate(); + const AngleImp* a = static_cast( args[2] ); + const double angle = a->angle(); + const Coordinate dir = p - center; + const double startangle = atan2( dir.y, dir.x ); + const double radius = center.distance( p ); + + return new ArcImp( center, radius, startangle, angle ); +} + +const ObjectImpType* ArcBCPAType::impRequirement( const ObjectImp*, const Args& ) const +{ + return PointImp::stype(); +} + +bool ArcBCPAType::inherits( int type ) const +{ + return Parent::inherits( type ); +} + +const ObjectImpType* ArcBCPAType::resultId() const +{ + return ArcImp::stype(); +} diff --git a/kig/objects/base_type.cc b/kig/objects/base_type.cc deleted file mode 100644 index 0f8eecec..00000000 --- a/kig/objects/base_type.cc +++ /dev/null @@ -1,112 +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 "base_type.h" - -#include "point_imp.h" -#include "line_imp.h" -#include "bogus_imp.h" -#include "object_calcer.h" - -#include "../misc/common.h" - -ObjectABType::ObjectABType( const char* fulltypename, const ArgsParser::spec* spec, int n ) - : ArgsParserObjectType( fulltypename, spec, n ) -{ -} - -ObjectABType::~ObjectABType() -{ -} - -ObjectImp* ObjectABType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) - return new InvalidImp; - - Coordinate a = static_cast( parents[0] )->coordinate(); - Coordinate b = static_cast( parents[1] )->coordinate(); - - return calc( a, b ); -} - -bool ObjectABType::canMove( const ObjectTypeCalcer& o ) const -{ - return isFreelyTranslatable( o ); -/* - * as observed by domi: this object is actually movable also - * if one point is FreelyTranslatable and the other is - * only movable, but then the "move" itself requires some - * trickery. - */ -} - -bool ObjectABType::isFreelyTranslatable( const ObjectTypeCalcer& o ) const -{ - std::vector parents = o.parents(); - return parents[0]->isFreelyTranslatable() && parents[1]->isFreelyTranslatable(); -} - -void ObjectABType::move( ObjectTypeCalcer& o, const Coordinate& to, - const KigDocument& d ) const -{ - std::vector parents = o.parents(); - assert( margsparser.checkArgs( parents ) ); - const Coordinate a = static_cast( parents[0]->imp() )->coordinate(); - const Coordinate b = static_cast( parents[1]->imp() )->coordinate(); - const Coordinate dist = b - a; - if ( parents[0]->canMove() ) - parents[0]->move( to, d ); - if ( parents[1]->canMove() ) - parents[1]->move( to + dist, d ); -} - -ObjectLPType::ObjectLPType( const char* fullname, const ArgsParser::spec* spec, int n ) - : ArgsParserObjectType( fullname, spec, n ) -{ -} - -ObjectLPType::~ObjectLPType() -{ -} - -ObjectImp* ObjectLPType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - LineData l = static_cast( args[0] )->data(); - Coordinate c = static_cast( args[1] )->coordinate(); - return calc( l, c ); -} - -const Coordinate ObjectABType::moveReferencePoint( const ObjectTypeCalcer& o ) const -{ - std::vector parents = o.parents(); - assert( margsparser.checkArgs( parents ) ); - return static_cast( parents[0]->imp() )->coordinate(); -} - -std::vector ObjectABType::movableParents( const ObjectTypeCalcer& ourobj ) const -{ - std::vector parents = ourobj.parents(); - std::set ret; - std::vector tmp = parents[0]->movableParents(); - ret.insert( tmp.begin(), tmp.end() ); - tmp = parents[1]->movableParents(); - ret.insert( tmp.begin(), tmp.end() ); - ret.insert( parents.begin(), parents.end() ); - return std::vector( ret.begin(), ret.end() ); -} diff --git a/kig/objects/base_type.cpp b/kig/objects/base_type.cpp new file mode 100644 index 00000000..0f8eecec --- /dev/null +++ b/kig/objects/base_type.cpp @@ -0,0 +1,112 @@ +// 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 "base_type.h" + +#include "point_imp.h" +#include "line_imp.h" +#include "bogus_imp.h" +#include "object_calcer.h" + +#include "../misc/common.h" + +ObjectABType::ObjectABType( const char* fulltypename, const ArgsParser::spec* spec, int n ) + : ArgsParserObjectType( fulltypename, spec, n ) +{ +} + +ObjectABType::~ObjectABType() +{ +} + +ObjectImp* ObjectABType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) + return new InvalidImp; + + Coordinate a = static_cast( parents[0] )->coordinate(); + Coordinate b = static_cast( parents[1] )->coordinate(); + + return calc( a, b ); +} + +bool ObjectABType::canMove( const ObjectTypeCalcer& o ) const +{ + return isFreelyTranslatable( o ); +/* + * as observed by domi: this object is actually movable also + * if one point is FreelyTranslatable and the other is + * only movable, but then the "move" itself requires some + * trickery. + */ +} + +bool ObjectABType::isFreelyTranslatable( const ObjectTypeCalcer& o ) const +{ + std::vector parents = o.parents(); + return parents[0]->isFreelyTranslatable() && parents[1]->isFreelyTranslatable(); +} + +void ObjectABType::move( ObjectTypeCalcer& o, const Coordinate& to, + const KigDocument& d ) const +{ + std::vector parents = o.parents(); + assert( margsparser.checkArgs( parents ) ); + const Coordinate a = static_cast( parents[0]->imp() )->coordinate(); + const Coordinate b = static_cast( parents[1]->imp() )->coordinate(); + const Coordinate dist = b - a; + if ( parents[0]->canMove() ) + parents[0]->move( to, d ); + if ( parents[1]->canMove() ) + parents[1]->move( to + dist, d ); +} + +ObjectLPType::ObjectLPType( const char* fullname, const ArgsParser::spec* spec, int n ) + : ArgsParserObjectType( fullname, spec, n ) +{ +} + +ObjectLPType::~ObjectLPType() +{ +} + +ObjectImp* ObjectLPType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + LineData l = static_cast( args[0] )->data(); + Coordinate c = static_cast( args[1] )->coordinate(); + return calc( l, c ); +} + +const Coordinate ObjectABType::moveReferencePoint( const ObjectTypeCalcer& o ) const +{ + std::vector parents = o.parents(); + assert( margsparser.checkArgs( parents ) ); + return static_cast( parents[0]->imp() )->coordinate(); +} + +std::vector ObjectABType::movableParents( const ObjectTypeCalcer& ourobj ) const +{ + std::vector parents = ourobj.parents(); + std::set ret; + std::vector tmp = parents[0]->movableParents(); + ret.insert( tmp.begin(), tmp.end() ); + tmp = parents[1]->movableParents(); + ret.insert( tmp.begin(), tmp.end() ); + ret.insert( parents.begin(), parents.end() ); + return std::vector( ret.begin(), ret.end() ); +} diff --git a/kig/objects/bogus_imp.cc b/kig/objects/bogus_imp.cc deleted file mode 100644 index 76d724b1..00000000 --- a/kig/objects/bogus_imp.cc +++ /dev/null @@ -1,388 +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 "bogus_imp.h" - -#include -#include -#include - -#include "../misc/rect.h" - -Coordinate BogusImp::attachPoint( ) const -{ - return Coordinate::invalidCoord(); -} - -void BogusImp::draw( KigPainter& ) const -{ -} - -bool BogusImp::contains( const Coordinate&, int, const KigWidget& ) const -{ - return false; -} - -bool BogusImp::inRect( const Rect&, int, const KigWidget& ) const -{ - return false; -} - -DoubleImp::DoubleImp( const double d ) - : mdata( d ) -{ -} - -IntImp::IntImp( const int d ) - : mdata( d ) -{ -} - -StringImp::StringImp( const TQString& d ) - : mdata( d ) -{ -} - -DoubleImp* DoubleImp::copy() const -{ - return new DoubleImp( mdata ); -} - -IntImp* IntImp::copy() const -{ - return new IntImp( mdata ); -} - -StringImp* StringImp::copy() const -{ - return new StringImp( mdata ); -} - -ObjectImp* BogusImp::transform( const Transformation& ) const -{ - return copy(); -} - -InvalidImp* InvalidImp::copy() const -{ - return new InvalidImp(); -} - -InvalidImp::InvalidImp() -{ -} - -void InvalidImp::fillInNextEscape( TQString& s, const KigDocument& ) const -{ - s = s.arg( "[invalid]" ); -} - -void DoubleImp::fillInNextEscape( TQString& s, const KigDocument& ) const -{ - s = s.arg( mdata ); -} - -void IntImp::fillInNextEscape( TQString& s, const KigDocument& ) const -{ - s = s.arg( mdata ); -} - -void StringImp::fillInNextEscape( TQString& s, const KigDocument& ) const -{ - s = s.arg( mdata ); -} - -HierarchyImp::HierarchyImp( const ObjectHierarchy& h ) - : BogusImp(), mdata( h ) -{ -} - -HierarchyImp* HierarchyImp::copy() const -{ - return new HierarchyImp( mdata ); -} - -void InvalidImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -void DoubleImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -void IntImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -void StringImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -void HierarchyImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -TransformationImp::TransformationImp( const Transformation& h ) - : mdata( h ) -{ -} - -TransformationImp* TransformationImp::copy() const -{ - return new TransformationImp( mdata ); -} - -void TransformationImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -bool InvalidImp::equals( const ObjectImp& rhs ) const -{ - return !rhs.valid(); -} - -bool DoubleImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( DoubleImp::stype() ) && - static_cast( rhs ).data() == mdata; -} - -bool IntImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( IntImp::stype() ) && - static_cast( rhs ).data() == mdata; -} - -bool StringImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( StringImp::stype() ) && - static_cast( rhs ).data() == mdata; -} - -bool HierarchyImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( HierarchyImp::stype() ) && - static_cast( rhs ).data() == mdata; -} - -bool TransformationImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( TransformationImp::stype() ) && - static_cast( rhs ).data() == mdata; -} - -bool InvalidImp::canFillInNextEscape() const -{ - return true; -} - -bool DoubleImp::canFillInNextEscape() const -{ - return true; -} - -bool IntImp::canFillInNextEscape() const -{ - return true; -} - -bool StringImp::canFillInNextEscape() const -{ - return true; -} - -const ObjectImpType* InvalidImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "invalid", "", "", "", "", "", "", "", "", "" ); - return &t; -} - -const ObjectImpType* StringImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "string", - "string", "", "", "", "", "", "", "", "" ); - return &t; -} -const ObjectImpType* HierarchyImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "hierarchy", "", "", "", "", "", "", "", "", "" ); - return &t; -} -const ObjectImpType* TransformationImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "transformation", "", "", "", "", "", "", "", "", ""); - return &t; -} - -const ObjectImpType* InvalidImp::type() const -{ - return InvalidImp::stype(); -} - -const ObjectImpType* DoubleImp::type() const -{ - return DoubleImp::stype(); -} - -const ObjectImpType* IntImp::type() const -{ - return IntImp::stype(); -} - -const ObjectImpType* StringImp::type() const -{ - return StringImp::stype(); -} - -const ObjectImpType* HierarchyImp::type() const -{ - return HierarchyImp::stype(); -} - -const ObjectImpType* TransformationImp::type() const -{ - return TransformationImp::stype(); -} - -const ObjectImpType* DoubleImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "double", - "double", "", "", "", "", "", "", "", "" ); - return &t; -} - -const ObjectImpType* IntImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "int", - "int", "", "", "", "", "", "", "", "" ); - return &t; -} - -const ObjectImpType* BogusImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "bogus", - "", "", "", "", "", "", "", "", "" ); - return &t; -} - -const ObjectImpType* TestResultImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "testresult", "", "", "", "", "", "", "", "", "" ); - return &t; - -} - -TestResultImp::TestResultImp( const TQString& s ) - : mdata( s ) -{ -} - -TestResultImp* TestResultImp::copy() const -{ - return new TestResultImp( mdata ); -} - -const ObjectImpType* TestResultImp::type() const -{ - return stype(); -} - -void TestResultImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -bool TestResultImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( TestResultImp::stype() ) && - static_cast( rhs ).mdata == mdata; - -} - -const uint TestResultImp::numberOfProperties() const -{ - return Parent::numberOfProperties() + 1; -} - -const QCStringList TestResultImp::properties() const -{ - QCStringList l = Parent::properties(); - l << I18N_NOOP( "Test Result" ); - assert( l.size() == TestResultImp::numberOfProperties() ); - return l; -} - -const QCStringList TestResultImp::propertiesInternalNames() const -{ - QCStringList s = Parent::propertiesInternalNames(); - s << "test-result"; - assert( s.size() == TestResultImp::numberOfProperties() ); - return s; -} - -ObjectImp* TestResultImp::property( uint which, const KigDocument& d ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::property( which, d ); - if ( which == Parent::numberOfProperties() ) - return new StringImp( data() ); - else assert( false ); - return new InvalidImp; -} - -const char* TestResultImp::iconForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::iconForProperty( which ); - if ( which == Parent::numberOfProperties() ) - return ""; // test-result - else assert( false ); - return ""; -} - -const ObjectImpType* TestResultImp::impRequirementForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::impRequirementForProperty( which ); - else return TestResultImp::stype(); -} - -bool TestResultImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::impRequirementForProperty( which ); - else return false; -} - -Rect BogusImp::surroundingRect() const -{ - return Rect::invalidRect(); -} diff --git a/kig/objects/bogus_imp.cpp b/kig/objects/bogus_imp.cpp new file mode 100644 index 00000000..76d724b1 --- /dev/null +++ b/kig/objects/bogus_imp.cpp @@ -0,0 +1,388 @@ +// 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 "bogus_imp.h" + +#include +#include +#include + +#include "../misc/rect.h" + +Coordinate BogusImp::attachPoint( ) const +{ + return Coordinate::invalidCoord(); +} + +void BogusImp::draw( KigPainter& ) const +{ +} + +bool BogusImp::contains( const Coordinate&, int, const KigWidget& ) const +{ + return false; +} + +bool BogusImp::inRect( const Rect&, int, const KigWidget& ) const +{ + return false; +} + +DoubleImp::DoubleImp( const double d ) + : mdata( d ) +{ +} + +IntImp::IntImp( const int d ) + : mdata( d ) +{ +} + +StringImp::StringImp( const TQString& d ) + : mdata( d ) +{ +} + +DoubleImp* DoubleImp::copy() const +{ + return new DoubleImp( mdata ); +} + +IntImp* IntImp::copy() const +{ + return new IntImp( mdata ); +} + +StringImp* StringImp::copy() const +{ + return new StringImp( mdata ); +} + +ObjectImp* BogusImp::transform( const Transformation& ) const +{ + return copy(); +} + +InvalidImp* InvalidImp::copy() const +{ + return new InvalidImp(); +} + +InvalidImp::InvalidImp() +{ +} + +void InvalidImp::fillInNextEscape( TQString& s, const KigDocument& ) const +{ + s = s.arg( "[invalid]" ); +} + +void DoubleImp::fillInNextEscape( TQString& s, const KigDocument& ) const +{ + s = s.arg( mdata ); +} + +void IntImp::fillInNextEscape( TQString& s, const KigDocument& ) const +{ + s = s.arg( mdata ); +} + +void StringImp::fillInNextEscape( TQString& s, const KigDocument& ) const +{ + s = s.arg( mdata ); +} + +HierarchyImp::HierarchyImp( const ObjectHierarchy& h ) + : BogusImp(), mdata( h ) +{ +} + +HierarchyImp* HierarchyImp::copy() const +{ + return new HierarchyImp( mdata ); +} + +void InvalidImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +void DoubleImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +void IntImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +void StringImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +void HierarchyImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +TransformationImp::TransformationImp( const Transformation& h ) + : mdata( h ) +{ +} + +TransformationImp* TransformationImp::copy() const +{ + return new TransformationImp( mdata ); +} + +void TransformationImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +bool InvalidImp::equals( const ObjectImp& rhs ) const +{ + return !rhs.valid(); +} + +bool DoubleImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( DoubleImp::stype() ) && + static_cast( rhs ).data() == mdata; +} + +bool IntImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( IntImp::stype() ) && + static_cast( rhs ).data() == mdata; +} + +bool StringImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( StringImp::stype() ) && + static_cast( rhs ).data() == mdata; +} + +bool HierarchyImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( HierarchyImp::stype() ) && + static_cast( rhs ).data() == mdata; +} + +bool TransformationImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( TransformationImp::stype() ) && + static_cast( rhs ).data() == mdata; +} + +bool InvalidImp::canFillInNextEscape() const +{ + return true; +} + +bool DoubleImp::canFillInNextEscape() const +{ + return true; +} + +bool IntImp::canFillInNextEscape() const +{ + return true; +} + +bool StringImp::canFillInNextEscape() const +{ + return true; +} + +const ObjectImpType* InvalidImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "invalid", "", "", "", "", "", "", "", "", "" ); + return &t; +} + +const ObjectImpType* StringImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "string", + "string", "", "", "", "", "", "", "", "" ); + return &t; +} +const ObjectImpType* HierarchyImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "hierarchy", "", "", "", "", "", "", "", "", "" ); + return &t; +} +const ObjectImpType* TransformationImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "transformation", "", "", "", "", "", "", "", "", ""); + return &t; +} + +const ObjectImpType* InvalidImp::type() const +{ + return InvalidImp::stype(); +} + +const ObjectImpType* DoubleImp::type() const +{ + return DoubleImp::stype(); +} + +const ObjectImpType* IntImp::type() const +{ + return IntImp::stype(); +} + +const ObjectImpType* StringImp::type() const +{ + return StringImp::stype(); +} + +const ObjectImpType* HierarchyImp::type() const +{ + return HierarchyImp::stype(); +} + +const ObjectImpType* TransformationImp::type() const +{ + return TransformationImp::stype(); +} + +const ObjectImpType* DoubleImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "double", + "double", "", "", "", "", "", "", "", "" ); + return &t; +} + +const ObjectImpType* IntImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "int", + "int", "", "", "", "", "", "", "", "" ); + return &t; +} + +const ObjectImpType* BogusImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "bogus", + "", "", "", "", "", "", "", "", "" ); + return &t; +} + +const ObjectImpType* TestResultImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "testresult", "", "", "", "", "", "", "", "", "" ); + return &t; + +} + +TestResultImp::TestResultImp( const TQString& s ) + : mdata( s ) +{ +} + +TestResultImp* TestResultImp::copy() const +{ + return new TestResultImp( mdata ); +} + +const ObjectImpType* TestResultImp::type() const +{ + return stype(); +} + +void TestResultImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +bool TestResultImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( TestResultImp::stype() ) && + static_cast( rhs ).mdata == mdata; + +} + +const uint TestResultImp::numberOfProperties() const +{ + return Parent::numberOfProperties() + 1; +} + +const QCStringList TestResultImp::properties() const +{ + QCStringList l = Parent::properties(); + l << I18N_NOOP( "Test Result" ); + assert( l.size() == TestResultImp::numberOfProperties() ); + return l; +} + +const QCStringList TestResultImp::propertiesInternalNames() const +{ + QCStringList s = Parent::propertiesInternalNames(); + s << "test-result"; + assert( s.size() == TestResultImp::numberOfProperties() ); + return s; +} + +ObjectImp* TestResultImp::property( uint which, const KigDocument& d ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::property( which, d ); + if ( which == Parent::numberOfProperties() ) + return new StringImp( data() ); + else assert( false ); + return new InvalidImp; +} + +const char* TestResultImp::iconForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::iconForProperty( which ); + if ( which == Parent::numberOfProperties() ) + return ""; // test-result + else assert( false ); + return ""; +} + +const ObjectImpType* TestResultImp::impRequirementForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::impRequirementForProperty( which ); + else return TestResultImp::stype(); +} + +bool TestResultImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::impRequirementForProperty( which ); + else return false; +} + +Rect BogusImp::surroundingRect() const +{ + return Rect::invalidRect(); +} diff --git a/kig/objects/centerofcurvature_type.cc b/kig/objects/centerofcurvature_type.cc deleted file mode 100644 index 8111410f..00000000 --- a/kig/objects/centerofcurvature_type.cc +++ /dev/null @@ -1,304 +0,0 @@ -// Copyright (C) 2004 Maurizio Paolini - -// 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 "centerofcurvature_type.h" - -#include "bogus_imp.h" -#include "conic_imp.h" -#include "cubic_imp.h" -//#include "other_imp.h" -#include "point_imp.h" -//#include "line_imp.h" - -#include "../misc/common.h" -#include "../misc/conic-common.h" -//#include "../misc/calcpaths.h" -#include "../kig/kig_part.h" -#include "../kig/kig_view.h" - -static const char constructcenterofcurvaturepoint[] = "SHOULDNOTBESEEN"; -// I18N_NOOP( "Construct the center of curvature corresponding to this point" ); -static const char selectcoc1[] = I18N_NOOP( "Select the curve..." ); -static const char selectcoc2[] = I18N_NOOP( "Select a point on the curve..." ); - -static const ArgsParser::spec argsspecCocConic[] = -{ - { ConicImp::stype(), "SHOULDNOTBESEEN", selectcoc1, false }, - { PointImp::stype(), constructcenterofcurvaturepoint, selectcoc2, false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CocConicType ) - -CocConicType::CocConicType() - : ArgsParserObjectType( "CocConic", argsspecCocConic, 2 ) -{ -} - -CocConicType::~CocConicType() -{ -} - -const CocConicType* CocConicType::instance() -{ - static const CocConicType t; - return &t; -} - -ObjectImp* CocConicType::calc( const Args& args, const KigDocument& doc ) const -{ - if ( !margsparser.checkArgs( args ) ) - return new InvalidImp; - - const ConicImp* conic = static_cast( args[0] ); - const Coordinate& p = static_cast( args[1] )->coordinate(); - - if ( !conic->containsPoint( p, doc ) ) - return new InvalidImp; - - double x = p.x; - double y = p.y; - ConicCartesianData data = conic->cartesianData(); -// double aconst = data.coeffs[5]; - double ax = data.coeffs[3]; - double ay = data.coeffs[4]; - double axx = data.coeffs[0]; - double axy = data.coeffs[2]; - double ayy = data.coeffs[1]; - -/* - * mp: we need to compute the normal vector and the curvature - * of the curve. The curve (conic) is given in implicit form - * f(x,y) = 0; the gradient of f gives the direction of the - * normal; for the curvature we can use the following formula: - * k = div(grad f/|grad f|) - * - * the hessian matrix has elements [hfxx, hfxy] - * [hfxy, hfyy] - * - * kgf is the curvature multiplied by the norm of grad f - */ - - double gradfx = 2*axx*x + axy*y + ax; - double gradfy = axy*x + 2*ayy*y + ay; - Coordinate gradf = Coordinate ( gradfx, gradfy ); - - double hfxx = 2*axx; - double hfyy = 2*ayy; - double hfxy = axy; - - double kgf = hfxx + hfyy - - (hfxx*gradfx*gradfx + hfyy*gradfy*gradfy + 2*hfxy*gradfx*gradfy) - /(gradfx*gradfx + gradfy*gradfy); - - bool ok = true; - - const Coordinate coc = p - 1/kgf*gradf; - - if ( !ok ) - return new InvalidImp; - - return new PointImp( coc ); -} - -const ObjectImpType* CocConicType::resultId() const -{ - return PointImp::stype(); -} - -/**** Cubic starts here ****/ - -static const ArgsParser::spec argsspecCocCubic[] = -{ - { CubicImp::stype(), "SHOULDNOTBESEEN", selectcoc1, false }, - { PointImp::stype(), constructcenterofcurvaturepoint, selectcoc2, false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CocCubicType ) - -CocCubicType::CocCubicType() - : ArgsParserObjectType( "CocCubic", argsspecCocCubic, 2 ) -{ -} - -CocCubicType::~CocCubicType() -{ -} - -const CocCubicType* CocCubicType::instance() -{ - static const CocCubicType t; - return &t; -} - -ObjectImp* CocCubicType::calc( const Args& args, const KigDocument& doc ) const -{ - if ( !margsparser.checkArgs( args ) ) - return new InvalidImp; - - const CubicImp* cubic = static_cast( args[0] ); - const Coordinate& p = static_cast( args[1] )->coordinate(); - - if ( !cubic->containsPoint( p, doc ) ) - return new InvalidImp; - - double x = p.x; - double y = p.y; - CubicCartesianData data = cubic->data(); -// double aconst = data.coeffs[0]; - double ax = data.coeffs[1]; - double ay = data.coeffs[2]; - double axx = data.coeffs[3]; - double axy = data.coeffs[4]; - double ayy = data.coeffs[5]; - double axxx = data.coeffs[6]; - double axxy = data.coeffs[7]; - double axyy = data.coeffs[8]; - double ayyy = data.coeffs[9]; - - /* - * we use here the same mechanism as for the - * conics, see above - */ - - double gradfx = 3*axxx*x*x + 2*axxy*x*y + axyy*y*y + 2*axx*x + axy*y + ax; - double gradfy = axxy*x*x + 2*axyy*x*y + 3*ayyy*y*y + axy*x + 2*ayy*y + ay; - Coordinate gradf = Coordinate ( gradfx, gradfy ); - - double hfxx = 6*axxx*x + 2*axxy*y + 2*axx; - double hfyy = 6*ayyy*y + 2*axyy*x + 2*ayy; - double hfxy = 2*axxy*x + 2*axyy*y + axy; - - double kgf = hfxx + hfyy - - (hfxx*gradfx*gradfx + hfyy*gradfy*gradfy + 2*hfxy*gradfx*gradfy) - /(gradfx*gradfx + gradfy*gradfy); - - bool ok = true; - - const Coordinate coc = p - 1/kgf*gradf; - - if ( !ok ) - return new InvalidImp; - - return new PointImp( coc ); -} - -const ObjectImpType* CocCubicType::resultId() const -{ - return PointImp::stype(); -} - -/**** Curve starts here ****/ - -static const ArgsParser::spec argsspecCocCurve[] = -{ - { CurveImp::stype(), "SHOULDNOTBESEEN", selectcoc1, false }, - { PointImp::stype(), constructcenterofcurvaturepoint, selectcoc2, false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CocCurveType ) - -CocCurveType::CocCurveType() - : ArgsParserObjectType( "CocCurve", argsspecCocCurve, 2 ) -{ -} - -CocCurveType::~CocCurveType() -{ -} - -const CocCurveType* CocCurveType::instance() -{ - static const CocCurveType t; - return &t; -} - -ObjectImp* CocCurveType::calc( const Args& args, const KigDocument& doc ) const -{ - if ( !margsparser.checkArgs( args ) ) - return new InvalidImp; - - const CurveImp* curve = static_cast( args[0] ); - const Coordinate& p = static_cast( args[1] )->coordinate(); - - if ( !curve->containsPoint( p, doc ) ) - return new InvalidImp; - - - const double t = curve->getParam( p, doc ); - const double tau0 = 5e-4; - const double sigmasq = 1e-12; - const int maxiter = 20; - - double tau = tau0; - Coordinate gminus, g, gplus, tang, acc, curv, err; - double velsq, curvsq; - double tplus = t + tau; - double tminus = t - tau; - double t0 = t; - if ( tplus > 1 ) {tplus = 1; t0 = 1 - tau; tminus = 1 - 2*tau;} - if ( tminus < 0 ) {tminus = 0; t0 = tau; tplus = 2*tau;} - gminus = curve->getPoint( tminus, doc ); - g = curve->getPoint( t0, doc ); - gplus = curve->getPoint( tplus, doc ); - tang = (gplus - gminus)/(2*tau); - acc = (gminus + gplus - 2*g)/(tau*tau); - velsq = tang.x*tang.x + tang.y*tang.y; - tang = tang/velsq; - Coordinate curvold = acc/velsq - (acc.x*tang.x + acc.y*tang.y)*tang; - curvsq = curvold.x*curvold.x + curvold.y*curvold.y; - curvold = curvold/curvsq; - - for (int i = 0; i < maxiter; i++) - { - tau = tau/2; - tplus = t + tau; - tminus = t - tau; - t0 = t; - if ( tplus > 1 ) {tplus = 1; t0 = 1 - tau; tminus = 1 - 2*tau;} - if ( tminus < 0 ) {tminus = 0; t0 = tau; tplus = 2*tau;} - - gminus = curve->getPoint( tminus, doc ); - g = curve->getPoint( t0, doc ); - gplus = curve->getPoint( tplus, doc ); - tang = (gplus - gminus)/(2*tau); - acc = (gminus + gplus - 2*g)/(tau*tau); - velsq = tang.x*tang.x + tang.y*tang.y; - tang = tang/velsq; - curv = acc/velsq - (acc.x*tang.x + acc.y*tang.y)*tang; - curvsq = curv.x*curv.x + curv.y*curv.y; - curv = curv/curvsq; - - err = (curvold - curv)/3; - /* - * curvsq is the inverse squared of the norm of curvsq - * so this is actually a relative test - * in the end we return an extrapolated value - */ - if (err.squareLength() < sigmasq/curvsq) - { - curv = (4*curv - curvold)/3; - return new PointImp( p + curv ); - } - curvold = curv; - } - return new InvalidImp; -} - -const ObjectImpType* CocCurveType::resultId() const -{ - return PointImp::stype(); -} diff --git a/kig/objects/centerofcurvature_type.cpp b/kig/objects/centerofcurvature_type.cpp new file mode 100644 index 00000000..8111410f --- /dev/null +++ b/kig/objects/centerofcurvature_type.cpp @@ -0,0 +1,304 @@ +// Copyright (C) 2004 Maurizio Paolini + +// 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 "centerofcurvature_type.h" + +#include "bogus_imp.h" +#include "conic_imp.h" +#include "cubic_imp.h" +//#include "other_imp.h" +#include "point_imp.h" +//#include "line_imp.h" + +#include "../misc/common.h" +#include "../misc/conic-common.h" +//#include "../misc/calcpaths.h" +#include "../kig/kig_part.h" +#include "../kig/kig_view.h" + +static const char constructcenterofcurvaturepoint[] = "SHOULDNOTBESEEN"; +// I18N_NOOP( "Construct the center of curvature corresponding to this point" ); +static const char selectcoc1[] = I18N_NOOP( "Select the curve..." ); +static const char selectcoc2[] = I18N_NOOP( "Select a point on the curve..." ); + +static const ArgsParser::spec argsspecCocConic[] = +{ + { ConicImp::stype(), "SHOULDNOTBESEEN", selectcoc1, false }, + { PointImp::stype(), constructcenterofcurvaturepoint, selectcoc2, false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CocConicType ) + +CocConicType::CocConicType() + : ArgsParserObjectType( "CocConic", argsspecCocConic, 2 ) +{ +} + +CocConicType::~CocConicType() +{ +} + +const CocConicType* CocConicType::instance() +{ + static const CocConicType t; + return &t; +} + +ObjectImp* CocConicType::calc( const Args& args, const KigDocument& doc ) const +{ + if ( !margsparser.checkArgs( args ) ) + return new InvalidImp; + + const ConicImp* conic = static_cast( args[0] ); + const Coordinate& p = static_cast( args[1] )->coordinate(); + + if ( !conic->containsPoint( p, doc ) ) + return new InvalidImp; + + double x = p.x; + double y = p.y; + ConicCartesianData data = conic->cartesianData(); +// double aconst = data.coeffs[5]; + double ax = data.coeffs[3]; + double ay = data.coeffs[4]; + double axx = data.coeffs[0]; + double axy = data.coeffs[2]; + double ayy = data.coeffs[1]; + +/* + * mp: we need to compute the normal vector and the curvature + * of the curve. The curve (conic) is given in implicit form + * f(x,y) = 0; the gradient of f gives the direction of the + * normal; for the curvature we can use the following formula: + * k = div(grad f/|grad f|) + * + * the hessian matrix has elements [hfxx, hfxy] + * [hfxy, hfyy] + * + * kgf is the curvature multiplied by the norm of grad f + */ + + double gradfx = 2*axx*x + axy*y + ax; + double gradfy = axy*x + 2*ayy*y + ay; + Coordinate gradf = Coordinate ( gradfx, gradfy ); + + double hfxx = 2*axx; + double hfyy = 2*ayy; + double hfxy = axy; + + double kgf = hfxx + hfyy + - (hfxx*gradfx*gradfx + hfyy*gradfy*gradfy + 2*hfxy*gradfx*gradfy) + /(gradfx*gradfx + gradfy*gradfy); + + bool ok = true; + + const Coordinate coc = p - 1/kgf*gradf; + + if ( !ok ) + return new InvalidImp; + + return new PointImp( coc ); +} + +const ObjectImpType* CocConicType::resultId() const +{ + return PointImp::stype(); +} + +/**** Cubic starts here ****/ + +static const ArgsParser::spec argsspecCocCubic[] = +{ + { CubicImp::stype(), "SHOULDNOTBESEEN", selectcoc1, false }, + { PointImp::stype(), constructcenterofcurvaturepoint, selectcoc2, false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CocCubicType ) + +CocCubicType::CocCubicType() + : ArgsParserObjectType( "CocCubic", argsspecCocCubic, 2 ) +{ +} + +CocCubicType::~CocCubicType() +{ +} + +const CocCubicType* CocCubicType::instance() +{ + static const CocCubicType t; + return &t; +} + +ObjectImp* CocCubicType::calc( const Args& args, const KigDocument& doc ) const +{ + if ( !margsparser.checkArgs( args ) ) + return new InvalidImp; + + const CubicImp* cubic = static_cast( args[0] ); + const Coordinate& p = static_cast( args[1] )->coordinate(); + + if ( !cubic->containsPoint( p, doc ) ) + return new InvalidImp; + + double x = p.x; + double y = p.y; + CubicCartesianData data = cubic->data(); +// double aconst = data.coeffs[0]; + double ax = data.coeffs[1]; + double ay = data.coeffs[2]; + double axx = data.coeffs[3]; + double axy = data.coeffs[4]; + double ayy = data.coeffs[5]; + double axxx = data.coeffs[6]; + double axxy = data.coeffs[7]; + double axyy = data.coeffs[8]; + double ayyy = data.coeffs[9]; + + /* + * we use here the same mechanism as for the + * conics, see above + */ + + double gradfx = 3*axxx*x*x + 2*axxy*x*y + axyy*y*y + 2*axx*x + axy*y + ax; + double gradfy = axxy*x*x + 2*axyy*x*y + 3*ayyy*y*y + axy*x + 2*ayy*y + ay; + Coordinate gradf = Coordinate ( gradfx, gradfy ); + + double hfxx = 6*axxx*x + 2*axxy*y + 2*axx; + double hfyy = 6*ayyy*y + 2*axyy*x + 2*ayy; + double hfxy = 2*axxy*x + 2*axyy*y + axy; + + double kgf = hfxx + hfyy + - (hfxx*gradfx*gradfx + hfyy*gradfy*gradfy + 2*hfxy*gradfx*gradfy) + /(gradfx*gradfx + gradfy*gradfy); + + bool ok = true; + + const Coordinate coc = p - 1/kgf*gradf; + + if ( !ok ) + return new InvalidImp; + + return new PointImp( coc ); +} + +const ObjectImpType* CocCubicType::resultId() const +{ + return PointImp::stype(); +} + +/**** Curve starts here ****/ + +static const ArgsParser::spec argsspecCocCurve[] = +{ + { CurveImp::stype(), "SHOULDNOTBESEEN", selectcoc1, false }, + { PointImp::stype(), constructcenterofcurvaturepoint, selectcoc2, false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CocCurveType ) + +CocCurveType::CocCurveType() + : ArgsParserObjectType( "CocCurve", argsspecCocCurve, 2 ) +{ +} + +CocCurveType::~CocCurveType() +{ +} + +const CocCurveType* CocCurveType::instance() +{ + static const CocCurveType t; + return &t; +} + +ObjectImp* CocCurveType::calc( const Args& args, const KigDocument& doc ) const +{ + if ( !margsparser.checkArgs( args ) ) + return new InvalidImp; + + const CurveImp* curve = static_cast( args[0] ); + const Coordinate& p = static_cast( args[1] )->coordinate(); + + if ( !curve->containsPoint( p, doc ) ) + return new InvalidImp; + + + const double t = curve->getParam( p, doc ); + const double tau0 = 5e-4; + const double sigmasq = 1e-12; + const int maxiter = 20; + + double tau = tau0; + Coordinate gminus, g, gplus, tang, acc, curv, err; + double velsq, curvsq; + double tplus = t + tau; + double tminus = t - tau; + double t0 = t; + if ( tplus > 1 ) {tplus = 1; t0 = 1 - tau; tminus = 1 - 2*tau;} + if ( tminus < 0 ) {tminus = 0; t0 = tau; tplus = 2*tau;} + gminus = curve->getPoint( tminus, doc ); + g = curve->getPoint( t0, doc ); + gplus = curve->getPoint( tplus, doc ); + tang = (gplus - gminus)/(2*tau); + acc = (gminus + gplus - 2*g)/(tau*tau); + velsq = tang.x*tang.x + tang.y*tang.y; + tang = tang/velsq; + Coordinate curvold = acc/velsq - (acc.x*tang.x + acc.y*tang.y)*tang; + curvsq = curvold.x*curvold.x + curvold.y*curvold.y; + curvold = curvold/curvsq; + + for (int i = 0; i < maxiter; i++) + { + tau = tau/2; + tplus = t + tau; + tminus = t - tau; + t0 = t; + if ( tplus > 1 ) {tplus = 1; t0 = 1 - tau; tminus = 1 - 2*tau;} + if ( tminus < 0 ) {tminus = 0; t0 = tau; tplus = 2*tau;} + + gminus = curve->getPoint( tminus, doc ); + g = curve->getPoint( t0, doc ); + gplus = curve->getPoint( tplus, doc ); + tang = (gplus - gminus)/(2*tau); + acc = (gminus + gplus - 2*g)/(tau*tau); + velsq = tang.x*tang.x + tang.y*tang.y; + tang = tang/velsq; + curv = acc/velsq - (acc.x*tang.x + acc.y*tang.y)*tang; + curvsq = curv.x*curv.x + curv.y*curv.y; + curv = curv/curvsq; + + err = (curvold - curv)/3; + /* + * curvsq is the inverse squared of the norm of curvsq + * so this is actually a relative test + * in the end we return an extrapolated value + */ + if (err.squareLength() < sigmasq/curvsq) + { + curv = (4*curv - curvold)/3; + return new PointImp( p + curv ); + } + curvold = curv; + } + return new InvalidImp; +} + +const ObjectImpType* CocCurveType::resultId() const +{ + return PointImp::stype(); +} diff --git a/kig/objects/circle_imp.cc b/kig/objects/circle_imp.cc deleted file mode 100644 index 16b3a5b7..00000000 --- a/kig/objects/circle_imp.cc +++ /dev/null @@ -1,356 +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 "circle_imp.h" - -#include "bogus_imp.h" -#include "point_imp.h" - -#include "../misc/kigtransform.h" -#include "../misc/kigpainter.h" -#include "../misc/coordinate_system.h" - -#include "../kig/kig_document.h" -#include "../kig/kig_view.h" - -#include - -#include - -CircleImp::CircleImp( const Coordinate& center, double radius ) - : mcenter( center ), mradius( radius ) -{ -} - -CircleImp::~CircleImp() -{ -} - -ObjectImp* CircleImp::transform( const Transformation& t ) const -{ - if ( t.isHomothetic() ) - { - Coordinate nc = t.apply( mcenter ); - double nr = t.apply( mradius ); - if ( nc.valid() ) - return new CircleImp( nc, nr ); - else return new InvalidImp; - } - else - { - // domi: i should return a ConicImp here, but i don't know how to - // calculate it.. - return Parent::transform( t ); - }; -} - -void CircleImp::draw( KigPainter& p ) const -{ - p.drawCircle( mcenter, mradius ); -} - -bool CircleImp::contains( const Coordinate& p, int width, const KigWidget& w ) const -{ - return fabs((mcenter - p).length() - mradius) <= w.screenInfo().normalMiss( width ); -} - -bool CircleImp::inRect( const Rect& r, int width, const KigWidget& w ) const -{ - // first we check if the rect contains at least one of the - // north/south/east/west points of the circle - if ( r.contains( mcenter + Coordinate( 0, -mradius ) ) ) return true; - if ( r.contains( mcenter + Coordinate( mradius, 0 ) ) ) return true; - if ( r.contains( mcenter + Coordinate( 0, mradius ) ) ) return true; - if ( r.contains( mcenter + Coordinate( -mradius, 0 ) ) ) return true; - - // we allow a miss of some pixels .. - double miss = w.screenInfo().normalMiss( width ); - double bigradius = mradius + miss; - bigradius *= bigradius; - double smallradius = mradius - miss; - smallradius *= smallradius; - - const int in = -1; - const int undecided = 0; - const int out = 1; - - int inorout = undecided; - - Coordinate coords[4]; - coords[0] = r.topLeft(); - coords[1] = r.topRight(); - coords[2] = r.bottomRight(); - coords[3] = r.bottomLeft(); - - // we check if the corners of the rect are either - for ( Coordinate* i = coords; i < coords + 4; ++i ) - { - double t = ( *i - mcenter ).squareLength(); - if ( t >= bigradius ) - { - if ( inorout == in ) return true; - inorout = out; - } - else if ( t <= smallradius ) - { - if ( inorout == out ) return true; - inorout = in; - } - } - return inorout == undecided; -} - -bool CircleImp::valid() const -{ - return true; -} - -const uint CircleImp::numberOfProperties() const -{ - // We _intentionally_ do not use the Conic properties.. - return CurveImp::numberOfProperties() + 7; -} - -const QCStringList CircleImp::propertiesInternalNames() const -{ - QCStringList l = CurveImp::propertiesInternalNames(); - l << "surface"; - l << "circumference"; - l << "radius"; - l << "center"; - l << "cartesian-equation"; - l << "simply-cartesian-equation"; - l << "polar-equation"; - assert( l.size() == CircleImp::numberOfProperties() ); - return l; -} - -const QCStringList CircleImp::properties() const -{ - QCStringList l = CurveImp::properties(); - l << I18N_NOOP( "Surface" ); - l << I18N_NOOP( "Circumference" ); - l << I18N_NOOP( "Radius" ); - l << I18N_NOOP( "Center" ); - l << I18N_NOOP( "Expanded Cartesian Equation" ); - l << I18N_NOOP( "Cartesian Equation" ); - l << I18N_NOOP( "Polar Equation" ); - assert( l.size() == CircleImp::numberOfProperties() ); - return l; -} - -const ObjectImpType* CircleImp::impRequirementForProperty( uint which ) const -{ - if ( which < CurveImp::numberOfProperties() ) - return CurveImp::impRequirementForProperty( which ); - else return CircleImp::stype(); -} - -const char* CircleImp::iconForProperty( uint which ) const -{ - assert( which < CircleImp::numberOfProperties() ); - if ( which < CurveImp::numberOfProperties() ) - return CurveImp::iconForProperty( which ); - else if ( which == CurveImp::numberOfProperties() ) - return "areaCircle"; // surface - else if ( which == CurveImp::numberOfProperties() + 1 ) - return "circumference"; // circumference - else if ( which == CurveImp::numberOfProperties() + 2 ) - return ""; //radius - else if ( which == CurveImp::numberOfProperties() + 3 ) - return "baseCircle"; // circle center - else if ( which == CurveImp::numberOfProperties() + 4 ) - return "kig_text"; // cartesian equation - else if ( which == CurveImp::numberOfProperties() + 5 ) - return "kig_text"; // simply cartesian equation - else if ( which == CurveImp::numberOfProperties() + 6 ) - return "kig_text"; // polar equation - else assert( false ); - return ""; -} - -ObjectImp* CircleImp::property( uint which, const KigDocument& w ) const -{ - assert( which < CircleImp::numberOfProperties() ); - if ( which < CurveImp::numberOfProperties() ) - return CurveImp::property( which, w ); - if ( which == CurveImp::numberOfProperties() ) - return new DoubleImp( surface() ); - else if ( which == CurveImp::numberOfProperties() + 1 ) - return new DoubleImp( circumference() ); - else if ( which == CurveImp::numberOfProperties() + 2 ) - return new DoubleImp( radius() ); - else if ( which == CurveImp::numberOfProperties() + 3 ) - return new PointImp( center() ); - else if ( which == CurveImp::numberOfProperties() + 4 ) - return new StringImp( cartesianEquationString( w ) ); - else if ( which == CurveImp::numberOfProperties() + 5 ) - return new StringImp( simplyCartesianEquationString( w ) ); - else if ( which == CurveImp::numberOfProperties() + 6 ) - return new StringImp( polarEquationString( w ) ); - else assert( false ); - return new InvalidImp; -} - -const Coordinate CircleImp::center() const -{ - return mcenter; -} - -double CircleImp::radius() const -{ - return mradius; -} - -double CircleImp::surface() const -{ - return M_PI * squareRadius(); -} - -double CircleImp::squareRadius() const -{ - return mradius * mradius; -} - -double CircleImp::circumference() const -{ - return 2 * M_PI * radius(); -} - -TQString CircleImp::polarEquationString( const KigDocument& w ) const -{ - TQString ret = i18n( "rho = %1 [centered at %2]" ); - ConicPolarData data = polarData(); - ret = ret.arg( data.pdimen, 0, 'g', 3 ); - ret = ret.arg( w.coordinateSystem().fromScreen( data.focus1, w ) ); - return ret; -} - -TQString CircleImp::cartesianEquationString( const KigDocument& ) const -{ - TQString ret = i18n( "x² + y² + %1 x + %2 y + %3 = 0" ); - ConicCartesianData data = cartesianData(); - ret = ret.arg( data.coeffs[3], 0, 'g', 3 ); - ret = ret.arg( data.coeffs[4], 0, 'g', 3 ); - ret = ret.arg( data.coeffs[5], 0, 'g', 3 ); - return ret; -} - -TQString CircleImp::simplyCartesianEquationString( const KigDocument& ) const -{ - TQString ret = i18n( "( x - %1 )² + ( y - %2 )² = %3" ); - ret = ret.arg( mcenter.x, 0, 'g', 3 ); - ret = ret.arg( mcenter.y, 0, 'g', 3 ); - ret = ret.arg( mradius * mradius, 0, 'g', 3 ); - return ret; -} - -Coordinate CircleImp::focus1() const -{ - return center(); -} - -Coordinate CircleImp::focus2() const -{ - return center(); -} - -int CircleImp::conicType() const -{ - return 1; -} - -const ConicCartesianData CircleImp::cartesianData() const -{ - Coordinate c = center(); - double sqr = squareRadius(); - ConicCartesianData data( - 1.0, 1.0, 0.0, -2*c.x, -2*c.y, - c.x*c.x + c.y*c.y - sqr ); - return data; -} - -const ConicPolarData CircleImp::polarData() const -{ - return ConicPolarData( center(), radius(), 0, 0 ); -} - -CircleImp* CircleImp::copy() const -{ - return new CircleImp( mcenter, mradius ); -} - -double CircleImp::getParam( const Coordinate& point, const KigDocument& ) const -{ - Coordinate tmp = point - mcenter; - double ret = atan2(tmp.y, tmp.x) / ( 2 * M_PI ); - if ( ret > 0 ) return ret; - else return ret + 1; -} - -const Coordinate CircleImp::getPoint( double p, const KigDocument& ) const -{ - return mcenter + Coordinate (cos(p * 2 * M_PI), sin(p * 2 * M_PI)) * mradius; -} - -void CircleImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -bool CircleImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( CircleImp::stype() ) && - static_cast( rhs ).center() == center() && - static_cast( rhs ).radius() == radius(); -} - -const ObjectImpType* CircleImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "circle", - I18N_NOOP( "circle" ), - I18N_NOOP( "Select this circle" ), - I18N_NOOP( "Select circle %1" ), - I18N_NOOP( "Remove a Circle" ), - I18N_NOOP( "Add a Circle" ), - I18N_NOOP( "Move a Circle" ), - I18N_NOOP( "Attach to this circle" ), - I18N_NOOP( "Show a Circle" ), - I18N_NOOP( "Hide a Circle" ) - ); - return &t; -} - -const ObjectImpType* CircleImp::type() const -{ - return CircleImp::stype(); -} - -bool CircleImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const -{ - assert( which < CircleImp::numberOfProperties() ); - if ( which < CurveImp::numberOfProperties() ) - return CurveImp::isPropertyDefinedOnOrThroughThisImp( which ); - return false; -} - -Rect CircleImp::surroundingRect() const -{ - Coordinate d( mradius, mradius ); - return Rect( mcenter - d, mcenter + d ); -} diff --git a/kig/objects/circle_imp.cpp b/kig/objects/circle_imp.cpp new file mode 100644 index 00000000..16b3a5b7 --- /dev/null +++ b/kig/objects/circle_imp.cpp @@ -0,0 +1,356 @@ +// 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 "circle_imp.h" + +#include "bogus_imp.h" +#include "point_imp.h" + +#include "../misc/kigtransform.h" +#include "../misc/kigpainter.h" +#include "../misc/coordinate_system.h" + +#include "../kig/kig_document.h" +#include "../kig/kig_view.h" + +#include + +#include + +CircleImp::CircleImp( const Coordinate& center, double radius ) + : mcenter( center ), mradius( radius ) +{ +} + +CircleImp::~CircleImp() +{ +} + +ObjectImp* CircleImp::transform( const Transformation& t ) const +{ + if ( t.isHomothetic() ) + { + Coordinate nc = t.apply( mcenter ); + double nr = t.apply( mradius ); + if ( nc.valid() ) + return new CircleImp( nc, nr ); + else return new InvalidImp; + } + else + { + // domi: i should return a ConicImp here, but i don't know how to + // calculate it.. + return Parent::transform( t ); + }; +} + +void CircleImp::draw( KigPainter& p ) const +{ + p.drawCircle( mcenter, mradius ); +} + +bool CircleImp::contains( const Coordinate& p, int width, const KigWidget& w ) const +{ + return fabs((mcenter - p).length() - mradius) <= w.screenInfo().normalMiss( width ); +} + +bool CircleImp::inRect( const Rect& r, int width, const KigWidget& w ) const +{ + // first we check if the rect contains at least one of the + // north/south/east/west points of the circle + if ( r.contains( mcenter + Coordinate( 0, -mradius ) ) ) return true; + if ( r.contains( mcenter + Coordinate( mradius, 0 ) ) ) return true; + if ( r.contains( mcenter + Coordinate( 0, mradius ) ) ) return true; + if ( r.contains( mcenter + Coordinate( -mradius, 0 ) ) ) return true; + + // we allow a miss of some pixels .. + double miss = w.screenInfo().normalMiss( width ); + double bigradius = mradius + miss; + bigradius *= bigradius; + double smallradius = mradius - miss; + smallradius *= smallradius; + + const int in = -1; + const int undecided = 0; + const int out = 1; + + int inorout = undecided; + + Coordinate coords[4]; + coords[0] = r.topLeft(); + coords[1] = r.topRight(); + coords[2] = r.bottomRight(); + coords[3] = r.bottomLeft(); + + // we check if the corners of the rect are either + for ( Coordinate* i = coords; i < coords + 4; ++i ) + { + double t = ( *i - mcenter ).squareLength(); + if ( t >= bigradius ) + { + if ( inorout == in ) return true; + inorout = out; + } + else if ( t <= smallradius ) + { + if ( inorout == out ) return true; + inorout = in; + } + } + return inorout == undecided; +} + +bool CircleImp::valid() const +{ + return true; +} + +const uint CircleImp::numberOfProperties() const +{ + // We _intentionally_ do not use the Conic properties.. + return CurveImp::numberOfProperties() + 7; +} + +const QCStringList CircleImp::propertiesInternalNames() const +{ + QCStringList l = CurveImp::propertiesInternalNames(); + l << "surface"; + l << "circumference"; + l << "radius"; + l << "center"; + l << "cartesian-equation"; + l << "simply-cartesian-equation"; + l << "polar-equation"; + assert( l.size() == CircleImp::numberOfProperties() ); + return l; +} + +const QCStringList CircleImp::properties() const +{ + QCStringList l = CurveImp::properties(); + l << I18N_NOOP( "Surface" ); + l << I18N_NOOP( "Circumference" ); + l << I18N_NOOP( "Radius" ); + l << I18N_NOOP( "Center" ); + l << I18N_NOOP( "Expanded Cartesian Equation" ); + l << I18N_NOOP( "Cartesian Equation" ); + l << I18N_NOOP( "Polar Equation" ); + assert( l.size() == CircleImp::numberOfProperties() ); + return l; +} + +const ObjectImpType* CircleImp::impRequirementForProperty( uint which ) const +{ + if ( which < CurveImp::numberOfProperties() ) + return CurveImp::impRequirementForProperty( which ); + else return CircleImp::stype(); +} + +const char* CircleImp::iconForProperty( uint which ) const +{ + assert( which < CircleImp::numberOfProperties() ); + if ( which < CurveImp::numberOfProperties() ) + return CurveImp::iconForProperty( which ); + else if ( which == CurveImp::numberOfProperties() ) + return "areaCircle"; // surface + else if ( which == CurveImp::numberOfProperties() + 1 ) + return "circumference"; // circumference + else if ( which == CurveImp::numberOfProperties() + 2 ) + return ""; //radius + else if ( which == CurveImp::numberOfProperties() + 3 ) + return "baseCircle"; // circle center + else if ( which == CurveImp::numberOfProperties() + 4 ) + return "kig_text"; // cartesian equation + else if ( which == CurveImp::numberOfProperties() + 5 ) + return "kig_text"; // simply cartesian equation + else if ( which == CurveImp::numberOfProperties() + 6 ) + return "kig_text"; // polar equation + else assert( false ); + return ""; +} + +ObjectImp* CircleImp::property( uint which, const KigDocument& w ) const +{ + assert( which < CircleImp::numberOfProperties() ); + if ( which < CurveImp::numberOfProperties() ) + return CurveImp::property( which, w ); + if ( which == CurveImp::numberOfProperties() ) + return new DoubleImp( surface() ); + else if ( which == CurveImp::numberOfProperties() + 1 ) + return new DoubleImp( circumference() ); + else if ( which == CurveImp::numberOfProperties() + 2 ) + return new DoubleImp( radius() ); + else if ( which == CurveImp::numberOfProperties() + 3 ) + return new PointImp( center() ); + else if ( which == CurveImp::numberOfProperties() + 4 ) + return new StringImp( cartesianEquationString( w ) ); + else if ( which == CurveImp::numberOfProperties() + 5 ) + return new StringImp( simplyCartesianEquationString( w ) ); + else if ( which == CurveImp::numberOfProperties() + 6 ) + return new StringImp( polarEquationString( w ) ); + else assert( false ); + return new InvalidImp; +} + +const Coordinate CircleImp::center() const +{ + return mcenter; +} + +double CircleImp::radius() const +{ + return mradius; +} + +double CircleImp::surface() const +{ + return M_PI * squareRadius(); +} + +double CircleImp::squareRadius() const +{ + return mradius * mradius; +} + +double CircleImp::circumference() const +{ + return 2 * M_PI * radius(); +} + +TQString CircleImp::polarEquationString( const KigDocument& w ) const +{ + TQString ret = i18n( "rho = %1 [centered at %2]" ); + ConicPolarData data = polarData(); + ret = ret.arg( data.pdimen, 0, 'g', 3 ); + ret = ret.arg( w.coordinateSystem().fromScreen( data.focus1, w ) ); + return ret; +} + +TQString CircleImp::cartesianEquationString( const KigDocument& ) const +{ + TQString ret = i18n( "x² + y² + %1 x + %2 y + %3 = 0" ); + ConicCartesianData data = cartesianData(); + ret = ret.arg( data.coeffs[3], 0, 'g', 3 ); + ret = ret.arg( data.coeffs[4], 0, 'g', 3 ); + ret = ret.arg( data.coeffs[5], 0, 'g', 3 ); + return ret; +} + +TQString CircleImp::simplyCartesianEquationString( const KigDocument& ) const +{ + TQString ret = i18n( "( x - %1 )² + ( y - %2 )² = %3" ); + ret = ret.arg( mcenter.x, 0, 'g', 3 ); + ret = ret.arg( mcenter.y, 0, 'g', 3 ); + ret = ret.arg( mradius * mradius, 0, 'g', 3 ); + return ret; +} + +Coordinate CircleImp::focus1() const +{ + return center(); +} + +Coordinate CircleImp::focus2() const +{ + return center(); +} + +int CircleImp::conicType() const +{ + return 1; +} + +const ConicCartesianData CircleImp::cartesianData() const +{ + Coordinate c = center(); + double sqr = squareRadius(); + ConicCartesianData data( + 1.0, 1.0, 0.0, -2*c.x, -2*c.y, + c.x*c.x + c.y*c.y - sqr ); + return data; +} + +const ConicPolarData CircleImp::polarData() const +{ + return ConicPolarData( center(), radius(), 0, 0 ); +} + +CircleImp* CircleImp::copy() const +{ + return new CircleImp( mcenter, mradius ); +} + +double CircleImp::getParam( const Coordinate& point, const KigDocument& ) const +{ + Coordinate tmp = point - mcenter; + double ret = atan2(tmp.y, tmp.x) / ( 2 * M_PI ); + if ( ret > 0 ) return ret; + else return ret + 1; +} + +const Coordinate CircleImp::getPoint( double p, const KigDocument& ) const +{ + return mcenter + Coordinate (cos(p * 2 * M_PI), sin(p * 2 * M_PI)) * mradius; +} + +void CircleImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +bool CircleImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( CircleImp::stype() ) && + static_cast( rhs ).center() == center() && + static_cast( rhs ).radius() == radius(); +} + +const ObjectImpType* CircleImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "circle", + I18N_NOOP( "circle" ), + I18N_NOOP( "Select this circle" ), + I18N_NOOP( "Select circle %1" ), + I18N_NOOP( "Remove a Circle" ), + I18N_NOOP( "Add a Circle" ), + I18N_NOOP( "Move a Circle" ), + I18N_NOOP( "Attach to this circle" ), + I18N_NOOP( "Show a Circle" ), + I18N_NOOP( "Hide a Circle" ) + ); + return &t; +} + +const ObjectImpType* CircleImp::type() const +{ + return CircleImp::stype(); +} + +bool CircleImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const +{ + assert( which < CircleImp::numberOfProperties() ); + if ( which < CurveImp::numberOfProperties() ) + return CurveImp::isPropertyDefinedOnOrThroughThisImp( which ); + return false; +} + +Rect CircleImp::surroundingRect() const +{ + Coordinate d( mradius, mradius ); + return Rect( mcenter - d, mcenter + d ); +} diff --git a/kig/objects/circle_type.cc b/kig/objects/circle_type.cc deleted file mode 100644 index c47677ab..00000000 --- a/kig/objects/circle_type.cc +++ /dev/null @@ -1,181 +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 "circle_type.h" - -#include "circle_imp.h" -#include "bogus_imp.h" -#include "line_imp.h" -#include "point_imp.h" - -#include "../misc/common.h" - -#include - -static const char constructcirclethroughpointstat[] = I18N_NOOP( "Construct a circle through this point" ); - -static const char constructcirclewithcenterstat[] = I18N_NOOP( "Construct a circle with this center" ); - -static const ArgsParser::spec argsspecCircleBCP[] = -{ - { PointImp::stype(), constructcirclewithcenterstat, - I18N_NOOP( "Select the center of the new circle..." ), false }, - { PointImp::stype(), constructcirclethroughpointstat, - I18N_NOOP( "Select a point for the new circle to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CircleBCPType ) - -CircleBCPType::CircleBCPType() - : ObjectABType( "CircleBCP", argsspecCircleBCP, 2 ) -{ -} - -CircleBCPType::~CircleBCPType() -{ -} - -const CircleBCPType* CircleBCPType::instance() -{ - static const CircleBCPType s; - return &s; -} - -ObjectImp* CircleBCPType::calc( const Coordinate& a, const Coordinate& b ) const -{ - return new CircleImp( a, ( b - a ).length() ); -} - -const CircleBTPType* CircleBTPType::instance() -{ - static const CircleBTPType t; - return &t; -} - -static const ArgsParser::spec argsspecCircleBTP[] = -{ - { PointImp::stype(), constructcirclethroughpointstat, - I18N_NOOP( "Select a point for the new circle to go through..." ), true }, - { PointImp::stype(), constructcirclethroughpointstat, - I18N_NOOP( "Select a point for the new circle to go through..." ), true }, - { PointImp::stype(), constructcirclethroughpointstat, - I18N_NOOP( "Select a point for the new circle to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CircleBTPType ) - -CircleBTPType::CircleBTPType() - : ArgsParserObjectType( "CircleBTP", argsspecCircleBTP, 3 ) -{ -} - -CircleBTPType::~CircleBTPType() -{ -} - -ObjectImp* CircleBTPType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args, 2 ) ) return new InvalidImp; - - const Coordinate a = static_cast( args[0] )->coordinate(); - const Coordinate b = static_cast( args[1] )->coordinate(); - Coordinate c; - if ( args.size() == 3 ) - c = static_cast( args[2] )->coordinate(); - else - { - // we pick the third point so that the three points form a - // triangle with equal sides... - - // midpoint: - Coordinate m = ( b + a ) / 2; - if ( b.y != a.y ) - { - // direction of the perpend: - double d = -(b.x-a.x)/(b.y-a.y); - - // length: - // sqrt( 3 ) == tan( 60° ) == sqrt( 2^2 - 1^2 ) - double l = 1.73205080756 * (a-b).length() / 2; - - double d2 = d*d; - double l2 = l*l; - double dx = sqrt( l2 / ( d2 + 1 ) ); - double dy = sqrt( l2 * d2 / ( d2 + 1 ) ); - if( d < 0 ) dy = -dy; - - c.x = m.x + dx; - c.y = m.y + dy; - } - else - { - c.x = m.x; - c.y = m.y + ( a.x - b.x ); - }; - }; - - const Coordinate center = calcCenter( a, b, c ); - if ( center.valid() ) - return new CircleImp( center, (center - a ).length() ); - else return new InvalidImp; -} - -const ObjectImpType* CircleBCPType::resultId() const -{ - return CircleImp::stype(); -} - -const ObjectImpType* CircleBTPType::resultId() const -{ - return CircleImp::stype(); -} - -static const ArgsParser::spec argsspecCircleBPR[] = -{ - { PointImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", false }, - { DoubleImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CircleBPRType ) - -CircleBPRType::CircleBPRType() - : ArgsParserObjectType( "CircleBPR", argsspecCircleBPR, 2 ) -{ -} - -CircleBPRType::~CircleBPRType() -{ -} - -const CircleBPRType* CircleBPRType::instance() -{ - static const CircleBPRType t; - return &t; -} - -ObjectImp* CircleBPRType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - const Coordinate c = static_cast( args[0] )->coordinate(); - double r = static_cast( args[1] )->data(); - return new CircleImp( c, r ); -} - -const ObjectImpType* CircleBPRType::resultId() const -{ - return CircleImp::stype(); -} diff --git a/kig/objects/circle_type.cpp b/kig/objects/circle_type.cpp new file mode 100644 index 00000000..c47677ab --- /dev/null +++ b/kig/objects/circle_type.cpp @@ -0,0 +1,181 @@ +// 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 "circle_type.h" + +#include "circle_imp.h" +#include "bogus_imp.h" +#include "line_imp.h" +#include "point_imp.h" + +#include "../misc/common.h" + +#include + +static const char constructcirclethroughpointstat[] = I18N_NOOP( "Construct a circle through this point" ); + +static const char constructcirclewithcenterstat[] = I18N_NOOP( "Construct a circle with this center" ); + +static const ArgsParser::spec argsspecCircleBCP[] = +{ + { PointImp::stype(), constructcirclewithcenterstat, + I18N_NOOP( "Select the center of the new circle..." ), false }, + { PointImp::stype(), constructcirclethroughpointstat, + I18N_NOOP( "Select a point for the new circle to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CircleBCPType ) + +CircleBCPType::CircleBCPType() + : ObjectABType( "CircleBCP", argsspecCircleBCP, 2 ) +{ +} + +CircleBCPType::~CircleBCPType() +{ +} + +const CircleBCPType* CircleBCPType::instance() +{ + static const CircleBCPType s; + return &s; +} + +ObjectImp* CircleBCPType::calc( const Coordinate& a, const Coordinate& b ) const +{ + return new CircleImp( a, ( b - a ).length() ); +} + +const CircleBTPType* CircleBTPType::instance() +{ + static const CircleBTPType t; + return &t; +} + +static const ArgsParser::spec argsspecCircleBTP[] = +{ + { PointImp::stype(), constructcirclethroughpointstat, + I18N_NOOP( "Select a point for the new circle to go through..." ), true }, + { PointImp::stype(), constructcirclethroughpointstat, + I18N_NOOP( "Select a point for the new circle to go through..." ), true }, + { PointImp::stype(), constructcirclethroughpointstat, + I18N_NOOP( "Select a point for the new circle to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CircleBTPType ) + +CircleBTPType::CircleBTPType() + : ArgsParserObjectType( "CircleBTP", argsspecCircleBTP, 3 ) +{ +} + +CircleBTPType::~CircleBTPType() +{ +} + +ObjectImp* CircleBTPType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args, 2 ) ) return new InvalidImp; + + const Coordinate a = static_cast( args[0] )->coordinate(); + const Coordinate b = static_cast( args[1] )->coordinate(); + Coordinate c; + if ( args.size() == 3 ) + c = static_cast( args[2] )->coordinate(); + else + { + // we pick the third point so that the three points form a + // triangle with equal sides... + + // midpoint: + Coordinate m = ( b + a ) / 2; + if ( b.y != a.y ) + { + // direction of the perpend: + double d = -(b.x-a.x)/(b.y-a.y); + + // length: + // sqrt( 3 ) == tan( 60° ) == sqrt( 2^2 - 1^2 ) + double l = 1.73205080756 * (a-b).length() / 2; + + double d2 = d*d; + double l2 = l*l; + double dx = sqrt( l2 / ( d2 + 1 ) ); + double dy = sqrt( l2 * d2 / ( d2 + 1 ) ); + if( d < 0 ) dy = -dy; + + c.x = m.x + dx; + c.y = m.y + dy; + } + else + { + c.x = m.x; + c.y = m.y + ( a.x - b.x ); + }; + }; + + const Coordinate center = calcCenter( a, b, c ); + if ( center.valid() ) + return new CircleImp( center, (center - a ).length() ); + else return new InvalidImp; +} + +const ObjectImpType* CircleBCPType::resultId() const +{ + return CircleImp::stype(); +} + +const ObjectImpType* CircleBTPType::resultId() const +{ + return CircleImp::stype(); +} + +static const ArgsParser::spec argsspecCircleBPR[] = +{ + { PointImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", false }, + { DoubleImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CircleBPRType ) + +CircleBPRType::CircleBPRType() + : ArgsParserObjectType( "CircleBPR", argsspecCircleBPR, 2 ) +{ +} + +CircleBPRType::~CircleBPRType() +{ +} + +const CircleBPRType* CircleBPRType::instance() +{ + static const CircleBPRType t; + return &t; +} + +ObjectImp* CircleBPRType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + const Coordinate c = static_cast( args[0] )->coordinate(); + double r = static_cast( args[1] )->data(); + return new CircleImp( c, r ); +} + +const ObjectImpType* CircleBPRType::resultId() const +{ + return CircleImp::stype(); +} diff --git a/kig/objects/common.cc b/kig/objects/common.cc deleted file mode 100644 index 9932734c..00000000 --- a/kig/objects/common.cc +++ /dev/null @@ -1,43 +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 "common.h" -#include "object_holder.h" - -std::vector getAllCalcers( const std::vector& os ) -{ - std::set ret; - for ( std::vector::const_iterator i = os.begin(); - i != os.end(); ++i ) - { - if ( ( *i )->nameCalcer() ) - ret.insert( ( *i )->nameCalcer() ); - ret.insert( ( *i )->calcer() ); - } - return std::vector( ret.begin(), ret.end() ); -} - -std::vector getCalcers( const std::vector& os ) -{ - std::vector ret; - ret.reserve( os.size() ); - for ( std::vector::const_iterator i = os.begin(); - i != os.end(); ++i ) - ret.push_back( ( *i )->calcer() ); - return ret; -} - diff --git a/kig/objects/common.cpp b/kig/objects/common.cpp new file mode 100644 index 00000000..9932734c --- /dev/null +++ b/kig/objects/common.cpp @@ -0,0 +1,43 @@ +// 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 "common.h" +#include "object_holder.h" + +std::vector getAllCalcers( const std::vector& os ) +{ + std::set ret; + for ( std::vector::const_iterator i = os.begin(); + i != os.end(); ++i ) + { + if ( ( *i )->nameCalcer() ) + ret.insert( ( *i )->nameCalcer() ); + ret.insert( ( *i )->calcer() ); + } + return std::vector( ret.begin(), ret.end() ); +} + +std::vector getCalcers( const std::vector& os ) +{ + std::vector ret; + ret.reserve( os.size() ); + for ( std::vector::const_iterator i = os.begin(); + i != os.end(); ++i ) + ret.push_back( ( *i )->calcer() ); + return ret; +} + diff --git a/kig/objects/conic_imp.cc b/kig/objects/conic_imp.cc deleted file mode 100644 index dcbd23fd..00000000 --- a/kig/objects/conic_imp.cc +++ /dev/null @@ -1,385 +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 "conic_imp.h" - -#include "bogus_imp.h" -#include "point_imp.h" - -#include "../misc/kigpainter.h" -#include "../misc/common.h" -#include "../misc/coordinate_system.h" - -#include "../kig/kig_document.h" -#include "../kig/kig_view.h" - -#include - -ObjectImp* ConicImp::transform( const Transformation& t ) const -{ - bool valid = true; - ConicCartesianData d = calcConicTransformation( cartesianData(), t, valid ); - if ( ! valid ) return new InvalidImp; - else return new ConicImpCart( d ); -} - -void ConicImp::draw( KigPainter& p ) const -{ - p.drawCurve( this ); -} - -bool ConicImp::valid() const -{ - return true; -} - -bool ConicImp::contains( const Coordinate& o, int width, const KigWidget& w ) const -{ - return internalContainsPoint( o, w.screenInfo().normalMiss( width ) ); -} - -bool ConicImp::inRect( const Rect&, int, const KigWidget& ) const -{ - // TODO - return false; -} - -const uint ConicImp::numberOfProperties() const -{ - return Parent::numberOfProperties() + 5; -} - -const QCStringList ConicImp::propertiesInternalNames() const -{ - QCStringList l = Parent::propertiesInternalNames(); - l << "type"; - l << "first-focus"; - l << "second-focus"; - l << "cartesian-equation"; - l << "polar-equation"; - assert( l.size() == ConicImp::numberOfProperties() ); - return l; -} - -const QCStringList ConicImp::properties() const -{ - QCStringList l = Parent::properties(); - l << I18N_NOOP( "Conic Type" ); - l << I18N_NOOP( "First Focus" ); - l << I18N_NOOP( "Second Focus" ); - l << I18N_NOOP( "Cartesian Equation" ); - l << I18N_NOOP( "Polar Equation" ); - assert( l.size() == ConicImp::numberOfProperties() ); - return l; -} - -const ObjectImpType* ConicImp::impRequirementForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::impRequirementForProperty( which ); - else return ConicImp::stype(); -} - -const char* ConicImp::iconForProperty( uint which ) const -{ - int pnum = 0; - if ( which < Parent::numberOfProperties() ) - return Parent::iconForProperty( which ); - if ( which == Parent::numberOfProperties() + pnum++ ) - return "kig_text"; // conic type string - else if ( which == Parent::numberOfProperties() + pnum++ ) - return ""; // focus1 - else if ( which == Parent::numberOfProperties() + pnum++ ) - return ""; // focus2 - else if ( which == Parent::numberOfProperties() + pnum++ ) - return "kig_text"; // cartesian equation string - else if ( which == Parent::numberOfProperties() + pnum++ ) - return "kig_text"; // polar equation string - else assert( false ); - return ""; -} - -ObjectImp* ConicImp::property( uint which, const KigDocument& w ) const -{ - int pnum = 0; - - if ( which < Parent::numberOfProperties() ) - return Parent::property( which, w ); - if ( which == Parent::numberOfProperties() + pnum++ ) - return new StringImp( conicTypeString() ); - else if ( which == Parent::numberOfProperties() + pnum++ ) - return new PointImp( focus1() ); - else if ( which == Parent::numberOfProperties() + pnum++ ) - return new PointImp( focus2() ); - else if ( which == Parent::numberOfProperties() + pnum++ ) - return new StringImp( cartesianEquationString( w ) ); - else if ( which == Parent::numberOfProperties() + pnum++ ) - return new StringImp( polarEquationString( w ) ); - else assert( false ); - return new InvalidImp; -} - -double ConicImp::getParam( const Coordinate& p, const KigDocument& ) const -{ - const ConicPolarData d = polarData(); - Coordinate tmp = p - d.focus1; - double l = tmp.length(); - double theta = atan2(tmp.y, tmp.x); - double costheta = cos(theta); - double sintheta = sin(theta); - double ecosthetamtheta0 = costheta*d.ecostheta0 + sintheta*d.esintheta0; - double esinthetamtheta0 = sintheta*d.ecostheta0 - costheta*d.esintheta0; - double oneplus = 1.0 + d.ecostheta0*d.ecostheta0 + d.esintheta0*d.esintheta0; - double fact = esinthetamtheta0*(1.0 - ecosthetamtheta0)/(oneplus - 2*ecosthetamtheta0); -// fact is sin(a)*cos(a) where a is the angle between the ray from the first -// focus and the normal to the conic. We need it in order to adjust the -// angle according to the projection onto the conic of our point - double rho1 = d.pdimen / (1 - ecosthetamtheta0); - double rho2 = - d.pdimen / (1 + ecosthetamtheta0); - if (fabs(rho1 - l) < fabs(rho2 - l)) - { - theta += (rho1 - l)*fact/rho1; - return fmod(theta / ( 2 * M_PI ) + 1, 1); - } else { - theta += (rho2 - l)*fact/rho2; - return fmod(theta / ( 2 * M_PI ) + 0.5, 1); - } -} - -const Coordinate ConicImp::getPoint( double p, const KigDocument& ) const -{ - const ConicPolarData d = polarData(); - - double costheta = cos(p * 2 * M_PI); - double sintheta = sin(p * 2 * M_PI); - double rho = d.pdimen / (1 - costheta* d.ecostheta0 - sintheta* d.esintheta0); - return d.focus1 + Coordinate (costheta, sintheta) * rho; -} - -int ConicImp::conicType() const -{ - const ConicPolarData d = polarData(); - double ec = d.ecostheta0; - double es = d.esintheta0; - double esquare = ec*ec + es*es; - const double parabolamiss = 1e-3; // don't know what a good value could be - - if (esquare < 1.0 - parabolamiss) return 1; - if (esquare > 1.0 + parabolamiss) return -1; - - return 0; -} - -TQString ConicImp::conicTypeString() const -{ - switch (conicType()) - { - case 1: - return i18n("Ellipse"); - case -1: - return i18n("Hyperbola"); - case 0: - return i18n("Parabola"); - default: - assert( false ); - return ""; - } -} - -TQString ConicImp::cartesianEquationString( const KigDocument& ) const -{ - TQString ret = i18n( "%1 x² + %2 y² + %3 xy + %4 x + %5 y + %6 = 0" ); - ConicCartesianData data = cartesianData(); - ret = ret.arg( data.coeffs[0], 0, 'g', 3 ); - ret = ret.arg( data.coeffs[1], 0, 'g', 3 ); - ret = ret.arg( data.coeffs[2], 0, 'g', 3 ); - ret = ret.arg( data.coeffs[3], 0, 'g', 3 ); - ret = ret.arg( data.coeffs[4], 0, 'g', 3 ); - ret = ret.arg( data.coeffs[5], 0, 'g', 3 ); - return ret; -} - -TQString ConicImp::polarEquationString( const KigDocument& w ) const -{ - TQString ret = i18n( "rho = %1/(1 + %2 cos theta + %3 sin theta)\n [centered at %4]" ); - const ConicPolarData data = polarData(); - - ret = ret.arg( data.pdimen, 0, 'g', 3 ); - ret = ret.arg( -data.ecostheta0, 0, 'g', 3 ); - ret = ret.arg( -data.esintheta0, 0, 'g', 3 ); - - ret = ret.arg( w.coordinateSystem().fromScreen( data.focus1, w ) ); - return ret; -} - -const ConicCartesianData ConicImp::cartesianData() const -{ - return ConicCartesianData( polarData() ); -} - -Coordinate ConicImp::focus1() const -{ - return polarData().focus1; -} - -Coordinate ConicImp::focus2() const -{ - const ConicPolarData d = polarData(); - double ec = d.ecostheta0; - double es = d.esintheta0; - - double fact = 2*d.pdimen/(1 - ec*ec - es*es); - - return d.focus1 + fact*Coordinate(ec, es); -} - -const ConicPolarData ConicImpCart::polarData() const -{ - return mpolardata; -} - -const ConicCartesianData ConicImpCart::cartesianData() const -{ - return mcartdata; -} - -ConicImpCart::ConicImpCart( const ConicCartesianData& data ) - : ConicImp(), mcartdata( data ), mpolardata( data ) -{ - assert( data.valid() ); -} - -ConicImpPolar::ConicImpPolar( const ConicPolarData& data ) - : ConicImp(), mdata( data ) -{ -} - -ConicImpPolar::~ConicImpPolar() -{ -} - -const ConicPolarData ConicImpPolar::polarData() const -{ - return mdata; -} - -ConicImpCart* ConicImpCart::copy() const -{ - return new ConicImpCart( mcartdata ); -} - -ConicImpPolar* ConicImpPolar::copy() const -{ - return new ConicImpPolar( mdata ); -} - -ConicImp::ConicImp() -{ -} - -ConicImp::~ConicImp() -{ -} - -ConicImpCart::~ConicImpCart() -{ -} - -void ConicImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -bool ConicImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( ConicImp::stype() ) && - static_cast( rhs ).polarData() == polarData(); -} - -const ObjectImpType* ConicImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "conic", - I18N_NOOP( "conic" ), - I18N_NOOP( "Select this conic" ), - I18N_NOOP( "Select conic %1" ), - I18N_NOOP( "Remove a Conic" ), - I18N_NOOP( "Add a Conic" ), - I18N_NOOP( "Move a Conic" ), - I18N_NOOP( "Attach to this conic" ), - I18N_NOOP( "Show a Conic" ), - I18N_NOOP( "Hide a Conic" ) - ); - return &t; -} - -const ObjectImpType* ConicImp::type() const -{ - return ConicImp::stype(); -} - -bool ConicImp::containsPoint( const Coordinate& p, const KigDocument& ) const -{ - const ConicPolarData d = polarData(); - -// the threshold is relative to the size of the conic (mp) - return internalContainsPoint( p, test_threshold*d.pdimen ); -} - -bool ConicImp::internalContainsPoint( const Coordinate& p, double threshold ) const -{ - const ConicPolarData d = polarData(); - - Coordinate focus1 = d.focus1; - double ecostheta0 = d.ecostheta0; - double esintheta0 = d.esintheta0; - double pdimen = d.pdimen; - - Coordinate pos = p - focus1; - double len = pos.length(); - double costheta = pos.x / len; - double sintheta = pos.y / len; - - double ecosthetamtheta0 = costheta*ecostheta0 + sintheta*esintheta0; - double rho = pdimen / (1.0 - ecosthetamtheta0); - - double oneplus = 1.0 + ecostheta0*ecostheta0 + esintheta0*esintheta0; - -// fact is the cosine of the angle between the ray from the first focus -// and the normal to the conic, so that we compute the real distance - - double fact = (1.0 - ecosthetamtheta0)/sqrt(oneplus - 2*ecosthetamtheta0); - if ( fabs((len - rho)*fact) <= threshold ) return true; - rho = - pdimen / ( 1.0 + ecosthetamtheta0 ); - fact = (1.0 + ecosthetamtheta0)/sqrt(oneplus + 2*ecosthetamtheta0); - return fabs(( len - rho )*fact) <= threshold; -} - -bool ConicImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::isPropertyDefinedOnOrThroughThisImp( which ); - return false; -} - -Rect ConicImp::surroundingRect() const -{ - // it's prolly possible to calculate this ( in the case that the - // conic is limited in size ), but for now we don't. - - return Rect::invalidRect(); -} diff --git a/kig/objects/conic_imp.cpp b/kig/objects/conic_imp.cpp new file mode 100644 index 00000000..dcbd23fd --- /dev/null +++ b/kig/objects/conic_imp.cpp @@ -0,0 +1,385 @@ +// 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 "conic_imp.h" + +#include "bogus_imp.h" +#include "point_imp.h" + +#include "../misc/kigpainter.h" +#include "../misc/common.h" +#include "../misc/coordinate_system.h" + +#include "../kig/kig_document.h" +#include "../kig/kig_view.h" + +#include + +ObjectImp* ConicImp::transform( const Transformation& t ) const +{ + bool valid = true; + ConicCartesianData d = calcConicTransformation( cartesianData(), t, valid ); + if ( ! valid ) return new InvalidImp; + else return new ConicImpCart( d ); +} + +void ConicImp::draw( KigPainter& p ) const +{ + p.drawCurve( this ); +} + +bool ConicImp::valid() const +{ + return true; +} + +bool ConicImp::contains( const Coordinate& o, int width, const KigWidget& w ) const +{ + return internalContainsPoint( o, w.screenInfo().normalMiss( width ) ); +} + +bool ConicImp::inRect( const Rect&, int, const KigWidget& ) const +{ + // TODO + return false; +} + +const uint ConicImp::numberOfProperties() const +{ + return Parent::numberOfProperties() + 5; +} + +const QCStringList ConicImp::propertiesInternalNames() const +{ + QCStringList l = Parent::propertiesInternalNames(); + l << "type"; + l << "first-focus"; + l << "second-focus"; + l << "cartesian-equation"; + l << "polar-equation"; + assert( l.size() == ConicImp::numberOfProperties() ); + return l; +} + +const QCStringList ConicImp::properties() const +{ + QCStringList l = Parent::properties(); + l << I18N_NOOP( "Conic Type" ); + l << I18N_NOOP( "First Focus" ); + l << I18N_NOOP( "Second Focus" ); + l << I18N_NOOP( "Cartesian Equation" ); + l << I18N_NOOP( "Polar Equation" ); + assert( l.size() == ConicImp::numberOfProperties() ); + return l; +} + +const ObjectImpType* ConicImp::impRequirementForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::impRequirementForProperty( which ); + else return ConicImp::stype(); +} + +const char* ConicImp::iconForProperty( uint which ) const +{ + int pnum = 0; + if ( which < Parent::numberOfProperties() ) + return Parent::iconForProperty( which ); + if ( which == Parent::numberOfProperties() + pnum++ ) + return "kig_text"; // conic type string + else if ( which == Parent::numberOfProperties() + pnum++ ) + return ""; // focus1 + else if ( which == Parent::numberOfProperties() + pnum++ ) + return ""; // focus2 + else if ( which == Parent::numberOfProperties() + pnum++ ) + return "kig_text"; // cartesian equation string + else if ( which == Parent::numberOfProperties() + pnum++ ) + return "kig_text"; // polar equation string + else assert( false ); + return ""; +} + +ObjectImp* ConicImp::property( uint which, const KigDocument& w ) const +{ + int pnum = 0; + + if ( which < Parent::numberOfProperties() ) + return Parent::property( which, w ); + if ( which == Parent::numberOfProperties() + pnum++ ) + return new StringImp( conicTypeString() ); + else if ( which == Parent::numberOfProperties() + pnum++ ) + return new PointImp( focus1() ); + else if ( which == Parent::numberOfProperties() + pnum++ ) + return new PointImp( focus2() ); + else if ( which == Parent::numberOfProperties() + pnum++ ) + return new StringImp( cartesianEquationString( w ) ); + else if ( which == Parent::numberOfProperties() + pnum++ ) + return new StringImp( polarEquationString( w ) ); + else assert( false ); + return new InvalidImp; +} + +double ConicImp::getParam( const Coordinate& p, const KigDocument& ) const +{ + const ConicPolarData d = polarData(); + Coordinate tmp = p - d.focus1; + double l = tmp.length(); + double theta = atan2(tmp.y, tmp.x); + double costheta = cos(theta); + double sintheta = sin(theta); + double ecosthetamtheta0 = costheta*d.ecostheta0 + sintheta*d.esintheta0; + double esinthetamtheta0 = sintheta*d.ecostheta0 - costheta*d.esintheta0; + double oneplus = 1.0 + d.ecostheta0*d.ecostheta0 + d.esintheta0*d.esintheta0; + double fact = esinthetamtheta0*(1.0 - ecosthetamtheta0)/(oneplus - 2*ecosthetamtheta0); +// fact is sin(a)*cos(a) where a is the angle between the ray from the first +// focus and the normal to the conic. We need it in order to adjust the +// angle according to the projection onto the conic of our point + double rho1 = d.pdimen / (1 - ecosthetamtheta0); + double rho2 = - d.pdimen / (1 + ecosthetamtheta0); + if (fabs(rho1 - l) < fabs(rho2 - l)) + { + theta += (rho1 - l)*fact/rho1; + return fmod(theta / ( 2 * M_PI ) + 1, 1); + } else { + theta += (rho2 - l)*fact/rho2; + return fmod(theta / ( 2 * M_PI ) + 0.5, 1); + } +} + +const Coordinate ConicImp::getPoint( double p, const KigDocument& ) const +{ + const ConicPolarData d = polarData(); + + double costheta = cos(p * 2 * M_PI); + double sintheta = sin(p * 2 * M_PI); + double rho = d.pdimen / (1 - costheta* d.ecostheta0 - sintheta* d.esintheta0); + return d.focus1 + Coordinate (costheta, sintheta) * rho; +} + +int ConicImp::conicType() const +{ + const ConicPolarData d = polarData(); + double ec = d.ecostheta0; + double es = d.esintheta0; + double esquare = ec*ec + es*es; + const double parabolamiss = 1e-3; // don't know what a good value could be + + if (esquare < 1.0 - parabolamiss) return 1; + if (esquare > 1.0 + parabolamiss) return -1; + + return 0; +} + +TQString ConicImp::conicTypeString() const +{ + switch (conicType()) + { + case 1: + return i18n("Ellipse"); + case -1: + return i18n("Hyperbola"); + case 0: + return i18n("Parabola"); + default: + assert( false ); + return ""; + } +} + +TQString ConicImp::cartesianEquationString( const KigDocument& ) const +{ + TQString ret = i18n( "%1 x² + %2 y² + %3 xy + %4 x + %5 y + %6 = 0" ); + ConicCartesianData data = cartesianData(); + ret = ret.arg( data.coeffs[0], 0, 'g', 3 ); + ret = ret.arg( data.coeffs[1], 0, 'g', 3 ); + ret = ret.arg( data.coeffs[2], 0, 'g', 3 ); + ret = ret.arg( data.coeffs[3], 0, 'g', 3 ); + ret = ret.arg( data.coeffs[4], 0, 'g', 3 ); + ret = ret.arg( data.coeffs[5], 0, 'g', 3 ); + return ret; +} + +TQString ConicImp::polarEquationString( const KigDocument& w ) const +{ + TQString ret = i18n( "rho = %1/(1 + %2 cos theta + %3 sin theta)\n [centered at %4]" ); + const ConicPolarData data = polarData(); + + ret = ret.arg( data.pdimen, 0, 'g', 3 ); + ret = ret.arg( -data.ecostheta0, 0, 'g', 3 ); + ret = ret.arg( -data.esintheta0, 0, 'g', 3 ); + + ret = ret.arg( w.coordinateSystem().fromScreen( data.focus1, w ) ); + return ret; +} + +const ConicCartesianData ConicImp::cartesianData() const +{ + return ConicCartesianData( polarData() ); +} + +Coordinate ConicImp::focus1() const +{ + return polarData().focus1; +} + +Coordinate ConicImp::focus2() const +{ + const ConicPolarData d = polarData(); + double ec = d.ecostheta0; + double es = d.esintheta0; + + double fact = 2*d.pdimen/(1 - ec*ec - es*es); + + return d.focus1 + fact*Coordinate(ec, es); +} + +const ConicPolarData ConicImpCart::polarData() const +{ + return mpolardata; +} + +const ConicCartesianData ConicImpCart::cartesianData() const +{ + return mcartdata; +} + +ConicImpCart::ConicImpCart( const ConicCartesianData& data ) + : ConicImp(), mcartdata( data ), mpolardata( data ) +{ + assert( data.valid() ); +} + +ConicImpPolar::ConicImpPolar( const ConicPolarData& data ) + : ConicImp(), mdata( data ) +{ +} + +ConicImpPolar::~ConicImpPolar() +{ +} + +const ConicPolarData ConicImpPolar::polarData() const +{ + return mdata; +} + +ConicImpCart* ConicImpCart::copy() const +{ + return new ConicImpCart( mcartdata ); +} + +ConicImpPolar* ConicImpPolar::copy() const +{ + return new ConicImpPolar( mdata ); +} + +ConicImp::ConicImp() +{ +} + +ConicImp::~ConicImp() +{ +} + +ConicImpCart::~ConicImpCart() +{ +} + +void ConicImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +bool ConicImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( ConicImp::stype() ) && + static_cast( rhs ).polarData() == polarData(); +} + +const ObjectImpType* ConicImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "conic", + I18N_NOOP( "conic" ), + I18N_NOOP( "Select this conic" ), + I18N_NOOP( "Select conic %1" ), + I18N_NOOP( "Remove a Conic" ), + I18N_NOOP( "Add a Conic" ), + I18N_NOOP( "Move a Conic" ), + I18N_NOOP( "Attach to this conic" ), + I18N_NOOP( "Show a Conic" ), + I18N_NOOP( "Hide a Conic" ) + ); + return &t; +} + +const ObjectImpType* ConicImp::type() const +{ + return ConicImp::stype(); +} + +bool ConicImp::containsPoint( const Coordinate& p, const KigDocument& ) const +{ + const ConicPolarData d = polarData(); + +// the threshold is relative to the size of the conic (mp) + return internalContainsPoint( p, test_threshold*d.pdimen ); +} + +bool ConicImp::internalContainsPoint( const Coordinate& p, double threshold ) const +{ + const ConicPolarData d = polarData(); + + Coordinate focus1 = d.focus1; + double ecostheta0 = d.ecostheta0; + double esintheta0 = d.esintheta0; + double pdimen = d.pdimen; + + Coordinate pos = p - focus1; + double len = pos.length(); + double costheta = pos.x / len; + double sintheta = pos.y / len; + + double ecosthetamtheta0 = costheta*ecostheta0 + sintheta*esintheta0; + double rho = pdimen / (1.0 - ecosthetamtheta0); + + double oneplus = 1.0 + ecostheta0*ecostheta0 + esintheta0*esintheta0; + +// fact is the cosine of the angle between the ray from the first focus +// and the normal to the conic, so that we compute the real distance + + double fact = (1.0 - ecosthetamtheta0)/sqrt(oneplus - 2*ecosthetamtheta0); + if ( fabs((len - rho)*fact) <= threshold ) return true; + rho = - pdimen / ( 1.0 + ecosthetamtheta0 ); + fact = (1.0 + ecosthetamtheta0)/sqrt(oneplus + 2*ecosthetamtheta0); + return fabs(( len - rho )*fact) <= threshold; +} + +bool ConicImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::isPropertyDefinedOnOrThroughThisImp( which ); + return false; +} + +Rect ConicImp::surroundingRect() const +{ + // it's prolly possible to calculate this ( in the case that the + // conic is limited in size ), but for now we don't. + + return Rect::invalidRect(); +} diff --git a/kig/objects/conic_types.cc b/kig/objects/conic_types.cc deleted file mode 100644 index be94cf56..00000000 --- a/kig/objects/conic_types.cc +++ /dev/null @@ -1,689 +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 "conic_types.h" - -#include "bogus_imp.h" -#include "conic_imp.h" -#include "point_imp.h" -#include "circle_imp.h" -#include "line_imp.h" -#include "object_calcer.h" -#include "../misc/conic-common.h" -#include "../misc/common.h" -#include "../kig/kig_commands.h" -#include "../kig/kig_part.h" - -#include - -static const char conic_constructstatement[] = I18N_NOOP( "Construct a conic through this point" ); - -static const struct ArgsParser::spec argsspecConicB5P[] = -{ - { PointImp::stype(), conic_constructstatement, - I18N_NOOP( "Select a point for the new conic to go through..." ), true }, - { PointImp::stype(), conic_constructstatement, - I18N_NOOP( "Select a point for the new conic to go through..." ), true }, - { PointImp::stype(), conic_constructstatement, - I18N_NOOP( "Select a point for the new conic to go through..." ), true }, - { PointImp::stype(), conic_constructstatement, - I18N_NOOP( "Select a point for the new conic to go through..." ), true }, - { PointImp::stype(), conic_constructstatement, - I18N_NOOP( "Select a point for the new conic to go through..." ),true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicB5PType ) - -ConicB5PType::ConicB5PType() - : ArgsParserObjectType( "ConicB5P", argsspecConicB5P, 5 ) -{ -} - -ConicB5PType::~ConicB5PType() -{ -} - -ObjectImp* ConicB5PType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents, 1 ) ) return new InvalidImp; - std::vector points; - - for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) - points.push_back( static_cast( *i )->coordinate() ); - - ConicCartesianData d = - calcConicThroughPoints( points, zerotilt, parabolaifzt, ysymmetry ); - if ( d.valid() ) - return new ConicImpCart( d ); - else return new InvalidImp; -} - -const ConicB5PType* ConicB5PType::instance() -{ - static const ConicB5PType t; - return &t; -} - -static const ArgsParser::spec argsspecConicBAAP[] = -{ - { AbstractLineImp::stype(), I18N_NOOP( "Construct a conic with this asymptote" ), - I18N_NOOP( "Select the first asymptote of the new conic..." ), false }, - { AbstractLineImp::stype(), I18N_NOOP( "Construct a conic with this asymptote" ), - I18N_NOOP( "Select the second asymptote of the new conic..." ), false }, - { PointImp::stype(), I18N_NOOP( "Construct a conic through this point" ), - I18N_NOOP( "Select a point for the new conic to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicBAAPType ) - -ConicBAAPType::ConicBAAPType() - : ArgsParserObjectType( "ConicBAAP", argsspecConicBAAP, 3 ) -{ -} - -ConicBAAPType::~ConicBAAPType() -{ -} - -const ConicBAAPType* ConicBAAPType::instance() -{ - static const ConicBAAPType t; - return &t; -} - -ObjectImp* ConicBAAPType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) - return new InvalidImp; - const LineData la = static_cast( parents[0] )->data(); - const LineData lb = static_cast( parents[1] )->data(); - const Coordinate c = static_cast( parents[2] )->coordinate(); - - return new ConicImpCart( calcConicByAsymptotes( la, lb, c ) ); -} - -ObjectImp* ConicBFFPType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; - std::vector cs; - - for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) - cs.push_back( static_cast( *i )->coordinate() ); - - return new ConicImpPolar( calcConicBFFP( cs, type() ) ); -} - -ConicBFFPType::ConicBFFPType( const char* fullname, const ArgsParser::spec* spec, int n ) - : ArgsParserObjectType( fullname, spec, n ) -{ -} - -ConicBFFPType::~ConicBFFPType() -{ -} - -static const char constructellipsewithfocusstat[] = - I18N_NOOP( "Construct an ellipse with this focus" ); - -static const ArgsParser::spec argsspecEllipseBFFP[] = -{ - { PointImp::stype(), constructellipsewithfocusstat, - I18N_NOOP( "Select the first focus of the new ellipse..." ), false }, - { PointImp::stype(), constructellipsewithfocusstat, - I18N_NOOP( "Select the second focus of the new ellipse..." ), false }, - { PointImp::stype(), I18N_NOOP( "Construct an ellipse through this point" ), - I18N_NOOP( "Select a point for the new ellipse to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( EllipseBFFPType ) - -EllipseBFFPType::EllipseBFFPType() - : ConicBFFPType( "EllipseBFFP", argsspecEllipseBFFP, 3 ) -{ -} - -EllipseBFFPType::~EllipseBFFPType() -{ -} - -int EllipseBFFPType::type() const -{ - return 1; -} - -const EllipseBFFPType* EllipseBFFPType::instance() -{ - static const EllipseBFFPType t; - return &t; -} - -static const char constructhyperbolawithfocusstat[] = - I18N_NOOP( "Construct a hyperbola with this focus" ); - -static const ArgsParser::spec argsspecHyperbolaBFFP[] = -{ - { PointImp::stype(), constructhyperbolawithfocusstat, - I18N_NOOP( "Select the first focus of the new hyperbola..." ), false }, - { PointImp::stype(), constructhyperbolawithfocusstat, - I18N_NOOP( "Select the second focus of the new hyperbola..." ), false }, - { PointImp::stype(), I18N_NOOP( "Construct a hyperbola through this point" ), - I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( HyperbolaBFFPType ) - -HyperbolaBFFPType::HyperbolaBFFPType() - : ConicBFFPType( "HyperbolaBFFP", argsspecHyperbolaBFFP, 3 ) -{ -} - -HyperbolaBFFPType::~HyperbolaBFFPType() -{ -} - -const HyperbolaBFFPType* HyperbolaBFFPType::instance() -{ - static const HyperbolaBFFPType t; - return &t; -} - -int HyperbolaBFFPType::type() const -{ - return -1; -} - -const ConicBDFPType* ConicBDFPType::instance() -{ - static const ConicBDFPType t; - return &t; -} - -static const struct ArgsParser::spec argsspecConicBDFP[] = -{ - { AbstractLineImp::stype(), I18N_NOOP( "Construct a conic with this line as directrix" ), - I18N_NOOP( "Select the directrix of the new conic..." ), false }, - { PointImp::stype(), I18N_NOOP( "Construct a conic with this point as focus" ), - I18N_NOOP( "Select the focus of the new conic..." ), false }, - { PointImp::stype(), I18N_NOOP( "Construct a conic through this point" ), - I18N_NOOP( "Select a point for the new conic to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicBDFPType ) - -ConicBDFPType::ConicBDFPType() - : ArgsParserObjectType( "ConicBDFP", argsspecConicBDFP, 3 ) -{ -} - -ConicBDFPType::~ConicBDFPType() -{ -} - -ObjectImp* ConicBDFPType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; - - const LineData line = static_cast( parents[0] )->data(); - const Coordinate focus = - static_cast( parents[1] )->coordinate(); - - Coordinate point; - if ( parents.size() == 3 ) - point = static_cast( parents[2] )->coordinate(); - else - { - /* !!!! costruisci point come punto medio dell'altezza tra fuoco e d. */ - Coordinate ba = line.dir(); - Coordinate fa = focus - line.b; - double balsq = ba.x*ba.x + ba.y*ba.y; - double scal = (fa.x*ba.x + fa.y*ba.y)/balsq; - point = 0.5*(line.a + focus + scal*ba); - }; - return new ConicImpPolar( calcConicBDFP( line, focus, point ) ); -} - -static const char constructparabolathroughpointstat[] = - I18N_NOOP( "Construct a parabola through this point" ); - -static const ArgsParser::spec argsspecParabolaBTP[] = -{ - { PointImp::stype(), constructparabolathroughpointstat, - I18N_NOOP( "Select a point for the new parabola to go through..." ), true }, - { PointImp::stype(), constructparabolathroughpointstat, - I18N_NOOP( "Select a point for the new parabola to go through..." ), true }, - { PointImp::stype(), constructparabolathroughpointstat, - I18N_NOOP( "Select a point for the new parabola to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ParabolaBTPType ) - -ParabolaBTPType::ParabolaBTPType() - : ArgsParserObjectType( "ParabolaBTP", argsspecParabolaBTP, 3 ) -{ -} - -ParabolaBTPType::~ParabolaBTPType() -{ -} - -const ParabolaBTPType* ParabolaBTPType::instance() -{ - static const ParabolaBTPType t; - return &t; -} - -ObjectImp* ParabolaBTPType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; - - std::vector points; - for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) - points.push_back( static_cast( *i )->coordinate() ); - - ConicCartesianData d = - calcConicThroughPoints( points, zerotilt, parabolaifzt, ysymmetry ); - if ( d.valid() ) - return new ConicImpCart( d ); - else - return new InvalidImp; -} - -static const ArgsParser::spec argsspecConicPolarPoint[] = -{ - { ConicImp::stype(), I18N_NOOP( "Construct a polar point wrt. this conic" ), - I18N_NOOP( "Select the conic wrt. which you want to construct a polar point..." ), false }, - { AbstractLineImp::stype(), I18N_NOOP( "Construct the polar point of this line" ), - I18N_NOOP( "Select the line of which you want to construct the polar point..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicPolarPointType ) - -ConicPolarPointType::ConicPolarPointType() - : ArgsParserObjectType( "ConicPolarPoint", argsspecConicPolarPoint, 2 ) -{ -} - -ConicPolarPointType::~ConicPolarPointType() -{ -} - -const ConicPolarPointType* ConicPolarPointType::instance() -{ - static const ConicPolarPointType t; - return &t; -} - -ObjectImp* ConicPolarPointType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - const ConicCartesianData c = static_cast( parents[0] )->cartesianData(); - const LineData l = static_cast( parents[1] )->data(); - const Coordinate p = calcConicPolarPoint( c, l ); - if ( p.valid() ) return new PointImp( p ); - else return new InvalidImp; -} - -static const ArgsParser::spec argsspecConicPolarLine[] = -{ - { ConicImp::stype(), I18N_NOOP( "Construct a polar line wrt. this conic" ), - I18N_NOOP( "Select the conic wrt. which you want to construct a polar point..." ), false }, - { PointImp::stype(), I18N_NOOP( "Construct the polar line of this point" ), - I18N_NOOP( "Select the line of which you want to construct the polar point..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicPolarLineType ) - -ConicPolarLineType::ConicPolarLineType() - : ArgsParserObjectType( "ConicPolarLine", argsspecConicPolarLine, 2 ) -{ -} - -ConicPolarLineType::~ConicPolarLineType() -{ -} - -const ConicPolarLineType* ConicPolarLineType::instance() -{ - static const ConicPolarLineType t; - return &t; -} - -ObjectImp* ConicPolarLineType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - const ConicCartesianData c = static_cast( parents[0] )->cartesianData(); - const Coordinate p = static_cast( parents[1] )->coordinate(); - bool valid = true; - const LineData l = calcConicPolarLine( c, p, valid ); - if ( valid ) return new LineImp( l ); - else return new InvalidImp; -} - -static const ArgsParser::spec argsspecConicDirectrix[] = -{ - { ConicImp::stype(), I18N_NOOP( "Construct the directrix of this conic" ), - I18N_NOOP( "Select the conic of which you want to construct the directrix..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicDirectrixType ) - -ConicDirectrixType::ConicDirectrixType() - : ArgsParserObjectType( "ConicDirectrix", argsspecConicDirectrix, 1 ) -{ -} - -ConicDirectrixType::~ConicDirectrixType() -{ -} - -const ConicDirectrixType* ConicDirectrixType::instance() -{ - static const ConicDirectrixType t; - return &t; -} - -ObjectImp* ConicDirectrixType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - const ConicPolarData data = - static_cast( parents[0] )->polarData(); - - double ec = data.ecostheta0; - double es = data.esintheta0; - double eccsq = ec*ec + es*es; - - Coordinate a = data.focus1 - data.pdimen/eccsq*Coordinate(ec,es); - Coordinate b = a + Coordinate(-es,ec); - return new LineImp( a, b ); -} - -static const char hyperbolatpstatement[] = I18N_NOOP( "Construct a hyperbola through this point" ); - -static const ArgsParser::spec argsspecHyperbolaB4P[] = -{ - { PointImp::stype(), hyperbolatpstatement, - I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true }, - { PointImp::stype(), hyperbolatpstatement, - I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true }, - { PointImp::stype(), hyperbolatpstatement, - I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true }, - { PointImp::stype(), hyperbolatpstatement, - I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( EquilateralHyperbolaB4PType ) - -EquilateralHyperbolaB4PType::EquilateralHyperbolaB4PType() - : ArgsParserObjectType( "EquilateralHyperbolaB4P", argsspecHyperbolaB4P, 4 ) -{ -} - -EquilateralHyperbolaB4PType::~EquilateralHyperbolaB4PType() -{ -} - -const EquilateralHyperbolaB4PType* EquilateralHyperbolaB4PType::instance() -{ - static const EquilateralHyperbolaB4PType t; - return &t; -} - -ObjectImp* EquilateralHyperbolaB4PType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents, 1 ) ) return new InvalidImp; - - std::vector pts; - for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) - pts.push_back( static_cast( *i )->coordinate() ); - - ConicCartesianData d = calcConicThroughPoints( pts, equilateral ); - if ( d.valid() ) - return new ConicImpCart( d ); - else - return new InvalidImp; -} - -static const ArgsParser::spec argsspecParabolaBDP[] = -{ - { AbstractLineImp::stype(), I18N_NOOP( "Construct a parabola with this directrix" ), - I18N_NOOP( "Select the directrix of the new parabola..." ), false }, - { PointImp::stype(), I18N_NOOP( "Construct a parabola with this focus" ), - I18N_NOOP( "Select the focus of the new parabola..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ParabolaBDPType ) - -ParabolaBDPType::ParabolaBDPType() - : ObjectLPType( "ParabolaBDP", argsspecParabolaBDP, 2 ) -{ -} - -ParabolaBDPType::~ParabolaBDPType() -{ -} - -const ParabolaBDPType* ParabolaBDPType::instance() -{ - static const ParabolaBDPType t; - return &t; -} - -ObjectImp* ParabolaBDPType::calc( const LineData& l, const Coordinate& c ) const -{ - ConicPolarData ret; - Coordinate ldir = l.dir(); - ldir = ldir.normalize(); - ret.focus1 = c; - ret.ecostheta0 = - ldir.y; - ret.esintheta0 = ldir.x; - Coordinate fa = c - l.a; - ret.pdimen = fa.y*ldir.x - fa.x*ldir.y; - ConicImpPolar* r = new ConicImpPolar( ret ); - kdDebug() << k_funcinfo << r->conicTypeString() << endl; - return r; -} - -static const ArgsParser::spec argsspecConicAsymptote[] = -{ - { ConicImp::stype(), I18N_NOOP( "Construct the asymptotes of this conic" ), - I18N_NOOP( "Select the conic of which you want to construct the asymptotes..." ), false }, - { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicAsymptoteType ) - -ConicAsymptoteType::ConicAsymptoteType() - : ArgsParserObjectType( "ConicAsymptote", argsspecConicAsymptote, 2 ) -{ -} - -ConicAsymptoteType::~ConicAsymptoteType() -{ -} - -const ConicAsymptoteType* ConicAsymptoteType::instance() -{ - static const ConicAsymptoteType t; - return &t; -} - -ObjectImp* ConicAsymptoteType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - bool valid = true; - const LineData ret = calcConicAsymptote( - static_cast( parents[0] )->cartesianData(), - static_cast( parents[1] )->data(), - valid ); - - if ( valid ) - return new LineImp( ret ); - else - return new InvalidImp; -} - -static const char radicallinesstatement[] = I18N_NOOP( "Construct the radical lines of this conic" ); - -static const ArgsParser::spec argsspecConicRadical[] = -{ - { ConicImp::stype(), radicallinesstatement, - I18N_NOOP( "Select the first of the two conics of which you want to construct the radical line..." ), false }, - { ConicImp::stype(), radicallinesstatement, - I18N_NOOP( "Select the other of the two conic of which you want to construct the radical line..." ), false }, - { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false }, - { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicRadicalType ) - -ConicRadicalType::ConicRadicalType() - : ArgsParserObjectType( "ConicRadical", argsspecConicRadical, 4 ) -{ -} - -const ConicRadicalType* ConicRadicalType::instance() -{ - static const ConicRadicalType t; - return &t; -} - -ObjectImp* ConicRadicalType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - if ( parents[0]->inherits( CircleImp::stype() ) && - parents[1]->inherits( CircleImp::stype() ) ) - { - if( static_cast( parents[2] )->data() != 1 ) - return new InvalidImp; - else - { - const CircleImp* c1 = static_cast( parents[0] ); - const CircleImp* c2 = static_cast( parents[1] ); - const Coordinate a = calcCircleRadicalStartPoint( - c1->center(), c2->center(), c1->squareRadius(), c2->squareRadius() - ); - return new LineImp( a, calcPointOnPerpend( - LineData( c1->center(), c2->center() ), a ) ); - }; - } - else - { - bool valid = true; - const LineData l = calcConicRadical( - static_cast( parents[0] )->cartesianData(), - static_cast( parents[1] )->cartesianData(), - static_cast( parents[2] )->data(), - static_cast( parents[3] )->data(), valid ); - if ( valid ) - return new LineImp( l ); - else - return new InvalidImp; - }; -} - -ConicRadicalType::~ConicRadicalType() -{ -} - -const ObjectImpType* ConicB5PType::resultId() const -{ - return ConicImp::stype(); -} - -const ObjectImpType* ConicBAAPType::resultId() const -{ - return ConicImp::stype(); -} - -const ObjectImpType* ConicBFFPType::resultId() const -{ - return ConicImp::stype(); -} - -const ObjectImpType* ConicBDFPType::resultId() const -{ - return ConicImp::stype(); -} - -const ObjectImpType* ParabolaBTPType::resultId() const -{ - return ConicImp::stype(); -} - -const ObjectImpType* EquilateralHyperbolaB4PType::resultId() const -{ - return ConicImp::stype(); -} - -const ObjectImpType* ConicPolarPointType::resultId() const -{ - return PointImp::stype(); -} - -const ObjectImpType* ConicPolarLineType::resultId() const -{ - return LineImp::stype(); -} - -const ObjectImpType* ConicDirectrixType::resultId() const -{ - return LineImp::stype(); -} - -const ObjectImpType* ParabolaBDPType::resultId() const -{ - return ConicImp::stype(); -} - -const ObjectImpType* ConicAsymptoteType::resultId() const -{ - return LineImp::stype(); -} - -const ObjectImpType* ConicRadicalType::resultId() const -{ - return LineImp::stype(); -} - -TQStringList ConicRadicalType::specialActions() const -{ - TQStringList ret; - ret << i18n( "Switch Radical Lines" ); - return ret; -} - -void ConicRadicalType::executeAction( int i, ObjectHolder&, ObjectTypeCalcer& t, - KigPart& d, KigWidget&, NormalMode& ) const -{ - assert( i == 0 ); - std::vector parents = t.parents(); - assert( dynamic_cast( parents[3] ) ); - ObjectConstCalcer* zeroindexo = static_cast( parents[3] ); - MonitorDataObjects mon( zeroindexo ); - assert( zeroindexo->imp()->inherits( IntImp::stype() ) ); - int oldzeroindex = static_cast( zeroindexo->imp() )->data(); - int newzeroindex = oldzeroindex % 3 + 1; - zeroindexo->setImp( new IntImp( newzeroindex ) ); - KigCommand* kc = new KigCommand( d, "Switch Conic Radical Lines" ); - mon.finish( kc ); - d.history()->addCommand( kc ); -} - diff --git a/kig/objects/conic_types.cpp b/kig/objects/conic_types.cpp new file mode 100644 index 00000000..be94cf56 --- /dev/null +++ b/kig/objects/conic_types.cpp @@ -0,0 +1,689 @@ +// 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 "conic_types.h" + +#include "bogus_imp.h" +#include "conic_imp.h" +#include "point_imp.h" +#include "circle_imp.h" +#include "line_imp.h" +#include "object_calcer.h" +#include "../misc/conic-common.h" +#include "../misc/common.h" +#include "../kig/kig_commands.h" +#include "../kig/kig_part.h" + +#include + +static const char conic_constructstatement[] = I18N_NOOP( "Construct a conic through this point" ); + +static const struct ArgsParser::spec argsspecConicB5P[] = +{ + { PointImp::stype(), conic_constructstatement, + I18N_NOOP( "Select a point for the new conic to go through..." ), true }, + { PointImp::stype(), conic_constructstatement, + I18N_NOOP( "Select a point for the new conic to go through..." ), true }, + { PointImp::stype(), conic_constructstatement, + I18N_NOOP( "Select a point for the new conic to go through..." ), true }, + { PointImp::stype(), conic_constructstatement, + I18N_NOOP( "Select a point for the new conic to go through..." ), true }, + { PointImp::stype(), conic_constructstatement, + I18N_NOOP( "Select a point for the new conic to go through..." ),true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicB5PType ) + +ConicB5PType::ConicB5PType() + : ArgsParserObjectType( "ConicB5P", argsspecConicB5P, 5 ) +{ +} + +ConicB5PType::~ConicB5PType() +{ +} + +ObjectImp* ConicB5PType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents, 1 ) ) return new InvalidImp; + std::vector points; + + for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) + points.push_back( static_cast( *i )->coordinate() ); + + ConicCartesianData d = + calcConicThroughPoints( points, zerotilt, parabolaifzt, ysymmetry ); + if ( d.valid() ) + return new ConicImpCart( d ); + else return new InvalidImp; +} + +const ConicB5PType* ConicB5PType::instance() +{ + static const ConicB5PType t; + return &t; +} + +static const ArgsParser::spec argsspecConicBAAP[] = +{ + { AbstractLineImp::stype(), I18N_NOOP( "Construct a conic with this asymptote" ), + I18N_NOOP( "Select the first asymptote of the new conic..." ), false }, + { AbstractLineImp::stype(), I18N_NOOP( "Construct a conic with this asymptote" ), + I18N_NOOP( "Select the second asymptote of the new conic..." ), false }, + { PointImp::stype(), I18N_NOOP( "Construct a conic through this point" ), + I18N_NOOP( "Select a point for the new conic to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicBAAPType ) + +ConicBAAPType::ConicBAAPType() + : ArgsParserObjectType( "ConicBAAP", argsspecConicBAAP, 3 ) +{ +} + +ConicBAAPType::~ConicBAAPType() +{ +} + +const ConicBAAPType* ConicBAAPType::instance() +{ + static const ConicBAAPType t; + return &t; +} + +ObjectImp* ConicBAAPType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) + return new InvalidImp; + const LineData la = static_cast( parents[0] )->data(); + const LineData lb = static_cast( parents[1] )->data(); + const Coordinate c = static_cast( parents[2] )->coordinate(); + + return new ConicImpCart( calcConicByAsymptotes( la, lb, c ) ); +} + +ObjectImp* ConicBFFPType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; + std::vector cs; + + for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) + cs.push_back( static_cast( *i )->coordinate() ); + + return new ConicImpPolar( calcConicBFFP( cs, type() ) ); +} + +ConicBFFPType::ConicBFFPType( const char* fullname, const ArgsParser::spec* spec, int n ) + : ArgsParserObjectType( fullname, spec, n ) +{ +} + +ConicBFFPType::~ConicBFFPType() +{ +} + +static const char constructellipsewithfocusstat[] = + I18N_NOOP( "Construct an ellipse with this focus" ); + +static const ArgsParser::spec argsspecEllipseBFFP[] = +{ + { PointImp::stype(), constructellipsewithfocusstat, + I18N_NOOP( "Select the first focus of the new ellipse..." ), false }, + { PointImp::stype(), constructellipsewithfocusstat, + I18N_NOOP( "Select the second focus of the new ellipse..." ), false }, + { PointImp::stype(), I18N_NOOP( "Construct an ellipse through this point" ), + I18N_NOOP( "Select a point for the new ellipse to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( EllipseBFFPType ) + +EllipseBFFPType::EllipseBFFPType() + : ConicBFFPType( "EllipseBFFP", argsspecEllipseBFFP, 3 ) +{ +} + +EllipseBFFPType::~EllipseBFFPType() +{ +} + +int EllipseBFFPType::type() const +{ + return 1; +} + +const EllipseBFFPType* EllipseBFFPType::instance() +{ + static const EllipseBFFPType t; + return &t; +} + +static const char constructhyperbolawithfocusstat[] = + I18N_NOOP( "Construct a hyperbola with this focus" ); + +static const ArgsParser::spec argsspecHyperbolaBFFP[] = +{ + { PointImp::stype(), constructhyperbolawithfocusstat, + I18N_NOOP( "Select the first focus of the new hyperbola..." ), false }, + { PointImp::stype(), constructhyperbolawithfocusstat, + I18N_NOOP( "Select the second focus of the new hyperbola..." ), false }, + { PointImp::stype(), I18N_NOOP( "Construct a hyperbola through this point" ), + I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( HyperbolaBFFPType ) + +HyperbolaBFFPType::HyperbolaBFFPType() + : ConicBFFPType( "HyperbolaBFFP", argsspecHyperbolaBFFP, 3 ) +{ +} + +HyperbolaBFFPType::~HyperbolaBFFPType() +{ +} + +const HyperbolaBFFPType* HyperbolaBFFPType::instance() +{ + static const HyperbolaBFFPType t; + return &t; +} + +int HyperbolaBFFPType::type() const +{ + return -1; +} + +const ConicBDFPType* ConicBDFPType::instance() +{ + static const ConicBDFPType t; + return &t; +} + +static const struct ArgsParser::spec argsspecConicBDFP[] = +{ + { AbstractLineImp::stype(), I18N_NOOP( "Construct a conic with this line as directrix" ), + I18N_NOOP( "Select the directrix of the new conic..." ), false }, + { PointImp::stype(), I18N_NOOP( "Construct a conic with this point as focus" ), + I18N_NOOP( "Select the focus of the new conic..." ), false }, + { PointImp::stype(), I18N_NOOP( "Construct a conic through this point" ), + I18N_NOOP( "Select a point for the new conic to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicBDFPType ) + +ConicBDFPType::ConicBDFPType() + : ArgsParserObjectType( "ConicBDFP", argsspecConicBDFP, 3 ) +{ +} + +ConicBDFPType::~ConicBDFPType() +{ +} + +ObjectImp* ConicBDFPType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; + + const LineData line = static_cast( parents[0] )->data(); + const Coordinate focus = + static_cast( parents[1] )->coordinate(); + + Coordinate point; + if ( parents.size() == 3 ) + point = static_cast( parents[2] )->coordinate(); + else + { + /* !!!! costruisci point come punto medio dell'altezza tra fuoco e d. */ + Coordinate ba = line.dir(); + Coordinate fa = focus - line.b; + double balsq = ba.x*ba.x + ba.y*ba.y; + double scal = (fa.x*ba.x + fa.y*ba.y)/balsq; + point = 0.5*(line.a + focus + scal*ba); + }; + return new ConicImpPolar( calcConicBDFP( line, focus, point ) ); +} + +static const char constructparabolathroughpointstat[] = + I18N_NOOP( "Construct a parabola through this point" ); + +static const ArgsParser::spec argsspecParabolaBTP[] = +{ + { PointImp::stype(), constructparabolathroughpointstat, + I18N_NOOP( "Select a point for the new parabola to go through..." ), true }, + { PointImp::stype(), constructparabolathroughpointstat, + I18N_NOOP( "Select a point for the new parabola to go through..." ), true }, + { PointImp::stype(), constructparabolathroughpointstat, + I18N_NOOP( "Select a point for the new parabola to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ParabolaBTPType ) + +ParabolaBTPType::ParabolaBTPType() + : ArgsParserObjectType( "ParabolaBTP", argsspecParabolaBTP, 3 ) +{ +} + +ParabolaBTPType::~ParabolaBTPType() +{ +} + +const ParabolaBTPType* ParabolaBTPType::instance() +{ + static const ParabolaBTPType t; + return &t; +} + +ObjectImp* ParabolaBTPType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; + + std::vector points; + for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) + points.push_back( static_cast( *i )->coordinate() ); + + ConicCartesianData d = + calcConicThroughPoints( points, zerotilt, parabolaifzt, ysymmetry ); + if ( d.valid() ) + return new ConicImpCart( d ); + else + return new InvalidImp; +} + +static const ArgsParser::spec argsspecConicPolarPoint[] = +{ + { ConicImp::stype(), I18N_NOOP( "Construct a polar point wrt. this conic" ), + I18N_NOOP( "Select the conic wrt. which you want to construct a polar point..." ), false }, + { AbstractLineImp::stype(), I18N_NOOP( "Construct the polar point of this line" ), + I18N_NOOP( "Select the line of which you want to construct the polar point..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicPolarPointType ) + +ConicPolarPointType::ConicPolarPointType() + : ArgsParserObjectType( "ConicPolarPoint", argsspecConicPolarPoint, 2 ) +{ +} + +ConicPolarPointType::~ConicPolarPointType() +{ +} + +const ConicPolarPointType* ConicPolarPointType::instance() +{ + static const ConicPolarPointType t; + return &t; +} + +ObjectImp* ConicPolarPointType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + const ConicCartesianData c = static_cast( parents[0] )->cartesianData(); + const LineData l = static_cast( parents[1] )->data(); + const Coordinate p = calcConicPolarPoint( c, l ); + if ( p.valid() ) return new PointImp( p ); + else return new InvalidImp; +} + +static const ArgsParser::spec argsspecConicPolarLine[] = +{ + { ConicImp::stype(), I18N_NOOP( "Construct a polar line wrt. this conic" ), + I18N_NOOP( "Select the conic wrt. which you want to construct a polar point..." ), false }, + { PointImp::stype(), I18N_NOOP( "Construct the polar line of this point" ), + I18N_NOOP( "Select the line of which you want to construct the polar point..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicPolarLineType ) + +ConicPolarLineType::ConicPolarLineType() + : ArgsParserObjectType( "ConicPolarLine", argsspecConicPolarLine, 2 ) +{ +} + +ConicPolarLineType::~ConicPolarLineType() +{ +} + +const ConicPolarLineType* ConicPolarLineType::instance() +{ + static const ConicPolarLineType t; + return &t; +} + +ObjectImp* ConicPolarLineType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + const ConicCartesianData c = static_cast( parents[0] )->cartesianData(); + const Coordinate p = static_cast( parents[1] )->coordinate(); + bool valid = true; + const LineData l = calcConicPolarLine( c, p, valid ); + if ( valid ) return new LineImp( l ); + else return new InvalidImp; +} + +static const ArgsParser::spec argsspecConicDirectrix[] = +{ + { ConicImp::stype(), I18N_NOOP( "Construct the directrix of this conic" ), + I18N_NOOP( "Select the conic of which you want to construct the directrix..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicDirectrixType ) + +ConicDirectrixType::ConicDirectrixType() + : ArgsParserObjectType( "ConicDirectrix", argsspecConicDirectrix, 1 ) +{ +} + +ConicDirectrixType::~ConicDirectrixType() +{ +} + +const ConicDirectrixType* ConicDirectrixType::instance() +{ + static const ConicDirectrixType t; + return &t; +} + +ObjectImp* ConicDirectrixType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + const ConicPolarData data = + static_cast( parents[0] )->polarData(); + + double ec = data.ecostheta0; + double es = data.esintheta0; + double eccsq = ec*ec + es*es; + + Coordinate a = data.focus1 - data.pdimen/eccsq*Coordinate(ec,es); + Coordinate b = a + Coordinate(-es,ec); + return new LineImp( a, b ); +} + +static const char hyperbolatpstatement[] = I18N_NOOP( "Construct a hyperbola through this point" ); + +static const ArgsParser::spec argsspecHyperbolaB4P[] = +{ + { PointImp::stype(), hyperbolatpstatement, + I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true }, + { PointImp::stype(), hyperbolatpstatement, + I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true }, + { PointImp::stype(), hyperbolatpstatement, + I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true }, + { PointImp::stype(), hyperbolatpstatement, + I18N_NOOP( "Select a point for the new hyperbola to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( EquilateralHyperbolaB4PType ) + +EquilateralHyperbolaB4PType::EquilateralHyperbolaB4PType() + : ArgsParserObjectType( "EquilateralHyperbolaB4P", argsspecHyperbolaB4P, 4 ) +{ +} + +EquilateralHyperbolaB4PType::~EquilateralHyperbolaB4PType() +{ +} + +const EquilateralHyperbolaB4PType* EquilateralHyperbolaB4PType::instance() +{ + static const EquilateralHyperbolaB4PType t; + return &t; +} + +ObjectImp* EquilateralHyperbolaB4PType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents, 1 ) ) return new InvalidImp; + + std::vector pts; + for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) + pts.push_back( static_cast( *i )->coordinate() ); + + ConicCartesianData d = calcConicThroughPoints( pts, equilateral ); + if ( d.valid() ) + return new ConicImpCart( d ); + else + return new InvalidImp; +} + +static const ArgsParser::spec argsspecParabolaBDP[] = +{ + { AbstractLineImp::stype(), I18N_NOOP( "Construct a parabola with this directrix" ), + I18N_NOOP( "Select the directrix of the new parabola..." ), false }, + { PointImp::stype(), I18N_NOOP( "Construct a parabola with this focus" ), + I18N_NOOP( "Select the focus of the new parabola..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ParabolaBDPType ) + +ParabolaBDPType::ParabolaBDPType() + : ObjectLPType( "ParabolaBDP", argsspecParabolaBDP, 2 ) +{ +} + +ParabolaBDPType::~ParabolaBDPType() +{ +} + +const ParabolaBDPType* ParabolaBDPType::instance() +{ + static const ParabolaBDPType t; + return &t; +} + +ObjectImp* ParabolaBDPType::calc( const LineData& l, const Coordinate& c ) const +{ + ConicPolarData ret; + Coordinate ldir = l.dir(); + ldir = ldir.normalize(); + ret.focus1 = c; + ret.ecostheta0 = - ldir.y; + ret.esintheta0 = ldir.x; + Coordinate fa = c - l.a; + ret.pdimen = fa.y*ldir.x - fa.x*ldir.y; + ConicImpPolar* r = new ConicImpPolar( ret ); + kdDebug() << k_funcinfo << r->conicTypeString() << endl; + return r; +} + +static const ArgsParser::spec argsspecConicAsymptote[] = +{ + { ConicImp::stype(), I18N_NOOP( "Construct the asymptotes of this conic" ), + I18N_NOOP( "Select the conic of which you want to construct the asymptotes..." ), false }, + { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicAsymptoteType ) + +ConicAsymptoteType::ConicAsymptoteType() + : ArgsParserObjectType( "ConicAsymptote", argsspecConicAsymptote, 2 ) +{ +} + +ConicAsymptoteType::~ConicAsymptoteType() +{ +} + +const ConicAsymptoteType* ConicAsymptoteType::instance() +{ + static const ConicAsymptoteType t; + return &t; +} + +ObjectImp* ConicAsymptoteType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + bool valid = true; + const LineData ret = calcConicAsymptote( + static_cast( parents[0] )->cartesianData(), + static_cast( parents[1] )->data(), + valid ); + + if ( valid ) + return new LineImp( ret ); + else + return new InvalidImp; +} + +static const char radicallinesstatement[] = I18N_NOOP( "Construct the radical lines of this conic" ); + +static const ArgsParser::spec argsspecConicRadical[] = +{ + { ConicImp::stype(), radicallinesstatement, + I18N_NOOP( "Select the first of the two conics of which you want to construct the radical line..." ), false }, + { ConicImp::stype(), radicallinesstatement, + I18N_NOOP( "Select the other of the two conic of which you want to construct the radical line..." ), false }, + { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false }, + { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicRadicalType ) + +ConicRadicalType::ConicRadicalType() + : ArgsParserObjectType( "ConicRadical", argsspecConicRadical, 4 ) +{ +} + +const ConicRadicalType* ConicRadicalType::instance() +{ + static const ConicRadicalType t; + return &t; +} + +ObjectImp* ConicRadicalType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + if ( parents[0]->inherits( CircleImp::stype() ) && + parents[1]->inherits( CircleImp::stype() ) ) + { + if( static_cast( parents[2] )->data() != 1 ) + return new InvalidImp; + else + { + const CircleImp* c1 = static_cast( parents[0] ); + const CircleImp* c2 = static_cast( parents[1] ); + const Coordinate a = calcCircleRadicalStartPoint( + c1->center(), c2->center(), c1->squareRadius(), c2->squareRadius() + ); + return new LineImp( a, calcPointOnPerpend( + LineData( c1->center(), c2->center() ), a ) ); + }; + } + else + { + bool valid = true; + const LineData l = calcConicRadical( + static_cast( parents[0] )->cartesianData(), + static_cast( parents[1] )->cartesianData(), + static_cast( parents[2] )->data(), + static_cast( parents[3] )->data(), valid ); + if ( valid ) + return new LineImp( l ); + else + return new InvalidImp; + }; +} + +ConicRadicalType::~ConicRadicalType() +{ +} + +const ObjectImpType* ConicB5PType::resultId() const +{ + return ConicImp::stype(); +} + +const ObjectImpType* ConicBAAPType::resultId() const +{ + return ConicImp::stype(); +} + +const ObjectImpType* ConicBFFPType::resultId() const +{ + return ConicImp::stype(); +} + +const ObjectImpType* ConicBDFPType::resultId() const +{ + return ConicImp::stype(); +} + +const ObjectImpType* ParabolaBTPType::resultId() const +{ + return ConicImp::stype(); +} + +const ObjectImpType* EquilateralHyperbolaB4PType::resultId() const +{ + return ConicImp::stype(); +} + +const ObjectImpType* ConicPolarPointType::resultId() const +{ + return PointImp::stype(); +} + +const ObjectImpType* ConicPolarLineType::resultId() const +{ + return LineImp::stype(); +} + +const ObjectImpType* ConicDirectrixType::resultId() const +{ + return LineImp::stype(); +} + +const ObjectImpType* ParabolaBDPType::resultId() const +{ + return ConicImp::stype(); +} + +const ObjectImpType* ConicAsymptoteType::resultId() const +{ + return LineImp::stype(); +} + +const ObjectImpType* ConicRadicalType::resultId() const +{ + return LineImp::stype(); +} + +TQStringList ConicRadicalType::specialActions() const +{ + TQStringList ret; + ret << i18n( "Switch Radical Lines" ); + return ret; +} + +void ConicRadicalType::executeAction( int i, ObjectHolder&, ObjectTypeCalcer& t, + KigPart& d, KigWidget&, NormalMode& ) const +{ + assert( i == 0 ); + std::vector parents = t.parents(); + assert( dynamic_cast( parents[3] ) ); + ObjectConstCalcer* zeroindexo = static_cast( parents[3] ); + MonitorDataObjects mon( zeroindexo ); + assert( zeroindexo->imp()->inherits( IntImp::stype() ) ); + int oldzeroindex = static_cast( zeroindexo->imp() )->data(); + int newzeroindex = oldzeroindex % 3 + 1; + zeroindexo->setImp( new IntImp( newzeroindex ) ); + KigCommand* kc = new KigCommand( d, "Switch Conic Radical Lines" ); + mon.finish( kc ); + d.history()->addCommand( kc ); +} + diff --git a/kig/objects/cubic_imp.cc b/kig/objects/cubic_imp.cc deleted file mode 100644 index 7fb5ec63..00000000 --- a/kig/objects/cubic_imp.cc +++ /dev/null @@ -1,437 +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 "cubic_imp.h" - -#include "bogus_imp.h" - -#include "../misc/kigpainter.h" -#include "../misc/screeninfo.h" -#include "../misc/kignumerics.h" -#include "../misc/common.h" -#include "../kig/kig_view.h" - -#include -#include - -CubicImp::CubicImp( const CubicCartesianData& data ) - : CurveImp(), mdata( data ) -{ -} - -CubicImp::~CubicImp() -{ -} - -ObjectImp* CubicImp::transform( const Transformation& t ) const -{ - bool valid = true; - CubicCartesianData d = calcCubicTransformation( data(), t, valid ); - if ( valid ) return new CubicImp( d ); - else return new InvalidImp; -} - -void CubicImp::draw( KigPainter& p ) const -{ - p.drawCurve( this ); -} - -bool CubicImp::contains( const Coordinate& o, int width, const KigWidget& w ) const -{ - return internalContainsPoint( o, w.screenInfo().normalMiss( width ) ); -} - -bool CubicImp::inRect( const Rect&, int, const KigWidget& ) const -{ - // TODO ? - return false; -} - -CubicImp* CubicImp::copy() const -{ - return new CubicImp( mdata ); -} - -double CubicImp::getParam( const Coordinate& p, const KigDocument& ) const -{ - double x = p.x; - double y = p.y; - double t; - - double a000 = mdata.coeffs[0]; - double a001 = mdata.coeffs[1]; - double a002 = mdata.coeffs[2]; - double a011 = mdata.coeffs[3]; - double a012 = mdata.coeffs[4]; - double a022 = mdata.coeffs[5]; - double a111 = mdata.coeffs[6]; - double a112 = mdata.coeffs[7]; - double a122 = mdata.coeffs[8]; - double a222 = mdata.coeffs[9]; - - /* - * first project p onto the cubic. This is done by computing the - * line through p in the direction of the gradient - */ - - double f = a000 + a001*x + a002*y + a011*x*x + a012*x*y + a022*y*y + - a111*x*x*x + a112*x*x*y + a122*x*y*y + a222*y*y*y; - if ( f != 0 ) - { - double fx = a001 + 2*a011*x + a012*y + 3*a111*x*x + 2*a112*x*y + a122*y*y; - double fy = a002 + 2*a022*y + a012*x + 3*a222*y*y + 2*a122*x*y + a112*x*x; - Coordinate v = Coordinate (fx, fy); - if ( f < 0 ) v = -v; // the line points away from the intersection - double a, b, c, d; - calcCubicLineRestriction ( mdata, p, v, a, b, c, d ); - if ( a < 0 ) - { - a *= -1; - b *= -1; - c *= -1; - d *= -1; - } - - // computing the coefficients of the Sturm sequence - double p1a = 2*b*b - 6*a*c; - double p1b = b*c - 9*a*d; - double p0a = c*p1a*p1a + p1b*(3*a*p1b - 2*b*p1a); - // compute the number of roots for negative lambda - int variations = calcCubicVariations ( 0, a, b, c, d, p1a, p1b, p0a ); - bool valid; - int numroots; - double lambda = calcCubicRoot ( -1e10, 1e10, a, b, c, d, variations, valid, - numroots ); - if ( valid ) - { - Coordinate pnew = p + lambda*v; - x = pnew.x; - y = pnew.y; - } - } - - if (x > 0) t = x/(1+x); - else t = x/(1-x); - t = 0.5*(t + 1); - t /= 3; - - Coordinate p1 = getPoint ( t ); - Coordinate p2 = getPoint ( t + 1.0/3.0 ); - Coordinate p3 = getPoint ( t + 2.0/3.0 ); - - double mint = t; - double mindist = p1.valid() ? fabs ( y - p1.y ) : double_inf; - if ( p2.valid() && fabs ( y - p2.y ) < mindist ) - { - mint = t + 1.0/3.0; - mindist = fabs ( y - p2.y ); - } - if ( p3.valid() && fabs ( y - p3.y ) < mindist ) - { - mint = t + 2.0/3.0; - } - - return mint; -} - -const Coordinate CubicImp::getPoint( double p, const KigDocument& ) const -{ - return getPoint( p ); -} - -const Coordinate CubicImp::getPoint( double p ) const -{ - /* - * this isn't really elegant... - * the magnitude of p tells which one of the maximum 3 intersections - * of the vertical line with the cubic to take. - */ - - p *= 3; - int root = (int) p; - assert ( root >= 0 ); - assert ( root <= 3 ); - if ( root == 3 ) root = 2; - - p -= root; - - assert ( 0 <= p && p <= 1 ); - if ( p <= 0. ) p = 1e-6; - if ( p >= 1. ) p = 1 - 1e-6; - root++; - p = 2*p - 1; - double x; - if (p > 0) x = p/(1 - p); - else x = p/(1 + p); - - // calc the third degree polynomial: - // compute the third degree polinomial: -// double a000 = mdata.coeffs[0]; -// double a001 = mdata.coeffs[1]; -// double a002 = mdata.coeffs[2]; -// double a011 = mdata.coeffs[3]; -// double a012 = mdata.coeffs[4]; -// double a022 = mdata.coeffs[5]; -// double a111 = mdata.coeffs[6]; -// double a112 = mdata.coeffs[7]; -// double a122 = mdata.coeffs[8]; -// double a222 = mdata.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; - -// commented out, since the bound is already computed when passing a huge -// interval; the normalization is not needed also - - // renormalize: positive a -// if ( a < 0 ) -// { -// a *= -1; -// b *= -1; -// c *= -1; -// d *= -1; -// } -// -// const double small = 1e-7; -// int degree = 3; -// if ( fabs(a) < small*fabs(b) || -// fabs(a) < small*fabs(c) || -// fabs(a) < small*fabs(d) ) -// { -// degree = 2; -// if ( fabs(b) < small*fabs(c) || -// fabs(b) < small*fabs(d) ) -// { -// degree = 1; -// } -// } - -// and a bound for all the real roots: - -// double bound; -// switch (degree) -// { -// case 3: -// bound = fabs(d/a); -// if ( fabs(c/a) + 1 > bound ) bound = fabs(c/a) + 1; -// if ( fabs(b/a) + 1 > bound ) bound = fabs(b/a) + 1; -// break; -// -// case 2: -// bound = fabs(d/b); -// if ( fabs(c/b) + 1 > bound ) bound = fabs(c/b) + 1; -// break; -// -// case 1: -// default: -// bound = fabs(d/c) + 1; -// break; -// } - - int numroots; - bool valid = true; - double y = calcCubicYvalue ( x, -double_inf, double_inf, root, mdata, valid, - numroots ); - if ( ! valid ) return Coordinate::invalidCoord(); - else return Coordinate(x,y); -// if ( valid ) return Coordinate(x,y); -// root--; if ( root <= 0) root += 3; -// y = calcCubicYvalue ( x, -bound, bound, root, mdata, valid, -// numroots ); -// if ( valid ) return Coordinate(x,y); -// root--; if ( root <= 0) root += 3; -// y = calcCubicYvalue ( x, -bound, bound, root, mdata, valid, -// numroots ); -// assert ( valid ); -// return Coordinate(x,y); -} - -const uint CubicImp::numberOfProperties() const -{ - return Parent::numberOfProperties() + 1; -} - -const QCStringList CubicImp::propertiesInternalNames() const -{ - QCStringList l = Parent::propertiesInternalNames(); - l << "cartesian-equation"; - assert( l.size() == CubicImp::numberOfProperties() ); - return l; - -} - -/* - * cartesian equation property contributed by Carlo Sardi - */ - -const QCStringList CubicImp::properties() const -{ - QCStringList l = Parent::properties(); - l << I18N_NOOP( "Cartesian Equation" ); - assert( l.size() == CubicImp::numberOfProperties() ); - return l; - -} - -const ObjectImpType* CubicImp::impRequirementForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::impRequirementForProperty( which ); - else return CubicImp::stype(); -} - -const char* CubicImp::iconForProperty( uint which ) const -{ - int pnum = 0; - if ( which < Parent::numberOfProperties() ) - return Parent::iconForProperty( which ); - if ( which == Parent::numberOfProperties() + pnum++ ) - return "kig_text"; // cartesian equation string - else - assert( false ); - return ""; -} - -ObjectImp* CubicImp::property( uint which, const KigDocument& w ) const -{ - int pnum = 0; - - if ( which < Parent::numberOfProperties() ) - return Parent::property( which, w ); - if ( which == Parent::numberOfProperties() + pnum++ ) - return new StringImp( cartesianEquationString( w ) ); - else - assert( false ); - return new InvalidImp; -} - -const CubicCartesianData CubicImp::data() const -{ - return mdata; -} - -void CubicImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -bool CubicImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( CubicImp::stype() ) && - static_cast( rhs ).data() == data(); -} - -const ObjectImpType* CubicImp::type() const -{ - return CubicImp::stype(); -} - -const ObjectImpType* CubicImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "cubic", - I18N_NOOP( "cubic curve" ), - I18N_NOOP( "Select this cubic curve" ), - I18N_NOOP( "Select cubic curve %1" ), - I18N_NOOP( "Remove a Cubic Curve" ), - I18N_NOOP( "Add a Cubic Curve" ), - I18N_NOOP( "Move a Cubic Curve" ), - I18N_NOOP( "Attach to this cubic curve" ), - I18N_NOOP( "Show a Cubic Curve" ), - I18N_NOOP( "Hide a Cubic Curve" ) - ); - return &t; -} - -bool CubicImp::containsPoint( const Coordinate& p, const KigDocument& ) const -{ - return internalContainsPoint( p, test_threshold ); -} - -bool CubicImp::internalContainsPoint( const Coordinate& p, double threshold ) const -{ - double a000 = mdata.coeffs[0]; - double a001 = mdata.coeffs[1]; - double a002 = mdata.coeffs[2]; - double a011 = mdata.coeffs[3]; - double a012 = mdata.coeffs[4]; - double a022 = mdata.coeffs[5]; - double a111 = mdata.coeffs[6]; - double a112 = mdata.coeffs[7]; - double a122 = mdata.coeffs[8]; - double a222 = mdata.coeffs[9]; - - double x = p.x; - double y = p.y; - - double f = a000 + a001*x + a002*y + a011*x*x + a012*x*y + a022*y*y + - a111*x*x*x + a112*x*x*y + a122*x*y*y + a222*y*y*y; - double fx = a001 + 2*a011*x + a012*y + 3*a111*x*x + 2*a112*x*y + a122*y*y; - double fy = a002 + a012*x + 2*a022*y + a112*x*x + 2*a122*x*y + 3*a222*y*y; - - double dist = fabs(f)/(fabs(fx) + fabs(fy)); - - return dist <= threshold; -} - -bool CubicImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const -{ - return Parent::isPropertyDefinedOnOrThroughThisImp( which ); -} - -Rect CubicImp::surroundingRect() const -{ - // it's probably possible to calculate this if it exists, but for - // now we don't. - return Rect::invalidRect(); -} - -TQString CubicImp::cartesianEquationString( const KigDocument& ) const -{ - /* - * unfortunately TQStrings.arg method is limited to %1, %9, so we cannot - * treat all 10 arguments! Let's split the equation in two parts... - * Now this ends up also in the translation machinery, is this really - * necessary? Otherwise we could do a little bit of tidy up on the - * the equation (removal of zeros, avoid " ... + -1234 x ", etc.) - */ - - TQString ret = i18n( "%6 x³ + %9 y³ + %7 x²y + %8 xy² + %5 y² + %3 x² + %4 xy + %1 x + %2 y" ); - ret = ret.arg( mdata.coeffs[1], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[2], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[3], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[4], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[5], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[6], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[7], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[8], 0, 'g', 3 ); - ret = ret.arg( mdata.coeffs[9], 0, 'g', 3 ); - - ret.append( i18n( " + %1 = 0" ) ); - ret = ret.arg( mdata.coeffs[0], 0, 'g', 3 ); - - // we should find a common place to do this... - ret.replace( "+ -", "- " ); - ret.replace( "+-", "-" ); - return ret; -} diff --git a/kig/objects/cubic_imp.cpp b/kig/objects/cubic_imp.cpp new file mode 100644 index 00000000..7fb5ec63 --- /dev/null +++ b/kig/objects/cubic_imp.cpp @@ -0,0 +1,437 @@ +// 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 "cubic_imp.h" + +#include "bogus_imp.h" + +#include "../misc/kigpainter.h" +#include "../misc/screeninfo.h" +#include "../misc/kignumerics.h" +#include "../misc/common.h" +#include "../kig/kig_view.h" + +#include +#include + +CubicImp::CubicImp( const CubicCartesianData& data ) + : CurveImp(), mdata( data ) +{ +} + +CubicImp::~CubicImp() +{ +} + +ObjectImp* CubicImp::transform( const Transformation& t ) const +{ + bool valid = true; + CubicCartesianData d = calcCubicTransformation( data(), t, valid ); + if ( valid ) return new CubicImp( d ); + else return new InvalidImp; +} + +void CubicImp::draw( KigPainter& p ) const +{ + p.drawCurve( this ); +} + +bool CubicImp::contains( const Coordinate& o, int width, const KigWidget& w ) const +{ + return internalContainsPoint( o, w.screenInfo().normalMiss( width ) ); +} + +bool CubicImp::inRect( const Rect&, int, const KigWidget& ) const +{ + // TODO ? + return false; +} + +CubicImp* CubicImp::copy() const +{ + return new CubicImp( mdata ); +} + +double CubicImp::getParam( const Coordinate& p, const KigDocument& ) const +{ + double x = p.x; + double y = p.y; + double t; + + double a000 = mdata.coeffs[0]; + double a001 = mdata.coeffs[1]; + double a002 = mdata.coeffs[2]; + double a011 = mdata.coeffs[3]; + double a012 = mdata.coeffs[4]; + double a022 = mdata.coeffs[5]; + double a111 = mdata.coeffs[6]; + double a112 = mdata.coeffs[7]; + double a122 = mdata.coeffs[8]; + double a222 = mdata.coeffs[9]; + + /* + * first project p onto the cubic. This is done by computing the + * line through p in the direction of the gradient + */ + + double f = a000 + a001*x + a002*y + a011*x*x + a012*x*y + a022*y*y + + a111*x*x*x + a112*x*x*y + a122*x*y*y + a222*y*y*y; + if ( f != 0 ) + { + double fx = a001 + 2*a011*x + a012*y + 3*a111*x*x + 2*a112*x*y + a122*y*y; + double fy = a002 + 2*a022*y + a012*x + 3*a222*y*y + 2*a122*x*y + a112*x*x; + Coordinate v = Coordinate (fx, fy); + if ( f < 0 ) v = -v; // the line points away from the intersection + double a, b, c, d; + calcCubicLineRestriction ( mdata, p, v, a, b, c, d ); + if ( a < 0 ) + { + a *= -1; + b *= -1; + c *= -1; + d *= -1; + } + + // computing the coefficients of the Sturm sequence + double p1a = 2*b*b - 6*a*c; + double p1b = b*c - 9*a*d; + double p0a = c*p1a*p1a + p1b*(3*a*p1b - 2*b*p1a); + // compute the number of roots for negative lambda + int variations = calcCubicVariations ( 0, a, b, c, d, p1a, p1b, p0a ); + bool valid; + int numroots; + double lambda = calcCubicRoot ( -1e10, 1e10, a, b, c, d, variations, valid, + numroots ); + if ( valid ) + { + Coordinate pnew = p + lambda*v; + x = pnew.x; + y = pnew.y; + } + } + + if (x > 0) t = x/(1+x); + else t = x/(1-x); + t = 0.5*(t + 1); + t /= 3; + + Coordinate p1 = getPoint ( t ); + Coordinate p2 = getPoint ( t + 1.0/3.0 ); + Coordinate p3 = getPoint ( t + 2.0/3.0 ); + + double mint = t; + double mindist = p1.valid() ? fabs ( y - p1.y ) : double_inf; + if ( p2.valid() && fabs ( y - p2.y ) < mindist ) + { + mint = t + 1.0/3.0; + mindist = fabs ( y - p2.y ); + } + if ( p3.valid() && fabs ( y - p3.y ) < mindist ) + { + mint = t + 2.0/3.0; + } + + return mint; +} + +const Coordinate CubicImp::getPoint( double p, const KigDocument& ) const +{ + return getPoint( p ); +} + +const Coordinate CubicImp::getPoint( double p ) const +{ + /* + * this isn't really elegant... + * the magnitude of p tells which one of the maximum 3 intersections + * of the vertical line with the cubic to take. + */ + + p *= 3; + int root = (int) p; + assert ( root >= 0 ); + assert ( root <= 3 ); + if ( root == 3 ) root = 2; + + p -= root; + + assert ( 0 <= p && p <= 1 ); + if ( p <= 0. ) p = 1e-6; + if ( p >= 1. ) p = 1 - 1e-6; + root++; + p = 2*p - 1; + double x; + if (p > 0) x = p/(1 - p); + else x = p/(1 + p); + + // calc the third degree polynomial: + // compute the third degree polinomial: +// double a000 = mdata.coeffs[0]; +// double a001 = mdata.coeffs[1]; +// double a002 = mdata.coeffs[2]; +// double a011 = mdata.coeffs[3]; +// double a012 = mdata.coeffs[4]; +// double a022 = mdata.coeffs[5]; +// double a111 = mdata.coeffs[6]; +// double a112 = mdata.coeffs[7]; +// double a122 = mdata.coeffs[8]; +// double a222 = mdata.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; + +// commented out, since the bound is already computed when passing a huge +// interval; the normalization is not needed also + + // renormalize: positive a +// if ( a < 0 ) +// { +// a *= -1; +// b *= -1; +// c *= -1; +// d *= -1; +// } +// +// const double small = 1e-7; +// int degree = 3; +// if ( fabs(a) < small*fabs(b) || +// fabs(a) < small*fabs(c) || +// fabs(a) < small*fabs(d) ) +// { +// degree = 2; +// if ( fabs(b) < small*fabs(c) || +// fabs(b) < small*fabs(d) ) +// { +// degree = 1; +// } +// } + +// and a bound for all the real roots: + +// double bound; +// switch (degree) +// { +// case 3: +// bound = fabs(d/a); +// if ( fabs(c/a) + 1 > bound ) bound = fabs(c/a) + 1; +// if ( fabs(b/a) + 1 > bound ) bound = fabs(b/a) + 1; +// break; +// +// case 2: +// bound = fabs(d/b); +// if ( fabs(c/b) + 1 > bound ) bound = fabs(c/b) + 1; +// break; +// +// case 1: +// default: +// bound = fabs(d/c) + 1; +// break; +// } + + int numroots; + bool valid = true; + double y = calcCubicYvalue ( x, -double_inf, double_inf, root, mdata, valid, + numroots ); + if ( ! valid ) return Coordinate::invalidCoord(); + else return Coordinate(x,y); +// if ( valid ) return Coordinate(x,y); +// root--; if ( root <= 0) root += 3; +// y = calcCubicYvalue ( x, -bound, bound, root, mdata, valid, +// numroots ); +// if ( valid ) return Coordinate(x,y); +// root--; if ( root <= 0) root += 3; +// y = calcCubicYvalue ( x, -bound, bound, root, mdata, valid, +// numroots ); +// assert ( valid ); +// return Coordinate(x,y); +} + +const uint CubicImp::numberOfProperties() const +{ + return Parent::numberOfProperties() + 1; +} + +const QCStringList CubicImp::propertiesInternalNames() const +{ + QCStringList l = Parent::propertiesInternalNames(); + l << "cartesian-equation"; + assert( l.size() == CubicImp::numberOfProperties() ); + return l; + +} + +/* + * cartesian equation property contributed by Carlo Sardi + */ + +const QCStringList CubicImp::properties() const +{ + QCStringList l = Parent::properties(); + l << I18N_NOOP( "Cartesian Equation" ); + assert( l.size() == CubicImp::numberOfProperties() ); + return l; + +} + +const ObjectImpType* CubicImp::impRequirementForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::impRequirementForProperty( which ); + else return CubicImp::stype(); +} + +const char* CubicImp::iconForProperty( uint which ) const +{ + int pnum = 0; + if ( which < Parent::numberOfProperties() ) + return Parent::iconForProperty( which ); + if ( which == Parent::numberOfProperties() + pnum++ ) + return "kig_text"; // cartesian equation string + else + assert( false ); + return ""; +} + +ObjectImp* CubicImp::property( uint which, const KigDocument& w ) const +{ + int pnum = 0; + + if ( which < Parent::numberOfProperties() ) + return Parent::property( which, w ); + if ( which == Parent::numberOfProperties() + pnum++ ) + return new StringImp( cartesianEquationString( w ) ); + else + assert( false ); + return new InvalidImp; +} + +const CubicCartesianData CubicImp::data() const +{ + return mdata; +} + +void CubicImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +bool CubicImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( CubicImp::stype() ) && + static_cast( rhs ).data() == data(); +} + +const ObjectImpType* CubicImp::type() const +{ + return CubicImp::stype(); +} + +const ObjectImpType* CubicImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "cubic", + I18N_NOOP( "cubic curve" ), + I18N_NOOP( "Select this cubic curve" ), + I18N_NOOP( "Select cubic curve %1" ), + I18N_NOOP( "Remove a Cubic Curve" ), + I18N_NOOP( "Add a Cubic Curve" ), + I18N_NOOP( "Move a Cubic Curve" ), + I18N_NOOP( "Attach to this cubic curve" ), + I18N_NOOP( "Show a Cubic Curve" ), + I18N_NOOP( "Hide a Cubic Curve" ) + ); + return &t; +} + +bool CubicImp::containsPoint( const Coordinate& p, const KigDocument& ) const +{ + return internalContainsPoint( p, test_threshold ); +} + +bool CubicImp::internalContainsPoint( const Coordinate& p, double threshold ) const +{ + double a000 = mdata.coeffs[0]; + double a001 = mdata.coeffs[1]; + double a002 = mdata.coeffs[2]; + double a011 = mdata.coeffs[3]; + double a012 = mdata.coeffs[4]; + double a022 = mdata.coeffs[5]; + double a111 = mdata.coeffs[6]; + double a112 = mdata.coeffs[7]; + double a122 = mdata.coeffs[8]; + double a222 = mdata.coeffs[9]; + + double x = p.x; + double y = p.y; + + double f = a000 + a001*x + a002*y + a011*x*x + a012*x*y + a022*y*y + + a111*x*x*x + a112*x*x*y + a122*x*y*y + a222*y*y*y; + double fx = a001 + 2*a011*x + a012*y + 3*a111*x*x + 2*a112*x*y + a122*y*y; + double fy = a002 + a012*x + 2*a022*y + a112*x*x + 2*a122*x*y + 3*a222*y*y; + + double dist = fabs(f)/(fabs(fx) + fabs(fy)); + + return dist <= threshold; +} + +bool CubicImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const +{ + return Parent::isPropertyDefinedOnOrThroughThisImp( which ); +} + +Rect CubicImp::surroundingRect() const +{ + // it's probably possible to calculate this if it exists, but for + // now we don't. + return Rect::invalidRect(); +} + +TQString CubicImp::cartesianEquationString( const KigDocument& ) const +{ + /* + * unfortunately TQStrings.arg method is limited to %1, %9, so we cannot + * treat all 10 arguments! Let's split the equation in two parts... + * Now this ends up also in the translation machinery, is this really + * necessary? Otherwise we could do a little bit of tidy up on the + * the equation (removal of zeros, avoid " ... + -1234 x ", etc.) + */ + + TQString ret = i18n( "%6 x³ + %9 y³ + %7 x²y + %8 xy² + %5 y² + %3 x² + %4 xy + %1 x + %2 y" ); + ret = ret.arg( mdata.coeffs[1], 0, 'g', 3 ); + ret = ret.arg( mdata.coeffs[2], 0, 'g', 3 ); + ret = ret.arg( mdata.coeffs[3], 0, 'g', 3 ); + ret = ret.arg( mdata.coeffs[4], 0, 'g', 3 ); + ret = ret.arg( mdata.coeffs[5], 0, 'g', 3 ); + ret = ret.arg( mdata.coeffs[6], 0, 'g', 3 ); + ret = ret.arg( mdata.coeffs[7], 0, 'g', 3 ); + ret = ret.arg( mdata.coeffs[8], 0, 'g', 3 ); + ret = ret.arg( mdata.coeffs[9], 0, 'g', 3 ); + + ret.append( i18n( " + %1 = 0" ) ); + ret = ret.arg( mdata.coeffs[0], 0, 'g', 3 ); + + // we should find a common place to do this... + ret.replace( "+ -", "- " ); + ret.replace( "+-", "-" ); + return ret; +} diff --git a/kig/objects/cubic_type.cc b/kig/objects/cubic_type.cc deleted file mode 100644 index 24bfbda4..00000000 --- a/kig/objects/cubic_type.cc +++ /dev/null @@ -1,185 +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 "cubic_type.h" - -#include "cubic_imp.h" -#include "point_imp.h" -#include "bogus_imp.h" - -#include - -static const char cubictpstatement[] = I18N_NOOP( "Construct a cubic curve through this point" ); - -static const struct ArgsParser::spec argsspecCubicB9P[] = -{ - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CubicB9PType ) - -CubicB9PType::CubicB9PType() - : ArgsParserObjectType( "CubicB9P", argsspecCubicB9P, 9 ) -{ -} - -CubicB9PType::~CubicB9PType() -{ -} - -const CubicB9PType* CubicB9PType::instance() -{ - static const CubicB9PType t; - return &t; -} - -ObjectImp* CubicB9PType::calc( const Args& os, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( os, 2 ) ) return new InvalidImp; - - std::vector points; - for ( uint i = 0; i < os.size(); ++i ) - points.push_back( static_cast( os[i] )->coordinate() ); - - CubicCartesianData d = calcCubicThroughPoints( points ); - if ( d.valid() ) - return new CubicImp( d ); - else - return new InvalidImp; -} - -static const ArgsParser::spec argsspecCubicNodeB6P[] = -{ - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CubicNodeB6PType ) - -CubicNodeB6PType::CubicNodeB6PType() - : ArgsParserObjectType( "CubicNodeB6P", argsspecCubicNodeB6P, 6 ) -{ -} - -CubicNodeB6PType::~CubicNodeB6PType() -{ -} - -const CubicNodeB6PType* CubicNodeB6PType::instance() -{ - static const CubicNodeB6PType t; - return &t; -} - -ObjectImp* CubicNodeB6PType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; - - std::vector points; - for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) - points.push_back( static_cast( *i )->coordinate() ); - - CubicCartesianData d = calcCubicNodeThroughPoints( points ); - if ( d.valid() ) - return new CubicImp( d ); - else - return new InvalidImp; -} - -static const ArgsParser::spec argsspecCubicCuspB4P[] = -{ - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, - { PointImp::stype(), cubictpstatement, - I18N_NOOP( "Select a point for the new cubic to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CubicCuspB4PType ) - -CubicCuspB4PType::CubicCuspB4PType() - : ArgsParserObjectType( "CubicCuspB4P", argsspecCubicCuspB4P, 4 ) -{ -} - -CubicCuspB4PType::~CubicCuspB4PType() -{ -} - -const CubicCuspB4PType* CubicCuspB4PType::instance() -{ - static const CubicCuspB4PType t; - return &t; -} - -ObjectImp* CubicCuspB4PType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; - - std::vector points; - for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) - points.push_back( static_cast( *i )->coordinate() ); - - CubicCartesianData d = calcCubicCuspThroughPoints( points ); - if ( d.valid() ) return new CubicImp( d ); - else return new InvalidImp; -} - -const ObjectImpType* CubicB9PType::resultId() const -{ - return CubicImp::stype(); -} - -const ObjectImpType* CubicNodeB6PType::resultId() const -{ - return CubicImp::stype(); -} - -const ObjectImpType* CubicCuspB4PType::resultId() const -{ - return CubicImp::stype(); -} diff --git a/kig/objects/cubic_type.cpp b/kig/objects/cubic_type.cpp new file mode 100644 index 00000000..24bfbda4 --- /dev/null +++ b/kig/objects/cubic_type.cpp @@ -0,0 +1,185 @@ +// 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 "cubic_type.h" + +#include "cubic_imp.h" +#include "point_imp.h" +#include "bogus_imp.h" + +#include + +static const char cubictpstatement[] = I18N_NOOP( "Construct a cubic curve through this point" ); + +static const struct ArgsParser::spec argsspecCubicB9P[] = +{ + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CubicB9PType ) + +CubicB9PType::CubicB9PType() + : ArgsParserObjectType( "CubicB9P", argsspecCubicB9P, 9 ) +{ +} + +CubicB9PType::~CubicB9PType() +{ +} + +const CubicB9PType* CubicB9PType::instance() +{ + static const CubicB9PType t; + return &t; +} + +ObjectImp* CubicB9PType::calc( const Args& os, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( os, 2 ) ) return new InvalidImp; + + std::vector points; + for ( uint i = 0; i < os.size(); ++i ) + points.push_back( static_cast( os[i] )->coordinate() ); + + CubicCartesianData d = calcCubicThroughPoints( points ); + if ( d.valid() ) + return new CubicImp( d ); + else + return new InvalidImp; +} + +static const ArgsParser::spec argsspecCubicNodeB6P[] = +{ + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CubicNodeB6PType ) + +CubicNodeB6PType::CubicNodeB6PType() + : ArgsParserObjectType( "CubicNodeB6P", argsspecCubicNodeB6P, 6 ) +{ +} + +CubicNodeB6PType::~CubicNodeB6PType() +{ +} + +const CubicNodeB6PType* CubicNodeB6PType::instance() +{ + static const CubicNodeB6PType t; + return &t; +} + +ObjectImp* CubicNodeB6PType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; + + std::vector points; + for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) + points.push_back( static_cast( *i )->coordinate() ); + + CubicCartesianData d = calcCubicNodeThroughPoints( points ); + if ( d.valid() ) + return new CubicImp( d ); + else + return new InvalidImp; +} + +static const ArgsParser::spec argsspecCubicCuspB4P[] = +{ + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true }, + { PointImp::stype(), cubictpstatement, + I18N_NOOP( "Select a point for the new cubic to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CubicCuspB4PType ) + +CubicCuspB4PType::CubicCuspB4PType() + : ArgsParserObjectType( "CubicCuspB4P", argsspecCubicCuspB4P, 4 ) +{ +} + +CubicCuspB4PType::~CubicCuspB4PType() +{ +} + +const CubicCuspB4PType* CubicCuspB4PType::instance() +{ + static const CubicCuspB4PType t; + return &t; +} + +ObjectImp* CubicCuspB4PType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents, 2 ) ) return new InvalidImp; + + std::vector points; + for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) + points.push_back( static_cast( *i )->coordinate() ); + + CubicCartesianData d = calcCubicCuspThroughPoints( points ); + if ( d.valid() ) return new CubicImp( d ); + else return new InvalidImp; +} + +const ObjectImpType* CubicB9PType::resultId() const +{ + return CubicImp::stype(); +} + +const ObjectImpType* CubicNodeB6PType::resultId() const +{ + return CubicImp::stype(); +} + +const ObjectImpType* CubicCuspB4PType::resultId() const +{ + return CubicImp::stype(); +} diff --git a/kig/objects/curve_imp.cc b/kig/objects/curve_imp.cc deleted file mode 100644 index 315cd8cb..00000000 --- a/kig/objects/curve_imp.cc +++ /dev/null @@ -1,41 +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 "curve_imp.h" -#include "../misc/coordinate.h" - -const ObjectImpType* CurveImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "curve", - I18N_NOOP( "curve" ), - I18N_NOOP( "Select this curve" ), - I18N_NOOP( "Select curve %1" ), - I18N_NOOP( "Remove a Curve" ), - I18N_NOOP( "Add a Curve" ), - I18N_NOOP( "Move a Curve" ), - I18N_NOOP( "Attach to this curve" ), - I18N_NOOP( "Show a Curve" ), - I18N_NOOP( "Hide a Curve" ) - ); - return &t; -} - -Coordinate CurveImp::attachPoint() const -{ - return Coordinate::invalidCoord(); -} diff --git a/kig/objects/curve_imp.cpp b/kig/objects/curve_imp.cpp new file mode 100644 index 00000000..315cd8cb --- /dev/null +++ b/kig/objects/curve_imp.cpp @@ -0,0 +1,41 @@ +// 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 "curve_imp.h" +#include "../misc/coordinate.h" + +const ObjectImpType* CurveImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "curve", + I18N_NOOP( "curve" ), + I18N_NOOP( "Select this curve" ), + I18N_NOOP( "Select curve %1" ), + I18N_NOOP( "Remove a Curve" ), + I18N_NOOP( "Add a Curve" ), + I18N_NOOP( "Move a Curve" ), + I18N_NOOP( "Attach to this curve" ), + I18N_NOOP( "Show a Curve" ), + I18N_NOOP( "Hide a Curve" ) + ); + return &t; +} + +Coordinate CurveImp::attachPoint() const +{ + return Coordinate::invalidCoord(); +} diff --git a/kig/objects/intersection_types.cc b/kig/objects/intersection_types.cc deleted file mode 100644 index 0718bc23..00000000 --- a/kig/objects/intersection_types.cc +++ /dev/null @@ -1,338 +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 "intersection_types.h" - -#include "bogus_imp.h" -#include "circle_imp.h" -#include "conic_imp.h" -#include "cubic_imp.h" -#include "line_imp.h" -#include "other_imp.h" -#include "point_imp.h" - -#include - -static const char intersectlinestat[] = I18N_NOOP( "Intersect with this line" ); - -static const ArgsParser::spec argsspecConicLineIntersection[] = -{ - { ConicImp::stype(), I18N_NOOP( "Intersect with this conic" ), - "SHOULD NOT BE SEEN", true }, - { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }, - { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicLineIntersectionType ) - -ConicLineIntersectionType::ConicLineIntersectionType() - : ArgsParserObjectType( "ConicLineIntersection", - argsspecConicLineIntersection, 3 ) -{ -} - -ConicLineIntersectionType::~ConicLineIntersectionType() -{ -} - -const ConicLineIntersectionType* ConicLineIntersectionType::instance() -{ - static const ConicLineIntersectionType t; - return &t; -} - -ObjectImp* ConicLineIntersectionType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - int side = static_cast( parents[2] )->data(); - assert( side == 1 || side == -1 ); - const LineData line = static_cast( parents[1] )->data(); - - Coordinate ret; - if ( parents[0]->inherits( CircleImp::stype() ) ) - { - // easy case.. - const CircleImp* c = static_cast( parents[0] ); - ret = calcCircleLineIntersect( - c->center(), c->squareRadius(), line, side ); - } - else - { - // harder case.. - ret = calcConicLineIntersect( - static_cast( parents[0] )->cartesianData(), - line, 0.0, side ); - } - if ( ret.valid() ) return new PointImp( ret ); - else return new InvalidImp; -} - -static const ArgsParser::spec argsspecConicLineOtherIntersection[] = -{ - { ConicImp::stype(), I18N_NOOP( "Intersect with this conic" ), - "SHOULD NOT BE SEEN", true }, - { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }, - { PointImp::stype(), I18N_NOOP( "Already computed intersection point"), - "SHOULD NOT BE SEEN", true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicLineOtherIntersectionType ) - -ConicLineOtherIntersectionType::ConicLineOtherIntersectionType() - : ArgsParserObjectType( "ConicLineOtherIntersection", - argsspecConicLineOtherIntersection, 3 ) -{ -} - -ConicLineOtherIntersectionType::~ConicLineOtherIntersectionType() -{ -} - -const ConicLineOtherIntersectionType* ConicLineOtherIntersectionType::instance() -{ - static const ConicLineOtherIntersectionType t; - return &t; -} - -ObjectImp* ConicLineOtherIntersectionType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - Coordinate p = static_cast( parents[2] )->coordinate(); - const LineData line = static_cast( parents[1] )->data(); - - Coordinate ret; -// if ( parents[0]->inherits( CircleImp::stype() ) ) -// { -// // easy case.. -// const CircleImp* c = static_cast( parents[0] ); -// ret = calcCircleLineIntersect( -// c->center(), c->squareRadius(), line, side, valid ); -// } -// else -// { - // harder case.. - double pax = p.x - line.a.x; - double pay = p.y - line.a.y; - double bax = line.b.x - line.a.x; - double bay = line.b.y - line.a.y; - double knownparam = (pax*bax + pay*bay)/(bax*bax + bay*bay); - ret = calcConicLineIntersect( - static_cast( parents[0] )->cartesianData(), - line, knownparam, 0 ); -// } - if ( ret.valid() ) return new PointImp( ret ); - else return new InvalidImp; -} - -static const ArgsParser::spec argsspecLineLineIntersection[] = -{ - { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }, - { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineLineIntersectionType ) - -LineLineIntersectionType::LineLineIntersectionType() - : ArgsParserObjectType( "LineLineIntersection", - argsspecLineLineIntersection, 2 ) -{ -} - -LineLineIntersectionType::~LineLineIntersectionType() -{ -} - -const LineLineIntersectionType* LineLineIntersectionType::instance() -{ - static const LineLineIntersectionType t; - return &t; -} - -ObjectImp* LineLineIntersectionType::calc( const Args& parents, const KigDocument& d ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - Coordinate p = - calcIntersectionPoint( - static_cast( parents[0] )->data(), - static_cast( parents[1] )->data() ); - if ( static_cast( parents[0] )->containsPoint( p, d ) && - static_cast( parents[1] )->containsPoint( p, d ) ) - return new PointImp( p ); - else return new InvalidImp(); -} - -static const ArgsParser::spec argsspecLineCubicIntersection[] = -{ - { CubicImp::stype(), I18N_NOOP( "Intersect with this cubic curve" ), - "SHOULD NOT BE SEEN", true }, - { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }, - { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineCubicIntersectionType ) - -LineCubicIntersectionType::LineCubicIntersectionType() - : ArgsParserObjectType( "LineCubicIntersection", - argsspecLineCubicIntersection, 3 ) -{ -} - -LineCubicIntersectionType::~LineCubicIntersectionType() -{ -} - -const LineCubicIntersectionType* LineCubicIntersectionType::instance() -{ - static const LineCubicIntersectionType t; - return &t; -} - -ObjectImp* LineCubicIntersectionType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - int which = static_cast( parents[2] )->data(); - bool valid = true; - const Coordinate c = calcCubicLineIntersect( - static_cast( parents[0] )->data(), - static_cast( parents[1] )->data(), - which, valid ); - if ( valid ) return new PointImp( c ); - else return new InvalidImp; -} - -const ObjectImpType* ConicLineIntersectionType::resultId() const -{ - return PointImp::stype(); -} - -const ObjectImpType* ConicLineOtherIntersectionType::resultId() const -{ - return PointImp::stype(); -} - -const ObjectImpType* LineLineIntersectionType::resultId() const -{ - return PointImp::stype(); -} - -const ObjectImpType* LineCubicIntersectionType::resultId() const -{ - return PointImp::stype(); -} - -static const ArgsParser::spec argsspecCircleCircleIntersection[] = -{ - { CircleImp::stype(), I18N_NOOP( "Intersect with this circle" ), - "SHOULD NOT BE SEEN", true }, - { CircleImp::stype(), I18N_NOOP( "Intersect with this circle" ), - "SHOULD NOT BE SEEN", true }, - { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CircleCircleIntersectionType ) - -CircleCircleIntersectionType::CircleCircleIntersectionType() - : ArgsParserObjectType( "CircleCircleIntersection", - argsspecCircleCircleIntersection, 3 ) -{ -} - -CircleCircleIntersectionType::~CircleCircleIntersectionType() -{ -} - -const CircleCircleIntersectionType* CircleCircleIntersectionType::instance() -{ - static const CircleCircleIntersectionType t; - return &t; -} - -ObjectImp* CircleCircleIntersectionType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - int side = static_cast( parents[2] )->data(); - assert( side == 1 || side == -1 ); - const CircleImp* c1 = static_cast( parents[0] ); - const CircleImp* c2 = static_cast( parents[1] ); - const Coordinate o1 = c1->center(); - const Coordinate o2 = c2->center(); - const double r1sq = c1->squareRadius(); - const Coordinate a = calcCircleRadicalStartPoint( - o1, o2, r1sq, c2->squareRadius() - ); - const LineData line = LineData (a, Coordinate ( a.x -o2.y + o1.y, a.y + o2.x - o1.x )); - Coordinate ret = calcCircleLineIntersect( o1, r1sq, line, side ); - if ( ret.valid() ) return new PointImp( ret ); - else return new InvalidImp; -} - -const ObjectImpType* CircleCircleIntersectionType::resultId() const -{ - return PointImp::stype(); -} - -static const ArgsParser::spec argsspecArcLineIntersection[] = -{ - { ArcImp::stype(), I18N_NOOP( "Intersect with this arc" ), - "SHOULD NOT BE SEEN", true }, - { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }, - { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ArcLineIntersectionType ) - -ArcLineIntersectionType::ArcLineIntersectionType() - : ArgsParserObjectType( "ArcLineIntersection", - argsspecArcLineIntersection, 3 ) -{ -} - -ArcLineIntersectionType::~ArcLineIntersectionType() -{ -} - -const ArcLineIntersectionType* ArcLineIntersectionType::instance() -{ - static const ArcLineIntersectionType t; - return &t; -} - -ObjectImp* ArcLineIntersectionType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - int side = static_cast( parents[2] )->data(); - assert( side == 1 || side == -1 ); - const LineData line = static_cast( parents[1] )->data(); - - const ArcImp* c = static_cast( parents[0] ); - const double r = c->radius(); - Coordinate ret = calcArcLineIntersect( c->center(), r*r, c->startAngle(), - c->angle(), line, side ); - if ( ret.valid() ) return new PointImp( ret ); - else return new InvalidImp; -} - -const ObjectImpType* ArcLineIntersectionType::resultId() const -{ - return PointImp::stype(); -} diff --git a/kig/objects/intersection_types.cpp b/kig/objects/intersection_types.cpp new file mode 100644 index 00000000..0718bc23 --- /dev/null +++ b/kig/objects/intersection_types.cpp @@ -0,0 +1,338 @@ +// 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 "intersection_types.h" + +#include "bogus_imp.h" +#include "circle_imp.h" +#include "conic_imp.h" +#include "cubic_imp.h" +#include "line_imp.h" +#include "other_imp.h" +#include "point_imp.h" + +#include + +static const char intersectlinestat[] = I18N_NOOP( "Intersect with this line" ); + +static const ArgsParser::spec argsspecConicLineIntersection[] = +{ + { ConicImp::stype(), I18N_NOOP( "Intersect with this conic" ), + "SHOULD NOT BE SEEN", true }, + { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }, + { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicLineIntersectionType ) + +ConicLineIntersectionType::ConicLineIntersectionType() + : ArgsParserObjectType( "ConicLineIntersection", + argsspecConicLineIntersection, 3 ) +{ +} + +ConicLineIntersectionType::~ConicLineIntersectionType() +{ +} + +const ConicLineIntersectionType* ConicLineIntersectionType::instance() +{ + static const ConicLineIntersectionType t; + return &t; +} + +ObjectImp* ConicLineIntersectionType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + int side = static_cast( parents[2] )->data(); + assert( side == 1 || side == -1 ); + const LineData line = static_cast( parents[1] )->data(); + + Coordinate ret; + if ( parents[0]->inherits( CircleImp::stype() ) ) + { + // easy case.. + const CircleImp* c = static_cast( parents[0] ); + ret = calcCircleLineIntersect( + c->center(), c->squareRadius(), line, side ); + } + else + { + // harder case.. + ret = calcConicLineIntersect( + static_cast( parents[0] )->cartesianData(), + line, 0.0, side ); + } + if ( ret.valid() ) return new PointImp( ret ); + else return new InvalidImp; +} + +static const ArgsParser::spec argsspecConicLineOtherIntersection[] = +{ + { ConicImp::stype(), I18N_NOOP( "Intersect with this conic" ), + "SHOULD NOT BE SEEN", true }, + { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }, + { PointImp::stype(), I18N_NOOP( "Already computed intersection point"), + "SHOULD NOT BE SEEN", true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConicLineOtherIntersectionType ) + +ConicLineOtherIntersectionType::ConicLineOtherIntersectionType() + : ArgsParserObjectType( "ConicLineOtherIntersection", + argsspecConicLineOtherIntersection, 3 ) +{ +} + +ConicLineOtherIntersectionType::~ConicLineOtherIntersectionType() +{ +} + +const ConicLineOtherIntersectionType* ConicLineOtherIntersectionType::instance() +{ + static const ConicLineOtherIntersectionType t; + return &t; +} + +ObjectImp* ConicLineOtherIntersectionType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + Coordinate p = static_cast( parents[2] )->coordinate(); + const LineData line = static_cast( parents[1] )->data(); + + Coordinate ret; +// if ( parents[0]->inherits( CircleImp::stype() ) ) +// { +// // easy case.. +// const CircleImp* c = static_cast( parents[0] ); +// ret = calcCircleLineIntersect( +// c->center(), c->squareRadius(), line, side, valid ); +// } +// else +// { + // harder case.. + double pax = p.x - line.a.x; + double pay = p.y - line.a.y; + double bax = line.b.x - line.a.x; + double bay = line.b.y - line.a.y; + double knownparam = (pax*bax + pay*bay)/(bax*bax + bay*bay); + ret = calcConicLineIntersect( + static_cast( parents[0] )->cartesianData(), + line, knownparam, 0 ); +// } + if ( ret.valid() ) return new PointImp( ret ); + else return new InvalidImp; +} + +static const ArgsParser::spec argsspecLineLineIntersection[] = +{ + { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }, + { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineLineIntersectionType ) + +LineLineIntersectionType::LineLineIntersectionType() + : ArgsParserObjectType( "LineLineIntersection", + argsspecLineLineIntersection, 2 ) +{ +} + +LineLineIntersectionType::~LineLineIntersectionType() +{ +} + +const LineLineIntersectionType* LineLineIntersectionType::instance() +{ + static const LineLineIntersectionType t; + return &t; +} + +ObjectImp* LineLineIntersectionType::calc( const Args& parents, const KigDocument& d ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + Coordinate p = + calcIntersectionPoint( + static_cast( parents[0] )->data(), + static_cast( parents[1] )->data() ); + if ( static_cast( parents[0] )->containsPoint( p, d ) && + static_cast( parents[1] )->containsPoint( p, d ) ) + return new PointImp( p ); + else return new InvalidImp(); +} + +static const ArgsParser::spec argsspecLineCubicIntersection[] = +{ + { CubicImp::stype(), I18N_NOOP( "Intersect with this cubic curve" ), + "SHOULD NOT BE SEEN", true }, + { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }, + { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineCubicIntersectionType ) + +LineCubicIntersectionType::LineCubicIntersectionType() + : ArgsParserObjectType( "LineCubicIntersection", + argsspecLineCubicIntersection, 3 ) +{ +} + +LineCubicIntersectionType::~LineCubicIntersectionType() +{ +} + +const LineCubicIntersectionType* LineCubicIntersectionType::instance() +{ + static const LineCubicIntersectionType t; + return &t; +} + +ObjectImp* LineCubicIntersectionType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + int which = static_cast( parents[2] )->data(); + bool valid = true; + const Coordinate c = calcCubicLineIntersect( + static_cast( parents[0] )->data(), + static_cast( parents[1] )->data(), + which, valid ); + if ( valid ) return new PointImp( c ); + else return new InvalidImp; +} + +const ObjectImpType* ConicLineIntersectionType::resultId() const +{ + return PointImp::stype(); +} + +const ObjectImpType* ConicLineOtherIntersectionType::resultId() const +{ + return PointImp::stype(); +} + +const ObjectImpType* LineLineIntersectionType::resultId() const +{ + return PointImp::stype(); +} + +const ObjectImpType* LineCubicIntersectionType::resultId() const +{ + return PointImp::stype(); +} + +static const ArgsParser::spec argsspecCircleCircleIntersection[] = +{ + { CircleImp::stype(), I18N_NOOP( "Intersect with this circle" ), + "SHOULD NOT BE SEEN", true }, + { CircleImp::stype(), I18N_NOOP( "Intersect with this circle" ), + "SHOULD NOT BE SEEN", true }, + { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CircleCircleIntersectionType ) + +CircleCircleIntersectionType::CircleCircleIntersectionType() + : ArgsParserObjectType( "CircleCircleIntersection", + argsspecCircleCircleIntersection, 3 ) +{ +} + +CircleCircleIntersectionType::~CircleCircleIntersectionType() +{ +} + +const CircleCircleIntersectionType* CircleCircleIntersectionType::instance() +{ + static const CircleCircleIntersectionType t; + return &t; +} + +ObjectImp* CircleCircleIntersectionType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + int side = static_cast( parents[2] )->data(); + assert( side == 1 || side == -1 ); + const CircleImp* c1 = static_cast( parents[0] ); + const CircleImp* c2 = static_cast( parents[1] ); + const Coordinate o1 = c1->center(); + const Coordinate o2 = c2->center(); + const double r1sq = c1->squareRadius(); + const Coordinate a = calcCircleRadicalStartPoint( + o1, o2, r1sq, c2->squareRadius() + ); + const LineData line = LineData (a, Coordinate ( a.x -o2.y + o1.y, a.y + o2.x - o1.x )); + Coordinate ret = calcCircleLineIntersect( o1, r1sq, line, side ); + if ( ret.valid() ) return new PointImp( ret ); + else return new InvalidImp; +} + +const ObjectImpType* CircleCircleIntersectionType::resultId() const +{ + return PointImp::stype(); +} + +static const ArgsParser::spec argsspecArcLineIntersection[] = +{ + { ArcImp::stype(), I18N_NOOP( "Intersect with this arc" ), + "SHOULD NOT BE SEEN", true }, + { AbstractLineImp::stype(), intersectlinestat, "SHOULD NOT BE SEEN", true }, + { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ArcLineIntersectionType ) + +ArcLineIntersectionType::ArcLineIntersectionType() + : ArgsParserObjectType( "ArcLineIntersection", + argsspecArcLineIntersection, 3 ) +{ +} + +ArcLineIntersectionType::~ArcLineIntersectionType() +{ +} + +const ArcLineIntersectionType* ArcLineIntersectionType::instance() +{ + static const ArcLineIntersectionType t; + return &t; +} + +ObjectImp* ArcLineIntersectionType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + int side = static_cast( parents[2] )->data(); + assert( side == 1 || side == -1 ); + const LineData line = static_cast( parents[1] )->data(); + + const ArcImp* c = static_cast( parents[0] ); + const double r = c->radius(); + Coordinate ret = calcArcLineIntersect( c->center(), r*r, c->startAngle(), + c->angle(), line, side ); + if ( ret.valid() ) return new PointImp( ret ); + else return new InvalidImp; +} + +const ObjectImpType* ArcLineIntersectionType::resultId() const +{ + return PointImp::stype(); +} diff --git a/kig/objects/inversion_type.cc b/kig/objects/inversion_type.cc deleted file mode 100644 index 4f270582..00000000 --- a/kig/objects/inversion_type.cc +++ /dev/null @@ -1,412 +0,0 @@ -// Copyright (C) 2005 Maurizio Paolini - -// 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 "inversion_type.h" -#include "point_imp.h" -#include "line_imp.h" -#include "circle_imp.h" -#include "other_imp.h" -#include "bogus_imp.h" - -#include "../misc/common.h" - -#include - -static const char str1[] = I18N_NOOP( "Invert with respect to this circle" ); -static const char str2[] = I18N_NOOP( "Select the circle we want to invert against..." ); - -static const ArgsParser::spec argsspecInvertPoint[] = -{ - { PointImp::stype(), I18N_NOOP( "Compute the inversion of this point" ), - I18N_NOOP( "Select the point to invert..." ), false }, - { CircleImp::stype(), str1, str2, false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertPointType ) - -InvertPointType::InvertPointType() - : ArgsParserObjectType( "InvertPoint", argsspecInvertPoint, 2 ) -{ -} - -InvertPointType::~InvertPointType() -{ -} - -const InvertPointType* InvertPointType::instance() -{ - static const InvertPointType s; - return &s; -} - -const ObjectImpType* InvertPointType::resultId() const -{ - return PointImp::stype(); -} - -ObjectImp* InvertPointType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - const CircleImp* c = static_cast( args[1] ); - Coordinate center = c->center(); - Coordinate relp = static_cast( args[0] )->coordinate() - center; - double radiussq = c->squareRadius(); - double normsq = relp.x*relp.x + relp.y*relp.y; - if ( normsq == 0 ) return new InvalidImp; - return new PointImp( center + (radiussq/normsq)*relp ); -} - -/* - * inversion of a line - */ - -static const ArgsParser::spec argsspecInvertLine[] = -{ - { LineImp::stype(), I18N_NOOP( "Compute the inversion of this line" ), - I18N_NOOP( "Select the line to invert..." ), false }, - { CircleImp::stype(), str1, str2, false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertLineType ) - -InvertLineType::InvertLineType() - : ArgsParserObjectType( "InvertLine", argsspecInvertLine, 2 ) -{ -} - -InvertLineType::~InvertLineType() -{ -} - -const InvertLineType* InvertLineType::instance() -{ - static const InvertLineType s; - return &s; -} - -const ObjectImpType* InvertLineType::resultId() const -{ - return CircleImp::stype(); -} - -ObjectImp* InvertLineType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - const CircleImp* c = static_cast( args[1] ); - Coordinate center = c->center(); - double radiussq = c->squareRadius(); - const LineData line = static_cast( args[0] )->data(); - Coordinate relb = line.b - center; - Coordinate ab = line.b - line.a; - double t = (relb.x*ab.x + relb.y*ab.y)/(ab.x*ab.x + ab.y*ab.y); - Coordinate relh = relb - t*ab; - double normhsq = relh.x*relh.x + relh.y*relh.y; - if ( normhsq < 1e-12*radiussq ) return new LineImp( line.a, line.b ); - Coordinate newcenter = center + 0.5*radiussq/normhsq*relh; - double newradius = 0.5*radiussq/sqrt(normhsq); - - return new CircleImp( newcenter, newradius ); -} - -/* - * inversion of a segment - */ - -static const ArgsParser::spec argsspecInvertSegment[] = -{ - { SegmentImp::stype(), I18N_NOOP( "Compute the inversion of this segment" ), - I18N_NOOP( "Select the segment to invert..." ), false }, - { CircleImp::stype(), str1, str2, false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertSegmentType ) - -InvertSegmentType::InvertSegmentType() - : ArgsParserObjectType( "InvertSegment", argsspecInvertSegment, 2 ) -{ -} - -InvertSegmentType::~InvertSegmentType() -{ -} - -const InvertSegmentType* InvertSegmentType::instance() -{ - static const InvertSegmentType s; - return &s; -} - -const ObjectImpType* InvertSegmentType::resultId() const -{ - return ArcImp::stype(); -} - -ObjectImp* InvertSegmentType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - const CircleImp* c = static_cast( args[1] ); - Coordinate center = c->center(); - double radiussq = c->squareRadius(); - const LineData line = static_cast( args[0] )->data(); - Coordinate rela = line.a - center; - Coordinate relb = line.b - center; - Coordinate ab = relb - rela; - double t = (relb.x*ab.x + relb.y*ab.y)/(ab.x*ab.x + ab.y*ab.y); - Coordinate relh = relb - t*ab; - double normhsq = relh.x*relh.x + relh.y*relh.y; - - /* - * compute the inversion of the two endpoints - */ - - Coordinate newcenterrel = 0.5*radiussq/normhsq*relh; - Coordinate relainv = radiussq/rela.squareLength() * rela; - Coordinate relbinv = radiussq/relb.squareLength() * relb; - - if ( normhsq < 1e-12*radiussq ) - { - if ( rela.squareLength() < 1e-12 ) - { - return new RayImp( relbinv + center, 2*relbinv + center ); - } - if ( relb.squareLength() < 1e-12 ) - { - return new RayImp( relainv + center, 2*relainv + center ); - } - if ( relb.x*rela.x + relb.y*rela.y > 0 ) - { - return new SegmentImp( relainv + center, relbinv + center ); - } - return new InvalidImp(); - } - double newradius = 0.5*radiussq/sqrt(normhsq); - - relainv -= newcenterrel; - relbinv -= newcenterrel; - double angle1 = atan2( relainv.y, relainv.x ); - double angle2 = atan2( relbinv.y, relbinv.x ); - double angle = angle2 - angle1; - if ( ab.x*rela.y - ab.y*rela.x > 0 ) - { - angle1 = angle2; - angle = -angle; - } - while ( angle1 < 0 ) angle1 += 2*M_PI; - while ( angle1 >= 2*M_PI ) angle1 -= 2*M_PI; - while ( angle < 0 ) angle += 2*M_PI; - while ( angle >= 2*M_PI ) angle -= 2*M_PI; - return new ArcImp( newcenterrel + center, newradius, angle1, angle ); -} - -/* - * inversion of a circle - */ - -static const ArgsParser::spec argsspecInvertCircle[] = -{ - { CircleImp::stype(), I18N_NOOP( "Compute the inversion of this circle" ), - I18N_NOOP( "Select the circle to invert..." ), false }, - { CircleImp::stype(), str1, str2, false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertCircleType ) - -InvertCircleType::InvertCircleType() - : ArgsParserObjectType( "InvertCircle", argsspecInvertCircle, 2 ) -{ -} - -InvertCircleType::~InvertCircleType() -{ -} - -const InvertCircleType* InvertCircleType::instance() -{ - static const InvertCircleType s; - return &s; -} - -const ObjectImpType* InvertCircleType::resultId() const -{ - return CircleImp::stype(); -} - -ObjectImp* InvertCircleType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - const CircleImp* refcircle = static_cast( args[1] ); - Coordinate refc = refcircle->center(); - double refrsq = refcircle->squareRadius(); - const CircleImp* circle = static_cast( args[0] ); - Coordinate c = circle->center() - refc; - double clength = c.length(); - Coordinate cnorm = Coordinate (1.,0.); - if ( clength != 0.0 ) cnorm = c/clength; - double r = circle->radius(); - Coordinate tc = r*cnorm; - Coordinate b = c + tc; //(1 + t)*c; - double bsq = b.x*b.x + b.y*b.y; - Coordinate bprime = refrsq*b/bsq; - if ( std::fabs( clength - r ) < 1e-6*clength ) // circle through origin -> line - { - return new LineImp( bprime+refc, bprime+refc+Coordinate( -c.y, c.x ) ); - } - - Coordinate a = c - tc; - double asq = a.x*a.x + a.y*a.y; - Coordinate aprime = refrsq*a/asq; - - Coordinate cprime = 0.5*(aprime + bprime); - double rprime = 0.5*( bprime - aprime ).length(); - - return new CircleImp( cprime + refc, rprime ); -} - -/* - * inversion of an arc - */ - -static const ArgsParser::spec argsspecInvertArc[] = -{ - { ArcImp::stype(), I18N_NOOP( "Compute the inversion of this arc" ), - I18N_NOOP( "Select the arc to invert..." ), false }, - { CircleImp::stype(), str1, str2, false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertArcType ) - -InvertArcType::InvertArcType() - : ArgsParserObjectType( "InvertArc", argsspecInvertArc, 2 ) -{ -} - -InvertArcType::~InvertArcType() -{ -} - -const InvertArcType* InvertArcType::instance() -{ - static const InvertArcType s; - return &s; -} - -const ObjectImpType* InvertArcType::resultId() const -{ - return ArcImp::stype(); -} - -ObjectImp* InvertArcType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - const CircleImp* refcircle = static_cast( args[1] ); - Coordinate refc = refcircle->center(); - double refrsq = refcircle->squareRadius(); - const ArcImp* arc = static_cast( args[0] ); - Coordinate c = arc->center() - refc; - double clength = c.length(); - Coordinate cnorm = Coordinate (1.,0.); - if ( clength != 0.0 ) cnorm = c/clength; - double r = arc->radius(); - /* - * r > clength means center of inversion circle inside of circle supporting arc - */ - Coordinate tc = r*cnorm; - Coordinate b = c + tc; - double bsq = b.x*b.x + b.y*b.y; - Coordinate bprime = refrsq*b/bsq; - if ( std::fabs( clength - r ) < 1e-6*clength ) // support circle through origin -> - // segment, ray or invalid - // (reversed segment, union of two rays) - { - bool valid1 = false; - bool valid2 = false; - Coordinate ep1 = arc->firstEndPoint() - refc; - Coordinate ep2 = arc->secondEndPoint() - refc; - Coordinate ep1inv = Coordinate::invalidCoord(); - Coordinate ep2inv = Coordinate::invalidCoord(); - double ep1sq = ep1.squareLength(); - if ( ep1sq > 1e-12 ) - { - valid1 = true; - ep1inv = refrsq/ep1sq * ep1; - } - Coordinate rayendp = ep1inv; - int sign = 1; - double ep2sq = ep2.squareLength(); - if ( ep2sq > 1e-12 ) - { - valid2 = true; - ep2inv = refrsq/ep2sq * ep2; - rayendp = ep2inv; - sign = -1; - } - if ( valid1 || valid2 ) - { - if ( valid1 && valid2 ) - { - // this gives either a segment or the complement of a segment (relative - // to its support line). We return a segment in any case (fixme) - double ang = atan2( -c.y, -c.x ); - double sa = arc->startAngle(); - if ( ang < sa ) ang += 2*M_PI; - if ( ang - sa - arc->angle() < 0 ) return new InvalidImp(); - return new SegmentImp( ep1inv + refc, ep2inv + refc ); - } else - return new RayImp ( rayendp + refc, - rayendp + refc + sign*Coordinate( -c.y, c.x ) ); // this should give a Ray - } else - return new LineImp( bprime+refc, bprime+refc+Coordinate( -c.y, c.x ) ); - } - - Coordinate a = c - tc; - double asq = a.x*a.x + a.y*a.y; - Coordinate aprime = refrsq*a/asq; - - Coordinate cprime = 0.5*(aprime + bprime); - double rprime = 0.5*( bprime - aprime ).length(); - - Coordinate ep1 = arc->firstEndPoint() - refc; - double ang1 = arc->startAngle(); - double newstartangle = 2*atan2(ep1.y,ep1.x) - ang1; - Coordinate ep2 = arc->secondEndPoint() - refc; - double ang2 = ang1 + arc->angle(); - double newendangle = 2*atan2(ep2.y,ep2.x) - ang2; - double newangle = newendangle - newstartangle; - - /* - * newstartangle and newendangle might have to be exchanged: - * this is the case if the circle supporting our arc does not - * contain the center of the inversion circle - */ - if ( r < clength ) - { - newstartangle = newendangle - M_PI; - newangle = - newangle; - // newendangle is no-longer valid - } - while ( newstartangle < 0 ) newstartangle += 2*M_PI; - while ( newstartangle >= 2*M_PI ) newstartangle -= 2*M_PI; - while ( newangle < 0 ) newangle += 2*M_PI; - while ( newangle >= 2*M_PI ) newangle -= 2*M_PI; - return new ArcImp( cprime + refc, rprime, newstartangle, newangle ); -} - diff --git a/kig/objects/inversion_type.cpp b/kig/objects/inversion_type.cpp new file mode 100644 index 00000000..4f270582 --- /dev/null +++ b/kig/objects/inversion_type.cpp @@ -0,0 +1,412 @@ +// Copyright (C) 2005 Maurizio Paolini + +// 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 "inversion_type.h" +#include "point_imp.h" +#include "line_imp.h" +#include "circle_imp.h" +#include "other_imp.h" +#include "bogus_imp.h" + +#include "../misc/common.h" + +#include + +static const char str1[] = I18N_NOOP( "Invert with respect to this circle" ); +static const char str2[] = I18N_NOOP( "Select the circle we want to invert against..." ); + +static const ArgsParser::spec argsspecInvertPoint[] = +{ + { PointImp::stype(), I18N_NOOP( "Compute the inversion of this point" ), + I18N_NOOP( "Select the point to invert..." ), false }, + { CircleImp::stype(), str1, str2, false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertPointType ) + +InvertPointType::InvertPointType() + : ArgsParserObjectType( "InvertPoint", argsspecInvertPoint, 2 ) +{ +} + +InvertPointType::~InvertPointType() +{ +} + +const InvertPointType* InvertPointType::instance() +{ + static const InvertPointType s; + return &s; +} + +const ObjectImpType* InvertPointType::resultId() const +{ + return PointImp::stype(); +} + +ObjectImp* InvertPointType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + const CircleImp* c = static_cast( args[1] ); + Coordinate center = c->center(); + Coordinate relp = static_cast( args[0] )->coordinate() - center; + double radiussq = c->squareRadius(); + double normsq = relp.x*relp.x + relp.y*relp.y; + if ( normsq == 0 ) return new InvalidImp; + return new PointImp( center + (radiussq/normsq)*relp ); +} + +/* + * inversion of a line + */ + +static const ArgsParser::spec argsspecInvertLine[] = +{ + { LineImp::stype(), I18N_NOOP( "Compute the inversion of this line" ), + I18N_NOOP( "Select the line to invert..." ), false }, + { CircleImp::stype(), str1, str2, false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertLineType ) + +InvertLineType::InvertLineType() + : ArgsParserObjectType( "InvertLine", argsspecInvertLine, 2 ) +{ +} + +InvertLineType::~InvertLineType() +{ +} + +const InvertLineType* InvertLineType::instance() +{ + static const InvertLineType s; + return &s; +} + +const ObjectImpType* InvertLineType::resultId() const +{ + return CircleImp::stype(); +} + +ObjectImp* InvertLineType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + const CircleImp* c = static_cast( args[1] ); + Coordinate center = c->center(); + double radiussq = c->squareRadius(); + const LineData line = static_cast( args[0] )->data(); + Coordinate relb = line.b - center; + Coordinate ab = line.b - line.a; + double t = (relb.x*ab.x + relb.y*ab.y)/(ab.x*ab.x + ab.y*ab.y); + Coordinate relh = relb - t*ab; + double normhsq = relh.x*relh.x + relh.y*relh.y; + if ( normhsq < 1e-12*radiussq ) return new LineImp( line.a, line.b ); + Coordinate newcenter = center + 0.5*radiussq/normhsq*relh; + double newradius = 0.5*radiussq/sqrt(normhsq); + + return new CircleImp( newcenter, newradius ); +} + +/* + * inversion of a segment + */ + +static const ArgsParser::spec argsspecInvertSegment[] = +{ + { SegmentImp::stype(), I18N_NOOP( "Compute the inversion of this segment" ), + I18N_NOOP( "Select the segment to invert..." ), false }, + { CircleImp::stype(), str1, str2, false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertSegmentType ) + +InvertSegmentType::InvertSegmentType() + : ArgsParserObjectType( "InvertSegment", argsspecInvertSegment, 2 ) +{ +} + +InvertSegmentType::~InvertSegmentType() +{ +} + +const InvertSegmentType* InvertSegmentType::instance() +{ + static const InvertSegmentType s; + return &s; +} + +const ObjectImpType* InvertSegmentType::resultId() const +{ + return ArcImp::stype(); +} + +ObjectImp* InvertSegmentType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + const CircleImp* c = static_cast( args[1] ); + Coordinate center = c->center(); + double radiussq = c->squareRadius(); + const LineData line = static_cast( args[0] )->data(); + Coordinate rela = line.a - center; + Coordinate relb = line.b - center; + Coordinate ab = relb - rela; + double t = (relb.x*ab.x + relb.y*ab.y)/(ab.x*ab.x + ab.y*ab.y); + Coordinate relh = relb - t*ab; + double normhsq = relh.x*relh.x + relh.y*relh.y; + + /* + * compute the inversion of the two endpoints + */ + + Coordinate newcenterrel = 0.5*radiussq/normhsq*relh; + Coordinate relainv = radiussq/rela.squareLength() * rela; + Coordinate relbinv = radiussq/relb.squareLength() * relb; + + if ( normhsq < 1e-12*radiussq ) + { + if ( rela.squareLength() < 1e-12 ) + { + return new RayImp( relbinv + center, 2*relbinv + center ); + } + if ( relb.squareLength() < 1e-12 ) + { + return new RayImp( relainv + center, 2*relainv + center ); + } + if ( relb.x*rela.x + relb.y*rela.y > 0 ) + { + return new SegmentImp( relainv + center, relbinv + center ); + } + return new InvalidImp(); + } + double newradius = 0.5*radiussq/sqrt(normhsq); + + relainv -= newcenterrel; + relbinv -= newcenterrel; + double angle1 = atan2( relainv.y, relainv.x ); + double angle2 = atan2( relbinv.y, relbinv.x ); + double angle = angle2 - angle1; + if ( ab.x*rela.y - ab.y*rela.x > 0 ) + { + angle1 = angle2; + angle = -angle; + } + while ( angle1 < 0 ) angle1 += 2*M_PI; + while ( angle1 >= 2*M_PI ) angle1 -= 2*M_PI; + while ( angle < 0 ) angle += 2*M_PI; + while ( angle >= 2*M_PI ) angle -= 2*M_PI; + return new ArcImp( newcenterrel + center, newradius, angle1, angle ); +} + +/* + * inversion of a circle + */ + +static const ArgsParser::spec argsspecInvertCircle[] = +{ + { CircleImp::stype(), I18N_NOOP( "Compute the inversion of this circle" ), + I18N_NOOP( "Select the circle to invert..." ), false }, + { CircleImp::stype(), str1, str2, false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertCircleType ) + +InvertCircleType::InvertCircleType() + : ArgsParserObjectType( "InvertCircle", argsspecInvertCircle, 2 ) +{ +} + +InvertCircleType::~InvertCircleType() +{ +} + +const InvertCircleType* InvertCircleType::instance() +{ + static const InvertCircleType s; + return &s; +} + +const ObjectImpType* InvertCircleType::resultId() const +{ + return CircleImp::stype(); +} + +ObjectImp* InvertCircleType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + const CircleImp* refcircle = static_cast( args[1] ); + Coordinate refc = refcircle->center(); + double refrsq = refcircle->squareRadius(); + const CircleImp* circle = static_cast( args[0] ); + Coordinate c = circle->center() - refc; + double clength = c.length(); + Coordinate cnorm = Coordinate (1.,0.); + if ( clength != 0.0 ) cnorm = c/clength; + double r = circle->radius(); + Coordinate tc = r*cnorm; + Coordinate b = c + tc; //(1 + t)*c; + double bsq = b.x*b.x + b.y*b.y; + Coordinate bprime = refrsq*b/bsq; + if ( std::fabs( clength - r ) < 1e-6*clength ) // circle through origin -> line + { + return new LineImp( bprime+refc, bprime+refc+Coordinate( -c.y, c.x ) ); + } + + Coordinate a = c - tc; + double asq = a.x*a.x + a.y*a.y; + Coordinate aprime = refrsq*a/asq; + + Coordinate cprime = 0.5*(aprime + bprime); + double rprime = 0.5*( bprime - aprime ).length(); + + return new CircleImp( cprime + refc, rprime ); +} + +/* + * inversion of an arc + */ + +static const ArgsParser::spec argsspecInvertArc[] = +{ + { ArcImp::stype(), I18N_NOOP( "Compute the inversion of this arc" ), + I18N_NOOP( "Select the arc to invert..." ), false }, + { CircleImp::stype(), str1, str2, false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InvertArcType ) + +InvertArcType::InvertArcType() + : ArgsParserObjectType( "InvertArc", argsspecInvertArc, 2 ) +{ +} + +InvertArcType::~InvertArcType() +{ +} + +const InvertArcType* InvertArcType::instance() +{ + static const InvertArcType s; + return &s; +} + +const ObjectImpType* InvertArcType::resultId() const +{ + return ArcImp::stype(); +} + +ObjectImp* InvertArcType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + const CircleImp* refcircle = static_cast( args[1] ); + Coordinate refc = refcircle->center(); + double refrsq = refcircle->squareRadius(); + const ArcImp* arc = static_cast( args[0] ); + Coordinate c = arc->center() - refc; + double clength = c.length(); + Coordinate cnorm = Coordinate (1.,0.); + if ( clength != 0.0 ) cnorm = c/clength; + double r = arc->radius(); + /* + * r > clength means center of inversion circle inside of circle supporting arc + */ + Coordinate tc = r*cnorm; + Coordinate b = c + tc; + double bsq = b.x*b.x + b.y*b.y; + Coordinate bprime = refrsq*b/bsq; + if ( std::fabs( clength - r ) < 1e-6*clength ) // support circle through origin -> + // segment, ray or invalid + // (reversed segment, union of two rays) + { + bool valid1 = false; + bool valid2 = false; + Coordinate ep1 = arc->firstEndPoint() - refc; + Coordinate ep2 = arc->secondEndPoint() - refc; + Coordinate ep1inv = Coordinate::invalidCoord(); + Coordinate ep2inv = Coordinate::invalidCoord(); + double ep1sq = ep1.squareLength(); + if ( ep1sq > 1e-12 ) + { + valid1 = true; + ep1inv = refrsq/ep1sq * ep1; + } + Coordinate rayendp = ep1inv; + int sign = 1; + double ep2sq = ep2.squareLength(); + if ( ep2sq > 1e-12 ) + { + valid2 = true; + ep2inv = refrsq/ep2sq * ep2; + rayendp = ep2inv; + sign = -1; + } + if ( valid1 || valid2 ) + { + if ( valid1 && valid2 ) + { + // this gives either a segment or the complement of a segment (relative + // to its support line). We return a segment in any case (fixme) + double ang = atan2( -c.y, -c.x ); + double sa = arc->startAngle(); + if ( ang < sa ) ang += 2*M_PI; + if ( ang - sa - arc->angle() < 0 ) return new InvalidImp(); + return new SegmentImp( ep1inv + refc, ep2inv + refc ); + } else + return new RayImp ( rayendp + refc, + rayendp + refc + sign*Coordinate( -c.y, c.x ) ); // this should give a Ray + } else + return new LineImp( bprime+refc, bprime+refc+Coordinate( -c.y, c.x ) ); + } + + Coordinate a = c - tc; + double asq = a.x*a.x + a.y*a.y; + Coordinate aprime = refrsq*a/asq; + + Coordinate cprime = 0.5*(aprime + bprime); + double rprime = 0.5*( bprime - aprime ).length(); + + Coordinate ep1 = arc->firstEndPoint() - refc; + double ang1 = arc->startAngle(); + double newstartangle = 2*atan2(ep1.y,ep1.x) - ang1; + Coordinate ep2 = arc->secondEndPoint() - refc; + double ang2 = ang1 + arc->angle(); + double newendangle = 2*atan2(ep2.y,ep2.x) - ang2; + double newangle = newendangle - newstartangle; + + /* + * newstartangle and newendangle might have to be exchanged: + * this is the case if the circle supporting our arc does not + * contain the center of the inversion circle + */ + if ( r < clength ) + { + newstartangle = newendangle - M_PI; + newangle = - newangle; + // newendangle is no-longer valid + } + while ( newstartangle < 0 ) newstartangle += 2*M_PI; + while ( newstartangle >= 2*M_PI ) newstartangle -= 2*M_PI; + while ( newangle < 0 ) newangle += 2*M_PI; + while ( newangle >= 2*M_PI ) newangle -= 2*M_PI; + return new ArcImp( cprime + refc, rprime, newstartangle, newangle ); +} + diff --git a/kig/objects/line_imp.cc b/kig/objects/line_imp.cc deleted file mode 100644 index 4223000b..00000000 --- a/kig/objects/line_imp.cc +++ /dev/null @@ -1,571 +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 "line_imp.h" - -#include "bogus_imp.h" -#include "point_imp.h" - -#include "../misc/rect.h" -#include "../misc/common.h" -#include "../misc/kigtransform.h" -#include "../misc/kigpainter.h" -#include "../kig/kig_view.h" - -#include - -#include -using namespace std; - -AbstractLineImp::AbstractLineImp( const Coordinate& a, const Coordinate& b ) - : mdata( a, b ) -{ -} - -AbstractLineImp::~AbstractLineImp() -{ -} - -bool AbstractLineImp::inRect( const Rect& r, int width, const KigWidget& w ) const -{ - return lineInRect( r, mdata.a, mdata.b, width, this, w ); -} - -const uint AbstractLineImp::numberOfProperties() const -{ - return Parent::numberOfProperties() + 2; -} - -const ObjectImpType* AbstractLineImp::impRequirementForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::impRequirementForProperty( which ); - else return AbstractLineImp::stype(); -} - -const char* AbstractLineImp::iconForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::iconForProperty( which ); - if ( which == Parent::numberOfProperties() ) - return "slope"; // slope - if ( which == Parent::numberOfProperties() + 1 ) - return "kig_text"; // equation - else assert( false ); - return ""; -} - -ObjectImp* AbstractLineImp::property( uint which, const KigDocument& w ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::property( which, w ); - if ( which == Parent::numberOfProperties() ) - return new DoubleImp( slope() ); - if ( which == Parent::numberOfProperties() + 1 ) - return new StringImp( equationString() ); - else assert( false ); - return new InvalidImp; -} - -const QCStringList AbstractLineImp::propertiesInternalNames() const -{ - QCStringList l = Parent::propertiesInternalNames(); - l << "slope"; - l << "equation"; - assert( l.size() == AbstractLineImp::numberOfProperties() ); - return l; -} - -const QCStringList AbstractLineImp::properties() const -{ - QCStringList l = Parent::properties(); - l << I18N_NOOP( "Slope" ); - l << I18N_NOOP( "Equation" ); - assert( l.size() == AbstractLineImp::numberOfProperties() ); - return l; -} - -const uint SegmentImp::numberOfProperties() const -{ - return Parent::numberOfProperties() + 4; -} - -const QCStringList SegmentImp::propertiesInternalNames() const -{ - QCStringList s = Parent::propertiesInternalNames(); - s << "length"; - s << "mid-point"; - s << "end-point-A"; - s << "end-point-B"; - assert( s.size() == SegmentImp::numberOfProperties() ); - return s; -} - -const QCStringList SegmentImp::properties() const -{ - QCStringList s = Parent::properties(); - s << I18N_NOOP( "Length" ); - s << I18N_NOOP( "Mid Point" ); - s << I18N_NOOP( "First End Point" ); - s << I18N_NOOP( "Second End Point" ); - assert( s.size() == SegmentImp::numberOfProperties() ); - return s; -} - -const ObjectImpType* SegmentImp::impRequirementForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::impRequirementForProperty( which ); - else return SegmentImp::stype(); -} - -const char* SegmentImp::iconForProperty( uint which ) const -{ - int pnum = 0; - if ( which < Parent::numberOfProperties() ) - return Parent::iconForProperty( which ); - else if ( which == Parent::numberOfProperties() + pnum++ ) - return "distance"; // length - else if ( which == Parent::numberOfProperties() + pnum++ ) - return "segment_midpoint"; // mid point - else if ( which == Parent::numberOfProperties() + pnum++ ) - return "endpoint1"; // mid point - else if ( which == Parent::numberOfProperties() + pnum++ ) - return "endpoint2"; // mid point - else assert( false ); - return ""; -} - -ObjectImp* SegmentImp::property( uint which, const KigDocument& w ) const -{ - int pnum = 0; - - if ( which < Parent::numberOfProperties() ) - return Parent::property( which, w ); - else if ( which == Parent::numberOfProperties() + pnum++ ) - return new DoubleImp( mdata.dir().length() ); - else if ( which == Parent::numberOfProperties() + pnum++ ) - return new PointImp( ( mdata.a + mdata.b ) / 2 ); - else if ( which == Parent::numberOfProperties() + pnum++ ) - return new PointImp( mdata.a ); - else if ( which == Parent::numberOfProperties() + pnum++ ) - return new PointImp( mdata.b ); - else assert( false ); - return new InvalidImp; -} - -double AbstractLineImp::slope() const -{ - Coordinate diff = mdata.dir(); - return diff.y / diff.x; -} - -const TQString AbstractLineImp::equationString() const -{ - Coordinate p = mdata.a; - Coordinate q = mdata.b; - - double m = ( q.y - p.y ) / ( q.x - p.x ); - double r = - ( q.y - p.y ) * p.x / ( q.x - p.x ) + p.y; - - TQString ret = TQString::fromUtf8( "y = %1x " ) + - TQString::fromUtf8( r > 0 ? "+" : "-" ) + - TQString::fromUtf8( " %2" ); - - ret = ret.arg( m, 0, 'g', 3 ); - ret = ret.arg( abs( r ), 0, 'g', 3 ); - - return ret; -} - -void SegmentImp::draw( KigPainter& p ) const -{ - p.drawSegment( mdata ); -} - -bool SegmentImp::contains( const Coordinate& p, int width, const KigWidget& w ) const -{ - return internalContainsPoint( p, w.screenInfo().normalMiss( width ) ); -} - -void RayImp::draw( KigPainter& p ) const -{ - p.drawRay( mdata ); -} - -bool RayImp::contains( const Coordinate& p, int width, const KigWidget& w ) const -{ - return internalContainsPoint( p, w.screenInfo().normalMiss( width ) ); -} - -void LineImp::draw( KigPainter& p ) const -{ - p.drawLine( mdata ); -} - -bool LineImp::contains( const Coordinate& p, int width, const KigWidget& w ) const -{ - return internalContainsPoint( p, w.screenInfo().normalMiss( width ) ); -} - -SegmentImp::SegmentImp( const Coordinate& a, const Coordinate& b ) - : AbstractLineImp( a, b ) -{ -} - -RayImp::RayImp( const Coordinate& a, const Coordinate& b ) - : AbstractLineImp( a, b ) -{ -} - -LineImp::LineImp( const Coordinate& a, const Coordinate& b ) - : AbstractLineImp( a, b ) -{ -} - -SegmentImp* SegmentImp::copy() const -{ - return new SegmentImp( mdata ); -} - -RayImp* RayImp::copy() const -{ - return new RayImp( mdata ); -} - -LineImp* LineImp::copy() const -{ - return new LineImp( mdata ); -} - -const Coordinate SegmentImp::getPoint( double param, const KigDocument& ) const -{ - return mdata.a + mdata.dir()*param; -} - -double SegmentImp::getParam( const Coordinate& p, const KigDocument& ) const -{ - Coordinate pt = calcPointOnPerpend( data(), p ); - pt = calcIntersectionPoint( data(), LineData( p, pt ) ); - // if pt is over the end of the segment ( i.e. it's on the line - // which the segment is a part of, but not of the segment itself..; - // ) we set it to one of the end points of the segment... - if ((pt - mdata.a).length() > mdata.dir().length() ) - pt = mdata.b; - else if ( (pt- mdata.b).length() > mdata.dir().length() ) - pt = mdata.a; - if (mdata.b == mdata.a) return 0; - return ((pt - mdata.a).length())/(mdata.dir().length()); -} - -LineData AbstractLineImp::data() const -{ - return mdata; -} - -const Coordinate RayImp::getPoint( double param, const KigDocument& ) const -{ - param = 1.0/param - 1.0; - return mdata.a + mdata.dir()*param; -} - -double RayImp::getParam( const Coordinate& p, const KigDocument& ) const -{ - const LineData ld = data(); - Coordinate pt = calcPointOnPerpend( ld, p ); - pt = calcIntersectionPoint( ld, LineData( p, pt )); - // if pt is over the end of the ray ( i.e. it's on the line - // which the ray is a part of, but not of the ray itself..; - // ) we set it to the start point of the ray... - Coordinate dir = ld.dir(); - pt -= ld.a; - double param; - if ( dir.x != 0 ) param = pt.x / dir.x; - else if ( dir.y != 0 ) param = pt.y / dir.y; - else param = 0.; - if ( param < 0. ) param = 0.; - - // mp: let's try with 1/(x+1), this reverses the mapping, but - // should allow to take advantage of the tightness of floating point - // numbers near zero, in order to get more possible positions near - // infinity - - param = 1./( param + 1. ); - - assert( param >= 0. && param <= 1. ); - return param; -} - -const Coordinate LineImp::getPoint( double p, const KigDocument& ) const -{ - // inspired upon KSeg - - // we need to spread the points over the line, it should also come near - // the (infinite) end of the line, but most points should be near - // the two points we contain... - if ( p <= 0. ) p = 1e-6; - if ( p >= 1. ) p = 1 - 1e-6; - p = 2*p - 1; - if (p > 0) p = p/(1 - p); - else p = p/(1 + p); -// p *= 1024; // such multiplying factor could be useful in order to - // have more points near infinity, at the expense of - // points near ma and mb - return mdata.a + p*mdata.dir(); -} - -double LineImp::getParam( const Coordinate& point, const KigDocument& ) const -{ - // somewhat the reverse of getPoint, although it also supports - // points not on the line... - - Coordinate pa = point - mdata.a; - Coordinate ba = mdata.dir(); - double balsq = ba.x*ba.x + ba.y*ba.y; - assert (balsq > 0); - - double p = (pa.x*ba.x + pa.y*ba.y)/balsq; -// p /= 1024; - if (p > 0) p = p/(1+p); - else p = p/(1-p); - - return 0.5*(p + 1); -} - -ObjectImp* SegmentImp::transform( const Transformation& t ) const -{ - if ( ! t.isAffine() ) /* we need to check the position of the two points */ - { - if ( t.getProjectiveIndicator( mdata.a ) * - t.getProjectiveIndicator( mdata.b ) < 0 ) - return new InvalidImp(); - } - Coordinate na = t.apply( mdata.a ); - Coordinate nb = t.apply( mdata.b ); - if( na.valid() && nb.valid() ) return new SegmentImp( na, nb ); - else return new InvalidImp(); -} - -ObjectImp* LineImp::transform( const Transformation& t ) const -{ - Coordinate na = t.apply( mdata.a ); - Coordinate nb = t.apply( mdata.b ); - if ( na.valid() && nb.valid() ) return new LineImp( na, nb ); - else return new InvalidImp(); -} - -ObjectImp* RayImp::transform( const Transformation& t ) const -{ - if ( ! t.isAffine() ) /* we need to check the position of the two points */ - { - double pa = t.getProjectiveIndicator( mdata.a ); - double pb = t.getProjectiveIndicator( mdata.b ); - if ( pa < 0 ) pb = -pb; - if ( pb < fabs (pa) ) return new InvalidImp(); - Coordinate na = t.apply( mdata.a ); - Coordinate nb = t.apply0( mdata.b - mdata.a ); - if ( na.valid() && nb.valid() ) return new SegmentImp( na, nb ); - else return new InvalidImp(); - } - Coordinate na = t.apply( mdata.a ); - Coordinate nb = t.apply( mdata.b ); - if ( na.valid() && nb.valid() ) return new RayImp( na, nb ); - else return new InvalidImp(); -} - -AbstractLineImp::AbstractLineImp( const LineData& d ) - : mdata( d ) -{ -} - -SegmentImp::SegmentImp( const LineData& d ) - : AbstractLineImp( d ) -{ -} - -RayImp::RayImp( const LineData& d ) - : AbstractLineImp( d ) -{ -} - -LineImp::LineImp( const LineData& d ) - : AbstractLineImp( d ) -{ -} - -double SegmentImp::length() const -{ - return mdata.length(); -} - -void SegmentImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -void RayImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -void LineImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -bool AbstractLineImp::equals( const ObjectImp& rhs ) const -{ - return rhs.type() == type() && - static_cast( rhs ).data() == data(); -} - -const ObjectImpType* AbstractLineImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "line", I18N_NOOP( "line" ), - I18N_NOOP( "Select a Line" ), 0, 0, 0, 0, 0, 0, 0 ); - return &t; -} - -const ObjectImpType* LineImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "line", - I18N_NOOP( "line" ), - I18N_NOOP( "Select this line" ), - I18N_NOOP( "Select line %1" ), - I18N_NOOP( "Remove a Line" ), - I18N_NOOP( "Add a Line" ), - I18N_NOOP( "Move a Line" ), - I18N_NOOP( "Attach to this line" ), - I18N_NOOP( "Show a Line" ), - I18N_NOOP( "Hide a Line" ) - ); - return &t; -} - -const ObjectImpType* SegmentImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "segment", - I18N_NOOP( "segment" ), - I18N_NOOP( "Select this segment" ), - I18N_NOOP( "Select segment %1" ), - I18N_NOOP( "Remove a Segment" ), - I18N_NOOP( "Add a Segment" ), - I18N_NOOP( "Move a Segment" ), - I18N_NOOP( "Attach to this segment" ), - I18N_NOOP( "Show a Segment" ), - I18N_NOOP( "Hide a Segment" ) - ); - return &t; -} - -const ObjectImpType* RayImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "ray", - I18N_NOOP( "half-line" ), - I18N_NOOP( "Select this half-line" ), - I18N_NOOP( "Select half-line %1" ), - I18N_NOOP( "Remove a Half-Line" ), - I18N_NOOP( "Add a Half-Line" ), - I18N_NOOP( "Move a Half-Line" ), - I18N_NOOP( "Attach to this half-line" ), - I18N_NOOP( "Show a Half-Line" ), - I18N_NOOP( "Hide a Half-Line" ) - ); - return &t; -} - -const ObjectImpType* SegmentImp::type() const -{ - return SegmentImp::stype(); -} - -const ObjectImpType* RayImp::type() const -{ - return RayImp::stype(); -} - -const ObjectImpType* LineImp::type() const -{ - return LineImp::stype(); -} - -bool SegmentImp::containsPoint( const Coordinate& p, const KigDocument& ) const -{ - return internalContainsPoint( p, test_threshold ); -} - -bool SegmentImp::internalContainsPoint( const Coordinate& p, double threshold ) const -{ - return isOnSegment( p, mdata.a, mdata.b, threshold ); -} - -bool RayImp::containsPoint( const Coordinate& p, const KigDocument& ) const -{ - return internalContainsPoint( p, test_threshold ); -} - -bool RayImp::internalContainsPoint( const Coordinate& p, double threshold ) const -{ - return isOnRay( p, mdata.a, mdata.b, threshold ); -} - -bool LineImp::containsPoint( const Coordinate& p, const KigDocument& ) const -{ - return internalContainsPoint( p, test_threshold ); -} - -bool LineImp::internalContainsPoint( const Coordinate& p, double threshold ) const -{ - return isOnLine( p, mdata.a, mdata.b, threshold ); -} - -bool AbstractLineImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const -{ - int pnum = 0; - - if ( which < Parent::numberOfProperties() ) - return Parent::isPropertyDefinedOnOrThroughThisImp( which ); - else if ( which == Parent::numberOfProperties() + pnum++ ) - return false; - else if ( which == Parent::numberOfProperties() + pnum++ ) - return true; - else if ( which == Parent::numberOfProperties() + pnum++ ) - return true; - else if ( which == Parent::numberOfProperties() + pnum++ ) - return true; - else assert( false ); - return false; -} - -Rect SegmentImp::surroundingRect() const -{ - return Rect( mdata.a, mdata.b ); -} - -Rect RayImp::surroundingRect() const -{ - return Rect::invalidRect(); -} - -Rect LineImp::surroundingRect() const -{ - return Rect::invalidRect(); -} diff --git a/kig/objects/line_imp.cpp b/kig/objects/line_imp.cpp new file mode 100644 index 00000000..4223000b --- /dev/null +++ b/kig/objects/line_imp.cpp @@ -0,0 +1,571 @@ +// 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 "line_imp.h" + +#include "bogus_imp.h" +#include "point_imp.h" + +#include "../misc/rect.h" +#include "../misc/common.h" +#include "../misc/kigtransform.h" +#include "../misc/kigpainter.h" +#include "../kig/kig_view.h" + +#include + +#include +using namespace std; + +AbstractLineImp::AbstractLineImp( const Coordinate& a, const Coordinate& b ) + : mdata( a, b ) +{ +} + +AbstractLineImp::~AbstractLineImp() +{ +} + +bool AbstractLineImp::inRect( const Rect& r, int width, const KigWidget& w ) const +{ + return lineInRect( r, mdata.a, mdata.b, width, this, w ); +} + +const uint AbstractLineImp::numberOfProperties() const +{ + return Parent::numberOfProperties() + 2; +} + +const ObjectImpType* AbstractLineImp::impRequirementForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::impRequirementForProperty( which ); + else return AbstractLineImp::stype(); +} + +const char* AbstractLineImp::iconForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::iconForProperty( which ); + if ( which == Parent::numberOfProperties() ) + return "slope"; // slope + if ( which == Parent::numberOfProperties() + 1 ) + return "kig_text"; // equation + else assert( false ); + return ""; +} + +ObjectImp* AbstractLineImp::property( uint which, const KigDocument& w ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::property( which, w ); + if ( which == Parent::numberOfProperties() ) + return new DoubleImp( slope() ); + if ( which == Parent::numberOfProperties() + 1 ) + return new StringImp( equationString() ); + else assert( false ); + return new InvalidImp; +} + +const QCStringList AbstractLineImp::propertiesInternalNames() const +{ + QCStringList l = Parent::propertiesInternalNames(); + l << "slope"; + l << "equation"; + assert( l.size() == AbstractLineImp::numberOfProperties() ); + return l; +} + +const QCStringList AbstractLineImp::properties() const +{ + QCStringList l = Parent::properties(); + l << I18N_NOOP( "Slope" ); + l << I18N_NOOP( "Equation" ); + assert( l.size() == AbstractLineImp::numberOfProperties() ); + return l; +} + +const uint SegmentImp::numberOfProperties() const +{ + return Parent::numberOfProperties() + 4; +} + +const QCStringList SegmentImp::propertiesInternalNames() const +{ + QCStringList s = Parent::propertiesInternalNames(); + s << "length"; + s << "mid-point"; + s << "end-point-A"; + s << "end-point-B"; + assert( s.size() == SegmentImp::numberOfProperties() ); + return s; +} + +const QCStringList SegmentImp::properties() const +{ + QCStringList s = Parent::properties(); + s << I18N_NOOP( "Length" ); + s << I18N_NOOP( "Mid Point" ); + s << I18N_NOOP( "First End Point" ); + s << I18N_NOOP( "Second End Point" ); + assert( s.size() == SegmentImp::numberOfProperties() ); + return s; +} + +const ObjectImpType* SegmentImp::impRequirementForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::impRequirementForProperty( which ); + else return SegmentImp::stype(); +} + +const char* SegmentImp::iconForProperty( uint which ) const +{ + int pnum = 0; + if ( which < Parent::numberOfProperties() ) + return Parent::iconForProperty( which ); + else if ( which == Parent::numberOfProperties() + pnum++ ) + return "distance"; // length + else if ( which == Parent::numberOfProperties() + pnum++ ) + return "segment_midpoint"; // mid point + else if ( which == Parent::numberOfProperties() + pnum++ ) + return "endpoint1"; // mid point + else if ( which == Parent::numberOfProperties() + pnum++ ) + return "endpoint2"; // mid point + else assert( false ); + return ""; +} + +ObjectImp* SegmentImp::property( uint which, const KigDocument& w ) const +{ + int pnum = 0; + + if ( which < Parent::numberOfProperties() ) + return Parent::property( which, w ); + else if ( which == Parent::numberOfProperties() + pnum++ ) + return new DoubleImp( mdata.dir().length() ); + else if ( which == Parent::numberOfProperties() + pnum++ ) + return new PointImp( ( mdata.a + mdata.b ) / 2 ); + else if ( which == Parent::numberOfProperties() + pnum++ ) + return new PointImp( mdata.a ); + else if ( which == Parent::numberOfProperties() + pnum++ ) + return new PointImp( mdata.b ); + else assert( false ); + return new InvalidImp; +} + +double AbstractLineImp::slope() const +{ + Coordinate diff = mdata.dir(); + return diff.y / diff.x; +} + +const TQString AbstractLineImp::equationString() const +{ + Coordinate p = mdata.a; + Coordinate q = mdata.b; + + double m = ( q.y - p.y ) / ( q.x - p.x ); + double r = - ( q.y - p.y ) * p.x / ( q.x - p.x ) + p.y; + + TQString ret = TQString::fromUtf8( "y = %1x " ) + + TQString::fromUtf8( r > 0 ? "+" : "-" ) + + TQString::fromUtf8( " %2" ); + + ret = ret.arg( m, 0, 'g', 3 ); + ret = ret.arg( abs( r ), 0, 'g', 3 ); + + return ret; +} + +void SegmentImp::draw( KigPainter& p ) const +{ + p.drawSegment( mdata ); +} + +bool SegmentImp::contains( const Coordinate& p, int width, const KigWidget& w ) const +{ + return internalContainsPoint( p, w.screenInfo().normalMiss( width ) ); +} + +void RayImp::draw( KigPainter& p ) const +{ + p.drawRay( mdata ); +} + +bool RayImp::contains( const Coordinate& p, int width, const KigWidget& w ) const +{ + return internalContainsPoint( p, w.screenInfo().normalMiss( width ) ); +} + +void LineImp::draw( KigPainter& p ) const +{ + p.drawLine( mdata ); +} + +bool LineImp::contains( const Coordinate& p, int width, const KigWidget& w ) const +{ + return internalContainsPoint( p, w.screenInfo().normalMiss( width ) ); +} + +SegmentImp::SegmentImp( const Coordinate& a, const Coordinate& b ) + : AbstractLineImp( a, b ) +{ +} + +RayImp::RayImp( const Coordinate& a, const Coordinate& b ) + : AbstractLineImp( a, b ) +{ +} + +LineImp::LineImp( const Coordinate& a, const Coordinate& b ) + : AbstractLineImp( a, b ) +{ +} + +SegmentImp* SegmentImp::copy() const +{ + return new SegmentImp( mdata ); +} + +RayImp* RayImp::copy() const +{ + return new RayImp( mdata ); +} + +LineImp* LineImp::copy() const +{ + return new LineImp( mdata ); +} + +const Coordinate SegmentImp::getPoint( double param, const KigDocument& ) const +{ + return mdata.a + mdata.dir()*param; +} + +double SegmentImp::getParam( const Coordinate& p, const KigDocument& ) const +{ + Coordinate pt = calcPointOnPerpend( data(), p ); + pt = calcIntersectionPoint( data(), LineData( p, pt ) ); + // if pt is over the end of the segment ( i.e. it's on the line + // which the segment is a part of, but not of the segment itself..; + // ) we set it to one of the end points of the segment... + if ((pt - mdata.a).length() > mdata.dir().length() ) + pt = mdata.b; + else if ( (pt- mdata.b).length() > mdata.dir().length() ) + pt = mdata.a; + if (mdata.b == mdata.a) return 0; + return ((pt - mdata.a).length())/(mdata.dir().length()); +} + +LineData AbstractLineImp::data() const +{ + return mdata; +} + +const Coordinate RayImp::getPoint( double param, const KigDocument& ) const +{ + param = 1.0/param - 1.0; + return mdata.a + mdata.dir()*param; +} + +double RayImp::getParam( const Coordinate& p, const KigDocument& ) const +{ + const LineData ld = data(); + Coordinate pt = calcPointOnPerpend( ld, p ); + pt = calcIntersectionPoint( ld, LineData( p, pt )); + // if pt is over the end of the ray ( i.e. it's on the line + // which the ray is a part of, but not of the ray itself..; + // ) we set it to the start point of the ray... + Coordinate dir = ld.dir(); + pt -= ld.a; + double param; + if ( dir.x != 0 ) param = pt.x / dir.x; + else if ( dir.y != 0 ) param = pt.y / dir.y; + else param = 0.; + if ( param < 0. ) param = 0.; + + // mp: let's try with 1/(x+1), this reverses the mapping, but + // should allow to take advantage of the tightness of floating point + // numbers near zero, in order to get more possible positions near + // infinity + + param = 1./( param + 1. ); + + assert( param >= 0. && param <= 1. ); + return param; +} + +const Coordinate LineImp::getPoint( double p, const KigDocument& ) const +{ + // inspired upon KSeg + + // we need to spread the points over the line, it should also come near + // the (infinite) end of the line, but most points should be near + // the two points we contain... + if ( p <= 0. ) p = 1e-6; + if ( p >= 1. ) p = 1 - 1e-6; + p = 2*p - 1; + if (p > 0) p = p/(1 - p); + else p = p/(1 + p); +// p *= 1024; // such multiplying factor could be useful in order to + // have more points near infinity, at the expense of + // points near ma and mb + return mdata.a + p*mdata.dir(); +} + +double LineImp::getParam( const Coordinate& point, const KigDocument& ) const +{ + // somewhat the reverse of getPoint, although it also supports + // points not on the line... + + Coordinate pa = point - mdata.a; + Coordinate ba = mdata.dir(); + double balsq = ba.x*ba.x + ba.y*ba.y; + assert (balsq > 0); + + double p = (pa.x*ba.x + pa.y*ba.y)/balsq; +// p /= 1024; + if (p > 0) p = p/(1+p); + else p = p/(1-p); + + return 0.5*(p + 1); +} + +ObjectImp* SegmentImp::transform( const Transformation& t ) const +{ + if ( ! t.isAffine() ) /* we need to check the position of the two points */ + { + if ( t.getProjectiveIndicator( mdata.a ) * + t.getProjectiveIndicator( mdata.b ) < 0 ) + return new InvalidImp(); + } + Coordinate na = t.apply( mdata.a ); + Coordinate nb = t.apply( mdata.b ); + if( na.valid() && nb.valid() ) return new SegmentImp( na, nb ); + else return new InvalidImp(); +} + +ObjectImp* LineImp::transform( const Transformation& t ) const +{ + Coordinate na = t.apply( mdata.a ); + Coordinate nb = t.apply( mdata.b ); + if ( na.valid() && nb.valid() ) return new LineImp( na, nb ); + else return new InvalidImp(); +} + +ObjectImp* RayImp::transform( const Transformation& t ) const +{ + if ( ! t.isAffine() ) /* we need to check the position of the two points */ + { + double pa = t.getProjectiveIndicator( mdata.a ); + double pb = t.getProjectiveIndicator( mdata.b ); + if ( pa < 0 ) pb = -pb; + if ( pb < fabs (pa) ) return new InvalidImp(); + Coordinate na = t.apply( mdata.a ); + Coordinate nb = t.apply0( mdata.b - mdata.a ); + if ( na.valid() && nb.valid() ) return new SegmentImp( na, nb ); + else return new InvalidImp(); + } + Coordinate na = t.apply( mdata.a ); + Coordinate nb = t.apply( mdata.b ); + if ( na.valid() && nb.valid() ) return new RayImp( na, nb ); + else return new InvalidImp(); +} + +AbstractLineImp::AbstractLineImp( const LineData& d ) + : mdata( d ) +{ +} + +SegmentImp::SegmentImp( const LineData& d ) + : AbstractLineImp( d ) +{ +} + +RayImp::RayImp( const LineData& d ) + : AbstractLineImp( d ) +{ +} + +LineImp::LineImp( const LineData& d ) + : AbstractLineImp( d ) +{ +} + +double SegmentImp::length() const +{ + return mdata.length(); +} + +void SegmentImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +void RayImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +void LineImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +bool AbstractLineImp::equals( const ObjectImp& rhs ) const +{ + return rhs.type() == type() && + static_cast( rhs ).data() == data(); +} + +const ObjectImpType* AbstractLineImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "line", I18N_NOOP( "line" ), + I18N_NOOP( "Select a Line" ), 0, 0, 0, 0, 0, 0, 0 ); + return &t; +} + +const ObjectImpType* LineImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "line", + I18N_NOOP( "line" ), + I18N_NOOP( "Select this line" ), + I18N_NOOP( "Select line %1" ), + I18N_NOOP( "Remove a Line" ), + I18N_NOOP( "Add a Line" ), + I18N_NOOP( "Move a Line" ), + I18N_NOOP( "Attach to this line" ), + I18N_NOOP( "Show a Line" ), + I18N_NOOP( "Hide a Line" ) + ); + return &t; +} + +const ObjectImpType* SegmentImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "segment", + I18N_NOOP( "segment" ), + I18N_NOOP( "Select this segment" ), + I18N_NOOP( "Select segment %1" ), + I18N_NOOP( "Remove a Segment" ), + I18N_NOOP( "Add a Segment" ), + I18N_NOOP( "Move a Segment" ), + I18N_NOOP( "Attach to this segment" ), + I18N_NOOP( "Show a Segment" ), + I18N_NOOP( "Hide a Segment" ) + ); + return &t; +} + +const ObjectImpType* RayImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "ray", + I18N_NOOP( "half-line" ), + I18N_NOOP( "Select this half-line" ), + I18N_NOOP( "Select half-line %1" ), + I18N_NOOP( "Remove a Half-Line" ), + I18N_NOOP( "Add a Half-Line" ), + I18N_NOOP( "Move a Half-Line" ), + I18N_NOOP( "Attach to this half-line" ), + I18N_NOOP( "Show a Half-Line" ), + I18N_NOOP( "Hide a Half-Line" ) + ); + return &t; +} + +const ObjectImpType* SegmentImp::type() const +{ + return SegmentImp::stype(); +} + +const ObjectImpType* RayImp::type() const +{ + return RayImp::stype(); +} + +const ObjectImpType* LineImp::type() const +{ + return LineImp::stype(); +} + +bool SegmentImp::containsPoint( const Coordinate& p, const KigDocument& ) const +{ + return internalContainsPoint( p, test_threshold ); +} + +bool SegmentImp::internalContainsPoint( const Coordinate& p, double threshold ) const +{ + return isOnSegment( p, mdata.a, mdata.b, threshold ); +} + +bool RayImp::containsPoint( const Coordinate& p, const KigDocument& ) const +{ + return internalContainsPoint( p, test_threshold ); +} + +bool RayImp::internalContainsPoint( const Coordinate& p, double threshold ) const +{ + return isOnRay( p, mdata.a, mdata.b, threshold ); +} + +bool LineImp::containsPoint( const Coordinate& p, const KigDocument& ) const +{ + return internalContainsPoint( p, test_threshold ); +} + +bool LineImp::internalContainsPoint( const Coordinate& p, double threshold ) const +{ + return isOnLine( p, mdata.a, mdata.b, threshold ); +} + +bool AbstractLineImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const +{ + int pnum = 0; + + if ( which < Parent::numberOfProperties() ) + return Parent::isPropertyDefinedOnOrThroughThisImp( which ); + else if ( which == Parent::numberOfProperties() + pnum++ ) + return false; + else if ( which == Parent::numberOfProperties() + pnum++ ) + return true; + else if ( which == Parent::numberOfProperties() + pnum++ ) + return true; + else if ( which == Parent::numberOfProperties() + pnum++ ) + return true; + else assert( false ); + return false; +} + +Rect SegmentImp::surroundingRect() const +{ + return Rect( mdata.a, mdata.b ); +} + +Rect RayImp::surroundingRect() const +{ + return Rect::invalidRect(); +} + +Rect LineImp::surroundingRect() const +{ + return Rect::invalidRect(); +} diff --git a/kig/objects/line_type.cc b/kig/objects/line_type.cc deleted file mode 100644 index bd9a5f3e..00000000 --- a/kig/objects/line_type.cc +++ /dev/null @@ -1,334 +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 "line_type.h" - -#include "bogus_imp.h" -#include "line_imp.h" -#include "object_holder.h" -#include "other_imp.h" -#include "point_imp.h" - -#include "../kig/kig_view.h" -#include "../kig/kig_part.h" -#include "../kig/kig_commands.h" -#include "../misc/common.h" -#include "../misc/calcpaths.h" - -#include - -#include - -static const ArgsParser::spec argsspecSegmentAB[] = -{ - { PointImp::stype(), I18N_NOOP( "Construct a segment starting at this point" ), - I18N_NOOP( "Select the start point of the new segment..." ), true }, - { PointImp::stype(), I18N_NOOP( "Construct a segment ending at this point" ), - I18N_NOOP( "Select the end point of the new segment..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( SegmentABType ) - -SegmentABType::SegmentABType() - : ObjectABType( "SegmentAB", argsspecSegmentAB, 2 ) -{ -} - -SegmentABType::~SegmentABType() -{ -} - -const SegmentABType* SegmentABType::instance() -{ - static const SegmentABType s; - return &s; -} - -ObjectImp* SegmentABType::calc( const Coordinate& a, const Coordinate& b ) const -{ - return new SegmentImp( a, b ); -} - -static const char constructlineabstat[] = I18N_NOOP( "Construct a line through this point" ); - -static const ArgsParser::spec argsspecLineAB[] = -{ - { PointImp::stype(), constructlineabstat, - I18N_NOOP( "Select a point for the line to go through..." ), true }, - { PointImp::stype(), constructlineabstat, - I18N_NOOP( "Select another point for the line to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineABType ) - -LineABType::LineABType() - : ObjectABType( "LineAB", argsspecLineAB, 2 ) -{ -} - -LineABType::~LineABType() -{ -} - -const LineABType* LineABType::instance() -{ - static const LineABType s; - return &s; -} - -ObjectImp* LineABType::calc( const Coordinate& a, const Coordinate& b ) const -{ - return new LineImp( a, b ); -} - -static const char constructhalflinestartingstat[] = I18N_NOOP( "Construct a half-line starting at this point" ); - -static const ArgsParser::spec argsspecRayAB[] = -{ - { PointImp::stype(), constructhalflinestartingstat, - I18N_NOOP( "Select the start point of the new half-line..." ), true }, - { PointImp::stype(), I18N_NOOP( "Construct a half-line through this point" ), - I18N_NOOP( "Select a point for the half-line to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( RayABType ) - -RayABType::RayABType() - : ObjectABType( "RayAB", argsspecRayAB, 2 ) -{ -} - -RayABType::~RayABType() -{ -} - -const RayABType* RayABType::instance() -{ - static const RayABType s; - return &s; -} - -ObjectImp* RayABType::calc( const Coordinate& a, const Coordinate& b ) const -{ - return new RayImp( a, b ); -} - -LinePerpendLPType* LinePerpendLPType::instance() -{ - static LinePerpendLPType l; - return &l; -} - -ObjectImp* LinePerpendLPType::calc( - const LineData& a, - const Coordinate& b ) const -{ - Coordinate p = calcPointOnPerpend( a, b ); - return new LineImp( b, p ); -} - -static const ArgsParser::spec argsspecLineParallel[] = -{ - { AbstractLineImp::stype(), I18N_NOOP( "Construct a line parallel to this line" ), - I18N_NOOP( "Select a line parallel to the new line..." ), false }, - { PointImp::stype(), I18N_NOOP( "Construct the parallel line through this point" ), - I18N_NOOP( "Select a point for the new line to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineParallelLPType ) - -LineParallelLPType::LineParallelLPType() - : ObjectLPType( "LineParallel", argsspecLineParallel, 2 ) -{ -} - -LineParallelLPType::~LineParallelLPType() -{ -} - -LineParallelLPType* LineParallelLPType::instance() -{ - static LineParallelLPType l; - return &l; -} - -ObjectImp* LineParallelLPType::calc( - const LineData& a, - const Coordinate& b ) const -{ - Coordinate r = calcPointOnParallel( a, b ); - return new LineImp( r, b ); -} - -static const ArgsParser::spec argsspecLinePerpend[] = -{ - { AbstractLineImp::stype(), I18N_NOOP( "Construct a line perpendicular to this line" ), - I18N_NOOP( "Select a line perpendicular to the new line..." ), false }, - { PointImp::stype(), I18N_NOOP( "Construct a perpendicular line through this point" ), - I18N_NOOP( "Select a point for the new line to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LinePerpendLPType ) - -LinePerpendLPType::LinePerpendLPType() - : ObjectLPType( "LinePerpend", argsspecLinePerpend, 2 ) -{ -} - -LinePerpendLPType::~LinePerpendLPType() -{ -} - -const ObjectImpType* SegmentABType::resultId() const -{ - return SegmentImp::stype(); -} - -const ObjectImpType* LineABType::resultId() const -{ - return LineImp::stype(); -} - -const ObjectImpType* RayABType::resultId() const -{ - return RayImp::stype(); -} - -const ObjectImpType* LinePerpendLPType::resultId() const -{ - return LineImp::stype(); -} - -const ObjectImpType* LineParallelLPType::resultId() const -{ - return LineImp::stype(); -} - -TQStringList SegmentABType::specialActions() const -{ - TQStringList ret; - ret << i18n( "Set &Length..." ); - return ret; -} - -void SegmentABType::executeAction( int i, ObjectHolder&, ObjectTypeCalcer& c, - KigPart& d, KigWidget& w, NormalMode& ) const -{ - assert( i == 0 ); - // pretend to use this var.. - (void) i; - - std::vector parents = c.parents(); - assert( margsparser.checkArgs( parents ) ); - - Coordinate a = static_cast( parents[0]->imp() )->coordinate(); - Coordinate b = static_cast( parents[1]->imp() )->coordinate(); - - bool ok = true; - double length = getDoubleFromUser( - i18n( "Set Segment Length" ), i18n( "Choose the new length: " ), - (b-a).length(), &w, &ok, -2147483647, 2147483647, 3 ); - if ( ! ok ) return; - - Coordinate nb = a + ( b - a ).normalize( length ); - - MonitorDataObjects mon( getAllParents( parents ) ); - parents[1]->move( nb, d.document() ); - KigCommand* cd = new KigCommand( d, i18n( "Resize Segment" ) ); - mon.finish( cd ); - d.history()->addCommand( cd ); -} - -static const ArgsParser::spec argsspecLineByVector[] = -{ - { VectorImp::stype(), I18N_NOOP( "Construct a line by this vector" ), - I18N_NOOP( "Select a vector in the direction of the new line..." ), true }, - { PointImp::stype(), constructlineabstat, - I18N_NOOP( "Select a point for the new line to go through..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineByVectorType ) - -LineByVectorType::LineByVectorType() - : ArgsParserObjectType( "LineByVector", argsspecLineByVector, 2 ) -{ -} - -LineByVectorType::~LineByVectorType() -{ -} - -const LineByVectorType* LineByVectorType::instance() -{ - static const LineByVectorType s; - return &s; -} - -ObjectImp* LineByVectorType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - const VectorImp& a = *static_cast( args[0] ); - const PointImp& b = *static_cast( args[1] ); - - return new LineImp( b.coordinate(), b.coordinate() + a.dir() ); -} - -const ObjectImpType* LineByVectorType::resultId() const -{ - return LineImp::stype(); -} - -static const ArgsParser::spec argsspecHalflineByVector[] = -{ - { VectorImp::stype(), I18N_NOOP( "Construct a half-line by this vector" ), - I18N_NOOP( "Select a vector in the direction of the new half-line..." ), true }, - { PointImp::stype(), constructhalflinestartingstat, - I18N_NOOP( "Select the start point of the new half-line..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( HalflineByVectorType ) - -HalflineByVectorType::HalflineByVectorType() - : ArgsParserObjectType( "HalflineByVector", argsspecHalflineByVector, 2 ) -{ -} - -HalflineByVectorType::~HalflineByVectorType() -{ -} - -const HalflineByVectorType* HalflineByVectorType::instance() -{ - static const HalflineByVectorType s; - return &s; -} - -ObjectImp* HalflineByVectorType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - const VectorImp& a = *static_cast( args[0] ); - const PointImp& b = *static_cast( args[1] ); - - return new RayImp( b.coordinate(), b.coordinate() + a.dir() ); -} - -const ObjectImpType* HalflineByVectorType::resultId() const -{ - return RayImp::stype(); -} diff --git a/kig/objects/line_type.cpp b/kig/objects/line_type.cpp new file mode 100644 index 00000000..bd9a5f3e --- /dev/null +++ b/kig/objects/line_type.cpp @@ -0,0 +1,334 @@ +// 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 "line_type.h" + +#include "bogus_imp.h" +#include "line_imp.h" +#include "object_holder.h" +#include "other_imp.h" +#include "point_imp.h" + +#include "../kig/kig_view.h" +#include "../kig/kig_part.h" +#include "../kig/kig_commands.h" +#include "../misc/common.h" +#include "../misc/calcpaths.h" + +#include + +#include + +static const ArgsParser::spec argsspecSegmentAB[] = +{ + { PointImp::stype(), I18N_NOOP( "Construct a segment starting at this point" ), + I18N_NOOP( "Select the start point of the new segment..." ), true }, + { PointImp::stype(), I18N_NOOP( "Construct a segment ending at this point" ), + I18N_NOOP( "Select the end point of the new segment..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( SegmentABType ) + +SegmentABType::SegmentABType() + : ObjectABType( "SegmentAB", argsspecSegmentAB, 2 ) +{ +} + +SegmentABType::~SegmentABType() +{ +} + +const SegmentABType* SegmentABType::instance() +{ + static const SegmentABType s; + return &s; +} + +ObjectImp* SegmentABType::calc( const Coordinate& a, const Coordinate& b ) const +{ + return new SegmentImp( a, b ); +} + +static const char constructlineabstat[] = I18N_NOOP( "Construct a line through this point" ); + +static const ArgsParser::spec argsspecLineAB[] = +{ + { PointImp::stype(), constructlineabstat, + I18N_NOOP( "Select a point for the line to go through..." ), true }, + { PointImp::stype(), constructlineabstat, + I18N_NOOP( "Select another point for the line to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineABType ) + +LineABType::LineABType() + : ObjectABType( "LineAB", argsspecLineAB, 2 ) +{ +} + +LineABType::~LineABType() +{ +} + +const LineABType* LineABType::instance() +{ + static const LineABType s; + return &s; +} + +ObjectImp* LineABType::calc( const Coordinate& a, const Coordinate& b ) const +{ + return new LineImp( a, b ); +} + +static const char constructhalflinestartingstat[] = I18N_NOOP( "Construct a half-line starting at this point" ); + +static const ArgsParser::spec argsspecRayAB[] = +{ + { PointImp::stype(), constructhalflinestartingstat, + I18N_NOOP( "Select the start point of the new half-line..." ), true }, + { PointImp::stype(), I18N_NOOP( "Construct a half-line through this point" ), + I18N_NOOP( "Select a point for the half-line to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( RayABType ) + +RayABType::RayABType() + : ObjectABType( "RayAB", argsspecRayAB, 2 ) +{ +} + +RayABType::~RayABType() +{ +} + +const RayABType* RayABType::instance() +{ + static const RayABType s; + return &s; +} + +ObjectImp* RayABType::calc( const Coordinate& a, const Coordinate& b ) const +{ + return new RayImp( a, b ); +} + +LinePerpendLPType* LinePerpendLPType::instance() +{ + static LinePerpendLPType l; + return &l; +} + +ObjectImp* LinePerpendLPType::calc( + const LineData& a, + const Coordinate& b ) const +{ + Coordinate p = calcPointOnPerpend( a, b ); + return new LineImp( b, p ); +} + +static const ArgsParser::spec argsspecLineParallel[] = +{ + { AbstractLineImp::stype(), I18N_NOOP( "Construct a line parallel to this line" ), + I18N_NOOP( "Select a line parallel to the new line..." ), false }, + { PointImp::stype(), I18N_NOOP( "Construct the parallel line through this point" ), + I18N_NOOP( "Select a point for the new line to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineParallelLPType ) + +LineParallelLPType::LineParallelLPType() + : ObjectLPType( "LineParallel", argsspecLineParallel, 2 ) +{ +} + +LineParallelLPType::~LineParallelLPType() +{ +} + +LineParallelLPType* LineParallelLPType::instance() +{ + static LineParallelLPType l; + return &l; +} + +ObjectImp* LineParallelLPType::calc( + const LineData& a, + const Coordinate& b ) const +{ + Coordinate r = calcPointOnParallel( a, b ); + return new LineImp( r, b ); +} + +static const ArgsParser::spec argsspecLinePerpend[] = +{ + { AbstractLineImp::stype(), I18N_NOOP( "Construct a line perpendicular to this line" ), + I18N_NOOP( "Select a line perpendicular to the new line..." ), false }, + { PointImp::stype(), I18N_NOOP( "Construct a perpendicular line through this point" ), + I18N_NOOP( "Select a point for the new line to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LinePerpendLPType ) + +LinePerpendLPType::LinePerpendLPType() + : ObjectLPType( "LinePerpend", argsspecLinePerpend, 2 ) +{ +} + +LinePerpendLPType::~LinePerpendLPType() +{ +} + +const ObjectImpType* SegmentABType::resultId() const +{ + return SegmentImp::stype(); +} + +const ObjectImpType* LineABType::resultId() const +{ + return LineImp::stype(); +} + +const ObjectImpType* RayABType::resultId() const +{ + return RayImp::stype(); +} + +const ObjectImpType* LinePerpendLPType::resultId() const +{ + return LineImp::stype(); +} + +const ObjectImpType* LineParallelLPType::resultId() const +{ + return LineImp::stype(); +} + +TQStringList SegmentABType::specialActions() const +{ + TQStringList ret; + ret << i18n( "Set &Length..." ); + return ret; +} + +void SegmentABType::executeAction( int i, ObjectHolder&, ObjectTypeCalcer& c, + KigPart& d, KigWidget& w, NormalMode& ) const +{ + assert( i == 0 ); + // pretend to use this var.. + (void) i; + + std::vector parents = c.parents(); + assert( margsparser.checkArgs( parents ) ); + + Coordinate a = static_cast( parents[0]->imp() )->coordinate(); + Coordinate b = static_cast( parents[1]->imp() )->coordinate(); + + bool ok = true; + double length = getDoubleFromUser( + i18n( "Set Segment Length" ), i18n( "Choose the new length: " ), + (b-a).length(), &w, &ok, -2147483647, 2147483647, 3 ); + if ( ! ok ) return; + + Coordinate nb = a + ( b - a ).normalize( length ); + + MonitorDataObjects mon( getAllParents( parents ) ); + parents[1]->move( nb, d.document() ); + KigCommand* cd = new KigCommand( d, i18n( "Resize Segment" ) ); + mon.finish( cd ); + d.history()->addCommand( cd ); +} + +static const ArgsParser::spec argsspecLineByVector[] = +{ + { VectorImp::stype(), I18N_NOOP( "Construct a line by this vector" ), + I18N_NOOP( "Select a vector in the direction of the new line..." ), true }, + { PointImp::stype(), constructlineabstat, + I18N_NOOP( "Select a point for the new line to go through..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineByVectorType ) + +LineByVectorType::LineByVectorType() + : ArgsParserObjectType( "LineByVector", argsspecLineByVector, 2 ) +{ +} + +LineByVectorType::~LineByVectorType() +{ +} + +const LineByVectorType* LineByVectorType::instance() +{ + static const LineByVectorType s; + return &s; +} + +ObjectImp* LineByVectorType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + const VectorImp& a = *static_cast( args[0] ); + const PointImp& b = *static_cast( args[1] ); + + return new LineImp( b.coordinate(), b.coordinate() + a.dir() ); +} + +const ObjectImpType* LineByVectorType::resultId() const +{ + return LineImp::stype(); +} + +static const ArgsParser::spec argsspecHalflineByVector[] = +{ + { VectorImp::stype(), I18N_NOOP( "Construct a half-line by this vector" ), + I18N_NOOP( "Select a vector in the direction of the new half-line..." ), true }, + { PointImp::stype(), constructhalflinestartingstat, + I18N_NOOP( "Select the start point of the new half-line..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( HalflineByVectorType ) + +HalflineByVectorType::HalflineByVectorType() + : ArgsParserObjectType( "HalflineByVector", argsspecHalflineByVector, 2 ) +{ +} + +HalflineByVectorType::~HalflineByVectorType() +{ +} + +const HalflineByVectorType* HalflineByVectorType::instance() +{ + static const HalflineByVectorType s; + return &s; +} + +ObjectImp* HalflineByVectorType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + const VectorImp& a = *static_cast( args[0] ); + const PointImp& b = *static_cast( args[1] ); + + return new RayImp( b.coordinate(), b.coordinate() + a.dir() ); +} + +const ObjectImpType* HalflineByVectorType::resultId() const +{ + return RayImp::stype(); +} diff --git a/kig/objects/locus_imp.cc b/kig/objects/locus_imp.cc deleted file mode 100644 index fcbfe7a7..00000000 --- a/kig/objects/locus_imp.cc +++ /dev/null @@ -1,397 +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 "locus_imp.h" - -#include "bogus_imp.h" -#include "point_imp.h" -#include "../misc/object_hierarchy.h" -#include "../misc/kigpainter.h" -#include "../misc/coordinate.h" -#include "../misc/common.h" - -#include "../kig/kig_view.h" - -#include - -#include - -using namespace std; - -static double cachedparam = 0.0; - -LocusImp::~LocusImp() -{ - delete mcurve; -} - -ObjectImp* LocusImp::transform( const Transformation& t ) const -{ - return new LocusImp( mcurve->copy(), mhier.transformFinalObject( t ) ); -} - -void LocusImp::draw( KigPainter& p ) const -{ - p.drawCurve( this ); -} - -bool LocusImp::contains( const Coordinate& p, int width, const KigWidget& w ) const -{ - return internalContainsPoint( p, w.screenInfo().normalMiss( width ), w.document() ); -} - -bool LocusImp::inRect( const Rect&, int, const KigWidget& ) const -{ - // TODO ? - return false; -} - -const Coordinate LocusImp::getPoint( double param, const KigDocument& doc ) const -{ - Coordinate arg = mcurve->getPoint( param, doc ); - if ( ! arg.valid() ) return arg; - PointImp argimp( arg ); - Args args; - args.push_back( &argimp ); - vector calcret = mhier.calc( args, doc ); - assert( calcret.size() == 1 ); - ObjectImp* imp = calcret.front(); - Coordinate ret; - if ( imp->inherits( PointImp::stype() ) ) - { - cachedparam = param; - ret = static_cast( imp )->coordinate(); - } - else - ret = Coordinate::invalidCoord(); - - delete imp; - return ret; -} - -LocusImp::LocusImp( CurveImp* curve, const ObjectHierarchy& hier ) - : mcurve( curve ), mhier( hier ) -{ -} - -const uint LocusImp::numberOfProperties() const -{ - return Parent::numberOfProperties(); -} - -const QCStringList LocusImp::propertiesInternalNames() const -{ - return Parent::propertiesInternalNames(); -} - -const QCStringList LocusImp::properties() const -{ - return Parent::properties(); -} - -const ObjectImpType* LocusImp::impRequirementForProperty( uint which ) const -{ - return Parent::impRequirementForProperty( which ); -} - -const char* LocusImp::iconForProperty( uint which ) const -{ - return Parent::iconForProperty( which ); -} - -ObjectImp* LocusImp::property( uint which, const KigDocument& w ) const -{ - return Parent::property( which, w ); -} - -LocusImp* LocusImp::copy() const -{ - return new LocusImp( mcurve->copy(), mhier ); -} - -const CurveImp* LocusImp::curve() const -{ - return mcurve; -} - -const ObjectHierarchy& LocusImp::hierarchy() const -{ - return mhier; -} - -/** - * This function returns the distance between the point with parameter - * param and point p. param is allowed to not be between 0 and 1, in - * which case we consider only the decimal part. - */ -double LocusImp::getDist(double param, const Coordinate& p, const KigDocument& doc) const -{ - param = fmod( param, 1 ); - if( param < 0 ) param += 1.; - Coordinate p1 = getPoint( param, doc ); - // i don't think the p1.valid() switch is really necessary, but I - // prefer to not take any chances :) - return p1.valid() ? ( p1 - p ).length() : +double_inf; -} - -/** - * This function searches starting from x1 for the first interval in - * which the function of the distance from the point at coordinate x - * starts to increase. The range found is returned in the parameters - * x1 and x2: [x1,x2]. - */ -void LocusImp::getInterval( double& x1, double& x2, - double incr,const Coordinate& p, - const KigDocument& doc) const -{ - double mm = getDist( x1, p, doc); - double mm1 = getDist( x2, p, doc); - if( mm <= mm1 ) return; - else - { - double x3 = x2 + incr; - double mm2 = getDist (x3, p, doc); - while( mm > mm1 & mm1 > mm2 ) - { - x1 = x2; - x2 = x3; - x3 = x2 + incr; - mm = mm1; - mm1 = mm2; - mm2 = getDist (x3, p, doc); - } - x2=x3; - } -} - -double LocusImp::getParam( const Coordinate& p, const KigDocument& doc ) const -{ - // this function ( and related functions like getInterval etc. ) is - // written by Franco Pasquarelli . - // I ( domi ) have adapted and documented it a bit. - - if ( cachedparam >= 0. && cachedparam <= 1. && - getPoint ( cachedparam, doc ) == p ) return cachedparam; - - // consider the function that returns the distance for a point at - // parameter x to the locus for a given parameter x. What we do - // here is look for the global minimum of this function. We do that - // by dividing the range ( [0,1] ) into N parts, and start looking - // for a local minimum from there on. If we find one, we keep it if - // it is the lowest of all the ones we've already found.. - - const int N = 50; - const double incr = 1. / (double) N; - - // xm is the best parameter we've found so far, fxm is the distance - // to the locus from that point. We start with some - // pseudo-values. - // (mp) note that if the distance is actually increasing in the - // whole interval [0,1] this value will be returned in the end. - double xm = 0.; - double fxm = getDist( xm, p, doc ); - - int j = 0; - double mm = fxm; - - while( j < N ) - { - // [x1,x2] is the range we're currently considering.. - double x1 = j * incr; - double x2 = x1 + incr; - - // check the range x1,x2 for the first local maximum.. - double mm1 = getDist( x2, p, doc); - double mm2; - j++; - if( mm < mm1 ) - mm = mm1; - - else - { - if ( mm > mm1 ) - { - double x3 = x2 + incr; - mm2 = getDist (x3, p, doc); - j++; - while( mm1 > mm2 & j <= N ) - { - x1 = x2; - x2 = x3; - x3 = x2 + incr; - mm = mm1; - mm1 = mm2; - mm2 = getDist (x3, p, doc); - j++; - } - x2 = x3; - } - else - mm2 = mm1; - - if ( mm1 <= mm2 ) - { - mm = mm2; - - double xm1 = getParamofmin( x1, x2, p, doc); - double fxm1 = getDist( xm1, p, doc ); - if( fxm1 < fxm ) - { - // we found a new minimum, save it.. - xm=xm1; - fxm=fxm1; - } - } - } - } - return xm; -} - -/** - * This function calculates the parameter of the point that realizes the - * minimum in [a,b] of the distance between the points of the locus and - * the point of coordinate p, using the golden ration method. - */ -double LocusImp::getParamofmin( double a, double b, - const Coordinate& p, - const KigDocument& doc ) const -{ - double epsilons = 1.e-08; - double epsilonl = 2.e-02; - - //assert( a < b && a >= 0. && b <= 1.0); - assert( a < b && a >= 0.); - - double r2 = ( sqrt( 5. ) - 1 ) / 2.; // golden ratio - double r1 = 1. - r2; - - double t2 = a + r2 * ( b - a ); - double t1 = a + r1 * ( b - a ); - Coordinate p1 = getPoint( fmod( t1, 1. ), doc); - double f1 = (p1 - p).length(); - Coordinate p2 = getPoint( fmod( t2, 1. ), doc); - double f2 = (p2 - p).length(); - - double fmin, tmin; - if (f1 < f2) - { - b = t2; - fmin = f1; - tmin = t1; - } - else - { - a = t1; - fmin = f2; - tmin = t2; - } - - while ( ( b - a ) > epsilons && - ( (p1 - p2).length() > 0.4 * fmin - || (b - a) > epsilonl) && - fmin > 1.e-8 ) - { - if ( f1 < f2 ) - { - t2 = t1; - t1 = a + r1*(b - a); - f2 = f1; - p1 = getPoint( fmod( t1, 1. ), doc); - f1 = (p1 - p).length(); - } - else - { - t1 = t2; - t2 = a + r2*(b - a); - f1 = f2; - p2 = getPoint( fmod( t2, 1. ), doc); - f2 = (p2 - p).length(); - } - if ( f1 < f2 ) - { - b = t2; - fmin = f1; - tmin = t1; - } - else - { - a = t1; - fmin = f2; - tmin = t2; - } - } - - return(tmin); -} - -void LocusImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -bool LocusImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( LocusImp::stype() ) && - static_cast( rhs ).curve()->equals( *curve() ) && - static_cast( rhs ).hierarchy() == hierarchy(); -} - -const ObjectImpType* LocusImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "locus", - I18N_NOOP( "locus" ), - I18N_NOOP( "Select this locus" ), - I18N_NOOP( "Select locus %1" ), - I18N_NOOP( "Remove a Locus" ), - I18N_NOOP( "Add a Locus" ), - I18N_NOOP( "Move a Locus" ), - I18N_NOOP( "Attach to this locus" ), - I18N_NOOP( "Show a Locus" ), - I18N_NOOP( "Hide a Locus" ) - ); - return &t; -} - -const ObjectImpType* LocusImp::type() const -{ - return LocusImp::stype(); -} - -bool LocusImp::containsPoint( const Coordinate& p, const KigDocument& doc ) const -{ - return internalContainsPoint( p, test_threshold, doc ); -} - -bool LocusImp::internalContainsPoint( const Coordinate& p, double threshold, const KigDocument& doc ) const -{ - double param = getParam( p, doc ); - double dist = getDist( param, p, doc ); - return fabs( dist ) <= threshold; -} - -bool LocusImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const -{ - return Parent::isPropertyDefinedOnOrThroughThisImp( which ); -} - -Rect LocusImp::surroundingRect() const -{ - // it's probably possible to calculate this, if it exists, but we - // don't for now. - return Rect::invalidRect(); -} diff --git a/kig/objects/locus_imp.cpp b/kig/objects/locus_imp.cpp new file mode 100644 index 00000000..fcbfe7a7 --- /dev/null +++ b/kig/objects/locus_imp.cpp @@ -0,0 +1,397 @@ +// 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 "locus_imp.h" + +#include "bogus_imp.h" +#include "point_imp.h" +#include "../misc/object_hierarchy.h" +#include "../misc/kigpainter.h" +#include "../misc/coordinate.h" +#include "../misc/common.h" + +#include "../kig/kig_view.h" + +#include + +#include + +using namespace std; + +static double cachedparam = 0.0; + +LocusImp::~LocusImp() +{ + delete mcurve; +} + +ObjectImp* LocusImp::transform( const Transformation& t ) const +{ + return new LocusImp( mcurve->copy(), mhier.transformFinalObject( t ) ); +} + +void LocusImp::draw( KigPainter& p ) const +{ + p.drawCurve( this ); +} + +bool LocusImp::contains( const Coordinate& p, int width, const KigWidget& w ) const +{ + return internalContainsPoint( p, w.screenInfo().normalMiss( width ), w.document() ); +} + +bool LocusImp::inRect( const Rect&, int, const KigWidget& ) const +{ + // TODO ? + return false; +} + +const Coordinate LocusImp::getPoint( double param, const KigDocument& doc ) const +{ + Coordinate arg = mcurve->getPoint( param, doc ); + if ( ! arg.valid() ) return arg; + PointImp argimp( arg ); + Args args; + args.push_back( &argimp ); + vector calcret = mhier.calc( args, doc ); + assert( calcret.size() == 1 ); + ObjectImp* imp = calcret.front(); + Coordinate ret; + if ( imp->inherits( PointImp::stype() ) ) + { + cachedparam = param; + ret = static_cast( imp )->coordinate(); + } + else + ret = Coordinate::invalidCoord(); + + delete imp; + return ret; +} + +LocusImp::LocusImp( CurveImp* curve, const ObjectHierarchy& hier ) + : mcurve( curve ), mhier( hier ) +{ +} + +const uint LocusImp::numberOfProperties() const +{ + return Parent::numberOfProperties(); +} + +const QCStringList LocusImp::propertiesInternalNames() const +{ + return Parent::propertiesInternalNames(); +} + +const QCStringList LocusImp::properties() const +{ + return Parent::properties(); +} + +const ObjectImpType* LocusImp::impRequirementForProperty( uint which ) const +{ + return Parent::impRequirementForProperty( which ); +} + +const char* LocusImp::iconForProperty( uint which ) const +{ + return Parent::iconForProperty( which ); +} + +ObjectImp* LocusImp::property( uint which, const KigDocument& w ) const +{ + return Parent::property( which, w ); +} + +LocusImp* LocusImp::copy() const +{ + return new LocusImp( mcurve->copy(), mhier ); +} + +const CurveImp* LocusImp::curve() const +{ + return mcurve; +} + +const ObjectHierarchy& LocusImp::hierarchy() const +{ + return mhier; +} + +/** + * This function returns the distance between the point with parameter + * param and point p. param is allowed to not be between 0 and 1, in + * which case we consider only the decimal part. + */ +double LocusImp::getDist(double param, const Coordinate& p, const KigDocument& doc) const +{ + param = fmod( param, 1 ); + if( param < 0 ) param += 1.; + Coordinate p1 = getPoint( param, doc ); + // i don't think the p1.valid() switch is really necessary, but I + // prefer to not take any chances :) + return p1.valid() ? ( p1 - p ).length() : +double_inf; +} + +/** + * This function searches starting from x1 for the first interval in + * which the function of the distance from the point at coordinate x + * starts to increase. The range found is returned in the parameters + * x1 and x2: [x1,x2]. + */ +void LocusImp::getInterval( double& x1, double& x2, + double incr,const Coordinate& p, + const KigDocument& doc) const +{ + double mm = getDist( x1, p, doc); + double mm1 = getDist( x2, p, doc); + if( mm <= mm1 ) return; + else + { + double x3 = x2 + incr; + double mm2 = getDist (x3, p, doc); + while( mm > mm1 & mm1 > mm2 ) + { + x1 = x2; + x2 = x3; + x3 = x2 + incr; + mm = mm1; + mm1 = mm2; + mm2 = getDist (x3, p, doc); + } + x2=x3; + } +} + +double LocusImp::getParam( const Coordinate& p, const KigDocument& doc ) const +{ + // this function ( and related functions like getInterval etc. ) is + // written by Franco Pasquarelli . + // I ( domi ) have adapted and documented it a bit. + + if ( cachedparam >= 0. && cachedparam <= 1. && + getPoint ( cachedparam, doc ) == p ) return cachedparam; + + // consider the function that returns the distance for a point at + // parameter x to the locus for a given parameter x. What we do + // here is look for the global minimum of this function. We do that + // by dividing the range ( [0,1] ) into N parts, and start looking + // for a local minimum from there on. If we find one, we keep it if + // it is the lowest of all the ones we've already found.. + + const int N = 50; + const double incr = 1. / (double) N; + + // xm is the best parameter we've found so far, fxm is the distance + // to the locus from that point. We start with some + // pseudo-values. + // (mp) note that if the distance is actually increasing in the + // whole interval [0,1] this value will be returned in the end. + double xm = 0.; + double fxm = getDist( xm, p, doc ); + + int j = 0; + double mm = fxm; + + while( j < N ) + { + // [x1,x2] is the range we're currently considering.. + double x1 = j * incr; + double x2 = x1 + incr; + + // check the range x1,x2 for the first local maximum.. + double mm1 = getDist( x2, p, doc); + double mm2; + j++; + if( mm < mm1 ) + mm = mm1; + + else + { + if ( mm > mm1 ) + { + double x3 = x2 + incr; + mm2 = getDist (x3, p, doc); + j++; + while( mm1 > mm2 & j <= N ) + { + x1 = x2; + x2 = x3; + x3 = x2 + incr; + mm = mm1; + mm1 = mm2; + mm2 = getDist (x3, p, doc); + j++; + } + x2 = x3; + } + else + mm2 = mm1; + + if ( mm1 <= mm2 ) + { + mm = mm2; + + double xm1 = getParamofmin( x1, x2, p, doc); + double fxm1 = getDist( xm1, p, doc ); + if( fxm1 < fxm ) + { + // we found a new minimum, save it.. + xm=xm1; + fxm=fxm1; + } + } + } + } + return xm; +} + +/** + * This function calculates the parameter of the point that realizes the + * minimum in [a,b] of the distance between the points of the locus and + * the point of coordinate p, using the golden ration method. + */ +double LocusImp::getParamofmin( double a, double b, + const Coordinate& p, + const KigDocument& doc ) const +{ + double epsilons = 1.e-08; + double epsilonl = 2.e-02; + + //assert( a < b && a >= 0. && b <= 1.0); + assert( a < b && a >= 0.); + + double r2 = ( sqrt( 5. ) - 1 ) / 2.; // golden ratio + double r1 = 1. - r2; + + double t2 = a + r2 * ( b - a ); + double t1 = a + r1 * ( b - a ); + Coordinate p1 = getPoint( fmod( t1, 1. ), doc); + double f1 = (p1 - p).length(); + Coordinate p2 = getPoint( fmod( t2, 1. ), doc); + double f2 = (p2 - p).length(); + + double fmin, tmin; + if (f1 < f2) + { + b = t2; + fmin = f1; + tmin = t1; + } + else + { + a = t1; + fmin = f2; + tmin = t2; + } + + while ( ( b - a ) > epsilons && + ( (p1 - p2).length() > 0.4 * fmin + || (b - a) > epsilonl) && + fmin > 1.e-8 ) + { + if ( f1 < f2 ) + { + t2 = t1; + t1 = a + r1*(b - a); + f2 = f1; + p1 = getPoint( fmod( t1, 1. ), doc); + f1 = (p1 - p).length(); + } + else + { + t1 = t2; + t2 = a + r2*(b - a); + f1 = f2; + p2 = getPoint( fmod( t2, 1. ), doc); + f2 = (p2 - p).length(); + } + if ( f1 < f2 ) + { + b = t2; + fmin = f1; + tmin = t1; + } + else + { + a = t1; + fmin = f2; + tmin = t2; + } + } + + return(tmin); +} + +void LocusImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +bool LocusImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( LocusImp::stype() ) && + static_cast( rhs ).curve()->equals( *curve() ) && + static_cast( rhs ).hierarchy() == hierarchy(); +} + +const ObjectImpType* LocusImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "locus", + I18N_NOOP( "locus" ), + I18N_NOOP( "Select this locus" ), + I18N_NOOP( "Select locus %1" ), + I18N_NOOP( "Remove a Locus" ), + I18N_NOOP( "Add a Locus" ), + I18N_NOOP( "Move a Locus" ), + I18N_NOOP( "Attach to this locus" ), + I18N_NOOP( "Show a Locus" ), + I18N_NOOP( "Hide a Locus" ) + ); + return &t; +} + +const ObjectImpType* LocusImp::type() const +{ + return LocusImp::stype(); +} + +bool LocusImp::containsPoint( const Coordinate& p, const KigDocument& doc ) const +{ + return internalContainsPoint( p, test_threshold, doc ); +} + +bool LocusImp::internalContainsPoint( const Coordinate& p, double threshold, const KigDocument& doc ) const +{ + double param = getParam( p, doc ); + double dist = getDist( param, p, doc ); + return fabs( dist ) <= threshold; +} + +bool LocusImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const +{ + return Parent::isPropertyDefinedOnOrThroughThisImp( which ); +} + +Rect LocusImp::surroundingRect() const +{ + // it's probably possible to calculate this, if it exists, but we + // don't for now. + return Rect::invalidRect(); +} diff --git a/kig/objects/object_calcer.cc b/kig/objects/object_calcer.cc deleted file mode 100644 index 40545ed1..00000000 --- a/kig/objects/object_calcer.cc +++ /dev/null @@ -1,323 +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_calcer.h" - -#include "object_holder.h" -#include "object_imp.h" -#include "object_type.h" -#include "../misc/coordinate.h" -#include "common.h" - -#include -#include - -void ObjectTypeCalcer::calc( const KigDocument& doc ) -{ - Args a; - a.reserve( mparents.size() ); - std::transform( mparents.begin(), mparents.end(), - std::back_inserter( a ), std::mem_fun( &ObjectCalcer::imp ) ); - ObjectImp* n = mtype->calc( a, doc ); - delete mimp; - mimp = n; -} - -ObjectTypeCalcer::ObjectTypeCalcer( const ObjectType* type, - const std::vector& parents, bool sort ) - : mparents( ( sort )?type->sortArgs( parents ):parents ), mtype( type ), mimp( 0 ) -{ - std::for_each( mparents.begin(), mparents.end(), - std::bind2nd( std::mem_fun( &ObjectCalcer::addChild ), this ) ); -} - -ObjectCalcer::~ObjectCalcer() -{ -} - -ObjectConstCalcer::ObjectConstCalcer( ObjectImp* imp ) - : mimp( imp ) -{ -} - -ObjectConstCalcer::~ObjectConstCalcer() -{ - delete mimp; -} - -const ObjectImp* ObjectConstCalcer::imp() const -{ - return mimp; -} - -void ObjectConstCalcer::calc( const KigDocument& ) -{ -} - -std::vector ObjectConstCalcer::parents() const -{ - // we have no parents.. - return std::vector(); -} - -void ObjectCalcer::ref() -{ - ++refcount; -} - -void ObjectCalcer::deref() -{ - if ( --refcount <= 0 ) delete this; -} - -void intrusive_ptr_add_ref( ObjectCalcer* p ) -{ - p->ref(); -} - -void intrusive_ptr_release( ObjectCalcer* p ) -{ - p->deref(); -} - -const ObjectImp* ObjectTypeCalcer::imp() const -{ - return mimp; -} - -std::vector ObjectTypeCalcer::parents() const -{ - return mparents; -} - -void ObjectCalcer::addChild( ObjectCalcer* c ) -{ - mchildren.push_back( c ); - ref(); -} - -void ObjectCalcer::delChild( ObjectCalcer* c ) -{ - std::vector::iterator i = std::find( mchildren.begin(), mchildren.end(), c ); - assert( i != mchildren.end() ); - - mchildren.erase( i ); - deref(); -} - -ObjectTypeCalcer::~ObjectTypeCalcer() -{ - std::for_each( mparents.begin(), mparents.end(), - std::bind2nd( std::mem_fun( &ObjectCalcer::delChild ), this ) ); - delete mimp; -} - -const ObjectType* ObjectTypeCalcer::type() const -{ - return mtype; -} - -ObjectPropertyCalcer::ObjectPropertyCalcer( ObjectCalcer* parent, int propid ) - : mimp( 0 ), mparent( parent ), mpropid( propid ) -{ - // Some weird C++ thing prevents me from calling protected members - // of ObjectCalcer on mparent.. This is an ugly workaround.. - ( mparent->*&ObjectCalcer::addChild )( this ); - //mparent->addChild( this ); -} - -ObjectPropertyCalcer::~ObjectPropertyCalcer() -{ - // Some weird C++ thing prevents me from calling protected members - // of ObjectCalcer on mparent.. This is an ugly workaround.. - ( mparent->*&ObjectCalcer::delChild )( this ); - //mparent->delChild( this ); - delete mimp; -} - -const ObjectImp* ObjectPropertyCalcer::imp() const -{ - return mimp; -} - -std::vector ObjectPropertyCalcer::parents() const -{ - std::vector ret; - ret.push_back( mparent ); - return ret; -} - -void ObjectPropertyCalcer::calc( const KigDocument& doc ) -{ - ObjectImp* n = mparent->imp()->property( mpropid, doc ); - delete mimp; - mimp = n; -} - -ObjectImp* ObjectConstCalcer::switchImp( ObjectImp* newimp ) -{ - ObjectImp* ret = mimp; - mimp = newimp; - return ret; -} - -std::vector ObjectCalcer::children() const -{ - return mchildren; -} - -const ObjectImpType* ObjectPropertyCalcer::impRequirement( - ObjectCalcer*, const std::vector& ) const -{ - return mparent->imp()->impRequirementForProperty( mpropid ); -} - -const ObjectImpType* ObjectConstCalcer::impRequirement( - ObjectCalcer*, const std::vector& ) const -{ - assert( false ); - return ObjectImp::stype(); -} - -const ObjectImpType* ObjectTypeCalcer::impRequirement( - ObjectCalcer* o, const std::vector& os ) const -{ - Args args; - args.reserve( mparents.size() ); - std::transform( - os.begin(), os.end(), - std::back_inserter( args ), - std::mem_fun( &ObjectCalcer::imp ) ); - assert( std::find( args.begin(), args.end(), o->imp() ) != args.end() ); - return mtype->impRequirement( o->imp(), args ); -} - -int ObjectPropertyCalcer::propId() const -{ - return mpropid; -} - -void ObjectConstCalcer::setImp( ObjectImp* newimp ) -{ - delete switchImp( newimp ); -} - -void ObjectTypeCalcer::setParents( const std::vector np ) -{ - std::for_each( np.begin(), np.end(), - std::bind2nd( std::mem_fun( &ObjectCalcer::addChild ), this ) ); - std::for_each( mparents.begin(), mparents.end(), - std::bind2nd( std::mem_fun( &ObjectCalcer::delChild ), this ) ); - mparents = np; -} - -void ObjectTypeCalcer::setType( const ObjectType* t ) -{ - mtype = t; -} - -bool ObjectCalcer::canMove() const -{ - return false; -} - -bool ObjectCalcer::isFreelyTranslatable() const -{ - return false; -} - -Coordinate ObjectCalcer::moveReferencePoint() const -{ - assert( false ); - return Coordinate::invalidCoord(); -} - -void ObjectCalcer::move( const Coordinate&, const KigDocument& ) -{ - assert( false ); -} - -bool ObjectTypeCalcer::canMove() const -{ - return mtype->canMove( *this ); -} - -bool ObjectTypeCalcer::isFreelyTranslatable() const -{ - return mtype->isFreelyTranslatable( *this ); -} - -Coordinate ObjectTypeCalcer::moveReferencePoint() const -{ - return mtype->moveReferencePoint( *this ); -} - -void ObjectTypeCalcer::move( const Coordinate& to, const KigDocument& doc ) -{ - // we need to check if type can in fact move, because this check is - // not done for us in all circumstances ( e.g. LineABType::move uses - // move on its parents to move them ), and the ObjectType's depend - // on move only being called if canMove() returns true.. - if ( mtype->canMove( *this ) ) - mtype->move( *this, to, doc ); -} - -ObjectCalcer* ObjectPropertyCalcer::parent() const -{ - return mparent; -} - -ObjectCalcer::ObjectCalcer() - : refcount( 0 ) -{ -} - -std::vector ObjectCalcer::movableParents() const -{ - return std::vector(); -} - -std::vector ObjectTypeCalcer::movableParents() const -{ - return mtype->movableParents( *this ); -} - -bool ObjectConstCalcer::isDefinedOnOrThrough( const ObjectCalcer* ) const -{ - return false; -} - -bool ObjectPropertyCalcer::isDefinedOnOrThrough( const ObjectCalcer* o ) const -{ - return o == mparent && - mparent->imp()->isPropertyDefinedOnOrThroughThisImp( propId() ); -} - -bool ObjectTypeCalcer::isDefinedOnOrThrough( const ObjectCalcer* o ) const -{ - Args args; - args.reserve( mparents.size() ); - std::transform( - mparents.begin(), mparents.end(), - std::back_inserter( args ), - std::mem_fun( &ObjectCalcer::imp ) ); - if ( std::find( args.begin(), args.end(), o->imp() ) == args.end() ) - return false; - - return mtype->isDefinedOnOrThrough( o->imp(), args ); -} - diff --git a/kig/objects/object_calcer.cpp b/kig/objects/object_calcer.cpp new file mode 100644 index 00000000..40545ed1 --- /dev/null +++ b/kig/objects/object_calcer.cpp @@ -0,0 +1,323 @@ +// 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_calcer.h" + +#include "object_holder.h" +#include "object_imp.h" +#include "object_type.h" +#include "../misc/coordinate.h" +#include "common.h" + +#include +#include + +void ObjectTypeCalcer::calc( const KigDocument& doc ) +{ + Args a; + a.reserve( mparents.size() ); + std::transform( mparents.begin(), mparents.end(), + std::back_inserter( a ), std::mem_fun( &ObjectCalcer::imp ) ); + ObjectImp* n = mtype->calc( a, doc ); + delete mimp; + mimp = n; +} + +ObjectTypeCalcer::ObjectTypeCalcer( const ObjectType* type, + const std::vector& parents, bool sort ) + : mparents( ( sort )?type->sortArgs( parents ):parents ), mtype( type ), mimp( 0 ) +{ + std::for_each( mparents.begin(), mparents.end(), + std::bind2nd( std::mem_fun( &ObjectCalcer::addChild ), this ) ); +} + +ObjectCalcer::~ObjectCalcer() +{ +} + +ObjectConstCalcer::ObjectConstCalcer( ObjectImp* imp ) + : mimp( imp ) +{ +} + +ObjectConstCalcer::~ObjectConstCalcer() +{ + delete mimp; +} + +const ObjectImp* ObjectConstCalcer::imp() const +{ + return mimp; +} + +void ObjectConstCalcer::calc( const KigDocument& ) +{ +} + +std::vector ObjectConstCalcer::parents() const +{ + // we have no parents.. + return std::vector(); +} + +void ObjectCalcer::ref() +{ + ++refcount; +} + +void ObjectCalcer::deref() +{ + if ( --refcount <= 0 ) delete this; +} + +void intrusive_ptr_add_ref( ObjectCalcer* p ) +{ + p->ref(); +} + +void intrusive_ptr_release( ObjectCalcer* p ) +{ + p->deref(); +} + +const ObjectImp* ObjectTypeCalcer::imp() const +{ + return mimp; +} + +std::vector ObjectTypeCalcer::parents() const +{ + return mparents; +} + +void ObjectCalcer::addChild( ObjectCalcer* c ) +{ + mchildren.push_back( c ); + ref(); +} + +void ObjectCalcer::delChild( ObjectCalcer* c ) +{ + std::vector::iterator i = std::find( mchildren.begin(), mchildren.end(), c ); + assert( i != mchildren.end() ); + + mchildren.erase( i ); + deref(); +} + +ObjectTypeCalcer::~ObjectTypeCalcer() +{ + std::for_each( mparents.begin(), mparents.end(), + std::bind2nd( std::mem_fun( &ObjectCalcer::delChild ), this ) ); + delete mimp; +} + +const ObjectType* ObjectTypeCalcer::type() const +{ + return mtype; +} + +ObjectPropertyCalcer::ObjectPropertyCalcer( ObjectCalcer* parent, int propid ) + : mimp( 0 ), mparent( parent ), mpropid( propid ) +{ + // Some weird C++ thing prevents me from calling protected members + // of ObjectCalcer on mparent.. This is an ugly workaround.. + ( mparent->*&ObjectCalcer::addChild )( this ); + //mparent->addChild( this ); +} + +ObjectPropertyCalcer::~ObjectPropertyCalcer() +{ + // Some weird C++ thing prevents me from calling protected members + // of ObjectCalcer on mparent.. This is an ugly workaround.. + ( mparent->*&ObjectCalcer::delChild )( this ); + //mparent->delChild( this ); + delete mimp; +} + +const ObjectImp* ObjectPropertyCalcer::imp() const +{ + return mimp; +} + +std::vector ObjectPropertyCalcer::parents() const +{ + std::vector ret; + ret.push_back( mparent ); + return ret; +} + +void ObjectPropertyCalcer::calc( const KigDocument& doc ) +{ + ObjectImp* n = mparent->imp()->property( mpropid, doc ); + delete mimp; + mimp = n; +} + +ObjectImp* ObjectConstCalcer::switchImp( ObjectImp* newimp ) +{ + ObjectImp* ret = mimp; + mimp = newimp; + return ret; +} + +std::vector ObjectCalcer::children() const +{ + return mchildren; +} + +const ObjectImpType* ObjectPropertyCalcer::impRequirement( + ObjectCalcer*, const std::vector& ) const +{ + return mparent->imp()->impRequirementForProperty( mpropid ); +} + +const ObjectImpType* ObjectConstCalcer::impRequirement( + ObjectCalcer*, const std::vector& ) const +{ + assert( false ); + return ObjectImp::stype(); +} + +const ObjectImpType* ObjectTypeCalcer::impRequirement( + ObjectCalcer* o, const std::vector& os ) const +{ + Args args; + args.reserve( mparents.size() ); + std::transform( + os.begin(), os.end(), + std::back_inserter( args ), + std::mem_fun( &ObjectCalcer::imp ) ); + assert( std::find( args.begin(), args.end(), o->imp() ) != args.end() ); + return mtype->impRequirement( o->imp(), args ); +} + +int ObjectPropertyCalcer::propId() const +{ + return mpropid; +} + +void ObjectConstCalcer::setImp( ObjectImp* newimp ) +{ + delete switchImp( newimp ); +} + +void ObjectTypeCalcer::setParents( const std::vector np ) +{ + std::for_each( np.begin(), np.end(), + std::bind2nd( std::mem_fun( &ObjectCalcer::addChild ), this ) ); + std::for_each( mparents.begin(), mparents.end(), + std::bind2nd( std::mem_fun( &ObjectCalcer::delChild ), this ) ); + mparents = np; +} + +void ObjectTypeCalcer::setType( const ObjectType* t ) +{ + mtype = t; +} + +bool ObjectCalcer::canMove() const +{ + return false; +} + +bool ObjectCalcer::isFreelyTranslatable() const +{ + return false; +} + +Coordinate ObjectCalcer::moveReferencePoint() const +{ + assert( false ); + return Coordinate::invalidCoord(); +} + +void ObjectCalcer::move( const Coordinate&, const KigDocument& ) +{ + assert( false ); +} + +bool ObjectTypeCalcer::canMove() const +{ + return mtype->canMove( *this ); +} + +bool ObjectTypeCalcer::isFreelyTranslatable() const +{ + return mtype->isFreelyTranslatable( *this ); +} + +Coordinate ObjectTypeCalcer::moveReferencePoint() const +{ + return mtype->moveReferencePoint( *this ); +} + +void ObjectTypeCalcer::move( const Coordinate& to, const KigDocument& doc ) +{ + // we need to check if type can in fact move, because this check is + // not done for us in all circumstances ( e.g. LineABType::move uses + // move on its parents to move them ), and the ObjectType's depend + // on move only being called if canMove() returns true.. + if ( mtype->canMove( *this ) ) + mtype->move( *this, to, doc ); +} + +ObjectCalcer* ObjectPropertyCalcer::parent() const +{ + return mparent; +} + +ObjectCalcer::ObjectCalcer() + : refcount( 0 ) +{ +} + +std::vector ObjectCalcer::movableParents() const +{ + return std::vector(); +} + +std::vector ObjectTypeCalcer::movableParents() const +{ + return mtype->movableParents( *this ); +} + +bool ObjectConstCalcer::isDefinedOnOrThrough( const ObjectCalcer* ) const +{ + return false; +} + +bool ObjectPropertyCalcer::isDefinedOnOrThrough( const ObjectCalcer* o ) const +{ + return o == mparent && + mparent->imp()->isPropertyDefinedOnOrThroughThisImp( propId() ); +} + +bool ObjectTypeCalcer::isDefinedOnOrThrough( const ObjectCalcer* o ) const +{ + Args args; + args.reserve( mparents.size() ); + std::transform( + mparents.begin(), mparents.end(), + std::back_inserter( args ), + std::mem_fun( &ObjectCalcer::imp ) ); + if ( std::find( args.begin(), args.end(), o->imp() ) == args.end() ) + return false; + + return mtype->isDefinedOnOrThrough( o->imp(), args ); +} + diff --git a/kig/objects/object_calcer.h b/kig/objects/object_calcer.h index 6df94fe8..777d3af8 100644 --- a/kig/objects/object_calcer.h +++ b/kig/objects/object_calcer.h @@ -19,7 +19,7 @@ #define KIG_OBJECTS_OBJECT_CALCER_H #include "common.h" -#include "../misc/boost_intrusive_pointer.hpp" +#include "../misc/boost_intrusive_pointer.h" class ObjectCalcer; diff --git a/kig/objects/object_drawer.cc b/kig/objects/object_drawer.cc deleted file mode 100644 index d6e41144..00000000 --- a/kig/objects/object_drawer.cc +++ /dev/null @@ -1,204 +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_drawer.h" - -#include "object_imp.h" -#include "../misc/kigpainter.h" - -#include -#include -#include - -#include - -void ObjectDrawer::draw( const ObjectImp& imp, KigPainter& p, bool sel ) const -{ - bool nv = p.getNightVision( ); - if ( mshown || nv ) - { - p.setBrushStyle( Qt::NoBrush ); - p.setBrushColor( sel ? TQt::red : ( mshown?mcolor:TQt::gray ) ); - p.setPen( TQPen ( sel ? TQt::red : ( mshown?mcolor:TQt::gray ), 1) ); - p.setWidth( mwidth ); - p.setStyle( mstyle ); - p.setPointStyle( mpointstyle ); - imp.draw( p ); - } -} - -bool ObjectDrawer::contains( const ObjectImp& imp, const Coordinate& pt, const KigWidget& w, bool nv ) const -{ - bool shownornv = mshown || nv; - return shownornv && imp.contains( pt, mwidth, w ); -} - -bool ObjectDrawer::shown( ) const -{ - return mshown; -} - -TQColor ObjectDrawer::color() const -{ - return mcolor; -} - -ObjectDrawer* ObjectDrawer::getCopyShown( bool s ) const -{ - ObjectDrawer* ret = new ObjectDrawer; - ret->mcolor = mcolor; - ret->mshown = s; - ret->mwidth = mwidth; - ret->mstyle = mstyle; - ret->mpointstyle = mpointstyle; - return ret; -} - -ObjectDrawer* ObjectDrawer::getCopyColor( const TQColor& c ) const -{ - ObjectDrawer* ret = new ObjectDrawer; - ret->mcolor = c; - ret->mshown = mshown; - ret->mwidth = mwidth; - ret->mstyle = mstyle; - ret->mpointstyle = mpointstyle; - return ret; -} - -ObjectDrawer* ObjectDrawer::getCopyWidth( int w ) const -{ - ObjectDrawer* ret = new ObjectDrawer; - ret->mcolor = mcolor; - ret->mshown = mshown; - ret->mwidth = w; - ret->mstyle = mstyle; - ret->mpointstyle = mpointstyle; - return ret; -} - -ObjectDrawer* ObjectDrawer::getCopyStyle( Qt::PenStyle s ) const -{ - ObjectDrawer* ret = new ObjectDrawer; - ret->mcolor = mcolor; - ret->mshown = mshown; - ret->mwidth = mwidth; - ret->mstyle = s; - ret->mpointstyle = mpointstyle; - return ret; -} - -ObjectDrawer* ObjectDrawer::getCopyPointStyle( int p ) const -{ - ObjectDrawer* ret = new ObjectDrawer; - ret->mcolor = mcolor; - ret->mshown = mshown; - ret->mwidth = mwidth; - ret->mstyle = mstyle; - ret->mpointstyle = p; - return ret; -} - -int ObjectDrawer::width() const -{ - return mwidth; -} - -Qt::PenStyle ObjectDrawer::style() const -{ - return mstyle; -} - -int ObjectDrawer::pointStyle() const -{ - return mpointstyle; -} - -ObjectDrawer::ObjectDrawer( const TQColor& color, int width, bool shown, Qt::PenStyle style, int pointStyle ) - : mcolor( color ), mshown( shown ), mwidth( width ), mstyle( style ), mpointstyle( pointStyle ) -{ -} - -ObjectDrawer::ObjectDrawer() - : mcolor( TQt::blue ), mshown( true ), mwidth( -1 ), mstyle( Qt::SolidLine ), mpointstyle( 0 ) -{ -} - -bool ObjectDrawer::inRect( const ObjectImp& imp, const Rect& r, const KigWidget& w ) const -{ - return mshown && imp.inRect( r, mwidth, w ); -} - -int ObjectDrawer::pointStyleFromString( const TQString& style ) -{ - if ( style == "Round" ) - return 0; - else if ( style == "RoundEmpty" ) - return 1; - else if ( style == "Rectangular" ) - return 2; - else if ( style == "RectangularEmpty" ) - return 3; - else if ( style == "Cross" ) - return 4; - return 0; -} - -TQString ObjectDrawer::pointStyleToString() const -{ - if ( mpointstyle == 0 ) - return "Round"; - else if ( mpointstyle == 1 ) - return "RoundEmpty"; - else if ( mpointstyle == 2 ) - return "Rectangular"; - else if ( mpointstyle == 3 ) - return "RectangularEmpty"; - else if ( mpointstyle == 4 ) - return "Cross"; - assert( false ); - return TQString(); -} - -Qt::PenStyle ObjectDrawer::styleFromString( const TQString& style ) -{ - if ( style == "SolidLine" ) - return Qt::SolidLine; - else if ( style == "DashLine" ) - return Qt::DashLine; - else if ( style == "DotLine" ) - return Qt::DotLine; - else if ( style == "DashDotLine" ) - return Qt::DashDotLine; - else if ( style == "DashDotDotLine" ) - return Qt::DashDotDotLine; - else return Qt::SolidLine; -} - -TQString ObjectDrawer::styleToString() const -{ - if ( mstyle == TQt::SolidLine ) - return "SolidLine"; - else if ( mstyle == TQt::DashLine ) - return "DashLine"; - else if ( mstyle == TQt::DotLine ) - return "DotLine"; - else if ( mstyle == TQt::DashDotLine ) - return "DashDotLine"; - else if ( mstyle == TQt::DashDotDotLine ) - return "DashDotDotLine"; - return "SolidLine"; -} diff --git a/kig/objects/object_drawer.cpp b/kig/objects/object_drawer.cpp new file mode 100644 index 00000000..d6e41144 --- /dev/null +++ b/kig/objects/object_drawer.cpp @@ -0,0 +1,204 @@ +// 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_drawer.h" + +#include "object_imp.h" +#include "../misc/kigpainter.h" + +#include +#include +#include + +#include + +void ObjectDrawer::draw( const ObjectImp& imp, KigPainter& p, bool sel ) const +{ + bool nv = p.getNightVision( ); + if ( mshown || nv ) + { + p.setBrushStyle( Qt::NoBrush ); + p.setBrushColor( sel ? TQt::red : ( mshown?mcolor:TQt::gray ) ); + p.setPen( TQPen ( sel ? TQt::red : ( mshown?mcolor:TQt::gray ), 1) ); + p.setWidth( mwidth ); + p.setStyle( mstyle ); + p.setPointStyle( mpointstyle ); + imp.draw( p ); + } +} + +bool ObjectDrawer::contains( const ObjectImp& imp, const Coordinate& pt, const KigWidget& w, bool nv ) const +{ + bool shownornv = mshown || nv; + return shownornv && imp.contains( pt, mwidth, w ); +} + +bool ObjectDrawer::shown( ) const +{ + return mshown; +} + +TQColor ObjectDrawer::color() const +{ + return mcolor; +} + +ObjectDrawer* ObjectDrawer::getCopyShown( bool s ) const +{ + ObjectDrawer* ret = new ObjectDrawer; + ret->mcolor = mcolor; + ret->mshown = s; + ret->mwidth = mwidth; + ret->mstyle = mstyle; + ret->mpointstyle = mpointstyle; + return ret; +} + +ObjectDrawer* ObjectDrawer::getCopyColor( const TQColor& c ) const +{ + ObjectDrawer* ret = new ObjectDrawer; + ret->mcolor = c; + ret->mshown = mshown; + ret->mwidth = mwidth; + ret->mstyle = mstyle; + ret->mpointstyle = mpointstyle; + return ret; +} + +ObjectDrawer* ObjectDrawer::getCopyWidth( int w ) const +{ + ObjectDrawer* ret = new ObjectDrawer; + ret->mcolor = mcolor; + ret->mshown = mshown; + ret->mwidth = w; + ret->mstyle = mstyle; + ret->mpointstyle = mpointstyle; + return ret; +} + +ObjectDrawer* ObjectDrawer::getCopyStyle( Qt::PenStyle s ) const +{ + ObjectDrawer* ret = new ObjectDrawer; + ret->mcolor = mcolor; + ret->mshown = mshown; + ret->mwidth = mwidth; + ret->mstyle = s; + ret->mpointstyle = mpointstyle; + return ret; +} + +ObjectDrawer* ObjectDrawer::getCopyPointStyle( int p ) const +{ + ObjectDrawer* ret = new ObjectDrawer; + ret->mcolor = mcolor; + ret->mshown = mshown; + ret->mwidth = mwidth; + ret->mstyle = mstyle; + ret->mpointstyle = p; + return ret; +} + +int ObjectDrawer::width() const +{ + return mwidth; +} + +Qt::PenStyle ObjectDrawer::style() const +{ + return mstyle; +} + +int ObjectDrawer::pointStyle() const +{ + return mpointstyle; +} + +ObjectDrawer::ObjectDrawer( const TQColor& color, int width, bool shown, Qt::PenStyle style, int pointStyle ) + : mcolor( color ), mshown( shown ), mwidth( width ), mstyle( style ), mpointstyle( pointStyle ) +{ +} + +ObjectDrawer::ObjectDrawer() + : mcolor( TQt::blue ), mshown( true ), mwidth( -1 ), mstyle( Qt::SolidLine ), mpointstyle( 0 ) +{ +} + +bool ObjectDrawer::inRect( const ObjectImp& imp, const Rect& r, const KigWidget& w ) const +{ + return mshown && imp.inRect( r, mwidth, w ); +} + +int ObjectDrawer::pointStyleFromString( const TQString& style ) +{ + if ( style == "Round" ) + return 0; + else if ( style == "RoundEmpty" ) + return 1; + else if ( style == "Rectangular" ) + return 2; + else if ( style == "RectangularEmpty" ) + return 3; + else if ( style == "Cross" ) + return 4; + return 0; +} + +TQString ObjectDrawer::pointStyleToString() const +{ + if ( mpointstyle == 0 ) + return "Round"; + else if ( mpointstyle == 1 ) + return "RoundEmpty"; + else if ( mpointstyle == 2 ) + return "Rectangular"; + else if ( mpointstyle == 3 ) + return "RectangularEmpty"; + else if ( mpointstyle == 4 ) + return "Cross"; + assert( false ); + return TQString(); +} + +Qt::PenStyle ObjectDrawer::styleFromString( const TQString& style ) +{ + if ( style == "SolidLine" ) + return Qt::SolidLine; + else if ( style == "DashLine" ) + return Qt::DashLine; + else if ( style == "DotLine" ) + return Qt::DotLine; + else if ( style == "DashDotLine" ) + return Qt::DashDotLine; + else if ( style == "DashDotDotLine" ) + return Qt::DashDotDotLine; + else return Qt::SolidLine; +} + +TQString ObjectDrawer::styleToString() const +{ + if ( mstyle == TQt::SolidLine ) + return "SolidLine"; + else if ( mstyle == TQt::DashLine ) + return "DashLine"; + else if ( mstyle == TQt::DotLine ) + return "DotLine"; + else if ( mstyle == TQt::DashDotLine ) + return "DashDotLine"; + else if ( mstyle == TQt::DashDotDotLine ) + return "DashDotDotLine"; + return "SolidLine"; +} diff --git a/kig/objects/object_factory.cc b/kig/objects/object_factory.cc deleted file mode 100644 index f2957a7e..00000000 --- a/kig/objects/object_factory.cc +++ /dev/null @@ -1,369 +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_factory.h" - -#include "bogus_imp.h" -#include "curve_imp.h" -#include "intersection_types.h" -#include "line_imp.h" -#include "object_drawer.h" -#include "object_holder.h" -#include "other_type.h" -#include "point_imp.h" -#include "point_type.h" -#include "text_type.h" - -#include "../kig/kig_document.h" -#include "../kig/kig_view.h" -#include "../misc/calcpaths.h" -#include "../misc/coordinate.h" -#include "../misc/object_hierarchy.h" - -#include -#include - -ObjectHolder* ObjectFactory::fixedPoint( const Coordinate& c ) const -{ - ObjectHolder* o = new ObjectHolder( fixedPointCalcer( c ) ); - return o; -} - -ObjectTypeCalcer* ObjectFactory::fixedPointCalcer( const Coordinate& c ) const -{ - std::vector args; - args.push_back( new ObjectConstCalcer( new DoubleImp( c.x ) ) ); - args.push_back( new ObjectConstCalcer( new DoubleImp( c.y ) ) ); - ObjectTypeCalcer* oc = new ObjectTypeCalcer( FixedPointType::instance(), args ); - return oc; -} - -ObjectTypeCalcer* ObjectFactory::cursorPointCalcer( const Coordinate& c ) const -{ - std::vector args; - args.push_back( new ObjectConstCalcer( new DoubleImp( c.x ) ) ); - args.push_back( new ObjectConstCalcer( new DoubleImp( c.y ) ) ); - ObjectTypeCalcer* oc = new ObjectTypeCalcer( CursorPointType::instance(), args ); - return oc; -} - -const ObjectFactory* ObjectFactory::instance() -{ - static ObjectFactory f; - return &f; -} - -ObjectTypeCalcer* ObjectFactory::sensiblePointCalcer( - const Coordinate& c, const KigDocument& d, const KigWidget& w ) const -{ - std::vector os = d.whatAmIOn( c, w ); - if ( os.size() == 2 ) - { - // we can calc intersection point *olny* between two objects... - std::vector args; - args.push_back( os[0]->calcer() ); - args.push_back( os[1]->calcer() ); - // the simpliest case: two lines... - if ( ( os[0]->imp()->inherits( AbstractLineImp::stype() ) ) && - ( os[1]->imp()->inherits( AbstractLineImp::stype() ) ) ) - return new ObjectTypeCalcer( LineLineIntersectionType::instance(), args ); - // other cases will follow... - } - for ( std::vector::iterator i = os.begin(); i != os.end(); ++i ) - if ( (*i)->imp()->inherits( CurveImp::stype() ) ) - return constrainedPointCalcer( (*i)->calcer(), c, d ); - return fixedPointCalcer( c ); -} - -ObjectHolder* ObjectFactory::sensiblePoint( - const Coordinate& c, const KigDocument& d, const KigWidget& w ) const -{ - return new ObjectHolder( sensiblePointCalcer( c, d, w ) ); -} - -ObjectTypeCalcer* ObjectFactory::relativePointCalcer( - ObjectCalcer* o, const Coordinate& loc ) const -{ - Coordinate reference = - static_cast( o->imp() )->attachPoint(); - assert( reference.valid() ); - - double x = 0.0; - double y = 0.0; - if ( loc.valid() ) - { - x = loc.x - reference.x; - y = loc.y - reference.y; - } - std::vector parents; - parents.push_back( new ObjectConstCalcer( new DoubleImp( x ) ) ); - parents.push_back( new ObjectConstCalcer( new DoubleImp( y ) ) ); - parents.push_back( o ); - return new ObjectTypeCalcer( RelativePointType::instance(), parents ); -} - -ObjectTypeCalcer* ObjectFactory::constrainedPointCalcer( - ObjectCalcer* curve, double param ) const -{ - assert( curve->imp()->inherits( CurveImp::stype() ) ); - std::vector parents; - parents.push_back( new ObjectConstCalcer( new DoubleImp( param ) ) ); - parents.push_back( curve ); - return new ObjectTypeCalcer( ConstrainedPointType::instance(), parents ); -} - -ObjectHolder* ObjectFactory::constrainedPoint( - ObjectCalcer* curve, double param ) const -{ - return new ObjectHolder( constrainedPointCalcer( curve, param ) ); -} - -ObjectTypeCalcer* ObjectFactory::constrainedPointCalcer( - ObjectCalcer* curve, const Coordinate& c, const KigDocument& d ) const -{ - assert( curve->imp()->inherits( CurveImp::stype() ) ); - double param = static_cast( curve->imp() )->getParam( c, d ); - return constrainedPointCalcer( curve, param ); -} - -ObjectHolder* ObjectFactory::constrainedPoint( - ObjectCalcer* curve, const Coordinate& c, const KigDocument& d ) const -{ - return new ObjectHolder( constrainedPointCalcer( curve, c, d ) ); -} - -ObjectTypeCalcer* ObjectFactory::locusCalcer( - ObjectCalcer* a, ObjectCalcer* b ) const -{ - assert( dynamic_cast( a ) ); - ObjectTypeCalcer* constrained = static_cast( a ); - assert( constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) ); - assert( constrained->parents().size() == 2 ); - ObjectCalcer* curve = a->parents().back(); - - const ObjectCalcer* moving = b; - - std::vector hierparents; - hierparents.push_back( constrained ); - std::vector sideOfTree = sideOfTreePath( hierparents, moving ); - std::copy( sideOfTree.begin(), sideOfTree.end(), std::back_inserter( hierparents ) ); - - ObjectHierarchy hier( hierparents, moving ); - - std::vector realparents( 2 + sideOfTree.size(), 0 ); - realparents[0] = new ObjectConstCalcer( new HierarchyImp( hier ) ); - realparents[1] = curve; - copy( sideOfTree.begin(), sideOfTree.end(), realparents.begin() + 2 ); - - return new ObjectTypeCalcer( LocusType::instance(), realparents ); -} - -ObjectHolder* ObjectFactory::locus( ObjectCalcer* a, ObjectCalcer* b ) const -{ - return new ObjectHolder( locusCalcer( a, b ) ); -} - -ObjectHolder* ObjectFactory::label( - const TQString& s, const Coordinate& loc, - bool needframe, const std::vector& parents, - const KigDocument& doc ) const -{ - return new ObjectHolder( labelCalcer( s, loc, needframe, parents, doc ) ); -} - -ObjectTypeCalcer* ObjectFactory::labelCalcer( - const TQString& s, const Coordinate& loc, - bool needframe, const std::vector& parents, - const KigDocument& doc ) const -{ - return attachedLabelCalcer( s, 0, loc, needframe, parents, doc ); -} - -ObjectTypeCalcer* ObjectFactory::attachedLabelCalcer( - const TQString& s, ObjectCalcer* p, - const Coordinate& loc, bool needframe, - const std::vector& nparents, - const KigDocument& doc ) const -{ - std::vector parents; - parents.reserve( nparents.size() + 3 ); - parents.push_back( new ObjectConstCalcer( new IntImp( needframe ? 1 : 0 ) ) ); - - parents.push_back( getAttachPoint( p, loc, doc ) ); - - parents.push_back( new ObjectConstCalcer( new StringImp( s ) ) ); - std::copy( nparents.begin(), nparents.end(), std::back_inserter( parents ) ); - ObjectTypeCalcer* ret = new ObjectTypeCalcer( TextType::instance(), parents ); - ret->calc( doc ); - return ret; -} - -ObjectCalcer* ObjectFactory::getAttachPoint( - ObjectCalcer* p, - const Coordinate& loc, - const KigDocument& doc ) const -{ -/* - * mp: (changes to add relative-attachment). Now an object is tested - * as follows: - * - if attachPoint() returns a valid coordinate, then we use the new method - * - if it is a point: 'old-style' treatment (we can change this shortly) - * - if it is a curve: 'old-style' treatment (we could use the new approach, - * which can be better/worse depending on personal taste, I think) - * - * the first condition that matches determines the behaviour. - * the new method works similarly to the curve case, but we generate a new - * RelativePointType instead of a ConstrainedPointType; this will in turn make use - * of the new attachPoint() method for objects. - * - * changed the preference order 2005/01/21 (now attachPoint has preference over points) - * - * NOTE: changes in the tests performed should be matched also in - * modes/popup.cc (addNameLabel) and in label.cc (TextLabelModeBase::mouseMoved) - */ - - if ( p && p->imp()->attachPoint().valid() ) - { - ObjectCalcer* o = relativePointCalcer( p, loc ); - o->calc( doc ); - return o; - } - else if ( p && p->imp()->inherits( PointImp::stype() ) ) - { - return p; - } - else if ( p && p->imp()->inherits( CurveImp::stype() ) ) - { - double param = 0.5; - if ( loc.valid() ) - param = static_cast( p->imp() )->getParam( loc, doc ); - - ObjectCalcer* o = constrainedPointCalcer( p, param ); - o->calc( doc ); - return o; - } - else - { - if ( loc.valid() ) - return new ObjectConstCalcer( new PointImp( loc ) ); - else - return new ObjectConstCalcer( new PointImp( Coordinate( 0, 0 ) ) ); - } -} - -ObjectHolder* ObjectFactory::attachedLabel( - const TQString& s, ObjectCalcer* locationparent, - const Coordinate& loc, bool needframe, - const std::vector& parents, - const KigDocument& doc ) const -{ - return new ObjectHolder( attachedLabelCalcer( s, locationparent, loc, needframe, parents, doc ) ); -} - -ObjectPropertyCalcer* ObjectFactory::propertyObjectCalcer( - ObjectCalcer* o, const char* p ) const -{ - int wp = o->imp()->propertiesInternalNames().findIndex( p ); - if ( wp == -1 ) return 0; - return new ObjectPropertyCalcer( o, wp ); -} - -ObjectHolder* ObjectFactory::propertyObject( - ObjectCalcer* o, const char* p ) const -{ - return new ObjectHolder( propertyObjectCalcer( o, p ) ); -} - -void ObjectFactory::redefinePoint( - ObjectTypeCalcer* point, const Coordinate& c, - KigDocument& doc, const KigWidget& w ) const -{ - std::vector hos = doc.whatAmIOn( c, w ); - std::vector os; - ObjectCalcer* (ObjectHolder::*calcmeth)() = &ObjectHolder::calcer; - std::transform( hos.begin(), hos.end(), std::back_inserter( os ), - std::mem_fun( calcmeth ) ); - ObjectCalcer* v = 0; - - // we don't want one of our children as a parent... - std::set children = getAllChildren( point ); - for ( std::vector::iterator i = os.begin(); - i != os.end(); ++i ) - if ( (*i)->imp()->inherits( CurveImp::stype() ) && - children.find( *i ) == children.end() ) - { - v = *i; - break; - }; - - if ( v ) - { - // we want a constrained point... - const CurveImp* curveimp = static_cast( v->imp() ); - double newparam = curveimp->getParam( c, doc ); - - if ( point->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) - { - // point already was constrained -> simply update the param - // DataObject and make sure point is on the right curve... - ObjectCalcer* dataobj = 0; - std::vector parents = point->parents(); - assert( parents.size() == 2 ); - assert ( parents[0]->imp()->inherits( DoubleImp::stype() ) ); - dataobj = parents[0]; - - parents.clear(); - parents.push_back( dataobj ); - parents.push_back( v ); - point->setParents( parents ); - - assert( dynamic_cast( dataobj ) ); - static_cast( dataobj )->setImp( - new DoubleImp( newparam ) ); - } - else - { - // point used to be fixed -> add a new DataObject etc. - std::vector args; - args.push_back( new ObjectConstCalcer( new DoubleImp( newparam ) ) ); - args.push_back( v ); - point->setType( ConstrainedPointType::instance() ); - point->setParents( args ); - } - } - else - { - // a fixed point... - if ( point->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) - { - // point used to be constrained.. - std::vector a; - a.push_back( new ObjectConstCalcer( new DoubleImp( c.x ) ) ); - a.push_back( new ObjectConstCalcer( new DoubleImp( c.y ) ) ); - - point->setType( FixedPointType::instance() ); - point->setParents( a ); - } - else - { - // point used to be fixed -> simply update the DataObject's - // we can use the point's move function for that.. - point->move( c, doc ); - }; - } -} - diff --git a/kig/objects/object_factory.cpp b/kig/objects/object_factory.cpp new file mode 100644 index 00000000..bf333094 --- /dev/null +++ b/kig/objects/object_factory.cpp @@ -0,0 +1,369 @@ +// 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_factory.h" + +#include "bogus_imp.h" +#include "curve_imp.h" +#include "intersection_types.h" +#include "line_imp.h" +#include "object_drawer.h" +#include "object_holder.h" +#include "other_type.h" +#include "point_imp.h" +#include "point_type.h" +#include "text_type.h" + +#include "../kig/kig_document.h" +#include "../kig/kig_view.h" +#include "../misc/calcpaths.h" +#include "../misc/coordinate.h" +#include "../misc/object_hierarchy.h" + +#include +#include + +ObjectHolder* ObjectFactory::fixedPoint( const Coordinate& c ) const +{ + ObjectHolder* o = new ObjectHolder( fixedPointCalcer( c ) ); + return o; +} + +ObjectTypeCalcer* ObjectFactory::fixedPointCalcer( const Coordinate& c ) const +{ + std::vector args; + args.push_back( new ObjectConstCalcer( new DoubleImp( c.x ) ) ); + args.push_back( new ObjectConstCalcer( new DoubleImp( c.y ) ) ); + ObjectTypeCalcer* oc = new ObjectTypeCalcer( FixedPointType::instance(), args ); + return oc; +} + +ObjectTypeCalcer* ObjectFactory::cursorPointCalcer( const Coordinate& c ) const +{ + std::vector args; + args.push_back( new ObjectConstCalcer( new DoubleImp( c.x ) ) ); + args.push_back( new ObjectConstCalcer( new DoubleImp( c.y ) ) ); + ObjectTypeCalcer* oc = new ObjectTypeCalcer( CursorPointType::instance(), args ); + return oc; +} + +const ObjectFactory* ObjectFactory::instance() +{ + static ObjectFactory f; + return &f; +} + +ObjectTypeCalcer* ObjectFactory::sensiblePointCalcer( + const Coordinate& c, const KigDocument& d, const KigWidget& w ) const +{ + std::vector os = d.whatAmIOn( c, w ); + if ( os.size() == 2 ) + { + // we can calc intersection point *olny* between two objects... + std::vector args; + args.push_back( os[0]->calcer() ); + args.push_back( os[1]->calcer() ); + // the simpliest case: two lines... + if ( ( os[0]->imp()->inherits( AbstractLineImp::stype() ) ) && + ( os[1]->imp()->inherits( AbstractLineImp::stype() ) ) ) + return new ObjectTypeCalcer( LineLineIntersectionType::instance(), args ); + // other cases will follow... + } + for ( std::vector::iterator i = os.begin(); i != os.end(); ++i ) + if ( (*i)->imp()->inherits( CurveImp::stype() ) ) + return constrainedPointCalcer( (*i)->calcer(), c, d ); + return fixedPointCalcer( c ); +} + +ObjectHolder* ObjectFactory::sensiblePoint( + const Coordinate& c, const KigDocument& d, const KigWidget& w ) const +{ + return new ObjectHolder( sensiblePointCalcer( c, d, w ) ); +} + +ObjectTypeCalcer* ObjectFactory::relativePointCalcer( + ObjectCalcer* o, const Coordinate& loc ) const +{ + Coordinate reference = + static_cast( o->imp() )->attachPoint(); + assert( reference.valid() ); + + double x = 0.0; + double y = 0.0; + if ( loc.valid() ) + { + x = loc.x - reference.x; + y = loc.y - reference.y; + } + std::vector parents; + parents.push_back( new ObjectConstCalcer( new DoubleImp( x ) ) ); + parents.push_back( new ObjectConstCalcer( new DoubleImp( y ) ) ); + parents.push_back( o ); + return new ObjectTypeCalcer( RelativePointType::instance(), parents ); +} + +ObjectTypeCalcer* ObjectFactory::constrainedPointCalcer( + ObjectCalcer* curve, double param ) const +{ + assert( curve->imp()->inherits( CurveImp::stype() ) ); + std::vector parents; + parents.push_back( new ObjectConstCalcer( new DoubleImp( param ) ) ); + parents.push_back( curve ); + return new ObjectTypeCalcer( ConstrainedPointType::instance(), parents ); +} + +ObjectHolder* ObjectFactory::constrainedPoint( + ObjectCalcer* curve, double param ) const +{ + return new ObjectHolder( constrainedPointCalcer( curve, param ) ); +} + +ObjectTypeCalcer* ObjectFactory::constrainedPointCalcer( + ObjectCalcer* curve, const Coordinate& c, const KigDocument& d ) const +{ + assert( curve->imp()->inherits( CurveImp::stype() ) ); + double param = static_cast( curve->imp() )->getParam( c, d ); + return constrainedPointCalcer( curve, param ); +} + +ObjectHolder* ObjectFactory::constrainedPoint( + ObjectCalcer* curve, const Coordinate& c, const KigDocument& d ) const +{ + return new ObjectHolder( constrainedPointCalcer( curve, c, d ) ); +} + +ObjectTypeCalcer* ObjectFactory::locusCalcer( + ObjectCalcer* a, ObjectCalcer* b ) const +{ + assert( dynamic_cast( a ) ); + ObjectTypeCalcer* constrained = static_cast( a ); + assert( constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) ); + assert( constrained->parents().size() == 2 ); + ObjectCalcer* curve = a->parents().back(); + + const ObjectCalcer* moving = b; + + std::vector hierparents; + hierparents.push_back( constrained ); + std::vector sideOfTree = sideOfTreePath( hierparents, moving ); + std::copy( sideOfTree.begin(), sideOfTree.end(), std::back_inserter( hierparents ) ); + + ObjectHierarchy hier( hierparents, moving ); + + std::vector realparents( 2 + sideOfTree.size(), 0 ); + realparents[0] = new ObjectConstCalcer( new HierarchyImp( hier ) ); + realparents[1] = curve; + copy( sideOfTree.begin(), sideOfTree.end(), realparents.begin() + 2 ); + + return new ObjectTypeCalcer( LocusType::instance(), realparents ); +} + +ObjectHolder* ObjectFactory::locus( ObjectCalcer* a, ObjectCalcer* b ) const +{ + return new ObjectHolder( locusCalcer( a, b ) ); +} + +ObjectHolder* ObjectFactory::label( + const TQString& s, const Coordinate& loc, + bool needframe, const std::vector& parents, + const KigDocument& doc ) const +{ + return new ObjectHolder( labelCalcer( s, loc, needframe, parents, doc ) ); +} + +ObjectTypeCalcer* ObjectFactory::labelCalcer( + const TQString& s, const Coordinate& loc, + bool needframe, const std::vector& parents, + const KigDocument& doc ) const +{ + return attachedLabelCalcer( s, 0, loc, needframe, parents, doc ); +} + +ObjectTypeCalcer* ObjectFactory::attachedLabelCalcer( + const TQString& s, ObjectCalcer* p, + const Coordinate& loc, bool needframe, + const std::vector& nparents, + const KigDocument& doc ) const +{ + std::vector parents; + parents.reserve( nparents.size() + 3 ); + parents.push_back( new ObjectConstCalcer( new IntImp( needframe ? 1 : 0 ) ) ); + + parents.push_back( getAttachPoint( p, loc, doc ) ); + + parents.push_back( new ObjectConstCalcer( new StringImp( s ) ) ); + std::copy( nparents.begin(), nparents.end(), std::back_inserter( parents ) ); + ObjectTypeCalcer* ret = new ObjectTypeCalcer( TextType::instance(), parents ); + ret->calc( doc ); + return ret; +} + +ObjectCalcer* ObjectFactory::getAttachPoint( + ObjectCalcer* p, + const Coordinate& loc, + const KigDocument& doc ) const +{ +/* + * mp: (changes to add relative-attachment). Now an object is tested + * as follows: + * - if attachPoint() returns a valid coordinate, then we use the new method + * - if it is a point: 'old-style' treatment (we can change this shortly) + * - if it is a curve: 'old-style' treatment (we could use the new approach, + * which can be better/worse depending on personal taste, I think) + * + * the first condition that matches determines the behaviour. + * the new method works similarly to the curve case, but we generate a new + * RelativePointType instead of a ConstrainedPointType; this will in turn make use + * of the new attachPoint() method for objects. + * + * changed the preference order 2005/01/21 (now attachPoint has preference over points) + * + * NOTE: changes in the tests performed should be matched also in + * modes/popup.cpp (addNameLabel) and in label.cpp (TextLabelModeBase::mouseMoved) + */ + + if ( p && p->imp()->attachPoint().valid() ) + { + ObjectCalcer* o = relativePointCalcer( p, loc ); + o->calc( doc ); + return o; + } + else if ( p && p->imp()->inherits( PointImp::stype() ) ) + { + return p; + } + else if ( p && p->imp()->inherits( CurveImp::stype() ) ) + { + double param = 0.5; + if ( loc.valid() ) + param = static_cast( p->imp() )->getParam( loc, doc ); + + ObjectCalcer* o = constrainedPointCalcer( p, param ); + o->calc( doc ); + return o; + } + else + { + if ( loc.valid() ) + return new ObjectConstCalcer( new PointImp( loc ) ); + else + return new ObjectConstCalcer( new PointImp( Coordinate( 0, 0 ) ) ); + } +} + +ObjectHolder* ObjectFactory::attachedLabel( + const TQString& s, ObjectCalcer* locationparent, + const Coordinate& loc, bool needframe, + const std::vector& parents, + const KigDocument& doc ) const +{ + return new ObjectHolder( attachedLabelCalcer( s, locationparent, loc, needframe, parents, doc ) ); +} + +ObjectPropertyCalcer* ObjectFactory::propertyObjectCalcer( + ObjectCalcer* o, const char* p ) const +{ + int wp = o->imp()->propertiesInternalNames().findIndex( p ); + if ( wp == -1 ) return 0; + return new ObjectPropertyCalcer( o, wp ); +} + +ObjectHolder* ObjectFactory::propertyObject( + ObjectCalcer* o, const char* p ) const +{ + return new ObjectHolder( propertyObjectCalcer( o, p ) ); +} + +void ObjectFactory::redefinePoint( + ObjectTypeCalcer* point, const Coordinate& c, + KigDocument& doc, const KigWidget& w ) const +{ + std::vector hos = doc.whatAmIOn( c, w ); + std::vector os; + ObjectCalcer* (ObjectHolder::*calcmeth)() = &ObjectHolder::calcer; + std::transform( hos.begin(), hos.end(), std::back_inserter( os ), + std::mem_fun( calcmeth ) ); + ObjectCalcer* v = 0; + + // we don't want one of our children as a parent... + std::set children = getAllChildren( point ); + for ( std::vector::iterator i = os.begin(); + i != os.end(); ++i ) + if ( (*i)->imp()->inherits( CurveImp::stype() ) && + children.find( *i ) == children.end() ) + { + v = *i; + break; + }; + + if ( v ) + { + // we want a constrained point... + const CurveImp* curveimp = static_cast( v->imp() ); + double newparam = curveimp->getParam( c, doc ); + + if ( point->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) + { + // point already was constrained -> simply update the param + // DataObject and make sure point is on the right curve... + ObjectCalcer* dataobj = 0; + std::vector parents = point->parents(); + assert( parents.size() == 2 ); + assert ( parents[0]->imp()->inherits( DoubleImp::stype() ) ); + dataobj = parents[0]; + + parents.clear(); + parents.push_back( dataobj ); + parents.push_back( v ); + point->setParents( parents ); + + assert( dynamic_cast( dataobj ) ); + static_cast( dataobj )->setImp( + new DoubleImp( newparam ) ); + } + else + { + // point used to be fixed -> add a new DataObject etc. + std::vector args; + args.push_back( new ObjectConstCalcer( new DoubleImp( newparam ) ) ); + args.push_back( v ); + point->setType( ConstrainedPointType::instance() ); + point->setParents( args ); + } + } + else + { + // a fixed point... + if ( point->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) + { + // point used to be constrained.. + std::vector a; + a.push_back( new ObjectConstCalcer( new DoubleImp( c.x ) ) ); + a.push_back( new ObjectConstCalcer( new DoubleImp( c.y ) ) ); + + point->setType( FixedPointType::instance() ); + point->setParents( a ); + } + else + { + // point used to be fixed -> simply update the DataObject's + // we can use the point's move function for that.. + point->move( c, doc ); + }; + } +} + diff --git a/kig/objects/object_holder.cc b/kig/objects/object_holder.cc deleted file mode 100644 index cdf06396..00000000 --- a/kig/objects/object_holder.cc +++ /dev/null @@ -1,164 +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_holder.h" - -#include "bogus_imp.h" -#include "object_calcer.h" -#include "object_drawer.h" - -#include "../misc/coordinate.h" - -ObjectHolder::ObjectHolder( ObjectCalcer* calcer ) - : mcalcer( calcer ), mdrawer( new ObjectDrawer ), mnamecalcer( 0 ) -{ -} - -ObjectHolder::ObjectHolder( ObjectCalcer* calcer, ObjectDrawer* drawer, - ObjectConstCalcer* namecalcer ) - : mcalcer( calcer ), mdrawer( drawer ), mnamecalcer( namecalcer ) -{ - assert( !namecalcer || namecalcer->imp()->inherits( StringImp::stype() ) ); -} - -ObjectHolder::ObjectHolder( ObjectCalcer* calcer, ObjectDrawer* drawer ) - : mcalcer( calcer ), mdrawer( drawer ), mnamecalcer( 0 ) -{ -} - -ObjectHolder::~ObjectHolder() -{ - delete mdrawer; -} - -const ObjectImp* ObjectHolder::imp() const -{ - return mcalcer->imp(); -} - -const ObjectCalcer* ObjectHolder::calcer() const -{ - return mcalcer.get(); -} - -const ObjectDrawer* ObjectHolder::drawer() const -{ - return mdrawer; -} - -const ObjectConstCalcer* ObjectHolder::nameCalcer() const -{ - return mnamecalcer.get(); -} - -void ObjectHolder::setDrawer( ObjectDrawer* d ) -{ - delete switchDrawer( d ); -} - -void ObjectHolder::calc( const KigDocument& d ) -{ - mcalcer->calc( d ); -} - -void ObjectHolder::draw( KigPainter& p, bool selected ) const -{ - mdrawer->draw( *imp(), p, selected ); -} - -bool ObjectHolder::contains( const Coordinate& pt, const KigWidget& w, bool nv ) const -{ - return mdrawer->contains( *imp(), pt, w, nv ); -} - -bool ObjectHolder::inRect( const Rect& r, const KigWidget& w ) const -{ - return mdrawer->inRect( *imp(), r, w ); -} - -ObjectCalcer* ObjectHolder::calcer() -{ - return mcalcer.get(); -} - -ObjectDrawer* ObjectHolder::drawer() -{ - return mdrawer; -} - -ObjectConstCalcer* ObjectHolder::nameCalcer() -{ - return mnamecalcer.get(); -} - -const Coordinate ObjectHolder::moveReferencePoint() const -{ - return mcalcer->moveReferencePoint(); -} - -void ObjectHolder::move( const Coordinate& to, const KigDocument& doc ) -{ - mcalcer->move( to, doc ); -} - -bool ObjectHolder::canMove() const -{ - return mcalcer->canMove(); -} - -bool ObjectHolder::isFreelyTranslatable() const -{ - return mcalcer->isFreelyTranslatable(); -} - -ObjectDrawer* ObjectHolder::switchDrawer( ObjectDrawer* d ) -{ - ObjectDrawer* tmp = mdrawer; - mdrawer = d; - return tmp; -} - -bool ObjectHolder::shown( ) const -{ - return mdrawer->shown( ); -} - -const TQString ObjectHolder::name() const -{ - if ( mnamecalcer ) - { - assert( mnamecalcer->imp()->inherits( StringImp::stype() ) ); - return static_cast( mnamecalcer->imp() )->data(); - } - else - return TQString(); -} - -void ObjectHolder::setNameCalcer( ObjectConstCalcer* namecalcer ) -{ - assert( !mnamecalcer ); - mnamecalcer = namecalcer; -} - -TQString ObjectHolder::selectStatement() const -{ - const TQString n = name(); - if ( n.isEmpty() ) - return i18n( imp()->type()->selectStatement() ); - else - return i18n( imp()->type()->selectNameStatement() ).arg( n ); -} diff --git a/kig/objects/object_holder.cpp b/kig/objects/object_holder.cpp new file mode 100644 index 00000000..cdf06396 --- /dev/null +++ b/kig/objects/object_holder.cpp @@ -0,0 +1,164 @@ +// 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_holder.h" + +#include "bogus_imp.h" +#include "object_calcer.h" +#include "object_drawer.h" + +#include "../misc/coordinate.h" + +ObjectHolder::ObjectHolder( ObjectCalcer* calcer ) + : mcalcer( calcer ), mdrawer( new ObjectDrawer ), mnamecalcer( 0 ) +{ +} + +ObjectHolder::ObjectHolder( ObjectCalcer* calcer, ObjectDrawer* drawer, + ObjectConstCalcer* namecalcer ) + : mcalcer( calcer ), mdrawer( drawer ), mnamecalcer( namecalcer ) +{ + assert( !namecalcer || namecalcer->imp()->inherits( StringImp::stype() ) ); +} + +ObjectHolder::ObjectHolder( ObjectCalcer* calcer, ObjectDrawer* drawer ) + : mcalcer( calcer ), mdrawer( drawer ), mnamecalcer( 0 ) +{ +} + +ObjectHolder::~ObjectHolder() +{ + delete mdrawer; +} + +const ObjectImp* ObjectHolder::imp() const +{ + return mcalcer->imp(); +} + +const ObjectCalcer* ObjectHolder::calcer() const +{ + return mcalcer.get(); +} + +const ObjectDrawer* ObjectHolder::drawer() const +{ + return mdrawer; +} + +const ObjectConstCalcer* ObjectHolder::nameCalcer() const +{ + return mnamecalcer.get(); +} + +void ObjectHolder::setDrawer( ObjectDrawer* d ) +{ + delete switchDrawer( d ); +} + +void ObjectHolder::calc( const KigDocument& d ) +{ + mcalcer->calc( d ); +} + +void ObjectHolder::draw( KigPainter& p, bool selected ) const +{ + mdrawer->draw( *imp(), p, selected ); +} + +bool ObjectHolder::contains( const Coordinate& pt, const KigWidget& w, bool nv ) const +{ + return mdrawer->contains( *imp(), pt, w, nv ); +} + +bool ObjectHolder::inRect( const Rect& r, const KigWidget& w ) const +{ + return mdrawer->inRect( *imp(), r, w ); +} + +ObjectCalcer* ObjectHolder::calcer() +{ + return mcalcer.get(); +} + +ObjectDrawer* ObjectHolder::drawer() +{ + return mdrawer; +} + +ObjectConstCalcer* ObjectHolder::nameCalcer() +{ + return mnamecalcer.get(); +} + +const Coordinate ObjectHolder::moveReferencePoint() const +{ + return mcalcer->moveReferencePoint(); +} + +void ObjectHolder::move( const Coordinate& to, const KigDocument& doc ) +{ + mcalcer->move( to, doc ); +} + +bool ObjectHolder::canMove() const +{ + return mcalcer->canMove(); +} + +bool ObjectHolder::isFreelyTranslatable() const +{ + return mcalcer->isFreelyTranslatable(); +} + +ObjectDrawer* ObjectHolder::switchDrawer( ObjectDrawer* d ) +{ + ObjectDrawer* tmp = mdrawer; + mdrawer = d; + return tmp; +} + +bool ObjectHolder::shown( ) const +{ + return mdrawer->shown( ); +} + +const TQString ObjectHolder::name() const +{ + if ( mnamecalcer ) + { + assert( mnamecalcer->imp()->inherits( StringImp::stype() ) ); + return static_cast( mnamecalcer->imp() )->data(); + } + else + return TQString(); +} + +void ObjectHolder::setNameCalcer( ObjectConstCalcer* namecalcer ) +{ + assert( !mnamecalcer ); + mnamecalcer = namecalcer; +} + +TQString ObjectHolder::selectStatement() const +{ + const TQString n = name(); + if ( n.isEmpty() ) + return i18n( imp()->type()->selectStatement() ); + else + return i18n( imp()->type()->selectNameStatement() ).arg( n ); +} diff --git a/kig/objects/object_imp.cc b/kig/objects/object_imp.cc deleted file mode 100644 index 1f7ad798..00000000 --- a/kig/objects/object_imp.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 "object_imp.h" - -#include "bogus_imp.h" - -#include "../misc/coordinate.h" - -#include -#include - -class ObjectImpType::StaticPrivate -{ -public: - std::map namemap; -}; - -ObjectImp::ObjectImp() -{ -} - -ObjectImp::~ObjectImp() -{ -} - -bool ObjectImp::valid() const -{ - return ! type()->inherits( InvalidImp::stype() ); -} - -void ObjectImp::fillInNextEscape( TQString&, const KigDocument& ) const -{ - assert( false ); -} - -const QCStringList ObjectImp::properties() const -{ - QCStringList ret; - ret << I18N_NOOP( "Object Type" ); - return ret; -} - -const uint ObjectImp::numberOfProperties() const -{ - return 1; -} - -const QCStringList ObjectImp::propertiesInternalNames() const -{ - QCStringList ret; - ret << "base-object-type"; - return ret; -} - -ObjectImp* ObjectImp::property( uint i, const KigDocument& ) const -{ - if ( i == 0 ) return new StringImp( type()->translatedName() ); - return new InvalidImp; -} - -const ObjectImpType* ObjectImp::impRequirementForProperty( uint ) const -{ - return ObjectImp::stype(); -} - -void ObjectImpVisitor::visit( const ObjectImp* imp ) -{ - imp->visit( this ); -} - -void ObjectImpVisitor::visit( const IntImp* ) -{ -} - -void ObjectImpVisitor::visit( const DoubleImp* ) -{ -} - -void ObjectImpVisitor::visit( const StringImp* ) -{ -} - -void ObjectImpVisitor::visit( const InvalidImp* ) -{ -} - -void ObjectImpVisitor::visit( const HierarchyImp* ) -{ -} - -void ObjectImpVisitor::visit( const LineImp* ) -{ -} - -void ObjectImpVisitor::visit( const PointImp* ) -{ -} - -void ObjectImpVisitor::visit( const TextImp* ) -{ -} - -void ObjectImpVisitor::visit( const AngleImp* ) -{ -} - -void ObjectImpVisitor::visit( const VectorImp* ) -{ -} - -void ObjectImpVisitor::visit( const LocusImp* ) -{ -} - -void ObjectImpVisitor::visit( const CircleImp* ) -{ -} - -void ObjectImpVisitor::visit( const ConicImp* ) -{ -} - -void ObjectImpVisitor::visit( const CubicImp* ) -{ -} - -void ObjectImpVisitor::visit( const SegmentImp* ) -{ -} - -void ObjectImpVisitor::visit( const RayImp* ) -{ -} - -void ObjectImpVisitor::visit( const ArcImp* ) -{ -} - -void ObjectImpVisitor::visit( const PolygonImp* ) -{ -} - -ObjectImpVisitor::~ObjectImpVisitor() -{ - -} - -void ObjectImpVisitor::visit( const TransformationImp* ) -{ -} - -void ObjectImpVisitor::visit( const TestResultImp* ) -{ -} - -const char* ObjectImp::iconForProperty( uint ) const -{ - return "kig_text"; -} - -bool ObjectImp::canFillInNextEscape() const -{ - return false; -} - -ObjectImpType::ObjectImpType( const ObjectImpType* parent, - const char* internalname, - const char* translatedname, - const char* selectstatement, - const char* selectnamestatement, - const char* removeastatement, - const char* addastatement, - const char* moveastatement, - const char* attachtothisstatement, - const char* showastatement, - const char* hideastatement ) - : mparent( parent ), minternalname( internalname ), - mtranslatedname( translatedname ), mselectstatement( selectstatement ), - mselectnamestatement( selectnamestatement ), - mremoveastatement( removeastatement ), maddastatement( addastatement ), - mmoveastatement( moveastatement ), - mattachtothisstatement( attachtothisstatement ), - mshowastatement( showastatement ), - mhideastatement( hideastatement ) -{ - sd()->namemap[minternalname] = this; -} - -ObjectImpType::~ObjectImpType() -{ -} - -bool ObjectImpType::inherits( const ObjectImpType* t ) const -{ - return t == this || (mparent && mparent->inherits( t ) ); -} - -const char* ObjectImpType::internalName() const -{ - return minternalname; -} - -TQString ObjectImpType::translatedName() const -{ - return i18n( mtranslatedname ); -} - -const char* ObjectImpType::selectStatement() const -{ - return mselectstatement; -} - -const char* ObjectImpType::selectNameStatement() const -{ - return mselectnamestatement; -} - -TQString ObjectImpType::removeAStatement() const -{ - return i18n( mremoveastatement ); -} - -TQString ObjectImpType::addAStatement() const -{ - return i18n( maddastatement ); -} - -TQString ObjectImpType::moveAStatement() const -{ - return i18n( mmoveastatement ); -} - -const ObjectImpType* ObjectImpType::typeFromInternalName( const char* string ) -{ - TQCString s( string ); - std::map::iterator i = sd()->namemap.find( s ); - if ( i == sd()->namemap.end() ) - return 0; - else return i->second; -} - -bool ObjectImp::inherits( const ObjectImpType* t ) const -{ - return type()->inherits( t ); -} - -const ObjectImpType* ObjectImp::stype() -{ - static const ObjectImpType t( - 0, "any", - I18N_NOOP( "Object" ), - I18N_NOOP( "Select this object" ), - I18N_NOOP( "Select object %1" ), - I18N_NOOP( "Remove an object" ), - I18N_NOOP( "Add an object" ), - I18N_NOOP( "Move an object" ), - I18N_NOOP( "Attach to this object" ), - I18N_NOOP( "Show an object" ), - I18N_NOOP( "Hide an object" ) ); - return &t; -} - -ObjectImpType::StaticPrivate* ObjectImpType::sd() -{ - static StaticPrivate d; - return &d; -} - -bool ObjectImp::isCache() const -{ - return false; -} - -TQString ObjectImpType::attachToThisStatement() const -{ - return i18n( mattachtothisstatement ); -} - -TQString ObjectImpType::showAStatement() const -{ - return i18n( mshowastatement ); -} - -TQString ObjectImpType::hideAStatement() const -{ - return i18n( mhideastatement ); -} - -bool ObjectImp::isPropertyDefinedOnOrThroughThisImp( uint ) const -{ - return false; -} - diff --git a/kig/objects/object_imp.cpp b/kig/objects/object_imp.cpp new file mode 100644 index 00000000..1f7ad798 --- /dev/null +++ b/kig/objects/object_imp.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 "object_imp.h" + +#include "bogus_imp.h" + +#include "../misc/coordinate.h" + +#include +#include + +class ObjectImpType::StaticPrivate +{ +public: + std::map namemap; +}; + +ObjectImp::ObjectImp() +{ +} + +ObjectImp::~ObjectImp() +{ +} + +bool ObjectImp::valid() const +{ + return ! type()->inherits( InvalidImp::stype() ); +} + +void ObjectImp::fillInNextEscape( TQString&, const KigDocument& ) const +{ + assert( false ); +} + +const QCStringList ObjectImp::properties() const +{ + QCStringList ret; + ret << I18N_NOOP( "Object Type" ); + return ret; +} + +const uint ObjectImp::numberOfProperties() const +{ + return 1; +} + +const QCStringList ObjectImp::propertiesInternalNames() const +{ + QCStringList ret; + ret << "base-object-type"; + return ret; +} + +ObjectImp* ObjectImp::property( uint i, const KigDocument& ) const +{ + if ( i == 0 ) return new StringImp( type()->translatedName() ); + return new InvalidImp; +} + +const ObjectImpType* ObjectImp::impRequirementForProperty( uint ) const +{ + return ObjectImp::stype(); +} + +void ObjectImpVisitor::visit( const ObjectImp* imp ) +{ + imp->visit( this ); +} + +void ObjectImpVisitor::visit( const IntImp* ) +{ +} + +void ObjectImpVisitor::visit( const DoubleImp* ) +{ +} + +void ObjectImpVisitor::visit( const StringImp* ) +{ +} + +void ObjectImpVisitor::visit( const InvalidImp* ) +{ +} + +void ObjectImpVisitor::visit( const HierarchyImp* ) +{ +} + +void ObjectImpVisitor::visit( const LineImp* ) +{ +} + +void ObjectImpVisitor::visit( const PointImp* ) +{ +} + +void ObjectImpVisitor::visit( const TextImp* ) +{ +} + +void ObjectImpVisitor::visit( const AngleImp* ) +{ +} + +void ObjectImpVisitor::visit( const VectorImp* ) +{ +} + +void ObjectImpVisitor::visit( const LocusImp* ) +{ +} + +void ObjectImpVisitor::visit( const CircleImp* ) +{ +} + +void ObjectImpVisitor::visit( const ConicImp* ) +{ +} + +void ObjectImpVisitor::visit( const CubicImp* ) +{ +} + +void ObjectImpVisitor::visit( const SegmentImp* ) +{ +} + +void ObjectImpVisitor::visit( const RayImp* ) +{ +} + +void ObjectImpVisitor::visit( const ArcImp* ) +{ +} + +void ObjectImpVisitor::visit( const PolygonImp* ) +{ +} + +ObjectImpVisitor::~ObjectImpVisitor() +{ + +} + +void ObjectImpVisitor::visit( const TransformationImp* ) +{ +} + +void ObjectImpVisitor::visit( const TestResultImp* ) +{ +} + +const char* ObjectImp::iconForProperty( uint ) const +{ + return "kig_text"; +} + +bool ObjectImp::canFillInNextEscape() const +{ + return false; +} + +ObjectImpType::ObjectImpType( const ObjectImpType* parent, + const char* internalname, + const char* translatedname, + const char* selectstatement, + const char* selectnamestatement, + const char* removeastatement, + const char* addastatement, + const char* moveastatement, + const char* attachtothisstatement, + const char* showastatement, + const char* hideastatement ) + : mparent( parent ), minternalname( internalname ), + mtranslatedname( translatedname ), mselectstatement( selectstatement ), + mselectnamestatement( selectnamestatement ), + mremoveastatement( removeastatement ), maddastatement( addastatement ), + mmoveastatement( moveastatement ), + mattachtothisstatement( attachtothisstatement ), + mshowastatement( showastatement ), + mhideastatement( hideastatement ) +{ + sd()->namemap[minternalname] = this; +} + +ObjectImpType::~ObjectImpType() +{ +} + +bool ObjectImpType::inherits( const ObjectImpType* t ) const +{ + return t == this || (mparent && mparent->inherits( t ) ); +} + +const char* ObjectImpType::internalName() const +{ + return minternalname; +} + +TQString ObjectImpType::translatedName() const +{ + return i18n( mtranslatedname ); +} + +const char* ObjectImpType::selectStatement() const +{ + return mselectstatement; +} + +const char* ObjectImpType::selectNameStatement() const +{ + return mselectnamestatement; +} + +TQString ObjectImpType::removeAStatement() const +{ + return i18n( mremoveastatement ); +} + +TQString ObjectImpType::addAStatement() const +{ + return i18n( maddastatement ); +} + +TQString ObjectImpType::moveAStatement() const +{ + return i18n( mmoveastatement ); +} + +const ObjectImpType* ObjectImpType::typeFromInternalName( const char* string ) +{ + TQCString s( string ); + std::map::iterator i = sd()->namemap.find( s ); + if ( i == sd()->namemap.end() ) + return 0; + else return i->second; +} + +bool ObjectImp::inherits( const ObjectImpType* t ) const +{ + return type()->inherits( t ); +} + +const ObjectImpType* ObjectImp::stype() +{ + static const ObjectImpType t( + 0, "any", + I18N_NOOP( "Object" ), + I18N_NOOP( "Select this object" ), + I18N_NOOP( "Select object %1" ), + I18N_NOOP( "Remove an object" ), + I18N_NOOP( "Add an object" ), + I18N_NOOP( "Move an object" ), + I18N_NOOP( "Attach to this object" ), + I18N_NOOP( "Show an object" ), + I18N_NOOP( "Hide an object" ) ); + return &t; +} + +ObjectImpType::StaticPrivate* ObjectImpType::sd() +{ + static StaticPrivate d; + return &d; +} + +bool ObjectImp::isCache() const +{ + return false; +} + +TQString ObjectImpType::attachToThisStatement() const +{ + return i18n( mattachtothisstatement ); +} + +TQString ObjectImpType::showAStatement() const +{ + return i18n( mshowastatement ); +} + +TQString ObjectImpType::hideAStatement() const +{ + return i18n( mhideastatement ); +} + +bool ObjectImp::isPropertyDefinedOnOrThroughThisImp( uint ) const +{ + return false; +} + diff --git a/kig/objects/object_imp_factory.cc b/kig/objects/object_imp_factory.cc deleted file mode 100644 index dd184295..00000000 --- a/kig/objects/object_imp_factory.cc +++ /dev/null @@ -1,510 +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_imp_factory.h" - -#include "object_imp.h" -#include "bogus_imp.h" -#include "circle_imp.h" -#include "conic_imp.h" -#include "cubic_imp.h" -#include "line_imp.h" -#include "locus_imp.h" -#include "other_imp.h" -#include "point_imp.h" -#include "text_imp.h" - -#include "../misc/coordinate.h" - -#include - -#include - -const ObjectImpFactory* ObjectImpFactory::instance() -{ - static const ObjectImpFactory t; - return &t; -} - -ObjectImpFactory::ObjectImpFactory() -{ -} - -ObjectImpFactory::~ObjectImpFactory() -{ -} - -static void addXYElements( const Coordinate& c, TQDomElement& parent, TQDomDocument& doc ) -{ - TQDomElement xe = doc.createElement( "x" ); - xe.appendChild( - doc.createTextNode( - TQString::number( c.x ) ) ); - parent.appendChild( xe ); - TQDomElement ye = doc.createElement( "y" ); - ye.appendChild( - doc.createTextNode( - TQString::number( c.y ) ) ); - parent.appendChild( ye ); -} - -static void addDoubleElement( const char* name, double d, TQDomElement& parent, TQDomDocument& doc ) -{ - TQDomElement e = doc.createElement( name ); - e.appendChild( doc.createTextNode( TQString::number( d ) ) ); - parent.appendChild( e ); -} - -static void addCoordinateElement( const char* name, const Coordinate& d, TQDomElement& p, TQDomDocument& doc ) -{ - TQDomElement e = doc.createElement( name ); - addXYElements( d, e, doc ); - p.appendChild( e ); -} - -TQString ObjectImpFactory::serialize( const ObjectImp& d, TQDomElement& parent, - TQDomDocument& doc ) const -{ - if( d.inherits( IntImp::stype() ) ) - { - parent.appendChild( - doc.createTextNode( - TQString::number( static_cast( d ).data() ) ) ); - return TQString::fromLatin1( "int" ); - } - else if ( d.inherits( DoubleImp::stype() ) ) - { - parent.appendChild( - doc.createTextNode( - TQString::number( static_cast( d ).data() ) ) ); - return TQString::fromLatin1( "double" ); - } - else if( d.inherits( StringImp::stype() ) ) - { - parent.appendChild( - doc.createTextNode( - static_cast( d ).data() ) ); - return TQString::fromLatin1( "string" ); - } - else if ( d.inherits( TestResultImp::stype() ) ) - { - parent.appendChild( - doc.createTextNode( - static_cast( d ).data() ) ); - return TQString::fromLatin1( "testresult" ); - } - else if( d.inherits( HierarchyImp::stype() ) ) - { - static_cast( d ).data().serialize( parent, doc ); - return TQString::fromLatin1( "hierarchy" ); - } - else if ( d.inherits( TransformationImp::stype() ) ) - { - const Transformation& trans = static_cast( d ).data(); - - TQDomElement matrixe = doc.createElement( "matrix" ); - for ( int i = 0; i < 3; ++i ) - { - for ( int j = 0; j < 3; ++j ) - { - TQDomElement elel = doc.createElement( "element" ); - elel.setAttribute( "row", TQString::number( i ) ); - elel.setAttribute( "column", TQString::number( j ) ); - elel.appendChild( doc.createTextNode( TQString::number( trans.data( i, j ) ) ) ); - matrixe.appendChild( elel ); - }; - } - parent.appendChild( matrixe ); - - TQDomElement homothetye = doc.createElement( "homothetic" ); - const char* ishomothety = trans.isHomothetic() ? "true" : "false"; - homothetye.appendChild( doc.createTextNode( ishomothety ) ); - parent.appendChild( homothetye ); - - return TQString::fromLatin1( "transformation" ); - } - else if( d.inherits( AbstractLineImp::stype() ) ) - { - LineData l = static_cast( d ).data(); - addCoordinateElement( "a", l.a, parent, doc ); - addCoordinateElement( "b", l.b, parent, doc ); - if( d.inherits( SegmentImp::stype() ) ) - return TQString::fromLatin1( "segment" ); - else if( d.inherits( RayImp::stype() ) ) - return TQString::fromLatin1( "ray" ); - else return TQString::fromLatin1( "line" ); - } - else if( d.inherits( PointImp::stype() ) ) - { - addXYElements( static_cast( d ).coordinate(), - parent, doc ); - return TQString::fromLatin1( "point" ); - } - else if( d.inherits( TextImp::stype() ) ) - { - TQString text = static_cast( d ).text(); - parent.appendChild( - doc.createTextNode( text ) ); - return TQString::fromLatin1( "text" ); - } - else if( d.inherits( AngleImp::stype() ) ) - { - addDoubleElement( "size", static_cast( d ).size(), parent, doc ); - return TQString::fromLatin1( "angle" ); - } - else if ( d.inherits( ArcImp::stype() ) ) - { - const ArcImp& a = static_cast( d ); - addCoordinateElement( "center", a.center(), parent, doc ); - addDoubleElement( "radius", a.radius(), parent, doc ); - addDoubleElement( "startangle", a.startAngle(), parent, doc ); - addDoubleElement( "angle", a.angle(), parent, doc ); - return TQString::fromLatin1( "arc" ); - } - else if( d.inherits( VectorImp::stype() ) ) - { - Coordinate dir = static_cast( d ).dir(); - addXYElements( dir, parent, doc ); - return TQString::fromLatin1( "vector" ); - } - else if( d.inherits( LocusImp::stype() ) ) - { - const LocusImp& locus = static_cast( d ); - - // serialize the curve.. - TQDomElement curve = doc.createElement( "curve" ); - const CurveImp& curveimp = *locus.curve(); - TQString type = serialize( curveimp, curve, doc ); - curve.setAttribute( "type", type ); - parent.appendChild( curve ); - - // serialize the hierarchy.. - TQDomElement hier = doc.createElement( "calculation" ); - locus.hierarchy().serialize( hier, doc ); - parent.appendChild( hier ); - - return TQString::fromLatin1( "locus" ); - } - else if( d.inherits( CircleImp::stype() ) ) - { - const CircleImp& c = static_cast( d ); - addCoordinateElement( "center", c.center(), parent, doc ); - addDoubleElement( "radius", c.radius(), parent, doc ); - return TQString::fromLatin1( "circle" ); - } - else if( d.inherits( ConicImp::stype() ) ) - { - const ConicPolarData data = static_cast( d ).polarData(); - addCoordinateElement( "focus1", data.focus1, parent, doc ); - addDoubleElement( "pdimen", data.pdimen, parent, doc ); - addDoubleElement( "ecostheta0", data.ecostheta0, parent, doc ); - addDoubleElement( "esintheta0", data.esintheta0, parent, doc ); - return TQString::fromLatin1( "conic" ); - } - else if( d.inherits( CubicImp::stype() ) ) - { - const CubicCartesianData data = static_cast( d ).data(); - TQDomElement coeffs = doc.createElement( "coefficients" ); - addDoubleElement( "a000", data.coeffs[0], coeffs, doc ); - addDoubleElement( "a001", data.coeffs[1], coeffs, doc ); - addDoubleElement( "a002", data.coeffs[2], coeffs, doc ); - addDoubleElement( "a011", data.coeffs[3], coeffs, doc ); - addDoubleElement( "a012", data.coeffs[4], coeffs, doc ); - addDoubleElement( "a022", data.coeffs[5], coeffs, doc ); - addDoubleElement( "a111", data.coeffs[6], coeffs, doc ); - addDoubleElement( "a112", data.coeffs[7], coeffs, doc ); - addDoubleElement( "a122", data.coeffs[8], coeffs, doc ); - addDoubleElement( "a222", data.coeffs[9], coeffs, doc ); - parent.appendChild( coeffs ); - return TQString::fromLatin1( "cubic" ); - } - assert( false ); - return TQString(); -} - -static Coordinate readXYElements( const TQDomElement& e, bool& ok ) -{ - double x, y; - ok = true; - TQDomElement xe = e.firstChild().toElement(); - if ( xe.isNull() || xe.tagName() != "x" ) - { - ok = false; - return Coordinate(); - } - else x = xe.text().toDouble( &ok ); - - TQDomElement ye = xe.nextSibling().toElement(); - if ( ye.isNull() || ye.tagName() != "y" ) - { - ok = false; - return Coordinate(); - } - else y = ye.text().toDouble( &ok ); - - return Coordinate( x, y ); -} - -static Coordinate readCoordinateElement( TQDomNode n, bool& ok, - const char* tagname ) -{ - TQDomElement e = n.toElement(); - if ( e.isNull() || e.tagName() != tagname ) - { - ok = false; - Coordinate ret; - return ret; - } - return readXYElements( e, ok ); -} - -static double readDoubleElement( TQDomNode n, bool& ok, - const char* tagname ) -{ - TQDomElement e = n.toElement(); - if ( e.isNull() || e.tagName() != tagname ) - { - ok = false; - return 0.; - }; - return e.text().toDouble( &ok ); -} - -ObjectImp* ObjectImpFactory::deserialize( const TQString& type, - const TQDomElement& parent, - TQString& error ) const -{ -#define KIG_GENERIC_PARSE_ERROR \ - { \ - error = i18n( "An error was encountered at line %1 in file %2." ) \ - .arg( __LINE__ ).arg( __FILE__ ); \ - return 0; \ - } - - bool ok = true; - if ( type == "int" ) - { - int ret = parent.text().toInt( &ok ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - return new IntImp( ret ); - } - else if ( type == "double" ) - { - double ret = parent.text().toDouble( &ok ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - return new DoubleImp( ret ); - } - else if ( type == "string" ) - { - return new StringImp( parent.text() ); - } - else if ( type == "testresult" ) - { - return new TestResultImp( parent.text() ); - } - else if ( type == "hierarchy" ) - { - ObjectHierarchy* hier = ObjectHierarchy::buildSafeObjectHierarchy( parent, error ); - if ( ! hier ) return 0; - HierarchyImp* imp = new HierarchyImp( *hier ); - delete hier; - return imp; - } - else if ( type == "transformation" ) - { - double data[3][3]; - bool homothetic = false; - for ( TQDomElement childe = parent.firstChild().toElement(); - ! childe.isNull(); childe = childe.nextSibling().toElement() ) - { - if ( childe.tagName() == "matrix" ) - { - for ( TQDomElement elel = childe.firstChild().toElement(); - ! elel.isNull(); elel = elel.nextSibling().toElement() ) - { - if ( elel.tagName() != "element" ) KIG_GENERIC_PARSE_ERROR; - bool ok = true; - int row = elel.attribute( "row" ).toInt( &ok ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - int column = elel.attribute( "column" ).toInt( &ok ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - data[row][column] = elel.text().toDouble( &ok ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - }; - } - else if ( childe.tagName() == "homothetic" ) - { - homothetic = childe.text() == "true"; - } - else continue; - }; - Transformation trans( data, homothetic ); - return new TransformationImp( trans ); - } - else if ( type == "point" ) - { - Coordinate ret = readXYElements( parent, ok ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - return new PointImp( ret ); - } - else if ( type == "line" || type == "segment" || type == "ray" ) - { - TQDomNode n = parent.firstChild(); - Coordinate a = readCoordinateElement( n, ok, "a" ); - if ( !ok ) KIG_GENERIC_PARSE_ERROR; - n = n.nextSibling(); - Coordinate b = readCoordinateElement( n, ok, "b" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - if ( type == "line" ) return new LineImp( a, b ); - else if ( type == "segment" ) return new SegmentImp( a, b ); - else return new RayImp( a, b ); - } - else if( type == "angle" ) - { - double size = readDoubleElement( parent.firstChild(), ok, "size" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - return new AngleImp( Coordinate(), 0, size ); - } - else if ( type == "arc" ) - { - TQDomNode n = parent.firstChild(); - Coordinate center = readCoordinateElement( n, ok, "center" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - n = n.nextSibling(); - double radius = readDoubleElement( n, ok, "radius" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - n = n.nextSibling(); - double startangle = readDoubleElement( n, ok, "startangle" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - n = n.nextSibling(); - double angle = readDoubleElement( n, ok, "angle" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - return new ArcImp( center, radius, startangle, angle ); - } - else if( type == "vector" ) - { - Coordinate dir = readXYElements( parent, ok ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - return new VectorImp( Coordinate(), dir ); - } - else if( type == "locus" ) - { - TQDomElement curvee = parent.firstChild().toElement(); - if ( curvee.isNull() || curvee.tagName() != "curve" ) KIG_GENERIC_PARSE_ERROR; - TQString type = curvee.attribute( "type" ); - ObjectImp* oi = deserialize( type, curvee, error ); - if ( ! oi || ! oi->inherits( CurveImp::stype() ) ) KIG_GENERIC_PARSE_ERROR; - //CurveImp* curvei = static_cast( oi ); - - TQDomElement hiere = curvee.nextSibling().toElement(); - if ( hiere.isNull() || hiere.tagName() != "calculation" ) KIG_GENERIC_PARSE_ERROR; - assert( false ); // TODO -// return new LocusImp( curvei, hier ); - } - else if( type == "circle" ) - { - TQDomNode n = parent.firstChild(); - Coordinate center = readCoordinateElement( n, ok, "center" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - n = n.nextSibling(); - double radius = readDoubleElement( n, ok, "radius" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - return new CircleImp( center, radius ); - } - else if( type == "conic" ) - { - TQDomNode n = parent.firstChild(); - Coordinate focus1 = readCoordinateElement( n, ok, "focus1" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - n = n.nextSibling(); - double pdimen = readDoubleElement( n, ok, "pdimen" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - n = n.nextSibling(); - double ecostheta0 = readDoubleElement( n, ok, "ecostheta0" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - n = n.nextSibling(); - double esintheta0 = readDoubleElement( n, ok, "esintheta0" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - return new ConicImpPolar( - ConicPolarData( focus1, pdimen, ecostheta0, esintheta0 ) ); - } - else if( type == "cubic" ) - { - TQDomElement coeffse = parent.firstChild().toElement(); - if ( coeffse.isNull() || coeffse.tagName() != "coefficients" ) - KIG_GENERIC_PARSE_ERROR; - - TQDomNode n = coeffse.firstChild(); - double a000 = readDoubleElement( n, ok, "a000" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - n = n.nextSibling(); - double a001 = readDoubleElement( n, ok, "a001" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - n = n.nextSibling(); - double a002 = readDoubleElement( n, ok, "a002" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - n = n.nextSibling(); - double a011 = readDoubleElement( n, ok, "a011" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - n = n.nextSibling(); - double a012 = readDoubleElement( n, ok, "a012" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - n = n.nextSibling(); - double a022 = readDoubleElement( n, ok, "a022" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - n = n.nextSibling(); - double a111 = readDoubleElement( n, ok, "a111" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - n = n.nextSibling(); - double a112 = readDoubleElement( n, ok, "a112" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - n = n.nextSibling(); - double a122 = readDoubleElement( n, ok, "a112" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - n = n.nextSibling(); - double a222 = readDoubleElement( n, ok, "a222" ); - if ( ! ok ) KIG_GENERIC_PARSE_ERROR; - - return new CubicImp( CubicCartesianData( a000, a001, a002, - a011, a012, a022, - a111, a112, a122, - a222 ) ); - } - - 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( type ); - return 0; -} - diff --git a/kig/objects/object_imp_factory.cpp b/kig/objects/object_imp_factory.cpp new file mode 100644 index 00000000..dd184295 --- /dev/null +++ b/kig/objects/object_imp_factory.cpp @@ -0,0 +1,510 @@ +// 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_imp_factory.h" + +#include "object_imp.h" +#include "bogus_imp.h" +#include "circle_imp.h" +#include "conic_imp.h" +#include "cubic_imp.h" +#include "line_imp.h" +#include "locus_imp.h" +#include "other_imp.h" +#include "point_imp.h" +#include "text_imp.h" + +#include "../misc/coordinate.h" + +#include + +#include + +const ObjectImpFactory* ObjectImpFactory::instance() +{ + static const ObjectImpFactory t; + return &t; +} + +ObjectImpFactory::ObjectImpFactory() +{ +} + +ObjectImpFactory::~ObjectImpFactory() +{ +} + +static void addXYElements( const Coordinate& c, TQDomElement& parent, TQDomDocument& doc ) +{ + TQDomElement xe = doc.createElement( "x" ); + xe.appendChild( + doc.createTextNode( + TQString::number( c.x ) ) ); + parent.appendChild( xe ); + TQDomElement ye = doc.createElement( "y" ); + ye.appendChild( + doc.createTextNode( + TQString::number( c.y ) ) ); + parent.appendChild( ye ); +} + +static void addDoubleElement( const char* name, double d, TQDomElement& parent, TQDomDocument& doc ) +{ + TQDomElement e = doc.createElement( name ); + e.appendChild( doc.createTextNode( TQString::number( d ) ) ); + parent.appendChild( e ); +} + +static void addCoordinateElement( const char* name, const Coordinate& d, TQDomElement& p, TQDomDocument& doc ) +{ + TQDomElement e = doc.createElement( name ); + addXYElements( d, e, doc ); + p.appendChild( e ); +} + +TQString ObjectImpFactory::serialize( const ObjectImp& d, TQDomElement& parent, + TQDomDocument& doc ) const +{ + if( d.inherits( IntImp::stype() ) ) + { + parent.appendChild( + doc.createTextNode( + TQString::number( static_cast( d ).data() ) ) ); + return TQString::fromLatin1( "int" ); + } + else if ( d.inherits( DoubleImp::stype() ) ) + { + parent.appendChild( + doc.createTextNode( + TQString::number( static_cast( d ).data() ) ) ); + return TQString::fromLatin1( "double" ); + } + else if( d.inherits( StringImp::stype() ) ) + { + parent.appendChild( + doc.createTextNode( + static_cast( d ).data() ) ); + return TQString::fromLatin1( "string" ); + } + else if ( d.inherits( TestResultImp::stype() ) ) + { + parent.appendChild( + doc.createTextNode( + static_cast( d ).data() ) ); + return TQString::fromLatin1( "testresult" ); + } + else if( d.inherits( HierarchyImp::stype() ) ) + { + static_cast( d ).data().serialize( parent, doc ); + return TQString::fromLatin1( "hierarchy" ); + } + else if ( d.inherits( TransformationImp::stype() ) ) + { + const Transformation& trans = static_cast( d ).data(); + + TQDomElement matrixe = doc.createElement( "matrix" ); + for ( int i = 0; i < 3; ++i ) + { + for ( int j = 0; j < 3; ++j ) + { + TQDomElement elel = doc.createElement( "element" ); + elel.setAttribute( "row", TQString::number( i ) ); + elel.setAttribute( "column", TQString::number( j ) ); + elel.appendChild( doc.createTextNode( TQString::number( trans.data( i, j ) ) ) ); + matrixe.appendChild( elel ); + }; + } + parent.appendChild( matrixe ); + + TQDomElement homothetye = doc.createElement( "homothetic" ); + const char* ishomothety = trans.isHomothetic() ? "true" : "false"; + homothetye.appendChild( doc.createTextNode( ishomothety ) ); + parent.appendChild( homothetye ); + + return TQString::fromLatin1( "transformation" ); + } + else if( d.inherits( AbstractLineImp::stype() ) ) + { + LineData l = static_cast( d ).data(); + addCoordinateElement( "a", l.a, parent, doc ); + addCoordinateElement( "b", l.b, parent, doc ); + if( d.inherits( SegmentImp::stype() ) ) + return TQString::fromLatin1( "segment" ); + else if( d.inherits( RayImp::stype() ) ) + return TQString::fromLatin1( "ray" ); + else return TQString::fromLatin1( "line" ); + } + else if( d.inherits( PointImp::stype() ) ) + { + addXYElements( static_cast( d ).coordinate(), + parent, doc ); + return TQString::fromLatin1( "point" ); + } + else if( d.inherits( TextImp::stype() ) ) + { + TQString text = static_cast( d ).text(); + parent.appendChild( + doc.createTextNode( text ) ); + return TQString::fromLatin1( "text" ); + } + else if( d.inherits( AngleImp::stype() ) ) + { + addDoubleElement( "size", static_cast( d ).size(), parent, doc ); + return TQString::fromLatin1( "angle" ); + } + else if ( d.inherits( ArcImp::stype() ) ) + { + const ArcImp& a = static_cast( d ); + addCoordinateElement( "center", a.center(), parent, doc ); + addDoubleElement( "radius", a.radius(), parent, doc ); + addDoubleElement( "startangle", a.startAngle(), parent, doc ); + addDoubleElement( "angle", a.angle(), parent, doc ); + return TQString::fromLatin1( "arc" ); + } + else if( d.inherits( VectorImp::stype() ) ) + { + Coordinate dir = static_cast( d ).dir(); + addXYElements( dir, parent, doc ); + return TQString::fromLatin1( "vector" ); + } + else if( d.inherits( LocusImp::stype() ) ) + { + const LocusImp& locus = static_cast( d ); + + // serialize the curve.. + TQDomElement curve = doc.createElement( "curve" ); + const CurveImp& curveimp = *locus.curve(); + TQString type = serialize( curveimp, curve, doc ); + curve.setAttribute( "type", type ); + parent.appendChild( curve ); + + // serialize the hierarchy.. + TQDomElement hier = doc.createElement( "calculation" ); + locus.hierarchy().serialize( hier, doc ); + parent.appendChild( hier ); + + return TQString::fromLatin1( "locus" ); + } + else if( d.inherits( CircleImp::stype() ) ) + { + const CircleImp& c = static_cast( d ); + addCoordinateElement( "center", c.center(), parent, doc ); + addDoubleElement( "radius", c.radius(), parent, doc ); + return TQString::fromLatin1( "circle" ); + } + else if( d.inherits( ConicImp::stype() ) ) + { + const ConicPolarData data = static_cast( d ).polarData(); + addCoordinateElement( "focus1", data.focus1, parent, doc ); + addDoubleElement( "pdimen", data.pdimen, parent, doc ); + addDoubleElement( "ecostheta0", data.ecostheta0, parent, doc ); + addDoubleElement( "esintheta0", data.esintheta0, parent, doc ); + return TQString::fromLatin1( "conic" ); + } + else if( d.inherits( CubicImp::stype() ) ) + { + const CubicCartesianData data = static_cast( d ).data(); + TQDomElement coeffs = doc.createElement( "coefficients" ); + addDoubleElement( "a000", data.coeffs[0], coeffs, doc ); + addDoubleElement( "a001", data.coeffs[1], coeffs, doc ); + addDoubleElement( "a002", data.coeffs[2], coeffs, doc ); + addDoubleElement( "a011", data.coeffs[3], coeffs, doc ); + addDoubleElement( "a012", data.coeffs[4], coeffs, doc ); + addDoubleElement( "a022", data.coeffs[5], coeffs, doc ); + addDoubleElement( "a111", data.coeffs[6], coeffs, doc ); + addDoubleElement( "a112", data.coeffs[7], coeffs, doc ); + addDoubleElement( "a122", data.coeffs[8], coeffs, doc ); + addDoubleElement( "a222", data.coeffs[9], coeffs, doc ); + parent.appendChild( coeffs ); + return TQString::fromLatin1( "cubic" ); + } + assert( false ); + return TQString(); +} + +static Coordinate readXYElements( const TQDomElement& e, bool& ok ) +{ + double x, y; + ok = true; + TQDomElement xe = e.firstChild().toElement(); + if ( xe.isNull() || xe.tagName() != "x" ) + { + ok = false; + return Coordinate(); + } + else x = xe.text().toDouble( &ok ); + + TQDomElement ye = xe.nextSibling().toElement(); + if ( ye.isNull() || ye.tagName() != "y" ) + { + ok = false; + return Coordinate(); + } + else y = ye.text().toDouble( &ok ); + + return Coordinate( x, y ); +} + +static Coordinate readCoordinateElement( TQDomNode n, bool& ok, + const char* tagname ) +{ + TQDomElement e = n.toElement(); + if ( e.isNull() || e.tagName() != tagname ) + { + ok = false; + Coordinate ret; + return ret; + } + return readXYElements( e, ok ); +} + +static double readDoubleElement( TQDomNode n, bool& ok, + const char* tagname ) +{ + TQDomElement e = n.toElement(); + if ( e.isNull() || e.tagName() != tagname ) + { + ok = false; + return 0.; + }; + return e.text().toDouble( &ok ); +} + +ObjectImp* ObjectImpFactory::deserialize( const TQString& type, + const TQDomElement& parent, + TQString& error ) const +{ +#define KIG_GENERIC_PARSE_ERROR \ + { \ + error = i18n( "An error was encountered at line %1 in file %2." ) \ + .arg( __LINE__ ).arg( __FILE__ ); \ + return 0; \ + } + + bool ok = true; + if ( type == "int" ) + { + int ret = parent.text().toInt( &ok ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + return new IntImp( ret ); + } + else if ( type == "double" ) + { + double ret = parent.text().toDouble( &ok ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + return new DoubleImp( ret ); + } + else if ( type == "string" ) + { + return new StringImp( parent.text() ); + } + else if ( type == "testresult" ) + { + return new TestResultImp( parent.text() ); + } + else if ( type == "hierarchy" ) + { + ObjectHierarchy* hier = ObjectHierarchy::buildSafeObjectHierarchy( parent, error ); + if ( ! hier ) return 0; + HierarchyImp* imp = new HierarchyImp( *hier ); + delete hier; + return imp; + } + else if ( type == "transformation" ) + { + double data[3][3]; + bool homothetic = false; + for ( TQDomElement childe = parent.firstChild().toElement(); + ! childe.isNull(); childe = childe.nextSibling().toElement() ) + { + if ( childe.tagName() == "matrix" ) + { + for ( TQDomElement elel = childe.firstChild().toElement(); + ! elel.isNull(); elel = elel.nextSibling().toElement() ) + { + if ( elel.tagName() != "element" ) KIG_GENERIC_PARSE_ERROR; + bool ok = true; + int row = elel.attribute( "row" ).toInt( &ok ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + int column = elel.attribute( "column" ).toInt( &ok ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + data[row][column] = elel.text().toDouble( &ok ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + }; + } + else if ( childe.tagName() == "homothetic" ) + { + homothetic = childe.text() == "true"; + } + else continue; + }; + Transformation trans( data, homothetic ); + return new TransformationImp( trans ); + } + else if ( type == "point" ) + { + Coordinate ret = readXYElements( parent, ok ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + return new PointImp( ret ); + } + else if ( type == "line" || type == "segment" || type == "ray" ) + { + TQDomNode n = parent.firstChild(); + Coordinate a = readCoordinateElement( n, ok, "a" ); + if ( !ok ) KIG_GENERIC_PARSE_ERROR; + n = n.nextSibling(); + Coordinate b = readCoordinateElement( n, ok, "b" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + if ( type == "line" ) return new LineImp( a, b ); + else if ( type == "segment" ) return new SegmentImp( a, b ); + else return new RayImp( a, b ); + } + else if( type == "angle" ) + { + double size = readDoubleElement( parent.firstChild(), ok, "size" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + return new AngleImp( Coordinate(), 0, size ); + } + else if ( type == "arc" ) + { + TQDomNode n = parent.firstChild(); + Coordinate center = readCoordinateElement( n, ok, "center" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + n = n.nextSibling(); + double radius = readDoubleElement( n, ok, "radius" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + n = n.nextSibling(); + double startangle = readDoubleElement( n, ok, "startangle" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + n = n.nextSibling(); + double angle = readDoubleElement( n, ok, "angle" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + return new ArcImp( center, radius, startangle, angle ); + } + else if( type == "vector" ) + { + Coordinate dir = readXYElements( parent, ok ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + return new VectorImp( Coordinate(), dir ); + } + else if( type == "locus" ) + { + TQDomElement curvee = parent.firstChild().toElement(); + if ( curvee.isNull() || curvee.tagName() != "curve" ) KIG_GENERIC_PARSE_ERROR; + TQString type = curvee.attribute( "type" ); + ObjectImp* oi = deserialize( type, curvee, error ); + if ( ! oi || ! oi->inherits( CurveImp::stype() ) ) KIG_GENERIC_PARSE_ERROR; + //CurveImp* curvei = static_cast( oi ); + + TQDomElement hiere = curvee.nextSibling().toElement(); + if ( hiere.isNull() || hiere.tagName() != "calculation" ) KIG_GENERIC_PARSE_ERROR; + assert( false ); // TODO +// return new LocusImp( curvei, hier ); + } + else if( type == "circle" ) + { + TQDomNode n = parent.firstChild(); + Coordinate center = readCoordinateElement( n, ok, "center" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + n = n.nextSibling(); + double radius = readDoubleElement( n, ok, "radius" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + return new CircleImp( center, radius ); + } + else if( type == "conic" ) + { + TQDomNode n = parent.firstChild(); + Coordinate focus1 = readCoordinateElement( n, ok, "focus1" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + n = n.nextSibling(); + double pdimen = readDoubleElement( n, ok, "pdimen" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + n = n.nextSibling(); + double ecostheta0 = readDoubleElement( n, ok, "ecostheta0" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + n = n.nextSibling(); + double esintheta0 = readDoubleElement( n, ok, "esintheta0" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + return new ConicImpPolar( + ConicPolarData( focus1, pdimen, ecostheta0, esintheta0 ) ); + } + else if( type == "cubic" ) + { + TQDomElement coeffse = parent.firstChild().toElement(); + if ( coeffse.isNull() || coeffse.tagName() != "coefficients" ) + KIG_GENERIC_PARSE_ERROR; + + TQDomNode n = coeffse.firstChild(); + double a000 = readDoubleElement( n, ok, "a000" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + n = n.nextSibling(); + double a001 = readDoubleElement( n, ok, "a001" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + n = n.nextSibling(); + double a002 = readDoubleElement( n, ok, "a002" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + n = n.nextSibling(); + double a011 = readDoubleElement( n, ok, "a011" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + n = n.nextSibling(); + double a012 = readDoubleElement( n, ok, "a012" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + n = n.nextSibling(); + double a022 = readDoubleElement( n, ok, "a022" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + n = n.nextSibling(); + double a111 = readDoubleElement( n, ok, "a111" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + n = n.nextSibling(); + double a112 = readDoubleElement( n, ok, "a112" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + n = n.nextSibling(); + double a122 = readDoubleElement( n, ok, "a112" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + n = n.nextSibling(); + double a222 = readDoubleElement( n, ok, "a222" ); + if ( ! ok ) KIG_GENERIC_PARSE_ERROR; + + return new CubicImp( CubicCartesianData( a000, a001, a002, + a011, a012, a022, + a111, a112, a122, + a222 ) ); + } + + 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( type ); + return 0; +} + diff --git a/kig/objects/object_type.cc b/kig/objects/object_type.cc deleted file mode 100644 index 3b2fc108..00000000 --- a/kig/objects/object_type.cc +++ /dev/null @@ -1,125 +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_type.h" - -#include "bogus_imp.h" -#include "object_type_factory.h" - -#include "../misc/coordinate.h" - -#include - -#include - -const char* ObjectType::fullName() const -{ - return mfulltypename; -} - -ObjectType::~ObjectType() -{ -} - -ObjectType::ObjectType( const char fulltypename[] ) - : mfulltypename( fulltypename ) -{ - ObjectTypeFactory::instance()->add( this ); -} - -bool ObjectType::canMove( const ObjectTypeCalcer& ) const -{ - return false; -} - -bool ObjectType::isFreelyTranslatable( const ObjectTypeCalcer& ) const -{ - return false; -} - -void ObjectType::move( ObjectTypeCalcer&, const Coordinate&, const KigDocument& ) const -{ - // we can't do an assert here, because sometimes ( like in - // ObjectABType::move, ObjectType::move is called without checking - // the object's canMove(). -// assert( false ); -} - -bool ObjectType::inherits( int ) const -{ - return false; -} - -ArgsParserObjectType::ArgsParserObjectType( const char fulltypename[], - const struct ArgsParser::spec argsspec[], - int n ) - : ObjectType( fulltypename ), margsparser( argsspec, n ) -{ -} - -const ObjectImpType* ArgsParserObjectType::impRequirement( const ObjectImp* o, const Args& parents ) const -{ - return margsparser.impRequirement( o, parents ); -} - -const ArgsParser& ArgsParserObjectType::argsParser() const -{ - return margsparser; -} - -bool ObjectType::isTransform() const -{ - return false; -} - -TQStringList ObjectType::specialActions() const -{ - return TQStringList(); -} - -void ObjectType::executeAction( int, ObjectHolder&, ObjectTypeCalcer&, KigPart&, KigWidget&, - NormalMode& ) const -{ - assert( false ); -} - -const Coordinate ObjectType::moveReferencePoint( const ObjectTypeCalcer& ) const -{ - assert( false ); - return Coordinate::invalidCoord(); -} - -std::vector ArgsParserObjectType::sortArgs( const std::vector& args ) const -{ - return margsparser.parse( args ); -} - -Args ArgsParserObjectType::sortArgs( const Args& args ) const -{ - return margsparser.parse( args ); -} - -std::vector ObjectType::movableParents( const ObjectTypeCalcer& ) const -{ - return std::vector(); -} - -bool ArgsParserObjectType::isDefinedOnOrThrough( const ObjectImp* o, const Args& parents ) const -{ - return margsparser.isDefinedOnOrThrough( o, parents ); -} - diff --git a/kig/objects/object_type.cpp b/kig/objects/object_type.cpp new file mode 100644 index 00000000..3b2fc108 --- /dev/null +++ b/kig/objects/object_type.cpp @@ -0,0 +1,125 @@ +// 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_type.h" + +#include "bogus_imp.h" +#include "object_type_factory.h" + +#include "../misc/coordinate.h" + +#include + +#include + +const char* ObjectType::fullName() const +{ + return mfulltypename; +} + +ObjectType::~ObjectType() +{ +} + +ObjectType::ObjectType( const char fulltypename[] ) + : mfulltypename( fulltypename ) +{ + ObjectTypeFactory::instance()->add( this ); +} + +bool ObjectType::canMove( const ObjectTypeCalcer& ) const +{ + return false; +} + +bool ObjectType::isFreelyTranslatable( const ObjectTypeCalcer& ) const +{ + return false; +} + +void ObjectType::move( ObjectTypeCalcer&, const Coordinate&, const KigDocument& ) const +{ + // we can't do an assert here, because sometimes ( like in + // ObjectABType::move, ObjectType::move is called without checking + // the object's canMove(). +// assert( false ); +} + +bool ObjectType::inherits( int ) const +{ + return false; +} + +ArgsParserObjectType::ArgsParserObjectType( const char fulltypename[], + const struct ArgsParser::spec argsspec[], + int n ) + : ObjectType( fulltypename ), margsparser( argsspec, n ) +{ +} + +const ObjectImpType* ArgsParserObjectType::impRequirement( const ObjectImp* o, const Args& parents ) const +{ + return margsparser.impRequirement( o, parents ); +} + +const ArgsParser& ArgsParserObjectType::argsParser() const +{ + return margsparser; +} + +bool ObjectType::isTransform() const +{ + return false; +} + +TQStringList ObjectType::specialActions() const +{ + return TQStringList(); +} + +void ObjectType::executeAction( int, ObjectHolder&, ObjectTypeCalcer&, KigPart&, KigWidget&, + NormalMode& ) const +{ + assert( false ); +} + +const Coordinate ObjectType::moveReferencePoint( const ObjectTypeCalcer& ) const +{ + assert( false ); + return Coordinate::invalidCoord(); +} + +std::vector ArgsParserObjectType::sortArgs( const std::vector& args ) const +{ + return margsparser.parse( args ); +} + +Args ArgsParserObjectType::sortArgs( const Args& args ) const +{ + return margsparser.parse( args ); +} + +std::vector ObjectType::movableParents( const ObjectTypeCalcer& ) const +{ + return std::vector(); +} + +bool ArgsParserObjectType::isDefinedOnOrThrough( const ObjectImp* o, const Args& parents ) const +{ + return margsparser.isDefinedOnOrThrough( o, parents ); +} + diff --git a/kig/objects/object_type_factory.cc b/kig/objects/object_type_factory.cc deleted file mode 100644 index a6d527ce..00000000 --- a/kig/objects/object_type_factory.cc +++ /dev/null @@ -1,148 +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_type_factory.h" - -#include - -#include "object_type.h" -#include "circle_type.h" -#include "conic_types.h" -#include "cubic_type.h" -#include "intersection_types.h" -#include "line_type.h" -#include "text_type.h" -#include "other_type.h" -#include "transform_types.h" -#include "point_type.h" -#include "tests_type.h" - -#ifdef KIG_ENABLE_PYTHON_SCRIPTING -#include "../scripting/python_type.h" -#endif - -#include -#include - -ObjectTypeFactory::ObjectTypeFactory() - : malreadysetup( false ) -{ - setupBuiltinTypes(); -} - -ObjectTypeFactory::~ObjectTypeFactory() -{ -} - -ObjectTypeFactory* ObjectTypeFactory::instance() -{ - static ObjectTypeFactory fact; - return &fact; -} - -void ObjectTypeFactory::add( const ObjectType* type ) -{ - assert( mmap.find( std::string( type->fullName() ) ) == mmap.end() ); - mmap[std::string( type->fullName() )] = type; -} - -const ObjectType* ObjectTypeFactory::find( const char* name ) const -{ - maptype::const_iterator i = mmap.find( std::string( name ) ); - if ( i == mmap.end() ) return 0; - else return i->second; -} - -void ObjectTypeFactory::setupBuiltinTypes() -{ -// assert( ! malreadysetup ); -// malreadysetup = true; - -// // circle_type.h -// add( CircleBCPType::instance() ); -// add( CircleBPRType::instance() ); -// add( CircleBTPType::instance() ); - -// // conic_types.h -// add( ConicB5PType::instance() ); -// add( ConicBAAPType::instance() ); -// add( EllipseBFFPType::instance() ); -// add( HyperbolaBFFPType::instance() ); -// add( ConicBDFPType::instance() ); -// add( ParabolaBTPType::instance() ); -// add( EquilateralHyperbolaB4PType::instance() ); -// add( ConicPolarPointType::instance() ); -// add( ConicPolarLineType::instance() ); -// add( ConicDirectrixType::instance() ); -// add( ParabolaBDPType::instance() ); -// add( ConicAsymptoteType::instance() ); -// add( ConicRadicalType::instance() ); - -// // cubic_type.h -// add( CubicB9PType::instance() ); -// add( CubicNodeB6PType::instance() ); -// add( CubicCuspB4PType::instance() ); - -// // intersection_types.h -// add( ConicLineIntersectionType::instance() ); -// add( ConicLineOtherIntersectionType::instance() ); -// add( LineLineIntersectionType::instance() ); -// add( LineCubicIntersectionType::instance() ); -// add( CircleCircleIntersectionType::instance() ); - -// // line_type.h -// add( SegmentABType::instance() ); -// add( LineABType::instance() ); -// add( RayABType::instance() ); -// add( LinePerpendLPType::instance() ); -// add( LineParallelLPType::instance() ); - -// // other_type.h -// add( AngleType::instance() ); -// add( VectorType::instance() ); -// add( LocusType::instance() ); -// add( ArcBTPType::instance() ); -// add( CopyObjectType::instance() ); - -// // point_type.h -// add( FixedPointType::instance() ); -// add( ConstrainedPointType::instance() ); -// add( MidPointType::instance() ); -// add( MeasureTransportType::instance() ); - -// // text_type.h -// add( TextType::instance() ); - -// // tests_type.h -// add( AreParallelType::instance() ); - -// // transform_types.h -// add( TranslatedType::instance() ); -// add( PointReflectionType::instance() ); -// add( LineReflectionType::instance() ); -// add( RotationType::instance() ); -// add( ScalingOverCenterType::instance() ); -// add( ScalingOverLineType::instance() ); -// add( ProjectiveRotationType::instance() ); -// add( CastShadowType::instance() ); - -// #ifdef KIG_ENABLE_PYTHON_SCRIPTING -// // python types -// add( PythonCompileType::instance() ); -// add( PythonExecuteType::instance() ); -// #endif -} diff --git a/kig/objects/object_type_factory.cpp b/kig/objects/object_type_factory.cpp new file mode 100644 index 00000000..a6d527ce --- /dev/null +++ b/kig/objects/object_type_factory.cpp @@ -0,0 +1,148 @@ +// 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_type_factory.h" + +#include + +#include "object_type.h" +#include "circle_type.h" +#include "conic_types.h" +#include "cubic_type.h" +#include "intersection_types.h" +#include "line_type.h" +#include "text_type.h" +#include "other_type.h" +#include "transform_types.h" +#include "point_type.h" +#include "tests_type.h" + +#ifdef KIG_ENABLE_PYTHON_SCRIPTING +#include "../scripting/python_type.h" +#endif + +#include +#include + +ObjectTypeFactory::ObjectTypeFactory() + : malreadysetup( false ) +{ + setupBuiltinTypes(); +} + +ObjectTypeFactory::~ObjectTypeFactory() +{ +} + +ObjectTypeFactory* ObjectTypeFactory::instance() +{ + static ObjectTypeFactory fact; + return &fact; +} + +void ObjectTypeFactory::add( const ObjectType* type ) +{ + assert( mmap.find( std::string( type->fullName() ) ) == mmap.end() ); + mmap[std::string( type->fullName() )] = type; +} + +const ObjectType* ObjectTypeFactory::find( const char* name ) const +{ + maptype::const_iterator i = mmap.find( std::string( name ) ); + if ( i == mmap.end() ) return 0; + else return i->second; +} + +void ObjectTypeFactory::setupBuiltinTypes() +{ +// assert( ! malreadysetup ); +// malreadysetup = true; + +// // circle_type.h +// add( CircleBCPType::instance() ); +// add( CircleBPRType::instance() ); +// add( CircleBTPType::instance() ); + +// // conic_types.h +// add( ConicB5PType::instance() ); +// add( ConicBAAPType::instance() ); +// add( EllipseBFFPType::instance() ); +// add( HyperbolaBFFPType::instance() ); +// add( ConicBDFPType::instance() ); +// add( ParabolaBTPType::instance() ); +// add( EquilateralHyperbolaB4PType::instance() ); +// add( ConicPolarPointType::instance() ); +// add( ConicPolarLineType::instance() ); +// add( ConicDirectrixType::instance() ); +// add( ParabolaBDPType::instance() ); +// add( ConicAsymptoteType::instance() ); +// add( ConicRadicalType::instance() ); + +// // cubic_type.h +// add( CubicB9PType::instance() ); +// add( CubicNodeB6PType::instance() ); +// add( CubicCuspB4PType::instance() ); + +// // intersection_types.h +// add( ConicLineIntersectionType::instance() ); +// add( ConicLineOtherIntersectionType::instance() ); +// add( LineLineIntersectionType::instance() ); +// add( LineCubicIntersectionType::instance() ); +// add( CircleCircleIntersectionType::instance() ); + +// // line_type.h +// add( SegmentABType::instance() ); +// add( LineABType::instance() ); +// add( RayABType::instance() ); +// add( LinePerpendLPType::instance() ); +// add( LineParallelLPType::instance() ); + +// // other_type.h +// add( AngleType::instance() ); +// add( VectorType::instance() ); +// add( LocusType::instance() ); +// add( ArcBTPType::instance() ); +// add( CopyObjectType::instance() ); + +// // point_type.h +// add( FixedPointType::instance() ); +// add( ConstrainedPointType::instance() ); +// add( MidPointType::instance() ); +// add( MeasureTransportType::instance() ); + +// // text_type.h +// add( TextType::instance() ); + +// // tests_type.h +// add( AreParallelType::instance() ); + +// // transform_types.h +// add( TranslatedType::instance() ); +// add( PointReflectionType::instance() ); +// add( LineReflectionType::instance() ); +// add( RotationType::instance() ); +// add( ScalingOverCenterType::instance() ); +// add( ScalingOverLineType::instance() ); +// add( ProjectiveRotationType::instance() ); +// add( CastShadowType::instance() ); + +// #ifdef KIG_ENABLE_PYTHON_SCRIPTING +// // python types +// add( PythonCompileType::instance() ); +// add( PythonExecuteType::instance() ); +// #endif +} diff --git a/kig/objects/other_imp.cc b/kig/objects/other_imp.cc deleted file mode 100644 index 5c063753..00000000 --- a/kig/objects/other_imp.cc +++ /dev/null @@ -1,710 +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 "other_imp.h" - -#include "bogus_imp.h" -#include "point_imp.h" -#include "line_imp.h" - -#include "../misc/screeninfo.h" -#include "../misc/common.h" -#include "../misc/kigtransform.h" -#include "../misc/kigpainter.h" -#include "../misc/goniometry.h" -#include "../kig/kig_view.h" - -#include - -#include -#include -using namespace std; - -AngleImp::~AngleImp() -{ -} - -ObjectImp* AngleImp::transform( const Transformation& ) const -{ - // TODO ? - return new InvalidImp; -} - -void AngleImp::draw( KigPainter& p ) const -{ - p.drawAngle( mpoint, mstartangle, mangle ); -} - -AngleImp::AngleImp( const Coordinate& pt, double start_angle_in_radials, - double angle_in_radials ) - : mpoint( pt ), mstartangle( start_angle_in_radials ), - mangle( angle_in_radials ) -{ -} - -bool AngleImp::contains( const Coordinate& p, int width, const KigWidget& w ) const -{ - double radius = 50*w.screenInfo().pixelWidth(); - - if ( fabs( (p-mpoint).length() - radius ) > w.screenInfo().normalMiss( width ) ) - return false; - - // and next we check if the angle is appropriate... - Coordinate vect = p - mpoint; - double angle = atan2( vect.y, vect.x ); - while ( angle < mstartangle ) angle += 2*M_PI; - return angle <= mstartangle + mangle; -} - -bool AngleImp::inRect( const Rect& r, int width, const KigWidget& w ) const -{ - // TODO ? - return r.contains( mpoint, w.screenInfo().normalMiss( width ) ); -} - -Coordinate AngleImp::attachPoint() const -{ - return mpoint; -} - -const uint AngleImp::numberOfProperties() const -{ - return Parent::numberOfProperties() + 3; -} - -const QCStringList AngleImp::propertiesInternalNames() const -{ - QCStringList l = Parent::propertiesInternalNames(); - l << "angle-radian"; - l << "angle-degrees"; - l << "angle-bisector"; - assert( l.size() == AngleImp::numberOfProperties() ); - return l; -} - -const QCStringList AngleImp::properties() const -{ - QCStringList l = Parent::properties(); - l << I18N_NOOP( "Angle in Radians" ); - l << I18N_NOOP( "Angle in Degrees" ); - l << I18N_NOOP( "Angle Bisector" ); - assert( l.size() == AngleImp::numberOfProperties() ); - return l; -} - -const ObjectImpType* AngleImp::impRequirementForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::impRequirementForProperty( which ); - else return AngleImp::stype(); -} - -const char* AngleImp::iconForProperty( uint which ) const -{ - int numprop = 0; - if ( which < Parent::numberOfProperties() ) - return Parent::iconForProperty( which ); - if ( which == Parent::numberOfProperties() + numprop++ ) - return "angle_size"; // size in radians - else if ( which == Parent::numberOfProperties() + numprop++ ) - return "angle_size"; // size in degrees - else if ( which == Parent::numberOfProperties() + numprop++ ) - return "angle_bisector"; // angle bisector.. - else assert( false ); - return ""; -} - -ObjectImp* AngleImp::property( uint which, const KigDocument& w ) const -{ - int numprop = 0; - if ( which < Parent::numberOfProperties() ) - return Parent::property( which, w ); - if ( which == Parent::numberOfProperties() + numprop++ ) - return new DoubleImp( size() ); - else if ( which == Parent::numberOfProperties() + numprop++ ) - return new DoubleImp( Goniometry::convert( size(), Goniometry::Rad, Goniometry::Deg ) ); - else if ( which == Parent::numberOfProperties() + numprop++ ) - { - const double angle = mstartangle + mangle / 2; - Coordinate p2 = mpoint + Coordinate( cos( angle ), sin( angle ) ) * 10; - return new RayImp( mpoint, p2 ); - } - else assert( false ); - return new InvalidImp; -} - -const double AngleImp::size() const -{ - return mangle; -} - -ObjectImp* AngleImp::copy() const -{ - return new AngleImp( mpoint, mstartangle, mangle ); -} - -VectorImp::VectorImp( const Coordinate& a, const Coordinate& b ) - : mdata( a, b ) -{ -} - -VectorImp::~VectorImp() -{ -} - -ObjectImp* VectorImp::transform( const Transformation& t ) const -{ - Coordinate ta = t.apply( mdata.a ); - Coordinate tb = t.apply( mdata.b ); - if ( ta.valid() && tb.valid() ) return new VectorImp( ta, tb ); - else return new InvalidImp; -} - -void VectorImp::draw( KigPainter& p ) const -{ - p.drawVector( mdata.a, mdata.b ); -} - -bool VectorImp::contains( const Coordinate& o, int width, const KigWidget& w ) const -{ - return internalContainsPoint( o, w.screenInfo().normalMiss( width ) ); -} - -bool VectorImp::inRect( const Rect& r, int width, const KigWidget& w ) const -{ - return lineInRect( r, mdata.a, mdata.b, width, this, w ); -} - -const uint VectorImp::numberOfProperties() const -{ - return Parent::numberOfProperties() + 5; -} - -const QCStringList VectorImp::propertiesInternalNames() const -{ - QCStringList ret = Parent::propertiesInternalNames(); - ret << "length"; - ret << "vect-mid-point"; - ret << "length-x"; - ret << "length-y"; - ret << "vector-opposite"; - assert( ret.size() == VectorImp::numberOfProperties() ); - return ret; -} - -const QCStringList VectorImp::properties() const -{ - QCStringList ret = Parent::properties(); - ret << I18N_NOOP( "Length" ); - ret << I18N_NOOP( "Midpoint" ); - ret << I18N_NOOP( "X length" ); - ret << I18N_NOOP( "Y length" ); - ret << I18N_NOOP( "Opposite Vector" ); - assert( ret.size() == VectorImp::numberOfProperties() ); - return ret; -} - -const ObjectImpType* VectorImp::impRequirementForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::impRequirementForProperty( which ); - else return VectorImp::stype(); -} - -const char* VectorImp::iconForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::iconForProperty( which ); - else if ( which == Parent::numberOfProperties() ) - return "distance"; // length - else if ( which == Parent::numberOfProperties() + 1 ) - return "bisection"; // mid point - else if ( which == Parent::numberOfProperties() + 2 ) - return "distance"; // length-x - else if ( which == Parent::numberOfProperties() + 3 ) - return "distance"; // length-y - else if ( which == Parent::numberOfProperties() + 4 ) - return "opposite-vector"; // opposite vector - else assert( false ); - return ""; -} - -ObjectImp* VectorImp::property( uint which, const KigDocument& w ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::property( which, w ); - else if ( which == Parent::numberOfProperties() ) - return new DoubleImp( length() ); - else if ( which == Parent::numberOfProperties() + 1 ) - return new PointImp( ( mdata.a + mdata.b ) / 2 ); - else if ( which == Parent::numberOfProperties() + 2 ) - return new DoubleImp( fabs( mdata.a.x - mdata.b.x ) ); - else if ( which == Parent::numberOfProperties() + 3 ) - return new DoubleImp( fabs( mdata.a.y - mdata.b.y ) ); - else if ( which == Parent::numberOfProperties() + 4 ) // opposite - return new VectorImp( mdata.a, 2*mdata.a-mdata.b ); - else assert( false ); - return new InvalidImp; -} - -VectorImp* VectorImp::copy() const -{ - return new VectorImp( mdata.a, mdata.b ); -} - -const Coordinate VectorImp::dir() const -{ - return mdata.dir(); -} - -void AngleImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -void VectorImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -const double VectorImp::length() const -{ - return ( mdata.a - mdata.b ).length(); -} - -ArcImp::ArcImp( const Coordinate& center, const double radius, - const double startangle, const double angle ) - : CurveImp(), mcenter( center ), mradius( radius ), - msa( startangle ), ma( angle ) -{ - if ( ma < 0 ) - { - // we want a positive angle.. - msa = msa + ma; - ma = -ma; - }; -} - -ArcImp::~ArcImp() -{ -} - -ArcImp* ArcImp::copy() const -{ - return new ArcImp( mcenter, mradius, msa, ma ); -} - -ObjectImp* ArcImp::transform( const Transformation& t ) const -{ - // - // we don't have conic arcs! So it is invalid to transform an arc - // with a nonhomothetic transformation - // - if ( ! t.isHomothetic() ) return new InvalidImp(); - - Coordinate nc = t.apply( mcenter ); - double nr = t.apply( mradius ); - // transform msa... - double nmsa = msa; - if ( t.getAffineDeterminant() > 0 ) - { - nmsa = msa - t.getRotationAngle(); - } else - { - Coordinate ar = t.apply2by2only( Coordinate( cos(msa), sin(msa) ) ); - nmsa = atan2( ar.y, ar.x ); - nmsa -= ma; - } - while ( nmsa < -M_PI ) nmsa += 2*M_PI; - while ( nmsa > M_PI ) nmsa -= 2*M_PI; - if ( nc.valid() ) return new ArcImp( nc, nr, nmsa, ma ); - else return new InvalidImp; -} - -void ArcImp::draw( KigPainter& p ) const -{ - p.drawArc( mcenter, mradius, msa, ma ); -} - -bool ArcImp::contains( const Coordinate& p, int width, const KigWidget& w ) const -{ - return internalContainsPoint( p, w.screenInfo().normalMiss( width ) ); -} - -bool ArcImp::inRect( const Rect&, int, const KigWidget& ) const -{ - // TODO - return false; -} - -bool ArcImp::valid() const -{ - return true; -} - -const uint ArcImp::numberOfProperties() const -{ - return Parent::numberOfProperties() + 9; -} - -const QCStringList ArcImp::properties() const -{ - QCStringList ret = Parent::properties(); - ret << I18N_NOOP( "Center" ); - ret << I18N_NOOP( "Radius" ); - ret << I18N_NOOP( "Angle" ); - ret << I18N_NOOP( "Angle in Degrees" ); - ret << I18N_NOOP( "Angle in Radians" ); - ret << I18N_NOOP( "Sector Surface" ); - ret << I18N_NOOP( "Arc Length" ); - ret << I18N_NOOP( "First End Point" ); - ret << I18N_NOOP( "Second End Point" ); - assert( ret.size() == ArcImp::numberOfProperties() ); - return ret; -} - -const QCStringList ArcImp::propertiesInternalNames() const -{ - QCStringList ret = Parent::propertiesInternalNames(); - ret << "center"; - ret << "radius"; - ret << "angle"; - ret << "angle-degrees"; - ret << "angle-radians"; - ret << "sector-surface"; - ret << "arc-length"; - ret << "end-point-A"; - ret << "end-point-B"; - return ret; -} - -const char* ArcImp::iconForProperty( uint which ) const -{ - int numprop = 0; - if ( which < Parent::numberOfProperties() ) - return Parent::iconForProperty( which ); - else if ( which == Parent::numberOfProperties() + numprop++ ) - return "arc_center"; // center - else if ( which == Parent::numberOfProperties() + numprop++ ) - return ""; - else if ( which == Parent::numberOfProperties() + numprop++ ) - return "angle"; - else if ( which == Parent::numberOfProperties() + numprop++ ) - return "angle_size"; - else if ( which == Parent::numberOfProperties() + numprop++ ) - return "angle_size"; - else if ( which == Parent::numberOfProperties() + numprop++ ) - return ""; - else if ( which == Parent::numberOfProperties() + numprop++ ) - return ""; - else if ( which == Parent::numberOfProperties() + numprop++ ) - return ""; - else if ( which == Parent::numberOfProperties() + numprop++ ) - return ""; - else assert( false ); - return ""; -} - -ObjectImp* ArcImp::property( uint which, const KigDocument& d ) const -{ - int numprop = 0; - if ( which < Parent::numberOfProperties() ) - return Parent::property( which, d ); - else if ( which == Parent::numberOfProperties() + numprop++ ) - return new PointImp( mcenter ); - else if ( which == Parent::numberOfProperties() + numprop++ ) - return new DoubleImp( mradius ); - else if ( which == Parent::numberOfProperties() + numprop++ ) - return new AngleImp( mcenter, msa, ma ); - else if ( which == Parent::numberOfProperties() + numprop++ ) - return new IntImp( static_cast( Goniometry::convert( ma, Goniometry::Rad, Goniometry::Deg ) ) ); - else if ( which == Parent::numberOfProperties() + numprop++ ) - return new DoubleImp( ma ); - else if ( which == Parent::numberOfProperties() + numprop++ ) - return new DoubleImp( sectorSurface() ); - else if ( which == Parent::numberOfProperties() + numprop++ ) - return new DoubleImp( mradius * ma ); - else if ( which == Parent::numberOfProperties() + numprop++ ) - return new PointImp( firstEndPoint() ); - else if ( which == Parent::numberOfProperties() + numprop++ ) - return new PointImp( secondEndPoint() ); - else assert( false ); - return new InvalidImp; -} - -const double ArcImp::sectorSurface() const -{ - return mradius * mradius * ma / 2; -} - -const ObjectImpType* ArcImp::impRequirementForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::impRequirementForProperty( which ); - else - return ArcImp::stype(); -} - -void ArcImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -double ArcImp::getParam( const Coordinate& c, const KigDocument& ) const -{ - Coordinate d = (c - mcenter).normalize(); - double angle = atan2( d.y, d.x ); - angle -= msa; -// mp: problems with large arcs - while ( angle > ma/2 + M_PI ) angle -= 2*M_PI; - while ( angle < ma/2 - M_PI ) angle += 2*M_PI; -// - angle = max( 0., min( angle, ma ) ); - angle /= ma; - return angle; -} - -const Coordinate ArcImp::getPoint( double p, const KigDocument& ) const -{ - double angle = msa + p * ma; - Coordinate d = Coordinate( cos( angle ), sin( angle ) ) * mradius; - return mcenter + d; -} - -const Coordinate ArcImp::center() const -{ - return mcenter; -} - -double ArcImp::radius() const -{ - return mradius; -} - -double ArcImp::startAngle() const -{ - return msa; -} - -double ArcImp::angle() const -{ - return ma; -} - -Coordinate ArcImp::firstEndPoint() const -{ - double angle = msa; - return mcenter + Coordinate( cos( angle ), sin( angle ) ) * mradius; -} - -Coordinate ArcImp::secondEndPoint() const -{ - double angle = msa + ma; - return mcenter + Coordinate( cos( angle ), sin( angle ) ) * mradius; -} - -const Coordinate VectorImp::a() const -{ - return mdata.a; -} - -const Coordinate VectorImp::b() const -{ - return mdata.b; -} - -bool ArcImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( ArcImp::stype() ) && - static_cast( rhs ).radius() == radius() && - static_cast( rhs ).startAngle() == startAngle() && - static_cast( rhs ).angle() == angle(); -} - -bool AngleImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( AngleImp::stype() ) && - static_cast( rhs ).point() == point() && - static_cast( rhs ).startAngle() == startAngle() && - static_cast( rhs ).angle() == angle(); -} - -bool VectorImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( VectorImp::stype() ) && - static_cast( rhs ).a() == a() && - static_cast( rhs ).b() == b(); -} - -const ObjectImpType* AngleImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "angle", - I18N_NOOP( "angle" ), - I18N_NOOP( "Select this angle" ), - I18N_NOOP( "Select angle %1" ), - I18N_NOOP( "Remove an Angle" ), - I18N_NOOP( "Add an Angle" ), - I18N_NOOP( "Move an Angle" ), - I18N_NOOP( "Attach to this angle" ), - I18N_NOOP( "Show an Angle" ), - I18N_NOOP( "Hide an Angle" ) - ); - return &t; -} -const ObjectImpType* VectorImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "vector", - I18N_NOOP( "vector" ), - I18N_NOOP( "Select this vector" ), - I18N_NOOP( "Select vector %1" ), - I18N_NOOP( "Remove a Vector" ), - I18N_NOOP( "Add a Vector" ), - I18N_NOOP( "Move a Vector" ), - I18N_NOOP( "Attach to this vector" ), - I18N_NOOP( "Show a Vector" ), - I18N_NOOP( "Hide a Vector" ) - ); - return &t; -} -const ObjectImpType* ArcImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "arc", - I18N_NOOP( "arc" ), - I18N_NOOP( "Select this arc" ), - I18N_NOOP( "Select arc %1" ), - I18N_NOOP( "Remove an Arc" ), - I18N_NOOP( "Add an Arc" ), - I18N_NOOP( "Move an Arc" ), - I18N_NOOP( "Attach to this arc" ), - I18N_NOOP( "Show an Arc" ), - I18N_NOOP( "Hide an Arc" ) - ); - return &t; -} - -const ObjectImpType* AngleImp::type() const -{ - return AngleImp::stype(); -} - -const ObjectImpType* VectorImp::type() const -{ - return VectorImp::stype(); -} - -const ObjectImpType* ArcImp::type() const -{ - return ArcImp::stype(); -} - -bool ArcImp::containsPoint( const Coordinate& p, const KigDocument& ) const -{ - return internalContainsPoint( p, test_threshold ); -} - -bool ArcImp::internalContainsPoint( const Coordinate& p, double threshold ) const -{ - return isOnArc( p, mcenter, mradius, msa, ma, threshold ); -} - -bool AngleImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::isPropertyDefinedOnOrThroughThisImp( which ); - return false; -} - -bool VectorImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const -{ - return Parent::isPropertyDefinedOnOrThroughThisImp( which ); -} - -bool ArcImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::isPropertyDefinedOnOrThroughThisImp( which ); - else if ( which == Parent::numberOfProperties() ) - return true; - else - return false; -} - -Rect AngleImp::surroundingRect() const -{ - return Rect( mpoint, 0, 0 ); -} - -Rect VectorImp::surroundingRect() const -{ - return Rect( mdata.a, mdata.b ); -} - -Rect ArcImp::surroundingRect() const -{ - // the returned rect should contain the center point(?), the two end - // points, and all extreme x and y positions in between. - //Rect ret( mcenter, 0, 0 ); - double a = msa; - //ret.setContains( mcenter + mradius*Coordinate( cos( a ), sin( a ) ) ); - Rect ret ( mcenter + mradius*Coordinate( cos( a ), sin( a ) ), 0, 0 ); - a = msa + ma; - ret.setContains( mcenter + mradius*Coordinate( cos( a ), sin( a ) ) ); - for ( a = -2*M_PI; a <= 2*M_PI; a+=M_PI/2 ) - { - Coordinate d = mcenter + mradius*Coordinate( cos( a ), sin( a ) ); - if ( msa <= a && a <= msa + ma ) - ret.setContains( d ); - } - return ret; -} - -const Coordinate VectorImp::getPoint( double param, const KigDocument& ) const -{ - return mdata.a + mdata.dir() * param; -} - -double VectorImp::getParam( const Coordinate& p, const KigDocument& ) const -{ - Coordinate pt = calcPointOnPerpend( mdata, p ); - pt = calcIntersectionPoint( mdata, LineData( p, pt ) ); - // if pt is over the end of the vector we set it to one of the end - // points of the vector... - if ( ( pt - mdata.a ).length() > dir().length() ) - pt = mdata.b; - else if ( ( pt - mdata.b ).length() > dir().length() ) - pt = mdata.a; - if ( mdata.b == mdata.a ) return 0; - return ( ( pt - mdata.a ).length() ) / ( dir().length() ); -} - -bool VectorImp::containsPoint( const Coordinate& p, const KigDocument& ) const -{ - return internalContainsPoint( p, test_threshold ); -} - -bool VectorImp::internalContainsPoint( const Coordinate& p, double threshold ) const -{ - return isOnSegment( p, mdata.a, mdata.b, threshold ); -} - -LineData VectorImp::data() const -{ - return mdata; -} diff --git a/kig/objects/other_imp.cpp b/kig/objects/other_imp.cpp new file mode 100644 index 00000000..5c063753 --- /dev/null +++ b/kig/objects/other_imp.cpp @@ -0,0 +1,710 @@ +// 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 "other_imp.h" + +#include "bogus_imp.h" +#include "point_imp.h" +#include "line_imp.h" + +#include "../misc/screeninfo.h" +#include "../misc/common.h" +#include "../misc/kigtransform.h" +#include "../misc/kigpainter.h" +#include "../misc/goniometry.h" +#include "../kig/kig_view.h" + +#include + +#include +#include +using namespace std; + +AngleImp::~AngleImp() +{ +} + +ObjectImp* AngleImp::transform( const Transformation& ) const +{ + // TODO ? + return new InvalidImp; +} + +void AngleImp::draw( KigPainter& p ) const +{ + p.drawAngle( mpoint, mstartangle, mangle ); +} + +AngleImp::AngleImp( const Coordinate& pt, double start_angle_in_radials, + double angle_in_radials ) + : mpoint( pt ), mstartangle( start_angle_in_radials ), + mangle( angle_in_radials ) +{ +} + +bool AngleImp::contains( const Coordinate& p, int width, const KigWidget& w ) const +{ + double radius = 50*w.screenInfo().pixelWidth(); + + if ( fabs( (p-mpoint).length() - radius ) > w.screenInfo().normalMiss( width ) ) + return false; + + // and next we check if the angle is appropriate... + Coordinate vect = p - mpoint; + double angle = atan2( vect.y, vect.x ); + while ( angle < mstartangle ) angle += 2*M_PI; + return angle <= mstartangle + mangle; +} + +bool AngleImp::inRect( const Rect& r, int width, const KigWidget& w ) const +{ + // TODO ? + return r.contains( mpoint, w.screenInfo().normalMiss( width ) ); +} + +Coordinate AngleImp::attachPoint() const +{ + return mpoint; +} + +const uint AngleImp::numberOfProperties() const +{ + return Parent::numberOfProperties() + 3; +} + +const QCStringList AngleImp::propertiesInternalNames() const +{ + QCStringList l = Parent::propertiesInternalNames(); + l << "angle-radian"; + l << "angle-degrees"; + l << "angle-bisector"; + assert( l.size() == AngleImp::numberOfProperties() ); + return l; +} + +const QCStringList AngleImp::properties() const +{ + QCStringList l = Parent::properties(); + l << I18N_NOOP( "Angle in Radians" ); + l << I18N_NOOP( "Angle in Degrees" ); + l << I18N_NOOP( "Angle Bisector" ); + assert( l.size() == AngleImp::numberOfProperties() ); + return l; +} + +const ObjectImpType* AngleImp::impRequirementForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::impRequirementForProperty( which ); + else return AngleImp::stype(); +} + +const char* AngleImp::iconForProperty( uint which ) const +{ + int numprop = 0; + if ( which < Parent::numberOfProperties() ) + return Parent::iconForProperty( which ); + if ( which == Parent::numberOfProperties() + numprop++ ) + return "angle_size"; // size in radians + else if ( which == Parent::numberOfProperties() + numprop++ ) + return "angle_size"; // size in degrees + else if ( which == Parent::numberOfProperties() + numprop++ ) + return "angle_bisector"; // angle bisector.. + else assert( false ); + return ""; +} + +ObjectImp* AngleImp::property( uint which, const KigDocument& w ) const +{ + int numprop = 0; + if ( which < Parent::numberOfProperties() ) + return Parent::property( which, w ); + if ( which == Parent::numberOfProperties() + numprop++ ) + return new DoubleImp( size() ); + else if ( which == Parent::numberOfProperties() + numprop++ ) + return new DoubleImp( Goniometry::convert( size(), Goniometry::Rad, Goniometry::Deg ) ); + else if ( which == Parent::numberOfProperties() + numprop++ ) + { + const double angle = mstartangle + mangle / 2; + Coordinate p2 = mpoint + Coordinate( cos( angle ), sin( angle ) ) * 10; + return new RayImp( mpoint, p2 ); + } + else assert( false ); + return new InvalidImp; +} + +const double AngleImp::size() const +{ + return mangle; +} + +ObjectImp* AngleImp::copy() const +{ + return new AngleImp( mpoint, mstartangle, mangle ); +} + +VectorImp::VectorImp( const Coordinate& a, const Coordinate& b ) + : mdata( a, b ) +{ +} + +VectorImp::~VectorImp() +{ +} + +ObjectImp* VectorImp::transform( const Transformation& t ) const +{ + Coordinate ta = t.apply( mdata.a ); + Coordinate tb = t.apply( mdata.b ); + if ( ta.valid() && tb.valid() ) return new VectorImp( ta, tb ); + else return new InvalidImp; +} + +void VectorImp::draw( KigPainter& p ) const +{ + p.drawVector( mdata.a, mdata.b ); +} + +bool VectorImp::contains( const Coordinate& o, int width, const KigWidget& w ) const +{ + return internalContainsPoint( o, w.screenInfo().normalMiss( width ) ); +} + +bool VectorImp::inRect( const Rect& r, int width, const KigWidget& w ) const +{ + return lineInRect( r, mdata.a, mdata.b, width, this, w ); +} + +const uint VectorImp::numberOfProperties() const +{ + return Parent::numberOfProperties() + 5; +} + +const QCStringList VectorImp::propertiesInternalNames() const +{ + QCStringList ret = Parent::propertiesInternalNames(); + ret << "length"; + ret << "vect-mid-point"; + ret << "length-x"; + ret << "length-y"; + ret << "vector-opposite"; + assert( ret.size() == VectorImp::numberOfProperties() ); + return ret; +} + +const QCStringList VectorImp::properties() const +{ + QCStringList ret = Parent::properties(); + ret << I18N_NOOP( "Length" ); + ret << I18N_NOOP( "Midpoint" ); + ret << I18N_NOOP( "X length" ); + ret << I18N_NOOP( "Y length" ); + ret << I18N_NOOP( "Opposite Vector" ); + assert( ret.size() == VectorImp::numberOfProperties() ); + return ret; +} + +const ObjectImpType* VectorImp::impRequirementForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::impRequirementForProperty( which ); + else return VectorImp::stype(); +} + +const char* VectorImp::iconForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::iconForProperty( which ); + else if ( which == Parent::numberOfProperties() ) + return "distance"; // length + else if ( which == Parent::numberOfProperties() + 1 ) + return "bisection"; // mid point + else if ( which == Parent::numberOfProperties() + 2 ) + return "distance"; // length-x + else if ( which == Parent::numberOfProperties() + 3 ) + return "distance"; // length-y + else if ( which == Parent::numberOfProperties() + 4 ) + return "opposite-vector"; // opposite vector + else assert( false ); + return ""; +} + +ObjectImp* VectorImp::property( uint which, const KigDocument& w ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::property( which, w ); + else if ( which == Parent::numberOfProperties() ) + return new DoubleImp( length() ); + else if ( which == Parent::numberOfProperties() + 1 ) + return new PointImp( ( mdata.a + mdata.b ) / 2 ); + else if ( which == Parent::numberOfProperties() + 2 ) + return new DoubleImp( fabs( mdata.a.x - mdata.b.x ) ); + else if ( which == Parent::numberOfProperties() + 3 ) + return new DoubleImp( fabs( mdata.a.y - mdata.b.y ) ); + else if ( which == Parent::numberOfProperties() + 4 ) // opposite + return new VectorImp( mdata.a, 2*mdata.a-mdata.b ); + else assert( false ); + return new InvalidImp; +} + +VectorImp* VectorImp::copy() const +{ + return new VectorImp( mdata.a, mdata.b ); +} + +const Coordinate VectorImp::dir() const +{ + return mdata.dir(); +} + +void AngleImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +void VectorImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +const double VectorImp::length() const +{ + return ( mdata.a - mdata.b ).length(); +} + +ArcImp::ArcImp( const Coordinate& center, const double radius, + const double startangle, const double angle ) + : CurveImp(), mcenter( center ), mradius( radius ), + msa( startangle ), ma( angle ) +{ + if ( ma < 0 ) + { + // we want a positive angle.. + msa = msa + ma; + ma = -ma; + }; +} + +ArcImp::~ArcImp() +{ +} + +ArcImp* ArcImp::copy() const +{ + return new ArcImp( mcenter, mradius, msa, ma ); +} + +ObjectImp* ArcImp::transform( const Transformation& t ) const +{ + // + // we don't have conic arcs! So it is invalid to transform an arc + // with a nonhomothetic transformation + // + if ( ! t.isHomothetic() ) return new InvalidImp(); + + Coordinate nc = t.apply( mcenter ); + double nr = t.apply( mradius ); + // transform msa... + double nmsa = msa; + if ( t.getAffineDeterminant() > 0 ) + { + nmsa = msa - t.getRotationAngle(); + } else + { + Coordinate ar = t.apply2by2only( Coordinate( cos(msa), sin(msa) ) ); + nmsa = atan2( ar.y, ar.x ); + nmsa -= ma; + } + while ( nmsa < -M_PI ) nmsa += 2*M_PI; + while ( nmsa > M_PI ) nmsa -= 2*M_PI; + if ( nc.valid() ) return new ArcImp( nc, nr, nmsa, ma ); + else return new InvalidImp; +} + +void ArcImp::draw( KigPainter& p ) const +{ + p.drawArc( mcenter, mradius, msa, ma ); +} + +bool ArcImp::contains( const Coordinate& p, int width, const KigWidget& w ) const +{ + return internalContainsPoint( p, w.screenInfo().normalMiss( width ) ); +} + +bool ArcImp::inRect( const Rect&, int, const KigWidget& ) const +{ + // TODO + return false; +} + +bool ArcImp::valid() const +{ + return true; +} + +const uint ArcImp::numberOfProperties() const +{ + return Parent::numberOfProperties() + 9; +} + +const QCStringList ArcImp::properties() const +{ + QCStringList ret = Parent::properties(); + ret << I18N_NOOP( "Center" ); + ret << I18N_NOOP( "Radius" ); + ret << I18N_NOOP( "Angle" ); + ret << I18N_NOOP( "Angle in Degrees" ); + ret << I18N_NOOP( "Angle in Radians" ); + ret << I18N_NOOP( "Sector Surface" ); + ret << I18N_NOOP( "Arc Length" ); + ret << I18N_NOOP( "First End Point" ); + ret << I18N_NOOP( "Second End Point" ); + assert( ret.size() == ArcImp::numberOfProperties() ); + return ret; +} + +const QCStringList ArcImp::propertiesInternalNames() const +{ + QCStringList ret = Parent::propertiesInternalNames(); + ret << "center"; + ret << "radius"; + ret << "angle"; + ret << "angle-degrees"; + ret << "angle-radians"; + ret << "sector-surface"; + ret << "arc-length"; + ret << "end-point-A"; + ret << "end-point-B"; + return ret; +} + +const char* ArcImp::iconForProperty( uint which ) const +{ + int numprop = 0; + if ( which < Parent::numberOfProperties() ) + return Parent::iconForProperty( which ); + else if ( which == Parent::numberOfProperties() + numprop++ ) + return "arc_center"; // center + else if ( which == Parent::numberOfProperties() + numprop++ ) + return ""; + else if ( which == Parent::numberOfProperties() + numprop++ ) + return "angle"; + else if ( which == Parent::numberOfProperties() + numprop++ ) + return "angle_size"; + else if ( which == Parent::numberOfProperties() + numprop++ ) + return "angle_size"; + else if ( which == Parent::numberOfProperties() + numprop++ ) + return ""; + else if ( which == Parent::numberOfProperties() + numprop++ ) + return ""; + else if ( which == Parent::numberOfProperties() + numprop++ ) + return ""; + else if ( which == Parent::numberOfProperties() + numprop++ ) + return ""; + else assert( false ); + return ""; +} + +ObjectImp* ArcImp::property( uint which, const KigDocument& d ) const +{ + int numprop = 0; + if ( which < Parent::numberOfProperties() ) + return Parent::property( which, d ); + else if ( which == Parent::numberOfProperties() + numprop++ ) + return new PointImp( mcenter ); + else if ( which == Parent::numberOfProperties() + numprop++ ) + return new DoubleImp( mradius ); + else if ( which == Parent::numberOfProperties() + numprop++ ) + return new AngleImp( mcenter, msa, ma ); + else if ( which == Parent::numberOfProperties() + numprop++ ) + return new IntImp( static_cast( Goniometry::convert( ma, Goniometry::Rad, Goniometry::Deg ) ) ); + else if ( which == Parent::numberOfProperties() + numprop++ ) + return new DoubleImp( ma ); + else if ( which == Parent::numberOfProperties() + numprop++ ) + return new DoubleImp( sectorSurface() ); + else if ( which == Parent::numberOfProperties() + numprop++ ) + return new DoubleImp( mradius * ma ); + else if ( which == Parent::numberOfProperties() + numprop++ ) + return new PointImp( firstEndPoint() ); + else if ( which == Parent::numberOfProperties() + numprop++ ) + return new PointImp( secondEndPoint() ); + else assert( false ); + return new InvalidImp; +} + +const double ArcImp::sectorSurface() const +{ + return mradius * mradius * ma / 2; +} + +const ObjectImpType* ArcImp::impRequirementForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::impRequirementForProperty( which ); + else + return ArcImp::stype(); +} + +void ArcImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +double ArcImp::getParam( const Coordinate& c, const KigDocument& ) const +{ + Coordinate d = (c - mcenter).normalize(); + double angle = atan2( d.y, d.x ); + angle -= msa; +// mp: problems with large arcs + while ( angle > ma/2 + M_PI ) angle -= 2*M_PI; + while ( angle < ma/2 - M_PI ) angle += 2*M_PI; +// + angle = max( 0., min( angle, ma ) ); + angle /= ma; + return angle; +} + +const Coordinate ArcImp::getPoint( double p, const KigDocument& ) const +{ + double angle = msa + p * ma; + Coordinate d = Coordinate( cos( angle ), sin( angle ) ) * mradius; + return mcenter + d; +} + +const Coordinate ArcImp::center() const +{ + return mcenter; +} + +double ArcImp::radius() const +{ + return mradius; +} + +double ArcImp::startAngle() const +{ + return msa; +} + +double ArcImp::angle() const +{ + return ma; +} + +Coordinate ArcImp::firstEndPoint() const +{ + double angle = msa; + return mcenter + Coordinate( cos( angle ), sin( angle ) ) * mradius; +} + +Coordinate ArcImp::secondEndPoint() const +{ + double angle = msa + ma; + return mcenter + Coordinate( cos( angle ), sin( angle ) ) * mradius; +} + +const Coordinate VectorImp::a() const +{ + return mdata.a; +} + +const Coordinate VectorImp::b() const +{ + return mdata.b; +} + +bool ArcImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( ArcImp::stype() ) && + static_cast( rhs ).radius() == radius() && + static_cast( rhs ).startAngle() == startAngle() && + static_cast( rhs ).angle() == angle(); +} + +bool AngleImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( AngleImp::stype() ) && + static_cast( rhs ).point() == point() && + static_cast( rhs ).startAngle() == startAngle() && + static_cast( rhs ).angle() == angle(); +} + +bool VectorImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( VectorImp::stype() ) && + static_cast( rhs ).a() == a() && + static_cast( rhs ).b() == b(); +} + +const ObjectImpType* AngleImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "angle", + I18N_NOOP( "angle" ), + I18N_NOOP( "Select this angle" ), + I18N_NOOP( "Select angle %1" ), + I18N_NOOP( "Remove an Angle" ), + I18N_NOOP( "Add an Angle" ), + I18N_NOOP( "Move an Angle" ), + I18N_NOOP( "Attach to this angle" ), + I18N_NOOP( "Show an Angle" ), + I18N_NOOP( "Hide an Angle" ) + ); + return &t; +} +const ObjectImpType* VectorImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "vector", + I18N_NOOP( "vector" ), + I18N_NOOP( "Select this vector" ), + I18N_NOOP( "Select vector %1" ), + I18N_NOOP( "Remove a Vector" ), + I18N_NOOP( "Add a Vector" ), + I18N_NOOP( "Move a Vector" ), + I18N_NOOP( "Attach to this vector" ), + I18N_NOOP( "Show a Vector" ), + I18N_NOOP( "Hide a Vector" ) + ); + return &t; +} +const ObjectImpType* ArcImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "arc", + I18N_NOOP( "arc" ), + I18N_NOOP( "Select this arc" ), + I18N_NOOP( "Select arc %1" ), + I18N_NOOP( "Remove an Arc" ), + I18N_NOOP( "Add an Arc" ), + I18N_NOOP( "Move an Arc" ), + I18N_NOOP( "Attach to this arc" ), + I18N_NOOP( "Show an Arc" ), + I18N_NOOP( "Hide an Arc" ) + ); + return &t; +} + +const ObjectImpType* AngleImp::type() const +{ + return AngleImp::stype(); +} + +const ObjectImpType* VectorImp::type() const +{ + return VectorImp::stype(); +} + +const ObjectImpType* ArcImp::type() const +{ + return ArcImp::stype(); +} + +bool ArcImp::containsPoint( const Coordinate& p, const KigDocument& ) const +{ + return internalContainsPoint( p, test_threshold ); +} + +bool ArcImp::internalContainsPoint( const Coordinate& p, double threshold ) const +{ + return isOnArc( p, mcenter, mradius, msa, ma, threshold ); +} + +bool AngleImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::isPropertyDefinedOnOrThroughThisImp( which ); + return false; +} + +bool VectorImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const +{ + return Parent::isPropertyDefinedOnOrThroughThisImp( which ); +} + +bool ArcImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::isPropertyDefinedOnOrThroughThisImp( which ); + else if ( which == Parent::numberOfProperties() ) + return true; + else + return false; +} + +Rect AngleImp::surroundingRect() const +{ + return Rect( mpoint, 0, 0 ); +} + +Rect VectorImp::surroundingRect() const +{ + return Rect( mdata.a, mdata.b ); +} + +Rect ArcImp::surroundingRect() const +{ + // the returned rect should contain the center point(?), the two end + // points, and all extreme x and y positions in between. + //Rect ret( mcenter, 0, 0 ); + double a = msa; + //ret.setContains( mcenter + mradius*Coordinate( cos( a ), sin( a ) ) ); + Rect ret ( mcenter + mradius*Coordinate( cos( a ), sin( a ) ), 0, 0 ); + a = msa + ma; + ret.setContains( mcenter + mradius*Coordinate( cos( a ), sin( a ) ) ); + for ( a = -2*M_PI; a <= 2*M_PI; a+=M_PI/2 ) + { + Coordinate d = mcenter + mradius*Coordinate( cos( a ), sin( a ) ); + if ( msa <= a && a <= msa + ma ) + ret.setContains( d ); + } + return ret; +} + +const Coordinate VectorImp::getPoint( double param, const KigDocument& ) const +{ + return mdata.a + mdata.dir() * param; +} + +double VectorImp::getParam( const Coordinate& p, const KigDocument& ) const +{ + Coordinate pt = calcPointOnPerpend( mdata, p ); + pt = calcIntersectionPoint( mdata, LineData( p, pt ) ); + // if pt is over the end of the vector we set it to one of the end + // points of the vector... + if ( ( pt - mdata.a ).length() > dir().length() ) + pt = mdata.b; + else if ( ( pt - mdata.b ).length() > dir().length() ) + pt = mdata.a; + if ( mdata.b == mdata.a ) return 0; + return ( ( pt - mdata.a ).length() ) / ( dir().length() ); +} + +bool VectorImp::containsPoint( const Coordinate& p, const KigDocument& ) const +{ + return internalContainsPoint( p, test_threshold ); +} + +bool VectorImp::internalContainsPoint( const Coordinate& p, double threshold ) const +{ + return isOnSegment( p, mdata.a, mdata.b, threshold ); +} + +LineData VectorImp::data() const +{ + return mdata; +} diff --git a/kig/objects/other_type.cc b/kig/objects/other_type.cc deleted file mode 100644 index 27787986..00000000 --- a/kig/objects/other_type.cc +++ /dev/null @@ -1,189 +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 "other_type.h" - -#include "bogus_imp.h" -#include "point_imp.h" -#include "locus_imp.h" - -#include "../misc/common.h" -#include "../misc/calcpaths.h" -#include "../misc/goniometry.h" -#include "../kig/kig_part.h" -#include "../kig/kig_view.h" -#include "../kig/kig_commands.h" - -#include -#include -#include - -using std::find; - -static const struct ArgsParser::spec argsspecLocus[] = -{ - { HierarchyImp::stype(), "hierarchy", "SHOULD NOT BE SEEN", false }, - { CurveImp::stype(), "curve", "SHOULD NOT BE SEEN", false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LocusType ) - -LocusType::LocusType() - : ArgsParserObjectType( "Locus", argsspecLocus, 2 ) -{ -} - -LocusType::~LocusType() -{ -} - -ObjectImp* LocusType::calc( const Args& args, const KigDocument& ) const -{ - using namespace std; - - assert( args.size() >= 2 ); - const Args firsttwo( args.begin(), args.begin() + 2 ); - Args fixedargs( args.begin() + 2, args.end() ); - - if ( ! margsparser.checkArgs( firsttwo ) ) return new InvalidImp; - for ( Args::iterator i = fixedargs.begin(); i != fixedargs.end(); ++i ) - if ( ! (*i)->valid() ) - return new InvalidImp; - - const ObjectHierarchy& hier = - static_cast( args[0] )->data(); - const CurveImp* curveimp = static_cast( args[1] ); - - return new LocusImp( curveimp->copy(), hier.withFixedArgs( fixedargs ) ); -} - -bool LocusType::inherits( int type ) const -{ - return type == ID_LocusType ? true : Parent::inherits( type ); -} - -const ObjectImpType* LocusType::resultId() const -{ - return LocusImp::stype(); -} - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CopyObjectType ) - -CopyObjectType::CopyObjectType() - : ObjectType( "Copy" ) -{ -} - -CopyObjectType::~CopyObjectType() -{ -} - -CopyObjectType* CopyObjectType::instance() -{ - static CopyObjectType t; - return &t; -} - -bool CopyObjectType::inherits( int ) const -{ - return false; -} - -ObjectImp* CopyObjectType::calc( const Args& parents, const KigDocument& ) const -{ - assert( parents.size() == 1 ); - return parents[0]->copy(); -} - -const ObjectImpType* CopyObjectType::impRequirement( const ObjectImp*, const Args& ) const -{ - return ObjectImp::stype(); -} - -const ObjectImpType* CopyObjectType::resultId() const -{ - // we don't know what we return.. - return ObjectImp::stype(); -} - -const ObjectImpType* LocusType::impRequirement( const ObjectImp* o, const Args& parents ) const -{ - assert( parents.size() >= 2 ); - Args firsttwo( parents.begin(), parents.begin() + 2 ); - if ( o == parents[0] || o == parents[1] ) - return margsparser.impRequirement( o, firsttwo ); - else - { - const HierarchyImp* h = dynamic_cast( parents[0] ); - if ( h ) - { - PointImp* p = new PointImp( Coordinate() ); - Args hargs( parents.begin()+ 2, parents.end() ); - hargs.push_back( p ); - ArgsParser hparser = h->data().argParser(); - const ObjectImpType* ret = hparser.impRequirement( o, hargs ); - delete p; - return ret; - } - else - return ObjectImp::stype(); - }; -} - -const LocusType* LocusType::instance() -{ - static const LocusType t; - return &t; -} - -std::vector CopyObjectType::sortArgs( const std::vector& os ) const -{ - assert( os.size() == 1 ); - return os; -} - -std::vector LocusType::sortArgs( const std::vector& args ) const -{ - assert( args.size() >= 2 ); - std::vector firsttwo( args.begin(), args.begin() + 2 ); - firsttwo = margsparser.parse( firsttwo ); - std::copy( args.begin() + 2, args.end(), std::back_inserter( firsttwo ) ); - return firsttwo; -} - -Args LocusType::sortArgs( const Args& args ) const -{ - assert( args.size() >= 2 ); - Args firsttwo( args.begin(), args.begin() + 2 ); - firsttwo = margsparser.parse( firsttwo ); - std::copy( args.begin() + 2, args.end(), std::back_inserter( firsttwo ) ); - return firsttwo; -} - -Args CopyObjectType::sortArgs( const Args& args ) const -{ - assert( args.size() == 1 ); - return args; -} - -bool CopyObjectType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const -{ - // TODO: vragen aan parent ? - // TODO: translate the above TODO ? - return false; -} - diff --git a/kig/objects/other_type.cpp b/kig/objects/other_type.cpp new file mode 100644 index 00000000..27787986 --- /dev/null +++ b/kig/objects/other_type.cpp @@ -0,0 +1,189 @@ +// 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 "other_type.h" + +#include "bogus_imp.h" +#include "point_imp.h" +#include "locus_imp.h" + +#include "../misc/common.h" +#include "../misc/calcpaths.h" +#include "../misc/goniometry.h" +#include "../kig/kig_part.h" +#include "../kig/kig_view.h" +#include "../kig/kig_commands.h" + +#include +#include +#include + +using std::find; + +static const struct ArgsParser::spec argsspecLocus[] = +{ + { HierarchyImp::stype(), "hierarchy", "SHOULD NOT BE SEEN", false }, + { CurveImp::stype(), "curve", "SHOULD NOT BE SEEN", false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LocusType ) + +LocusType::LocusType() + : ArgsParserObjectType( "Locus", argsspecLocus, 2 ) +{ +} + +LocusType::~LocusType() +{ +} + +ObjectImp* LocusType::calc( const Args& args, const KigDocument& ) const +{ + using namespace std; + + assert( args.size() >= 2 ); + const Args firsttwo( args.begin(), args.begin() + 2 ); + Args fixedargs( args.begin() + 2, args.end() ); + + if ( ! margsparser.checkArgs( firsttwo ) ) return new InvalidImp; + for ( Args::iterator i = fixedargs.begin(); i != fixedargs.end(); ++i ) + if ( ! (*i)->valid() ) + return new InvalidImp; + + const ObjectHierarchy& hier = + static_cast( args[0] )->data(); + const CurveImp* curveimp = static_cast( args[1] ); + + return new LocusImp( curveimp->copy(), hier.withFixedArgs( fixedargs ) ); +} + +bool LocusType::inherits( int type ) const +{ + return type == ID_LocusType ? true : Parent::inherits( type ); +} + +const ObjectImpType* LocusType::resultId() const +{ + return LocusImp::stype(); +} + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CopyObjectType ) + +CopyObjectType::CopyObjectType() + : ObjectType( "Copy" ) +{ +} + +CopyObjectType::~CopyObjectType() +{ +} + +CopyObjectType* CopyObjectType::instance() +{ + static CopyObjectType t; + return &t; +} + +bool CopyObjectType::inherits( int ) const +{ + return false; +} + +ObjectImp* CopyObjectType::calc( const Args& parents, const KigDocument& ) const +{ + assert( parents.size() == 1 ); + return parents[0]->copy(); +} + +const ObjectImpType* CopyObjectType::impRequirement( const ObjectImp*, const Args& ) const +{ + return ObjectImp::stype(); +} + +const ObjectImpType* CopyObjectType::resultId() const +{ + // we don't know what we return.. + return ObjectImp::stype(); +} + +const ObjectImpType* LocusType::impRequirement( const ObjectImp* o, const Args& parents ) const +{ + assert( parents.size() >= 2 ); + Args firsttwo( parents.begin(), parents.begin() + 2 ); + if ( o == parents[0] || o == parents[1] ) + return margsparser.impRequirement( o, firsttwo ); + else + { + const HierarchyImp* h = dynamic_cast( parents[0] ); + if ( h ) + { + PointImp* p = new PointImp( Coordinate() ); + Args hargs( parents.begin()+ 2, parents.end() ); + hargs.push_back( p ); + ArgsParser hparser = h->data().argParser(); + const ObjectImpType* ret = hparser.impRequirement( o, hargs ); + delete p; + return ret; + } + else + return ObjectImp::stype(); + }; +} + +const LocusType* LocusType::instance() +{ + static const LocusType t; + return &t; +} + +std::vector CopyObjectType::sortArgs( const std::vector& os ) const +{ + assert( os.size() == 1 ); + return os; +} + +std::vector LocusType::sortArgs( const std::vector& args ) const +{ + assert( args.size() >= 2 ); + std::vector firsttwo( args.begin(), args.begin() + 2 ); + firsttwo = margsparser.parse( firsttwo ); + std::copy( args.begin() + 2, args.end(), std::back_inserter( firsttwo ) ); + return firsttwo; +} + +Args LocusType::sortArgs( const Args& args ) const +{ + assert( args.size() >= 2 ); + Args firsttwo( args.begin(), args.begin() + 2 ); + firsttwo = margsparser.parse( firsttwo ); + std::copy( args.begin() + 2, args.end(), std::back_inserter( firsttwo ) ); + return firsttwo; +} + +Args CopyObjectType::sortArgs( const Args& args ) const +{ + assert( args.size() == 1 ); + return args; +} + +bool CopyObjectType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const +{ + // TODO: vragen aan parent ? + // TODO: translate the above TODO ? + return false; +} + diff --git a/kig/objects/point_imp.cc b/kig/objects/point_imp.cc deleted file mode 100644 index 4cc4168c..00000000 --- a/kig/objects/point_imp.cc +++ /dev/null @@ -1,223 +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 "point_imp.h" - -#include "bogus_imp.h" -#include "../misc/kigtransform.h" -#include "../misc/kigpainter.h" -#include "../misc/coordinate_system.h" -#include "../kig/kig_document.h" -#include "../kig/kig_view.h" - -#include - -PointImp::PointImp( const Coordinate& c ) - : mc( c ) -{ -} - -Coordinate PointImp::attachPoint() const -{ - return mc; -// return Coordinate::invalidCoord(); -} - -void PointImp::draw( KigPainter& p ) const -{ - p.drawFatPoint( mc ); -} - -bool PointImp::contains( const Coordinate& p, int width, const KigWidget& w ) const -{ - int twidth = width == -1 ? 5 : width; - return (p - mc).length() - twidth*w.screenInfo().pixelWidth() < 0; -} - -bool PointImp::inRect( const Rect& r, int width, const KigWidget& w ) const -{ - double am = w.screenInfo().normalMiss( width ); - return r.contains( mc, am ); -} - -const uint PointImp::numberOfProperties() const -{ - return Parent::numberOfProperties() + 3; -} - -const QCStringList PointImp::propertiesInternalNames() const -{ - QCStringList l = Parent::propertiesInternalNames(); - l << "coordinate"; - l << "coordinate-x"; - l << "coordinate-y"; - assert( l.size() == PointImp::numberOfProperties() ); - return l; -} - -const QCStringList PointImp::properties() const -{ - QCStringList l = Parent::properties(); - l << I18N_NOOP( "Coordinate" ); - l << I18N_NOOP( "X coordinate" ); - l << I18N_NOOP( "Y coordinate" ); - assert( l.size() == PointImp::numberOfProperties() ); - return l; -} - -const ObjectImpType* PointImp::impRequirementForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::impRequirementForProperty( which ); - else return PointImp::stype(); -} - -const char* PointImp::iconForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::iconForProperty( which ); - if ( which == Parent::numberOfProperties() ) - return "pointxy"; // coordinate - if ( which == Parent::numberOfProperties() + 1 ) - return "pointxy"; // coordinate-x - if ( which == Parent::numberOfProperties() + 2 ) - return "pointxy"; // coordinate-y - else assert( false ); - return ""; -} - -ObjectImp* PointImp::property( uint which, const KigDocument& d ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::property( which, d ); - if ( which == Parent::numberOfProperties() ) - return new PointImp( mc ); - if ( which == Parent::numberOfProperties() + 1 ) - return new DoubleImp( mc.x ); - if ( which == Parent::numberOfProperties() + 2 ) - return new DoubleImp( mc.y ); -// else assert( false ); - return new InvalidImp; -} - -PointImp::~PointImp() -{ -} - -PointImp* PointImp::copy() const -{ - return new PointImp( mc ); -} - -ObjectImp* PointImp::transform( const Transformation& t ) const -{ - Coordinate nc = t.apply( mc ); - if ( nc.valid() ) return new PointImp( nc ); - else return new InvalidImp(); -} - -void PointImp::setCoordinate( const Coordinate& c ) -{ - mc = c; -} - -void PointImp::fillInNextEscape( TQString& s, const KigDocument& doc ) const -{ - s = s.arg( doc.coordinateSystem().fromScreen( mc, doc ) ); -} - -void PointImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -bool PointImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( PointImp::stype() ) && - static_cast( rhs ).coordinate() == coordinate(); -} - -bool PointImp::canFillInNextEscape() const -{ - return true; -} - -const ObjectImpType* PointImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "point", - I18N_NOOP( "point" ), - I18N_NOOP( "Select this point" ), - I18N_NOOP( "Select point %1" ), - I18N_NOOP( "Remove a Point" ), - I18N_NOOP( "Add a Point" ), - I18N_NOOP( "Move a Point" ), - I18N_NOOP( "Attach to this point" ), - I18N_NOOP( "Show a Point" ), - I18N_NOOP( "Hide a Point" ) - ); - return &t; -} - -const ObjectImpType* PointImp::type() const -{ - return PointImp::stype(); -} - -bool PointImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const -{ - return Parent::isPropertyDefinedOnOrThroughThisImp( which ); -} - -Rect PointImp::surroundingRect() const -{ - return Rect( mc, 0., 0. ); -} - -/* - */ - -BogusPointImp::BogusPointImp( const Coordinate& c ) - : PointImp( c ) -{ -} - -BogusPointImp::~BogusPointImp() -{ -} - -const ObjectImpType* BogusPointImp::stype() -{ - static const ObjectImpType t( - 0, "boguspoint", - "SHOULDNOTBESEEN", - "SHOULDNOTBESEEN", - "SHOULDNOTBESEEN", - "SHOULDNOTBESEEN", - "SHOULDNOTBESEEN", - "SHOULDNOTBESEEN", - "SHOULDNOTBESEEN", - "SHOULDNOTBESEEN", - "SHOULDNOTBESEEN" - ); - return &t; -} - -const ObjectImpType* BogusPointImp::type() const -{ - return BogusPointImp::stype(); -} diff --git a/kig/objects/point_imp.cpp b/kig/objects/point_imp.cpp new file mode 100644 index 00000000..4cc4168c --- /dev/null +++ b/kig/objects/point_imp.cpp @@ -0,0 +1,223 @@ +// 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 "point_imp.h" + +#include "bogus_imp.h" +#include "../misc/kigtransform.h" +#include "../misc/kigpainter.h" +#include "../misc/coordinate_system.h" +#include "../kig/kig_document.h" +#include "../kig/kig_view.h" + +#include + +PointImp::PointImp( const Coordinate& c ) + : mc( c ) +{ +} + +Coordinate PointImp::attachPoint() const +{ + return mc; +// return Coordinate::invalidCoord(); +} + +void PointImp::draw( KigPainter& p ) const +{ + p.drawFatPoint( mc ); +} + +bool PointImp::contains( const Coordinate& p, int width, const KigWidget& w ) const +{ + int twidth = width == -1 ? 5 : width; + return (p - mc).length() - twidth*w.screenInfo().pixelWidth() < 0; +} + +bool PointImp::inRect( const Rect& r, int width, const KigWidget& w ) const +{ + double am = w.screenInfo().normalMiss( width ); + return r.contains( mc, am ); +} + +const uint PointImp::numberOfProperties() const +{ + return Parent::numberOfProperties() + 3; +} + +const QCStringList PointImp::propertiesInternalNames() const +{ + QCStringList l = Parent::propertiesInternalNames(); + l << "coordinate"; + l << "coordinate-x"; + l << "coordinate-y"; + assert( l.size() == PointImp::numberOfProperties() ); + return l; +} + +const QCStringList PointImp::properties() const +{ + QCStringList l = Parent::properties(); + l << I18N_NOOP( "Coordinate" ); + l << I18N_NOOP( "X coordinate" ); + l << I18N_NOOP( "Y coordinate" ); + assert( l.size() == PointImp::numberOfProperties() ); + return l; +} + +const ObjectImpType* PointImp::impRequirementForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::impRequirementForProperty( which ); + else return PointImp::stype(); +} + +const char* PointImp::iconForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::iconForProperty( which ); + if ( which == Parent::numberOfProperties() ) + return "pointxy"; // coordinate + if ( which == Parent::numberOfProperties() + 1 ) + return "pointxy"; // coordinate-x + if ( which == Parent::numberOfProperties() + 2 ) + return "pointxy"; // coordinate-y + else assert( false ); + return ""; +} + +ObjectImp* PointImp::property( uint which, const KigDocument& d ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::property( which, d ); + if ( which == Parent::numberOfProperties() ) + return new PointImp( mc ); + if ( which == Parent::numberOfProperties() + 1 ) + return new DoubleImp( mc.x ); + if ( which == Parent::numberOfProperties() + 2 ) + return new DoubleImp( mc.y ); +// else assert( false ); + return new InvalidImp; +} + +PointImp::~PointImp() +{ +} + +PointImp* PointImp::copy() const +{ + return new PointImp( mc ); +} + +ObjectImp* PointImp::transform( const Transformation& t ) const +{ + Coordinate nc = t.apply( mc ); + if ( nc.valid() ) return new PointImp( nc ); + else return new InvalidImp(); +} + +void PointImp::setCoordinate( const Coordinate& c ) +{ + mc = c; +} + +void PointImp::fillInNextEscape( TQString& s, const KigDocument& doc ) const +{ + s = s.arg( doc.coordinateSystem().fromScreen( mc, doc ) ); +} + +void PointImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +bool PointImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( PointImp::stype() ) && + static_cast( rhs ).coordinate() == coordinate(); +} + +bool PointImp::canFillInNextEscape() const +{ + return true; +} + +const ObjectImpType* PointImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "point", + I18N_NOOP( "point" ), + I18N_NOOP( "Select this point" ), + I18N_NOOP( "Select point %1" ), + I18N_NOOP( "Remove a Point" ), + I18N_NOOP( "Add a Point" ), + I18N_NOOP( "Move a Point" ), + I18N_NOOP( "Attach to this point" ), + I18N_NOOP( "Show a Point" ), + I18N_NOOP( "Hide a Point" ) + ); + return &t; +} + +const ObjectImpType* PointImp::type() const +{ + return PointImp::stype(); +} + +bool PointImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const +{ + return Parent::isPropertyDefinedOnOrThroughThisImp( which ); +} + +Rect PointImp::surroundingRect() const +{ + return Rect( mc, 0., 0. ); +} + +/* + */ + +BogusPointImp::BogusPointImp( const Coordinate& c ) + : PointImp( c ) +{ +} + +BogusPointImp::~BogusPointImp() +{ +} + +const ObjectImpType* BogusPointImp::stype() +{ + static const ObjectImpType t( + 0, "boguspoint", + "SHOULDNOTBESEEN", + "SHOULDNOTBESEEN", + "SHOULDNOTBESEEN", + "SHOULDNOTBESEEN", + "SHOULDNOTBESEEN", + "SHOULDNOTBESEEN", + "SHOULDNOTBESEEN", + "SHOULDNOTBESEEN", + "SHOULDNOTBESEEN" + ); + return &t; +} + +const ObjectImpType* BogusPointImp::type() const +{ + return BogusPointImp::stype(); +} diff --git a/kig/objects/point_type.cc b/kig/objects/point_type.cc deleted file mode 100644 index 59f495b9..00000000 --- a/kig/objects/point_type.cc +++ /dev/null @@ -1,665 +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 "point_type.h" - -#include "point_imp.h" -#include "curve_imp.h" -#include "line_imp.h" -#include "other_imp.h" -#include "bogus_imp.h" - -#include "../modes/moving.h" -#include "../misc/coordinate_system.h" -#include "../misc/common.h" -#include "../misc/calcpaths.h" -#include "../misc/kiginputdialog.h" -#include "../kig/kig_part.h" -#include "../kig/kig_document.h" -#include "../kig/kig_view.h" -#include "../kig/kig_commands.h" - -#include - -static const ArgsParser::spec argsspecFixedPoint[] = -{ - { DoubleImp::stype(), "x", "SHOULD NOT BE SEEN", false }, - { DoubleImp::stype(), "y", "SHOULD NOT BE SEEN", false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( FixedPointType ) - -FixedPointType::FixedPointType() - : ArgsParserObjectType( "FixedPoint", argsspecFixedPoint, 2 ) -{ -} - -FixedPointType::~FixedPointType() -{ -} - -ObjectImp* FixedPointType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - double a = static_cast( parents[0] )->data(); - double b = static_cast( parents[1] )->data(); - - return new PointImp( Coordinate( a, b ) ); -} - -static const ArgsParser::spec argsspecRelativePoint[] = -{ - { DoubleImp::stype(), "relative-x", "SHOULD NOT BE SEEN", false }, - { DoubleImp::stype(), "relative-y", "SHOULD NOT BE SEEN", false }, - { ObjectImp::stype(), "object", "SHOULD NOT BE SEEN", false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( RelativePointType ) - -RelativePointType::RelativePointType() - : ArgsParserObjectType( "RelativePoint", argsspecRelativePoint, 3 ) -{ -} - -RelativePointType::~RelativePointType() -{ -} - -ObjectImp* RelativePointType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - if ( ! parents[2]->attachPoint().valid() ) return new InvalidImp; - - Coordinate reference = static_cast( parents[2] )->attachPoint(); - double a = static_cast( parents[0] )->data(); - double b = static_cast( parents[1] )->data(); - - return new PointImp( reference + Coordinate( a, b ) ); -} - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CursorPointType ) - -CursorPointType::CursorPointType() - : ObjectType( "CursorPoint" ) -{ -} - -CursorPointType::~CursorPointType() -{ -} - -const CursorPointType* CursorPointType::instance() -{ - static const CursorPointType t; - return &t; -} - -ObjectImp* CursorPointType::calc( const Args& parents, const KigDocument& ) const -{ - assert ( parents[0]->inherits( DoubleImp::stype() ) ); - assert ( parents[1]->inherits( DoubleImp::stype() ) ); - double a = static_cast( parents[0] )->data(); - double b = static_cast( parents[1] )->data(); - - return new BogusPointImp( Coordinate( a, b ) ); -} - -const ObjectImpType* CursorPointType::resultId() const -{ - return BogusPointImp::stype(); -} - -ObjectImp* ConstrainedPointType::calc( const Args& parents, const KigDocument& doc ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - double param = static_cast( parents[0] )->data(); - const Coordinate nc = static_cast( parents[1] )->getPoint( param, doc ); - if ( nc.valid() ) return new PointImp( nc ); - else return new InvalidImp; -} - -const ArgsParser::spec argsspecConstrainedPoint[] = -{ - { DoubleImp::stype(), "parameter", "SHOULD NOT BE SEEN", false }, - { CurveImp::stype(), "Constrain the point to this curve", "SHOULD NOT BE SEEN", true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConstrainedPointType ) - -ConstrainedPointType::ConstrainedPointType() - : ArgsParserObjectType( "ConstrainedPoint", argsspecConstrainedPoint, 2 ) -{ -} - -ConstrainedPointType::~ConstrainedPointType() -{ -} - -void FixedPointType::move( ObjectTypeCalcer& ourobj, const Coordinate& to, - const KigDocument& ) const -{ - // fetch the old coord..; - std::vector pa = ourobj.parents(); - assert( margsparser.checkArgs( pa ) ); - assert( dynamic_cast( pa.front() ) ); - assert( dynamic_cast( pa.back() ) ); - - ObjectConstCalcer* ox = static_cast( pa.front() ); - ObjectConstCalcer* oy = static_cast( pa.back() ); - - ox->setImp( new DoubleImp( to.x ) ); - oy->setImp( new DoubleImp( to.y ) ); -} - -void RelativePointType::move( ObjectTypeCalcer& ourobj, const Coordinate& to, - const KigDocument& ) const -{ - // fetch the attach point..; - // this routine is tightly paired with what moveReferencePoint returns! - // right now moveReferencePoint always returns the origin - std::vector pa = ourobj.parents(); - assert( margsparser.checkArgs( pa ) ); - assert( dynamic_cast( pa[0] ) ); - assert( dynamic_cast( pa[1] ) ); - - ObjectConstCalcer* ox = static_cast( pa[0] ); - ObjectConstCalcer* oy = static_cast( pa[1] ); - ObjectCalcer* ob = static_cast( pa[2] ); - - Coordinate attach = ob->imp()->attachPoint(); - ox->setImp( new DoubleImp( to.x - attach.x ) ); - oy->setImp( new DoubleImp( to.y - attach.y ) ); -} - -void CursorPointType::move( ObjectTypeCalcer& ourobj, const Coordinate& to, - const KigDocument& ) const -{ - // fetch the old coord..; - - std::vector pa = ourobj.parents(); - assert( pa.size() == 2 ); - assert( dynamic_cast( pa.front() ) ); - assert( dynamic_cast( pa.back() ) ); - - ObjectConstCalcer* ox = static_cast( pa.front() ); - ObjectConstCalcer* oy = static_cast( pa.back() ); - - ox->setImp( new DoubleImp( to.x ) ); - oy->setImp( new DoubleImp( to.y ) ); -} - -void ConstrainedPointType::move( ObjectTypeCalcer& ourobj, const Coordinate& to, - const KigDocument& d ) const -{ - // fetch the CurveImp.. - std::vector parents = ourobj.parents(); - assert( margsparser.checkArgs( parents ) ); - - assert( dynamic_cast( parents[0] ) ); - ObjectConstCalcer* paramo = static_cast( parents[0] ); - const CurveImp* ci = static_cast( parents[1]->imp() ); - - // fetch the new param.. - const double np = ci->getParam( to, d ); - - paramo->setImp( new DoubleImp( np ) ); -} - -bool ConstrainedPointType::canMove( const ObjectTypeCalcer& ) const -{ - return true; -} - -bool ConstrainedPointType::isFreelyTranslatable( const ObjectTypeCalcer& ) const -{ - return false; -} - -bool FixedPointType::canMove( const ObjectTypeCalcer& ) const -{ - return true; -} - -bool FixedPointType::isFreelyTranslatable( const ObjectTypeCalcer& ) const -{ - return true; -} - -bool RelativePointType::canMove( const ObjectTypeCalcer& ) const -{ - return true; -} - -bool RelativePointType::isFreelyTranslatable( const ObjectTypeCalcer& ) const -{ - return true; -} - -bool CursorPointType::canMove( const ObjectTypeCalcer& ) const -{ - return true; -} - -static const ArgsParser::spec argsspecMidPoint[] = -{ - { PointImp::stype(), I18N_NOOP( "Construct the midpoint of this point and another point" ), - I18N_NOOP( "Select the first of the two points of which you want to construct the midpoint..." ), false }, - { PointImp::stype(), I18N_NOOP( "Construct the midpoint of this point and another point" ), - I18N_NOOP( "Select the other of the two points of which you want to construct the midpoint..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( MidPointType ) - -MidPointType::MidPointType() - : ObjectABType( "MidPoint", argsspecMidPoint, 2 ) -{ -} - -MidPointType::~MidPointType() -{ -} - -const MidPointType* MidPointType::instance() -{ - static const MidPointType t; - return &t; -} - -ObjectImp* MidPointType::calc( const Coordinate& a, const Coordinate& b ) const -{ - return new PointImp( ( a + b ) / 2 ); -} - -bool ConstrainedPointType::inherits( int type ) const -{ - return type == ID_ConstrainedPointType; -} - -const ConstrainedPointType* ConstrainedPointType::instance() -{ - static const ConstrainedPointType t; - return &t; -} - -bool FixedPointType::inherits( int type ) const -{ - return type == ID_FixedPointType; -} - -const FixedPointType* FixedPointType::instance() -{ - static const FixedPointType t; - return &t; -} - -const ObjectImpType* FixedPointType::resultId() const -{ - return PointImp::stype(); -} - -const RelativePointType* RelativePointType::instance() -{ - static const RelativePointType t; - return &t; -} - -const ObjectImpType* RelativePointType::resultId() const -{ - return PointImp::stype(); -} - -const ObjectImpType* ConstrainedPointType::resultId() const -{ - return PointImp::stype(); -} - -const ObjectImpType* CursorPointType::impRequirement( const ObjectImp* o, const Args& ) const -{ - if ( o->inherits( DoubleImp::stype() ) ) - return DoubleImp::stype(); - - if ( o->inherits( PointImp::stype() ) ) - return PointImp::stype(); - - return 0; -} - -bool CursorPointType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const -{ - return false; -} - -std::vector CursorPointType::sortArgs( const std::vector& args ) const -{ - return args; -} - -Args CursorPointType::sortArgs( const Args& args ) const -{ - return args; -} - -const ObjectImpType* MidPointType::resultId() const -{ - return PointImp::stype(); -} - -TQStringList FixedPointType::specialActions() const -{ - TQStringList ret; - ret << i18n( "Set &Coordinate..." ); - ret << i18n( "Redefine" ); - return ret; -} - -TQStringList ConstrainedPointType::specialActions() const -{ - TQStringList ret; - ret << i18n( "Set &Parameter..." ); - ret << i18n( "Redefine" ); - return ret; -} - -static void redefinePoint( ObjectHolder* o, KigPart& d, KigWidget& w ) -{ - PointRedefineMode pm( o, d, w ); - d.runMode( &pm ); -} - -void FixedPointType::executeAction( - int i, ObjectHolder& oh, ObjectTypeCalcer& o, - KigPart& d, KigWidget& w, NormalMode& ) const -{ - switch( i ) - { - case 0: - { - bool ok = true; - assert ( o.imp()->inherits( PointImp::stype() ) ); - Coordinate oldc = static_cast( o.imp() )->coordinate(); - KigInputDialog::getCoordinate( - i18n( "Set Coordinate" ), - i18n( "Enter the new coordinate." ) + TQString::fromLatin1( "
" ) + - d.document().coordinateSystem().coordinateFormatNoticeMarkup(), - &w, &ok, d.document(), &oldc ); - if ( ! ok ) break; - - MonitorDataObjects mon( getAllParents( &o ) ); - o.move( oldc, d.document() ); - KigCommand* kc = new KigCommand( d, PointImp::stype()->moveAStatement() ); - mon.finish( kc ); - - d.history()->addCommand( kc ); - break; - }; - case 1: - redefinePoint( &oh, d, w ); - break; - default: - assert( false ); - }; -} - -void ConstrainedPointType::executeAction( - int i, ObjectHolder& oh, ObjectTypeCalcer& o, KigPart& d, KigWidget& w, - NormalMode& ) const -{ - switch( i ) - { - case 1: - redefinePoint( &oh, d, w ); - break; - case 0: - { - std::vector parents = o.parents(); - assert( dynamic_cast( parents[0] ) && - parents[0]->imp()->inherits( DoubleImp::stype() ) ); - - ObjectConstCalcer* po = static_cast( parents[0] ); - double oldp = static_cast( po->imp() )->data(); - - bool ok = true; - double newp = getDoubleFromUser( - i18n( "Set Point Parameter" ), i18n( "Choose the new parameter: " ), - oldp, &w, &ok, 0, 1, 4 ); - if ( ! ok ) return; - - MonitorDataObjects mon( parents ); - po->setImp( new DoubleImp( newp ) ); - KigCommand* kc = new KigCommand( d, i18n( "Change Parameter of Constrained Point" ) ); - mon.finish( kc ); - d.history()->addCommand( kc ); - break; - }; - default: - assert( false ); - }; -} - -const Coordinate FixedPointType::moveReferencePoint( const ObjectTypeCalcer& ourobj ) const -{ - assert( ourobj.imp()->inherits( PointImp::stype() ) ); - return static_cast( ourobj.imp() )->coordinate(); -} - -const Coordinate RelativePointType::moveReferencePoint( const ObjectTypeCalcer& ourobj ) const -{ - assert( ourobj.imp()->inherits( PointImp::stype() ) ); -// return static_cast( ourobj.imp() )->coordinate(); - return Coordinate( 0., 0. ); -} - -const Coordinate ConstrainedPointType::moveReferencePoint( const ObjectTypeCalcer& ourobj ) const -{ - assert( ourobj.imp()->inherits( PointImp::stype() ) ); - return static_cast( ourobj.imp() )->coordinate(); -} - -std::vector FixedPointType::movableParents( const ObjectTypeCalcer& ourobj ) const -{ - return ourobj.parents(); -} - -std::vector RelativePointType::movableParents( const ObjectTypeCalcer& ourobj ) const -{ - std::vector ret; - ret.push_back( ourobj.parents()[0] ); - ret.push_back( ourobj.parents()[1] ); - return ret; -} - -std::vector ConstrainedPointType::movableParents( const ObjectTypeCalcer& ourobj ) const -{ - std::vector ret; - ret.push_back( ourobj.parents()[0] ); - return ret; -} - -/* ----------------- Transport of measure ------------------------------ */ - -ObjectImp* MeasureTransportType::calc( const Args& parents, const KigDocument& doc ) const -{ - double measure; - - if ( parents.size() != 3 ) return new InvalidImp; - - if ( parents[0]->inherits (SegmentImp::stype()) ) - { - const SegmentImp* s = static_cast( parents[0] ); - measure = s->length(); - } else if ( parents[0]->inherits (ArcImp::stype()) ) - { - const ArcImp* s = static_cast( parents[0] ); - measure = s->radius()*s->angle(); - } else return new InvalidImp; - - const Coordinate& p = static_cast( parents[2] )->coordinate(); - if ( parents[1]->inherits (LineImp::stype()) ) - { - const LineImp* c = static_cast( parents[1] ); - - if ( !c->containsPoint( p, doc ) ) - return new InvalidImp; - - const LineData line = c->data(); - const Coordinate dir = line.dir()/line.length(); - const Coordinate nc = p + measure*dir; - - if ( nc.valid() ) return new PointImp( nc ); - else return new InvalidImp; - } else if ( parents[1]->inherits (CircleImp::stype()) ) - { - const CircleImp* c = static_cast( parents[1] ); - if ( !c->containsPoint( p, doc ) ) - return new InvalidImp; - - double param = c->getParam( p, doc ); - measure /= 2*c->radius()*M_PI; - param += measure; - while (param > 1) param -= 1; - - const Coordinate nc = c->getPoint( param, doc ); - if ( nc.valid() ) return new PointImp( nc ); - else return new InvalidImp; - } - - return new InvalidImp; -} - -// I18N_NOOP( "Select the segment/arc to transport on the circle/line..." ), false }, -// I18N_NOOP( "Select the circle/line on which to transport a measure..." ), true }, -// I18N_NOOP( "Select a point on the circle/line..." ), false } - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( MeasureTransportType ) - -MeasureTransportType::MeasureTransportType() - : ObjectType( "TransportOfMeasure" ) -{ -} - -MeasureTransportType::~MeasureTransportType() -{ -} - -const MeasureTransportType* MeasureTransportType::instance() -{ - static const MeasureTransportType t; - return &t; -} - -const ObjectImpType* MeasureTransportType::resultId() const -{ - return PointImp::stype(); -} - -const ObjectImpType* MeasureTransportType::impRequirement( const ObjectImp* obj, const Args& ) const -{ - if ( obj->inherits( PointImp::stype () ) ) - return PointImp::stype (); - - if ( obj->inherits( LineImp::stype () ) ) - return LineImp::stype (); - - if ( obj->inherits( CircleImp::stype () ) ) - return CircleImp::stype (); - - if ( obj->inherits( SegmentImp::stype () ) ) - return SegmentImp::stype (); - - if ( obj->inherits( ArcImp::stype () ) ) - return ArcImp::stype (); - - return 0; -} - -bool MeasureTransportType::isDefinedOnOrThrough( const ObjectImp* o, const Args& ) const -{ - if ( o->inherits( LineImp::stype() ) ) return true; - if ( o->inherits( CircleImp::stype() ) ) return true; - return false; -} - -std::vector MeasureTransportType::sortArgs( const std::vector& args ) const -{ - return args; /* should already be in correct order */ -} - -Args MeasureTransportType::sortArgs( const Args& args ) const -{ - return args; -} - -/* - transport of measure (old, for compatibility with prev. kig files) - */ - -ObjectImp* MeasureTransportTypeOld::calc( const Args& parents, const KigDocument& doc ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - const CircleImp* c = static_cast( parents[0] ); - const Coordinate& p = static_cast( parents[1] )->coordinate(); - - if ( !c->containsPoint( p, doc ) ) - return new InvalidImp; - - const SegmentImp* s = static_cast( parents[2] ); - double param = c->getParam( p, doc ); - double measure = s->length(); - measure /= 2*c->radius()*M_PI; - param += measure; - while (param > 1) param -= 1; - - const Coordinate nc = c->getPoint( param, doc ); - if ( nc.valid() ) return new PointImp( nc ); - else return new InvalidImp; -} - -static const ArgsParser::spec argsspecMeasureTransportOld[] = -{ - { CircleImp::stype(), "Transport a measure on this circle", - I18N_NOOP( "Select the circle on which to transport a measure..." ), true }, - { PointImp::stype(), "Start transport from this point of the circle", - I18N_NOOP( "Select a point on the circle..." ), false }, - { SegmentImp::stype(), "Segment to transport", - I18N_NOOP( "Select the segment to transport on the circle..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( MeasureTransportTypeOld ) - -MeasureTransportTypeOld::MeasureTransportTypeOld() - : ArgsParserObjectType( "MeasureTransport", argsspecMeasureTransportOld, 3 ) -{ -} - -MeasureTransportTypeOld::~MeasureTransportTypeOld() -{ -} - -const MeasureTransportTypeOld* MeasureTransportTypeOld::instance() -{ - static const MeasureTransportTypeOld t; - return &t; -} - -const ObjectImpType* MeasureTransportTypeOld::resultId() const -{ - return PointImp::stype(); -} - -/* ----------------- end transport of measure ------------------------- */ - diff --git a/kig/objects/point_type.cpp b/kig/objects/point_type.cpp new file mode 100644 index 00000000..59f495b9 --- /dev/null +++ b/kig/objects/point_type.cpp @@ -0,0 +1,665 @@ +// 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 "point_type.h" + +#include "point_imp.h" +#include "curve_imp.h" +#include "line_imp.h" +#include "other_imp.h" +#include "bogus_imp.h" + +#include "../modes/moving.h" +#include "../misc/coordinate_system.h" +#include "../misc/common.h" +#include "../misc/calcpaths.h" +#include "../misc/kiginputdialog.h" +#include "../kig/kig_part.h" +#include "../kig/kig_document.h" +#include "../kig/kig_view.h" +#include "../kig/kig_commands.h" + +#include + +static const ArgsParser::spec argsspecFixedPoint[] = +{ + { DoubleImp::stype(), "x", "SHOULD NOT BE SEEN", false }, + { DoubleImp::stype(), "y", "SHOULD NOT BE SEEN", false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( FixedPointType ) + +FixedPointType::FixedPointType() + : ArgsParserObjectType( "FixedPoint", argsspecFixedPoint, 2 ) +{ +} + +FixedPointType::~FixedPointType() +{ +} + +ObjectImp* FixedPointType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + double a = static_cast( parents[0] )->data(); + double b = static_cast( parents[1] )->data(); + + return new PointImp( Coordinate( a, b ) ); +} + +static const ArgsParser::spec argsspecRelativePoint[] = +{ + { DoubleImp::stype(), "relative-x", "SHOULD NOT BE SEEN", false }, + { DoubleImp::stype(), "relative-y", "SHOULD NOT BE SEEN", false }, + { ObjectImp::stype(), "object", "SHOULD NOT BE SEEN", false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( RelativePointType ) + +RelativePointType::RelativePointType() + : ArgsParserObjectType( "RelativePoint", argsspecRelativePoint, 3 ) +{ +} + +RelativePointType::~RelativePointType() +{ +} + +ObjectImp* RelativePointType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + if ( ! parents[2]->attachPoint().valid() ) return new InvalidImp; + + Coordinate reference = static_cast( parents[2] )->attachPoint(); + double a = static_cast( parents[0] )->data(); + double b = static_cast( parents[1] )->data(); + + return new PointImp( reference + Coordinate( a, b ) ); +} + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CursorPointType ) + +CursorPointType::CursorPointType() + : ObjectType( "CursorPoint" ) +{ +} + +CursorPointType::~CursorPointType() +{ +} + +const CursorPointType* CursorPointType::instance() +{ + static const CursorPointType t; + return &t; +} + +ObjectImp* CursorPointType::calc( const Args& parents, const KigDocument& ) const +{ + assert ( parents[0]->inherits( DoubleImp::stype() ) ); + assert ( parents[1]->inherits( DoubleImp::stype() ) ); + double a = static_cast( parents[0] )->data(); + double b = static_cast( parents[1] )->data(); + + return new BogusPointImp( Coordinate( a, b ) ); +} + +const ObjectImpType* CursorPointType::resultId() const +{ + return BogusPointImp::stype(); +} + +ObjectImp* ConstrainedPointType::calc( const Args& parents, const KigDocument& doc ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + double param = static_cast( parents[0] )->data(); + const Coordinate nc = static_cast( parents[1] )->getPoint( param, doc ); + if ( nc.valid() ) return new PointImp( nc ); + else return new InvalidImp; +} + +const ArgsParser::spec argsspecConstrainedPoint[] = +{ + { DoubleImp::stype(), "parameter", "SHOULD NOT BE SEEN", false }, + { CurveImp::stype(), "Constrain the point to this curve", "SHOULD NOT BE SEEN", true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConstrainedPointType ) + +ConstrainedPointType::ConstrainedPointType() + : ArgsParserObjectType( "ConstrainedPoint", argsspecConstrainedPoint, 2 ) +{ +} + +ConstrainedPointType::~ConstrainedPointType() +{ +} + +void FixedPointType::move( ObjectTypeCalcer& ourobj, const Coordinate& to, + const KigDocument& ) const +{ + // fetch the old coord..; + std::vector pa = ourobj.parents(); + assert( margsparser.checkArgs( pa ) ); + assert( dynamic_cast( pa.front() ) ); + assert( dynamic_cast( pa.back() ) ); + + ObjectConstCalcer* ox = static_cast( pa.front() ); + ObjectConstCalcer* oy = static_cast( pa.back() ); + + ox->setImp( new DoubleImp( to.x ) ); + oy->setImp( new DoubleImp( to.y ) ); +} + +void RelativePointType::move( ObjectTypeCalcer& ourobj, const Coordinate& to, + const KigDocument& ) const +{ + // fetch the attach point..; + // this routine is tightly paired with what moveReferencePoint returns! + // right now moveReferencePoint always returns the origin + std::vector pa = ourobj.parents(); + assert( margsparser.checkArgs( pa ) ); + assert( dynamic_cast( pa[0] ) ); + assert( dynamic_cast( pa[1] ) ); + + ObjectConstCalcer* ox = static_cast( pa[0] ); + ObjectConstCalcer* oy = static_cast( pa[1] ); + ObjectCalcer* ob = static_cast( pa[2] ); + + Coordinate attach = ob->imp()->attachPoint(); + ox->setImp( new DoubleImp( to.x - attach.x ) ); + oy->setImp( new DoubleImp( to.y - attach.y ) ); +} + +void CursorPointType::move( ObjectTypeCalcer& ourobj, const Coordinate& to, + const KigDocument& ) const +{ + // fetch the old coord..; + + std::vector pa = ourobj.parents(); + assert( pa.size() == 2 ); + assert( dynamic_cast( pa.front() ) ); + assert( dynamic_cast( pa.back() ) ); + + ObjectConstCalcer* ox = static_cast( pa.front() ); + ObjectConstCalcer* oy = static_cast( pa.back() ); + + ox->setImp( new DoubleImp( to.x ) ); + oy->setImp( new DoubleImp( to.y ) ); +} + +void ConstrainedPointType::move( ObjectTypeCalcer& ourobj, const Coordinate& to, + const KigDocument& d ) const +{ + // fetch the CurveImp.. + std::vector parents = ourobj.parents(); + assert( margsparser.checkArgs( parents ) ); + + assert( dynamic_cast( parents[0] ) ); + ObjectConstCalcer* paramo = static_cast( parents[0] ); + const CurveImp* ci = static_cast( parents[1]->imp() ); + + // fetch the new param.. + const double np = ci->getParam( to, d ); + + paramo->setImp( new DoubleImp( np ) ); +} + +bool ConstrainedPointType::canMove( const ObjectTypeCalcer& ) const +{ + return true; +} + +bool ConstrainedPointType::isFreelyTranslatable( const ObjectTypeCalcer& ) const +{ + return false; +} + +bool FixedPointType::canMove( const ObjectTypeCalcer& ) const +{ + return true; +} + +bool FixedPointType::isFreelyTranslatable( const ObjectTypeCalcer& ) const +{ + return true; +} + +bool RelativePointType::canMove( const ObjectTypeCalcer& ) const +{ + return true; +} + +bool RelativePointType::isFreelyTranslatable( const ObjectTypeCalcer& ) const +{ + return true; +} + +bool CursorPointType::canMove( const ObjectTypeCalcer& ) const +{ + return true; +} + +static const ArgsParser::spec argsspecMidPoint[] = +{ + { PointImp::stype(), I18N_NOOP( "Construct the midpoint of this point and another point" ), + I18N_NOOP( "Select the first of the two points of which you want to construct the midpoint..." ), false }, + { PointImp::stype(), I18N_NOOP( "Construct the midpoint of this point and another point" ), + I18N_NOOP( "Select the other of the two points of which you want to construct the midpoint..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( MidPointType ) + +MidPointType::MidPointType() + : ObjectABType( "MidPoint", argsspecMidPoint, 2 ) +{ +} + +MidPointType::~MidPointType() +{ +} + +const MidPointType* MidPointType::instance() +{ + static const MidPointType t; + return &t; +} + +ObjectImp* MidPointType::calc( const Coordinate& a, const Coordinate& b ) const +{ + return new PointImp( ( a + b ) / 2 ); +} + +bool ConstrainedPointType::inherits( int type ) const +{ + return type == ID_ConstrainedPointType; +} + +const ConstrainedPointType* ConstrainedPointType::instance() +{ + static const ConstrainedPointType t; + return &t; +} + +bool FixedPointType::inherits( int type ) const +{ + return type == ID_FixedPointType; +} + +const FixedPointType* FixedPointType::instance() +{ + static const FixedPointType t; + return &t; +} + +const ObjectImpType* FixedPointType::resultId() const +{ + return PointImp::stype(); +} + +const RelativePointType* RelativePointType::instance() +{ + static const RelativePointType t; + return &t; +} + +const ObjectImpType* RelativePointType::resultId() const +{ + return PointImp::stype(); +} + +const ObjectImpType* ConstrainedPointType::resultId() const +{ + return PointImp::stype(); +} + +const ObjectImpType* CursorPointType::impRequirement( const ObjectImp* o, const Args& ) const +{ + if ( o->inherits( DoubleImp::stype() ) ) + return DoubleImp::stype(); + + if ( o->inherits( PointImp::stype() ) ) + return PointImp::stype(); + + return 0; +} + +bool CursorPointType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const +{ + return false; +} + +std::vector CursorPointType::sortArgs( const std::vector& args ) const +{ + return args; +} + +Args CursorPointType::sortArgs( const Args& args ) const +{ + return args; +} + +const ObjectImpType* MidPointType::resultId() const +{ + return PointImp::stype(); +} + +TQStringList FixedPointType::specialActions() const +{ + TQStringList ret; + ret << i18n( "Set &Coordinate..." ); + ret << i18n( "Redefine" ); + return ret; +} + +TQStringList ConstrainedPointType::specialActions() const +{ + TQStringList ret; + ret << i18n( "Set &Parameter..." ); + ret << i18n( "Redefine" ); + return ret; +} + +static void redefinePoint( ObjectHolder* o, KigPart& d, KigWidget& w ) +{ + PointRedefineMode pm( o, d, w ); + d.runMode( &pm ); +} + +void FixedPointType::executeAction( + int i, ObjectHolder& oh, ObjectTypeCalcer& o, + KigPart& d, KigWidget& w, NormalMode& ) const +{ + switch( i ) + { + case 0: + { + bool ok = true; + assert ( o.imp()->inherits( PointImp::stype() ) ); + Coordinate oldc = static_cast( o.imp() )->coordinate(); + KigInputDialog::getCoordinate( + i18n( "Set Coordinate" ), + i18n( "Enter the new coordinate." ) + TQString::fromLatin1( "
" ) + + d.document().coordinateSystem().coordinateFormatNoticeMarkup(), + &w, &ok, d.document(), &oldc ); + if ( ! ok ) break; + + MonitorDataObjects mon( getAllParents( &o ) ); + o.move( oldc, d.document() ); + KigCommand* kc = new KigCommand( d, PointImp::stype()->moveAStatement() ); + mon.finish( kc ); + + d.history()->addCommand( kc ); + break; + }; + case 1: + redefinePoint( &oh, d, w ); + break; + default: + assert( false ); + }; +} + +void ConstrainedPointType::executeAction( + int i, ObjectHolder& oh, ObjectTypeCalcer& o, KigPart& d, KigWidget& w, + NormalMode& ) const +{ + switch( i ) + { + case 1: + redefinePoint( &oh, d, w ); + break; + case 0: + { + std::vector parents = o.parents(); + assert( dynamic_cast( parents[0] ) && + parents[0]->imp()->inherits( DoubleImp::stype() ) ); + + ObjectConstCalcer* po = static_cast( parents[0] ); + double oldp = static_cast( po->imp() )->data(); + + bool ok = true; + double newp = getDoubleFromUser( + i18n( "Set Point Parameter" ), i18n( "Choose the new parameter: " ), + oldp, &w, &ok, 0, 1, 4 ); + if ( ! ok ) return; + + MonitorDataObjects mon( parents ); + po->setImp( new DoubleImp( newp ) ); + KigCommand* kc = new KigCommand( d, i18n( "Change Parameter of Constrained Point" ) ); + mon.finish( kc ); + d.history()->addCommand( kc ); + break; + }; + default: + assert( false ); + }; +} + +const Coordinate FixedPointType::moveReferencePoint( const ObjectTypeCalcer& ourobj ) const +{ + assert( ourobj.imp()->inherits( PointImp::stype() ) ); + return static_cast( ourobj.imp() )->coordinate(); +} + +const Coordinate RelativePointType::moveReferencePoint( const ObjectTypeCalcer& ourobj ) const +{ + assert( ourobj.imp()->inherits( PointImp::stype() ) ); +// return static_cast( ourobj.imp() )->coordinate(); + return Coordinate( 0., 0. ); +} + +const Coordinate ConstrainedPointType::moveReferencePoint( const ObjectTypeCalcer& ourobj ) const +{ + assert( ourobj.imp()->inherits( PointImp::stype() ) ); + return static_cast( ourobj.imp() )->coordinate(); +} + +std::vector FixedPointType::movableParents( const ObjectTypeCalcer& ourobj ) const +{ + return ourobj.parents(); +} + +std::vector RelativePointType::movableParents( const ObjectTypeCalcer& ourobj ) const +{ + std::vector ret; + ret.push_back( ourobj.parents()[0] ); + ret.push_back( ourobj.parents()[1] ); + return ret; +} + +std::vector ConstrainedPointType::movableParents( const ObjectTypeCalcer& ourobj ) const +{ + std::vector ret; + ret.push_back( ourobj.parents()[0] ); + return ret; +} + +/* ----------------- Transport of measure ------------------------------ */ + +ObjectImp* MeasureTransportType::calc( const Args& parents, const KigDocument& doc ) const +{ + double measure; + + if ( parents.size() != 3 ) return new InvalidImp; + + if ( parents[0]->inherits (SegmentImp::stype()) ) + { + const SegmentImp* s = static_cast( parents[0] ); + measure = s->length(); + } else if ( parents[0]->inherits (ArcImp::stype()) ) + { + const ArcImp* s = static_cast( parents[0] ); + measure = s->radius()*s->angle(); + } else return new InvalidImp; + + const Coordinate& p = static_cast( parents[2] )->coordinate(); + if ( parents[1]->inherits (LineImp::stype()) ) + { + const LineImp* c = static_cast( parents[1] ); + + if ( !c->containsPoint( p, doc ) ) + return new InvalidImp; + + const LineData line = c->data(); + const Coordinate dir = line.dir()/line.length(); + const Coordinate nc = p + measure*dir; + + if ( nc.valid() ) return new PointImp( nc ); + else return new InvalidImp; + } else if ( parents[1]->inherits (CircleImp::stype()) ) + { + const CircleImp* c = static_cast( parents[1] ); + if ( !c->containsPoint( p, doc ) ) + return new InvalidImp; + + double param = c->getParam( p, doc ); + measure /= 2*c->radius()*M_PI; + param += measure; + while (param > 1) param -= 1; + + const Coordinate nc = c->getPoint( param, doc ); + if ( nc.valid() ) return new PointImp( nc ); + else return new InvalidImp; + } + + return new InvalidImp; +} + +// I18N_NOOP( "Select the segment/arc to transport on the circle/line..." ), false }, +// I18N_NOOP( "Select the circle/line on which to transport a measure..." ), true }, +// I18N_NOOP( "Select a point on the circle/line..." ), false } + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( MeasureTransportType ) + +MeasureTransportType::MeasureTransportType() + : ObjectType( "TransportOfMeasure" ) +{ +} + +MeasureTransportType::~MeasureTransportType() +{ +} + +const MeasureTransportType* MeasureTransportType::instance() +{ + static const MeasureTransportType t; + return &t; +} + +const ObjectImpType* MeasureTransportType::resultId() const +{ + return PointImp::stype(); +} + +const ObjectImpType* MeasureTransportType::impRequirement( const ObjectImp* obj, const Args& ) const +{ + if ( obj->inherits( PointImp::stype () ) ) + return PointImp::stype (); + + if ( obj->inherits( LineImp::stype () ) ) + return LineImp::stype (); + + if ( obj->inherits( CircleImp::stype () ) ) + return CircleImp::stype (); + + if ( obj->inherits( SegmentImp::stype () ) ) + return SegmentImp::stype (); + + if ( obj->inherits( ArcImp::stype () ) ) + return ArcImp::stype (); + + return 0; +} + +bool MeasureTransportType::isDefinedOnOrThrough( const ObjectImp* o, const Args& ) const +{ + if ( o->inherits( LineImp::stype() ) ) return true; + if ( o->inherits( CircleImp::stype() ) ) return true; + return false; +} + +std::vector MeasureTransportType::sortArgs( const std::vector& args ) const +{ + return args; /* should already be in correct order */ +} + +Args MeasureTransportType::sortArgs( const Args& args ) const +{ + return args; +} + +/* - transport of measure (old, for compatibility with prev. kig files) - */ + +ObjectImp* MeasureTransportTypeOld::calc( const Args& parents, const KigDocument& doc ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + const CircleImp* c = static_cast( parents[0] ); + const Coordinate& p = static_cast( parents[1] )->coordinate(); + + if ( !c->containsPoint( p, doc ) ) + return new InvalidImp; + + const SegmentImp* s = static_cast( parents[2] ); + double param = c->getParam( p, doc ); + double measure = s->length(); + measure /= 2*c->radius()*M_PI; + param += measure; + while (param > 1) param -= 1; + + const Coordinate nc = c->getPoint( param, doc ); + if ( nc.valid() ) return new PointImp( nc ); + else return new InvalidImp; +} + +static const ArgsParser::spec argsspecMeasureTransportOld[] = +{ + { CircleImp::stype(), "Transport a measure on this circle", + I18N_NOOP( "Select the circle on which to transport a measure..." ), true }, + { PointImp::stype(), "Start transport from this point of the circle", + I18N_NOOP( "Select a point on the circle..." ), false }, + { SegmentImp::stype(), "Segment to transport", + I18N_NOOP( "Select the segment to transport on the circle..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( MeasureTransportTypeOld ) + +MeasureTransportTypeOld::MeasureTransportTypeOld() + : ArgsParserObjectType( "MeasureTransport", argsspecMeasureTransportOld, 3 ) +{ +} + +MeasureTransportTypeOld::~MeasureTransportTypeOld() +{ +} + +const MeasureTransportTypeOld* MeasureTransportTypeOld::instance() +{ + static const MeasureTransportTypeOld t; + return &t; +} + +const ObjectImpType* MeasureTransportTypeOld::resultId() const +{ + return PointImp::stype(); +} + +/* ----------------- end transport of measure ------------------------- */ + diff --git a/kig/objects/polygon_imp.cc b/kig/objects/polygon_imp.cc deleted file mode 100644 index 43ee16f9..00000000 --- a/kig/objects/polygon_imp.cc +++ /dev/null @@ -1,550 +0,0 @@ -// 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 "polygon_imp.h" - -#include "bogus_imp.h" -#include "line_imp.h" -#include "point_imp.h" - -#include "../misc/common.h" -#include "../misc/coordinate.h" -#include "../misc/kigpainter.h" -#include "../misc/kigtransform.h" - -#include "../kig/kig_document.h" -#include "../kig/kig_view.h" - -#include - -#include - -PolygonImp::PolygonImp( uint npoints, const std::vector& points, - const Coordinate& centerofmass ) - : mnpoints( npoints ), mpoints( points ), mcenterofmass( centerofmass ) -{ -// mpoints = points; -} - -PolygonImp::PolygonImp( const std::vector& points ) -{ - uint npoints = points.size(); - Coordinate centerofmassn = Coordinate( 0, 0 ); - - for ( uint i = 0; i < npoints; ++i ) - { - centerofmassn += points[i]; - } - mpoints = points; - mcenterofmass = centerofmassn/npoints; - mnpoints = npoints; -} - -PolygonImp::~PolygonImp() -{ -} - -Coordinate PolygonImp::attachPoint() const -{ - return mcenterofmass; -} - -ObjectImp* PolygonImp::transform( const Transformation& t ) const -{ -/*mp: - * any projective transformation makes sense for a polygon, - * since segments transform into segments (but see below...) - * of course regular polygons will no longer be - * regular if t is not homothetic. - * for projective transformations the polygon could transform to - * an unbounded nonconnected polygon; this happens if some side - * of the polygon crosses the critical line that maps to infinity - * this can be easily checked using the getProjectiveIndicator - * function - */ -// if ( ! t.isHomothetic() ) -// return new InvalidImp(); - - if ( ! t.isAffine() ) /* in this case we need a more extensive test */ - { - double maxp = -1.0; - double minp = 1.0; - for ( uint i = 0; i < mpoints.size(); ++i ) - { - double p = t.getProjectiveIndicator( mpoints[i] ); - if ( p > maxp ) maxp = p; - if ( p < minp ) minp = p; - } - if ( maxp > 0 && minp < 0 ) return new InvalidImp; - } - std::vector np; - for ( uint i = 0; i < mpoints.size(); ++i ) - { - Coordinate nc = t.apply( mpoints[i] ); - if ( !nc.valid() ) - return new InvalidImp; - np.push_back( nc ); - } - return new PolygonImp( np ); -} - -void PolygonImp::draw( KigPainter& p ) const -{ - p.drawPolygon( mpoints ); -} - -bool PolygonImp::isInPolygon( const Coordinate& p ) const -{ - // (algorithm sent to me by domi) - // We intersect with the horizontal ray from point to the right and - // count the number of intersections. That, along with some - // minor optimalisations of the intersection test.. - bool inside_flag = false; - double cx = p.x; - double cy = p.y; - - Coordinate prevpoint = mpoints.back(); - bool prevpointbelow = mpoints.back().y >= cy; - for ( uint i = 0; i < mpoints.size(); ++i ) - { - Coordinate point = mpoints[i]; - bool pointbelow = point.y >= cy; - if ( prevpointbelow != pointbelow ) - { - // possibility of intersection: points on different side from - // the X axis - //bool rightofpt = point.x >= cx; - // mp: we need to be a little bit more conservative here, in - // order to treat properly the case when the point is on the - // boundary - //if ( rightofpt == ( prevpoint.x >= cx ) ) - if ( ( point.x - cx )*(prevpoint.x - cx ) > 0 ) - { - // points on same side of Y axis -> easy to test intersection - // intersection iff one point to the right of c - if ( point.x >= cx ) - inside_flag = !inside_flag; - } - else - { - // points on different sides of Y axis -> we need to calculate - // the intersection. - // mp: we want to check if the point is on the boundary, and - // return false in such case - double num = ( point.y - cy )*( prevpoint.x - point.x ); - double den = prevpoint.y - point.y; - if ( num == den*( point.x - cx ) ) return false; - if ( num/den <= point.x - cx ) - inside_flag = !inside_flag; - } - } - prevpoint = point; - prevpointbelow = pointbelow; - } - return inside_flag; -} -#define selectpolygonwithinside 1 -#ifdef selectpolygonwithinside -bool PolygonImp::contains( const Coordinate& p, int, const KigWidget& ) const -{ - return isInPolygon( p ); -} -#else -bool PolygonImp::contains( const Coordinate& p, int width, const KigWidget& w ) const -{ - bool ret = false; - uint reduceddim = mpoints.size() - 1; - for ( uint i = 0; i < reduceddim; ++i ) - { - ret |= isOnSegment( p, mpoints[i], mpoints[i+1], w.screenInfo().normalMiss( width ) ); - } - ret |= isOnSegment( p, mpoints[reduceddim], mpoints[0], w.screenInfo().normalMiss( width ) ); - - return ret; -} -#endif - -bool PolygonImp::inRect( const Rect& r, int width, const KigWidget& w ) const -{ - bool ret = false; - uint reduceddim = mpoints.size() - 1; - for ( uint i = 0; i < reduceddim; ++i ) - { - SegmentImp* s = new SegmentImp( mpoints[i], mpoints[i+1] ); - ret |= lineInRect( r, mpoints[i], mpoints[i+1], width, s, w ); - delete s; - s = 0; - } - SegmentImp* t = new SegmentImp( mpoints[reduceddim], mpoints[0] ); - ret |= lineInRect( r, mpoints[reduceddim], mpoints[0], width, t, w ); - delete t; - t = 0; - - return ret; -} - -bool PolygonImp::valid() const -{ - return true; -} - -const uint PolygonImp::numberOfProperties() const -{ - return Parent::numberOfProperties() + 5; -} - -const QCStringList PolygonImp::propertiesInternalNames() const -{ - QCStringList l = Parent::propertiesInternalNames(); - l += "polygon-number-of-sides"; - l += "polygon-perimeter"; - l += "polygon-surface"; - l += "polygon-center-of-mass"; - l += "polygon-winding-number"; - assert( l.size() == PolygonImp::numberOfProperties() ); - return l; -} - -const QCStringList PolygonImp::properties() const -{ - QCStringList l = Parent::properties(); - l += I18N_NOOP( "Number of sides" ); - l += I18N_NOOP( "Perimeter" ); - l += I18N_NOOP( "Surface" ); - l += I18N_NOOP( "Center of Mass of the Vertices" ); - l += I18N_NOOP( "Winding Number" ); - assert( l.size() == PolygonImp::numberOfProperties() ); - return l; -} - -const ObjectImpType* PolygonImp::impRequirementForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::impRequirementForProperty( which ); - else return PolygonImp::stype(); -} - -const char* PolygonImp::iconForProperty( uint which ) const -{ - assert( which < PolygonImp::numberOfProperties() ); - if ( which < Parent::numberOfProperties() ) - return Parent::iconForProperty( which ); - else if ( which == Parent::numberOfProperties() ) - return "en"; // number of sides - else if ( which == Parent::numberOfProperties() + 1 ) - return "circumference"; // perimeter - else if ( which == Parent::numberOfProperties() + 2 ) - return "areaCircle"; // surface - else if ( which == Parent::numberOfProperties() + 3 ) - return "point"; // center of mass - else if ( which == Parent::numberOfProperties() + 4 ) - return "w"; // winding number - else assert( false ); - return ""; -} - -ObjectImp* PolygonImp::property( uint which, const KigDocument& w ) const -{ - assert( which < PolygonImp::numberOfProperties() ); - if ( which < Parent::numberOfProperties() ) - return Parent::property( which, w ); - else if ( which == Parent::numberOfProperties() ) - { - // number of points - return new IntImp( mnpoints ); - } - else if ( which == Parent::numberOfProperties() + 1) - { - double circumference = 0.; - // circumference - for ( uint i = 0; i < mpoints.size(); ++i ) - { - uint prev = ( i + mpoints.size() - 1 ) % mpoints.size(); - circumference += ( mpoints[i] - mpoints[prev] ).length(); - } - return new DoubleImp( circumference ); - } - else if ( which == Parent::numberOfProperties() + 2) - { - int wn = windingNumber (); // not able to compute area for such polygons... - if ( wn < 0 ) wn = -wn; - if ( wn != 1 ) return new InvalidImp; - double surface2 = 0.0; - Coordinate prevpoint = mpoints.back(); - for ( uint i = 0; i < mpoints.size(); ++i ) - { - Coordinate point = mpoints[i]; - surface2 += ( point.x - prevpoint.x ) * ( point.y + prevpoint.y ); - prevpoint = point; - } - return new DoubleImp( fabs( surface2 / 2 ) ); - } - else if ( which == Parent::numberOfProperties() + 3 ) - { - return new PointImp( mcenterofmass ); - } - else if ( which == Parent::numberOfProperties() + 4 ) - { - // winding number - return new IntImp( windingNumber() ); - } - else assert( false ); - return new InvalidImp; -} - -const std::vector PolygonImp::points() const -{ - std::vector np; - np.reserve( mpoints.size() ); - std::copy( mpoints.begin(), mpoints.end(), std::back_inserter( np ) ); - return np; -} - -const uint PolygonImp::npoints() const -{ - return mnpoints; -} - -PolygonImp* PolygonImp::copy() const -{ - return new PolygonImp( mpoints ); -} - -void PolygonImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -bool PolygonImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( PolygonImp::stype() ) && - static_cast( rhs ).points() == mpoints; -} - -const ObjectImpType* PolygonImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "polygon", - I18N_NOOP( "polygon" ), - I18N_NOOP( "Select this polygon" ), - I18N_NOOP( "Select polygon %1" ), - I18N_NOOP( "Remove a Polygon" ), - I18N_NOOP( "Add a Polygon" ), - I18N_NOOP( "Move a Polygon" ), - I18N_NOOP( "Attach to this polygon" ), - I18N_NOOP( "Show a Polygon" ), - I18N_NOOP( "Hide a Polygon" ) - ); - - return &t; -} - -const ObjectImpType* PolygonImp::stype3() -{ - static const ObjectImpType t3( - PolygonImp::stype(), "triangle", - I18N_NOOP( "triangle" ), - I18N_NOOP( "Select this triangle" ), - I18N_NOOP( "Select triangle %1" ), - I18N_NOOP( "Remove a Triangle" ), - I18N_NOOP( "Add a Triangle" ), - I18N_NOOP( "Move a Triangle" ), - I18N_NOOP( "Attach to this triangle" ), - I18N_NOOP( "Show a Triangle" ), - I18N_NOOP( "Hide a Triangle" ) - ); - - return &t3; -} - -const ObjectImpType* PolygonImp::stype4() -{ - static const ObjectImpType t4( - PolygonImp::stype(), "quadrilateral", - I18N_NOOP( "quadrilateral" ), - I18N_NOOP( "Select this quadrilateral" ), - I18N_NOOP( "Select quadrilateral %1" ), - I18N_NOOP( "Remove a Quadrilateral" ), - I18N_NOOP( "Add a Quadrilateral" ), - I18N_NOOP( "Move a Quadrilateral" ), - I18N_NOOP( "Attach to this quadrilateral" ), - I18N_NOOP( "Show a Quadrilateral" ), - I18N_NOOP( "Hide a Quadrilateral" ) - ); - - return &t4; -} - -const ObjectImpType* PolygonImp::type() const -{ - uint n = mpoints.size(); - - if ( n == 3 ) return PolygonImp::stype3(); - if ( n == 4 ) return PolygonImp::stype4(); - return PolygonImp::stype(); -} - -bool PolygonImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const -{ - assert( which < PolygonImp::numberOfProperties() ); - if ( which < Parent::numberOfProperties() ) - return Parent::isPropertyDefinedOnOrThroughThisImp( which ); - return false; -} - -Rect PolygonImp::surroundingRect() const -{ - Rect r( 0., 0., 0., 0. ); - for ( uint i = 0; i < mpoints.size(); ++i ) - { - r.setContains( mpoints[i] ); - } - return r; -} - -int PolygonImp::windingNumber() const -{ - /* - * this is defined as the sum of the external angles while at - * all vertices, then normalized by 2pi. The external angle - * is the angle we steer at each vertex while we walk along the - * boundary of the polygon. - * In the end we only need to count how many time we cross the (1,0) - * direction (positive x-axis) with a positive sign if we cross while - * steering left and a negative sign viceversa - */ - - int winding = 0; - uint npoints = mpoints.size(); - Coordinate prevside = mpoints[0] - mpoints[npoints-1]; - for ( uint i = 0; i < npoints; ++i ) - { - uint nexti = i + 1; - if ( nexti >= npoints ) nexti = 0; - Coordinate side = mpoints[nexti] - mpoints[i]; - double vecprod = side.x*prevside.y - side.y*prevside.x; - int steeringdir = ( vecprod > 0 ) ? 1 : -1; - if ( vecprod == 0.0 || side.y*prevside.y > 0 ) - { - prevside = side; - continue; // cannot cross the (1,0) direction - } - if ( side.y*steeringdir < 0 && prevside.y*steeringdir >= 0 ) - winding -= steeringdir; - prevside = side; - } - return winding; -} - -bool PolygonImp::isMonotoneSteering() const -{ - /* - * returns true if while walking along the boundary, - * steering is always in the same direction - */ - - uint npoints = mpoints.size(); - Coordinate prevside = mpoints[0] - mpoints[npoints-1]; - int prevsteeringdir = 0; - for ( uint i = 0; i < npoints; ++i ) - { - uint nexti = i + 1; - if ( nexti >= npoints ) nexti = 0; - Coordinate side = mpoints[nexti] - mpoints[i]; - double vecprod = side.x*prevside.y - side.y*prevside.x; - int steeringdir = ( vecprod > 0 ) ? 1 : -1; - if ( vecprod == 0.0 ) - { - prevside = side; - continue; // going straight - } - if ( prevsteeringdir*steeringdir < 0 ) return false; - prevside = side; - prevsteeringdir = steeringdir; - } - return true; -} - -bool PolygonImp::isConvex() const -{ - if ( ! isMonotoneSteering() ) return false; - int winding = windingNumber(); - if ( winding < 0 ) winding = -winding; - assert ( winding > 0 ); - return winding == 1; -} - -std::vector computeConvexHull( const std::vector& points ) -{ - /* - * compute the convex hull of the set of points, the resulting list - * is the vertices of the resulting polygon listed in a counter clockwise - * order. This algorithm is on order n^2, probably suboptimal, but - * we don't expect to have large values for n. - */ - - if ( points.size() < 3 ) return points; - std::vector worklist = points; - std::vector result; - - double ymin = worklist[0].y; - uint imin = 0; - for ( uint i = 1; i < worklist.size(); ++i ) - { - if ( worklist[i].y < ymin ) - { - ymin = worklist[i].y; - imin = i; - } - } - - // worklist[imin] is definitely on the convex hull, let's start from there - result.push_back( worklist[imin] ); - Coordinate startpoint = worklist[imin]; - Coordinate apoint = worklist[imin]; - double aangle = 0.0; - - while ( ! worklist.empty() ) - { - int besti = -1; - double anglemin = 10000.0; - for ( uint i = 0; i < worklist.size(); ++i ) - { - if ( worklist[i] == apoint ) continue; - Coordinate v = worklist[i] - apoint; - double angle = std::atan2( v.y, v.x ); - while ( angle < aangle ) angle += 2*M_PI; - if ( angle < anglemin ) - { // found a better point - besti = i; - anglemin = angle; - } - } - - if ( besti < 0 ) return result; // this happens, e.g. if all points coincide - apoint = worklist[besti]; - aangle = anglemin; - if ( apoint == startpoint ) - { - return result; - } - result.push_back( apoint ); - worklist.erase( worklist.begin() + besti, worklist.begin() + besti + 1 ); - } - assert( false ); - return result; -} diff --git a/kig/objects/polygon_imp.cpp b/kig/objects/polygon_imp.cpp new file mode 100644 index 00000000..43ee16f9 --- /dev/null +++ b/kig/objects/polygon_imp.cpp @@ -0,0 +1,550 @@ +// 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 "polygon_imp.h" + +#include "bogus_imp.h" +#include "line_imp.h" +#include "point_imp.h" + +#include "../misc/common.h" +#include "../misc/coordinate.h" +#include "../misc/kigpainter.h" +#include "../misc/kigtransform.h" + +#include "../kig/kig_document.h" +#include "../kig/kig_view.h" + +#include + +#include + +PolygonImp::PolygonImp( uint npoints, const std::vector& points, + const Coordinate& centerofmass ) + : mnpoints( npoints ), mpoints( points ), mcenterofmass( centerofmass ) +{ +// mpoints = points; +} + +PolygonImp::PolygonImp( const std::vector& points ) +{ + uint npoints = points.size(); + Coordinate centerofmassn = Coordinate( 0, 0 ); + + for ( uint i = 0; i < npoints; ++i ) + { + centerofmassn += points[i]; + } + mpoints = points; + mcenterofmass = centerofmassn/npoints; + mnpoints = npoints; +} + +PolygonImp::~PolygonImp() +{ +} + +Coordinate PolygonImp::attachPoint() const +{ + return mcenterofmass; +} + +ObjectImp* PolygonImp::transform( const Transformation& t ) const +{ +/*mp: + * any projective transformation makes sense for a polygon, + * since segments transform into segments (but see below...) + * of course regular polygons will no longer be + * regular if t is not homothetic. + * for projective transformations the polygon could transform to + * an unbounded nonconnected polygon; this happens if some side + * of the polygon crosses the critical line that maps to infinity + * this can be easily checked using the getProjectiveIndicator + * function + */ +// if ( ! t.isHomothetic() ) +// return new InvalidImp(); + + if ( ! t.isAffine() ) /* in this case we need a more extensive test */ + { + double maxp = -1.0; + double minp = 1.0; + for ( uint i = 0; i < mpoints.size(); ++i ) + { + double p = t.getProjectiveIndicator( mpoints[i] ); + if ( p > maxp ) maxp = p; + if ( p < minp ) minp = p; + } + if ( maxp > 0 && minp < 0 ) return new InvalidImp; + } + std::vector np; + for ( uint i = 0; i < mpoints.size(); ++i ) + { + Coordinate nc = t.apply( mpoints[i] ); + if ( !nc.valid() ) + return new InvalidImp; + np.push_back( nc ); + } + return new PolygonImp( np ); +} + +void PolygonImp::draw( KigPainter& p ) const +{ + p.drawPolygon( mpoints ); +} + +bool PolygonImp::isInPolygon( const Coordinate& p ) const +{ + // (algorithm sent to me by domi) + // We intersect with the horizontal ray from point to the right and + // count the number of intersections. That, along with some + // minor optimalisations of the intersection test.. + bool inside_flag = false; + double cx = p.x; + double cy = p.y; + + Coordinate prevpoint = mpoints.back(); + bool prevpointbelow = mpoints.back().y >= cy; + for ( uint i = 0; i < mpoints.size(); ++i ) + { + Coordinate point = mpoints[i]; + bool pointbelow = point.y >= cy; + if ( prevpointbelow != pointbelow ) + { + // possibility of intersection: points on different side from + // the X axis + //bool rightofpt = point.x >= cx; + // mp: we need to be a little bit more conservative here, in + // order to treat properly the case when the point is on the + // boundary + //if ( rightofpt == ( prevpoint.x >= cx ) ) + if ( ( point.x - cx )*(prevpoint.x - cx ) > 0 ) + { + // points on same side of Y axis -> easy to test intersection + // intersection iff one point to the right of c + if ( point.x >= cx ) + inside_flag = !inside_flag; + } + else + { + // points on different sides of Y axis -> we need to calculate + // the intersection. + // mp: we want to check if the point is on the boundary, and + // return false in such case + double num = ( point.y - cy )*( prevpoint.x - point.x ); + double den = prevpoint.y - point.y; + if ( num == den*( point.x - cx ) ) return false; + if ( num/den <= point.x - cx ) + inside_flag = !inside_flag; + } + } + prevpoint = point; + prevpointbelow = pointbelow; + } + return inside_flag; +} +#define selectpolygonwithinside 1 +#ifdef selectpolygonwithinside +bool PolygonImp::contains( const Coordinate& p, int, const KigWidget& ) const +{ + return isInPolygon( p ); +} +#else +bool PolygonImp::contains( const Coordinate& p, int width, const KigWidget& w ) const +{ + bool ret = false; + uint reduceddim = mpoints.size() - 1; + for ( uint i = 0; i < reduceddim; ++i ) + { + ret |= isOnSegment( p, mpoints[i], mpoints[i+1], w.screenInfo().normalMiss( width ) ); + } + ret |= isOnSegment( p, mpoints[reduceddim], mpoints[0], w.screenInfo().normalMiss( width ) ); + + return ret; +} +#endif + +bool PolygonImp::inRect( const Rect& r, int width, const KigWidget& w ) const +{ + bool ret = false; + uint reduceddim = mpoints.size() - 1; + for ( uint i = 0; i < reduceddim; ++i ) + { + SegmentImp* s = new SegmentImp( mpoints[i], mpoints[i+1] ); + ret |= lineInRect( r, mpoints[i], mpoints[i+1], width, s, w ); + delete s; + s = 0; + } + SegmentImp* t = new SegmentImp( mpoints[reduceddim], mpoints[0] ); + ret |= lineInRect( r, mpoints[reduceddim], mpoints[0], width, t, w ); + delete t; + t = 0; + + return ret; +} + +bool PolygonImp::valid() const +{ + return true; +} + +const uint PolygonImp::numberOfProperties() const +{ + return Parent::numberOfProperties() + 5; +} + +const QCStringList PolygonImp::propertiesInternalNames() const +{ + QCStringList l = Parent::propertiesInternalNames(); + l += "polygon-number-of-sides"; + l += "polygon-perimeter"; + l += "polygon-surface"; + l += "polygon-center-of-mass"; + l += "polygon-winding-number"; + assert( l.size() == PolygonImp::numberOfProperties() ); + return l; +} + +const QCStringList PolygonImp::properties() const +{ + QCStringList l = Parent::properties(); + l += I18N_NOOP( "Number of sides" ); + l += I18N_NOOP( "Perimeter" ); + l += I18N_NOOP( "Surface" ); + l += I18N_NOOP( "Center of Mass of the Vertices" ); + l += I18N_NOOP( "Winding Number" ); + assert( l.size() == PolygonImp::numberOfProperties() ); + return l; +} + +const ObjectImpType* PolygonImp::impRequirementForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::impRequirementForProperty( which ); + else return PolygonImp::stype(); +} + +const char* PolygonImp::iconForProperty( uint which ) const +{ + assert( which < PolygonImp::numberOfProperties() ); + if ( which < Parent::numberOfProperties() ) + return Parent::iconForProperty( which ); + else if ( which == Parent::numberOfProperties() ) + return "en"; // number of sides + else if ( which == Parent::numberOfProperties() + 1 ) + return "circumference"; // perimeter + else if ( which == Parent::numberOfProperties() + 2 ) + return "areaCircle"; // surface + else if ( which == Parent::numberOfProperties() + 3 ) + return "point"; // center of mass + else if ( which == Parent::numberOfProperties() + 4 ) + return "w"; // winding number + else assert( false ); + return ""; +} + +ObjectImp* PolygonImp::property( uint which, const KigDocument& w ) const +{ + assert( which < PolygonImp::numberOfProperties() ); + if ( which < Parent::numberOfProperties() ) + return Parent::property( which, w ); + else if ( which == Parent::numberOfProperties() ) + { + // number of points + return new IntImp( mnpoints ); + } + else if ( which == Parent::numberOfProperties() + 1) + { + double circumference = 0.; + // circumference + for ( uint i = 0; i < mpoints.size(); ++i ) + { + uint prev = ( i + mpoints.size() - 1 ) % mpoints.size(); + circumference += ( mpoints[i] - mpoints[prev] ).length(); + } + return new DoubleImp( circumference ); + } + else if ( which == Parent::numberOfProperties() + 2) + { + int wn = windingNumber (); // not able to compute area for such polygons... + if ( wn < 0 ) wn = -wn; + if ( wn != 1 ) return new InvalidImp; + double surface2 = 0.0; + Coordinate prevpoint = mpoints.back(); + for ( uint i = 0; i < mpoints.size(); ++i ) + { + Coordinate point = mpoints[i]; + surface2 += ( point.x - prevpoint.x ) * ( point.y + prevpoint.y ); + prevpoint = point; + } + return new DoubleImp( fabs( surface2 / 2 ) ); + } + else if ( which == Parent::numberOfProperties() + 3 ) + { + return new PointImp( mcenterofmass ); + } + else if ( which == Parent::numberOfProperties() + 4 ) + { + // winding number + return new IntImp( windingNumber() ); + } + else assert( false ); + return new InvalidImp; +} + +const std::vector PolygonImp::points() const +{ + std::vector np; + np.reserve( mpoints.size() ); + std::copy( mpoints.begin(), mpoints.end(), std::back_inserter( np ) ); + return np; +} + +const uint PolygonImp::npoints() const +{ + return mnpoints; +} + +PolygonImp* PolygonImp::copy() const +{ + return new PolygonImp( mpoints ); +} + +void PolygonImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +bool PolygonImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( PolygonImp::stype() ) && + static_cast( rhs ).points() == mpoints; +} + +const ObjectImpType* PolygonImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "polygon", + I18N_NOOP( "polygon" ), + I18N_NOOP( "Select this polygon" ), + I18N_NOOP( "Select polygon %1" ), + I18N_NOOP( "Remove a Polygon" ), + I18N_NOOP( "Add a Polygon" ), + I18N_NOOP( "Move a Polygon" ), + I18N_NOOP( "Attach to this polygon" ), + I18N_NOOP( "Show a Polygon" ), + I18N_NOOP( "Hide a Polygon" ) + ); + + return &t; +} + +const ObjectImpType* PolygonImp::stype3() +{ + static const ObjectImpType t3( + PolygonImp::stype(), "triangle", + I18N_NOOP( "triangle" ), + I18N_NOOP( "Select this triangle" ), + I18N_NOOP( "Select triangle %1" ), + I18N_NOOP( "Remove a Triangle" ), + I18N_NOOP( "Add a Triangle" ), + I18N_NOOP( "Move a Triangle" ), + I18N_NOOP( "Attach to this triangle" ), + I18N_NOOP( "Show a Triangle" ), + I18N_NOOP( "Hide a Triangle" ) + ); + + return &t3; +} + +const ObjectImpType* PolygonImp::stype4() +{ + static const ObjectImpType t4( + PolygonImp::stype(), "quadrilateral", + I18N_NOOP( "quadrilateral" ), + I18N_NOOP( "Select this quadrilateral" ), + I18N_NOOP( "Select quadrilateral %1" ), + I18N_NOOP( "Remove a Quadrilateral" ), + I18N_NOOP( "Add a Quadrilateral" ), + I18N_NOOP( "Move a Quadrilateral" ), + I18N_NOOP( "Attach to this quadrilateral" ), + I18N_NOOP( "Show a Quadrilateral" ), + I18N_NOOP( "Hide a Quadrilateral" ) + ); + + return &t4; +} + +const ObjectImpType* PolygonImp::type() const +{ + uint n = mpoints.size(); + + if ( n == 3 ) return PolygonImp::stype3(); + if ( n == 4 ) return PolygonImp::stype4(); + return PolygonImp::stype(); +} + +bool PolygonImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const +{ + assert( which < PolygonImp::numberOfProperties() ); + if ( which < Parent::numberOfProperties() ) + return Parent::isPropertyDefinedOnOrThroughThisImp( which ); + return false; +} + +Rect PolygonImp::surroundingRect() const +{ + Rect r( 0., 0., 0., 0. ); + for ( uint i = 0; i < mpoints.size(); ++i ) + { + r.setContains( mpoints[i] ); + } + return r; +} + +int PolygonImp::windingNumber() const +{ + /* + * this is defined as the sum of the external angles while at + * all vertices, then normalized by 2pi. The external angle + * is the angle we steer at each vertex while we walk along the + * boundary of the polygon. + * In the end we only need to count how many time we cross the (1,0) + * direction (positive x-axis) with a positive sign if we cross while + * steering left and a negative sign viceversa + */ + + int winding = 0; + uint npoints = mpoints.size(); + Coordinate prevside = mpoints[0] - mpoints[npoints-1]; + for ( uint i = 0; i < npoints; ++i ) + { + uint nexti = i + 1; + if ( nexti >= npoints ) nexti = 0; + Coordinate side = mpoints[nexti] - mpoints[i]; + double vecprod = side.x*prevside.y - side.y*prevside.x; + int steeringdir = ( vecprod > 0 ) ? 1 : -1; + if ( vecprod == 0.0 || side.y*prevside.y > 0 ) + { + prevside = side; + continue; // cannot cross the (1,0) direction + } + if ( side.y*steeringdir < 0 && prevside.y*steeringdir >= 0 ) + winding -= steeringdir; + prevside = side; + } + return winding; +} + +bool PolygonImp::isMonotoneSteering() const +{ + /* + * returns true if while walking along the boundary, + * steering is always in the same direction + */ + + uint npoints = mpoints.size(); + Coordinate prevside = mpoints[0] - mpoints[npoints-1]; + int prevsteeringdir = 0; + for ( uint i = 0; i < npoints; ++i ) + { + uint nexti = i + 1; + if ( nexti >= npoints ) nexti = 0; + Coordinate side = mpoints[nexti] - mpoints[i]; + double vecprod = side.x*prevside.y - side.y*prevside.x; + int steeringdir = ( vecprod > 0 ) ? 1 : -1; + if ( vecprod == 0.0 ) + { + prevside = side; + continue; // going straight + } + if ( prevsteeringdir*steeringdir < 0 ) return false; + prevside = side; + prevsteeringdir = steeringdir; + } + return true; +} + +bool PolygonImp::isConvex() const +{ + if ( ! isMonotoneSteering() ) return false; + int winding = windingNumber(); + if ( winding < 0 ) winding = -winding; + assert ( winding > 0 ); + return winding == 1; +} + +std::vector computeConvexHull( const std::vector& points ) +{ + /* + * compute the convex hull of the set of points, the resulting list + * is the vertices of the resulting polygon listed in a counter clockwise + * order. This algorithm is on order n^2, probably suboptimal, but + * we don't expect to have large values for n. + */ + + if ( points.size() < 3 ) return points; + std::vector worklist = points; + std::vector result; + + double ymin = worklist[0].y; + uint imin = 0; + for ( uint i = 1; i < worklist.size(); ++i ) + { + if ( worklist[i].y < ymin ) + { + ymin = worklist[i].y; + imin = i; + } + } + + // worklist[imin] is definitely on the convex hull, let's start from there + result.push_back( worklist[imin] ); + Coordinate startpoint = worklist[imin]; + Coordinate apoint = worklist[imin]; + double aangle = 0.0; + + while ( ! worklist.empty() ) + { + int besti = -1; + double anglemin = 10000.0; + for ( uint i = 0; i < worklist.size(); ++i ) + { + if ( worklist[i] == apoint ) continue; + Coordinate v = worklist[i] - apoint; + double angle = std::atan2( v.y, v.x ); + while ( angle < aangle ) angle += 2*M_PI; + if ( angle < anglemin ) + { // found a better point + besti = i; + anglemin = angle; + } + } + + if ( besti < 0 ) return result; // this happens, e.g. if all points coincide + apoint = worklist[besti]; + aangle = anglemin; + if ( apoint == startpoint ) + { + return result; + } + result.push_back( apoint ); + worklist.erase( worklist.begin() + besti, worklist.begin() + besti + 1 ); + } + assert( false ); + return result; +} diff --git a/kig/objects/polygon_type.cc b/kig/objects/polygon_type.cc deleted file mode 100644 index cd1fb544..00000000 --- a/kig/objects/polygon_type.cc +++ /dev/null @@ -1,669 +0,0 @@ -// Copyright (C) 2003 Maurizio Paolini - -// 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 "polygon_type.h" - -#include "bogus_imp.h" -#include "line_imp.h" -#include "point_imp.h" -#include "polygon_imp.h" -#include "object_calcer.h" - -#include "../misc/common.h" - -#include -#include -#include - -/* - * triangle by its vertices - */ - -static const char triangle_constructstatement[] = I18N_NOOP( "Construct a triangle with this vertex" ); -static const char triangle_constructstatement2[] = I18N_NOOP( "Select a point to be a vertex of the new triangle..." ); - -static const struct ArgsParser::spec argsspecTriangleB3P[] = -{ - { PointImp::stype(), triangle_constructstatement, triangle_constructstatement2, true }, - { PointImp::stype(), triangle_constructstatement, triangle_constructstatement2, true }, - { PointImp::stype(), triangle_constructstatement, triangle_constructstatement2, true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( TriangleB3PType ) - -TriangleB3PType::TriangleB3PType() - : ArgsParserObjectType( "TriangleB3P", argsspecTriangleB3P, 3 ) -{ -} - -TriangleB3PType::~TriangleB3PType() -{ -} - -const TriangleB3PType* TriangleB3PType::instance() -{ - static const TriangleB3PType s; - return &s; -} - -ObjectImp* TriangleB3PType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents, 1 ) ) return new InvalidImp; - std::vector points; - - Coordinate centerofmass3 = Coordinate( 0, 0 ); - for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) - { - Coordinate point = static_cast( *i )->coordinate(); - centerofmass3 += point; - points.push_back( point ); - } - return new PolygonImp( 3, points, centerofmass3/3 ); -} - -const ObjectImpType* TriangleB3PType::resultId() const -{ - return PolygonImp::stype(); -} - -bool TriangleB3PType::canMove( const ObjectTypeCalcer& o ) const -{ - return isFreelyTranslatable( o ); -} - -bool TriangleB3PType::isFreelyTranslatable( const ObjectTypeCalcer& o ) const -{ - std::vector parents = o.parents(); - return parents[0]->isFreelyTranslatable() && - parents[1]->isFreelyTranslatable() && - parents[2]->isFreelyTranslatable(); -} - -void TriangleB3PType::move( ObjectTypeCalcer& o, const Coordinate& to, - const KigDocument& d ) const -{ - std::vector parents = o.parents(); - assert( margsparser.checkArgs( parents ) ); - const Coordinate a = static_cast( parents[0]->imp() )->coordinate(); - const Coordinate b = static_cast( parents[1]->imp() )->coordinate(); - const Coordinate c = static_cast( parents[2]->imp() )->coordinate(); - if ( parents[0]->canMove() ) - parents[0]->move( to, d ); - if ( parents[1]->canMove() ) - parents[1]->move( to + b - a, d ); - if ( parents[2]->canMove() ) - parents[2]->move( to + c - a, d ); -} - -const Coordinate TriangleB3PType::moveReferencePoint( const ObjectTypeCalcer& o ) const -{ - std::vector parents = o.parents(); - assert( margsparser.checkArgs( parents ) ); - return static_cast( parents[0]->imp() )->coordinate(); -} - -std::vector TriangleB3PType::movableParents( const ObjectTypeCalcer& ourobj ) const -{ - std::vector parents = ourobj.parents(); - std::set ret; - std::vector tmp = parents[0]->movableParents(); - ret.insert( tmp.begin(), tmp.end() ); - tmp = parents[1]->movableParents(); - ret.insert( tmp.begin(), tmp.end() ); - tmp = parents[2]->movableParents(); - ret.insert( tmp.begin(), tmp.end() ); - ret.insert( parents.begin(), parents.end() ); - return std::vector( ret.begin(), ret.end() ); -} - -/* - * generic polygon - */ - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PolygonBNPType ) - -PolygonBNPType::PolygonBNPType() - : ObjectType( "PolygonBNP" ) -{ -} - -PolygonBNPType::~PolygonBNPType() -{ -} - -const PolygonBNPType* PolygonBNPType::instance() -{ - static const PolygonBNPType s; - return &s; -} - -ObjectImp* PolygonBNPType::calc( const Args& parents, const KigDocument& ) const -{ - uint count = parents.size(); - assert (count >= 3); /* non sono ammessi poligoni con meno di tre lati */ -// if ( parents[0] != parents[count] ) return new InvalidImp; - std::vector points; - - uint npoints = 0; - Coordinate centerofmassn = Coordinate( 0, 0 ); - - for ( uint i = 0; i < count; ++i ) - { - npoints++; - if ( ! parents[i]->inherits( PointImp::stype() ) ) return new InvalidImp; - Coordinate point = static_cast( parents[i] )->coordinate(); - centerofmassn += point; - points.push_back( point ); - } - return new PolygonImp( npoints, points, centerofmassn/npoints ); -} - -const ObjectImpType* PolygonBNPType::resultId() const -{ - return PolygonImp::stype(); -} - -const ObjectImpType* PolygonBNPType::impRequirement( const ObjectImp*, const Args& ) const -{ - return PointImp::stype(); -} - -bool PolygonBNPType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const -{ - return false; /* should be true? */ -} - -std::vector PolygonBNPType::sortArgs( const std::vector& args ) const -{ - return args; /* should already be in correct order */ -} - -Args PolygonBNPType::sortArgs( const Args& args ) const -{ - return args; -} - -bool PolygonBNPType::canMove( const ObjectTypeCalcer& o ) const -{ - return isFreelyTranslatable( o ); -} - -bool PolygonBNPType::isFreelyTranslatable( const ObjectTypeCalcer& o ) const -{ - std::vector parents = o.parents(); - for ( uint i = 0; i < parents.size(); ++i ) - { - if ( !parents[i]->isFreelyTranslatable() ) return false; - } - return true; -} - -void PolygonBNPType::move( ObjectTypeCalcer& o, const Coordinate& to, - const KigDocument& d ) const -{ - std::vector parents = o.parents(); - const Coordinate ref = static_cast( parents[0]->imp() )->coordinate(); - for ( uint i = 0; i < parents.size(); ++i ) - { - const Coordinate a = static_cast( parents[i]->imp() )->coordinate(); - parents[i]->move( to + a - ref, d ); - } -} - -const Coordinate PolygonBNPType::moveReferencePoint( const ObjectTypeCalcer& o -) const -{ - std::vector parents = o.parents(); - return static_cast( parents[0]->imp() )->coordinate(); -} - -std::vector PolygonBNPType::movableParents( const ObjectTypeCalcer& ourobj ) const -{ - std::vector parents = ourobj.parents(); - std::set ret; - for ( uint i = 0; i < parents.size(); ++i ) - { - std::vector tmp = parents[i]->movableParents(); - ret.insert( tmp.begin(), tmp.end() ); - } - ret.insert( parents.begin(), parents.end() ); - return std::vector( ret.begin(), ret.end() ); -} - -/* - * regular polygon by center and vertex - */ - -//static const char constructpoligonthroughpointstat[] = I18N_NOOP( "Construct a polygon with this vertex" ); -// -//static const char constructpoligonwithcenterstat[] = I18N_NOOP( "Construct a polygon with this center" ); -// -//static const ArgsParser::spec argsspecPoligonBCV[] = -//{ -// { PointImp::stype(), constructpoligonwithcenterstat, -// I18N_NOOP( "Select the center of the new polygon..." ), false }, -// { PointImp::stype(), constructpoligonthroughpointstat, -// I18N_NOOP( "Select a vertex for the new polygon..." ), true }, -// { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } -//}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PolygonBCVType ) - -PolygonBCVType::PolygonBCVType() - : ObjectType( "PoligonBCV" ) -// we keep the name "PoligonBCV" although syntactically incorrect for -// compatibility reasons with old kig files -// : ArgsParserObjectType( "PoligonBCV", argsspecPoligonBCV, 3 ) -{ -} - -PolygonBCVType::~PolygonBCVType() -{ -} - -const PolygonBCVType* PolygonBCVType::instance() -{ - static const PolygonBCVType s; - return &s; -} - -ObjectImp* PolygonBCVType::calc( const Args& parents, const KigDocument& ) const -{ - if ( parents.size() < 3 || parents.size() > 4 ) return new InvalidImp; - - if ( ( ! parents[0]->inherits( PointImp::stype() ) ) || - ( ! parents[1]->inherits( PointImp::stype() ) ) || - ( ! parents[2]->inherits( IntImp::stype() ) ) ) - return new InvalidImp; - - const Coordinate center = - static_cast( parents[0] )->coordinate(); - const Coordinate vertex = - static_cast( parents[1] )->coordinate(); - const int sides = - static_cast( parents[2] )->data(); - int twist = 1; - if ( parents.size() == 4 ) - { - if ( ! parents[3]->inherits( IntImp::stype() ) ) return new InvalidImp; - twist = static_cast( parents[3] )->data(); - } - std::vector vertexes; - - double dx = vertex.x - center.x; - double dy = vertex.y - center.y; - - for ( int i = 1; i <= sides; i++ ) - { - double alfa = 2*twist*M_PI/sides; - double theta1 = alfa*i - alfa; - double ctheta1 = cos(theta1); - double stheta1 = sin(theta1); - - Coordinate v1 = center + Coordinate( ctheta1*dx - stheta1*dy, - stheta1*dx + ctheta1*dy ); - vertexes.push_back( v1 ); - } - return new PolygonImp( uint (sides), vertexes, center ); -} - -const ObjectImpType* PolygonBCVType::resultId() const -{ - return SegmentImp::stype(); -} - -const ObjectImpType* PolygonBCVType::impRequirement( const ObjectImp* obj, const Args& ) const -{ - if ( obj->inherits( PointImp::stype() ) ) - return PointImp::stype(); - - if ( obj->inherits( IntImp::stype() ) ) - return IntImp::stype(); - - return 0; -} - -bool PolygonBCVType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const -{ - return false; /* should be true? */ -} - -std::vector PolygonBCVType::sortArgs( const std::vector& args ) const -{ - return args; /* should already be in correct order */ -} - -Args PolygonBCVType::sortArgs( const Args& args ) const -{ - return args; -} - -bool PolygonBCVType::canMove( const ObjectTypeCalcer& o ) const -{ - return isFreelyTranslatable( o ); -} - -bool PolygonBCVType::isFreelyTranslatable( const ObjectTypeCalcer& o ) const -{ - std::vector parents = o.parents(); - return parents[0]->isFreelyTranslatable() && - parents[1]->isFreelyTranslatable(); -} - -void PolygonBCVType::move( ObjectTypeCalcer& o, const Coordinate& to, - const KigDocument& d ) const -{ - std::vector parents = o.parents(); - // assert( margsparser.checkArgs( parents ) ); - if ( ! parents[0]->imp()->inherits( PointImp::stype() ) || - ! parents[1]->imp()->inherits( PointImp::stype() ) ) return; - - const Coordinate a = static_cast( parents[0]->imp() )->coordinate(); - const Coordinate b = static_cast( parents[1]->imp() )->coordinate(); - parents[0]->move( to, d ); - parents[1]->move( to + b - a, d ); -} - -const Coordinate PolygonBCVType::moveReferencePoint( const ObjectTypeCalcer& o) const -{ - std::vector parents = o.parents(); - // assert( margsparser.checkArgs( parents ) ); - if ( ! parents[0]->imp()->inherits( PointImp::stype() ) ) return Coordinate::invalidCoord(); - - return static_cast( parents[0]->imp() )->coordinate(); -} - -std::vector PolygonBCVType::movableParents( const ObjectTypeCalcer& ourobj ) const -{ - std::vector parents = ourobj.parents(); - std::set ret; - std::vector tmp = parents[0]->movableParents(); - ret.insert( tmp.begin(), tmp.end() ); - tmp = parents[1]->movableParents(); - ret.insert( tmp.begin(), tmp.end() ); - ret.insert( &parents[0], &parents[1] ); - return std::vector( ret.begin(), ret.end() ); -} - -/* polygon-line intersection */ - -static const ArgsParser::spec argsspecPolygonLineIntersection[] = -{ - { PolygonImp::stype(), I18N_NOOP( "Intersect this polygon with a line" ), - I18N_NOOP( "Select the polygon of which you want the intersection with a line..." ), false }, - { AbstractLineImp::stype(), "Intersect this line with a polygon", "Select the line of which you want the intersection with a polygon...", false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PolygonLineIntersectionType ) - -PolygonLineIntersectionType::PolygonLineIntersectionType() - : ArgsParserObjectType( "PolygonLineIntersection", argsspecPolygonLineIntersection, 2 ) -{ -} - -PolygonLineIntersectionType::~PolygonLineIntersectionType() -{ -} - -const PolygonLineIntersectionType* PolygonLineIntersectionType::instance() -{ - static const PolygonLineIntersectionType t; - return &t; -} - -/* - * Intersection of a polygon and a line/ray/segment. - * - * geometrically speaking the result is always a collection of - * collinear nonintersecting open segments (at most one if the - * polygon is convex). Since we don't know in advance how many - * segments will result, the obvious choice is to return an - * InvalidImp in cases when the result is *not* a single segment - * - * computing the two ends of this segment is more tricky then one - * expects especially when intersecting segments/rays. - * - * particularly "difficult" situations are those where we intersect - * a segment/ray with an/the endpoint coinciding with a vertex of - * the polygon, especially if that vertex is a "reentrant" (concave) - * vertex of the polygon. - */ - -ObjectImp* PolygonLineIntersectionType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - const PolygonImp* polygon = static_cast( parents[0] ); - const std::vector ppoints = polygon->points(); - const LineData line = static_cast( parents[1] )->data(); - Coordinate intersections[2]; - uint whichintersection = 0; - - bool boundleft = false; - bool boundright = false; - if ( parents[1]->inherits( SegmentImp::stype() ) ) - { - boundleft = boundright = true; - } - if ( parents[1]->inherits( RayImp::stype() ) ) - { - boundleft = true; - } - Coordinate a = line.a; - double abx = line.b.x - a.x; - double aby = line.b.y - a.y; - - double leftendinside = false; - double rightendinside = false; - Coordinate prevpoint = ppoints.back() - a; - bool prevpointbelow = ( abx*prevpoint.y <= aby*prevpoint.x ); - for ( uint i = 0; i < ppoints.size(); ++i ) - { - Coordinate point = ppoints[i] - a; - bool pointbelow = ( abx*point.y <= aby*point.x ); - if ( pointbelow != prevpointbelow ) - { - /* found an intersection with the support line - * compute the value of the parameter... - */ - double dcx = point.x - prevpoint.x; - double dcy = point.y - prevpoint.y; - double num = point.x*dcy - point.y*dcx; - double den = abx*dcy - aby*dcx; - if ( std::fabs( den ) <= 1.e-6*std::fabs( num ) ) continue; //parallel - double t = num/den; - if ( boundleft && t <= 0 ) - { - leftendinside = !leftendinside; - } - else if ( boundright && t >= 1 ) - { - rightendinside = !rightendinside; - } - else - { - if ( whichintersection >= 2 ) return new InvalidImp; - intersections[whichintersection++] = a + t*Coordinate( abx, aby ); - } - } - prevpoint = point; - prevpointbelow = pointbelow; - } - - if ( leftendinside ) - { - if ( whichintersection >= 2 ) return new InvalidImp; - intersections[whichintersection++] = a; - } - - if ( rightendinside ) - { - if ( whichintersection >= 2 ) return new InvalidImp; - intersections[whichintersection++] = line.b; - } - - switch (whichintersection) - { - case 1: /* just for completeness: this should never happen */ - return new PointImp( intersections[0] ); - break; - case 2: - return new SegmentImp( intersections[0], intersections[1] ); - break; - case 0: - default: - return new InvalidImp; - break; - } -} - -const ObjectImpType* PolygonLineIntersectionType::resultId() const -{ - return SegmentImp::stype(); -} - -/* polygon vertices */ - -static const ArgsParser::spec argsspecPolygonVertex[] = -{ - { PolygonImp::stype(), I18N_NOOP( "Construct the vertices of this polygon" ), - I18N_NOOP( "Select the polygon of which you want to construct the vertices..." ), true }, - { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PolygonVertexType ) - -PolygonVertexType::PolygonVertexType() - : ArgsParserObjectType( "PolygonVertex", argsspecPolygonVertex, 2 ) -{ -} - -PolygonVertexType::~PolygonVertexType() -{ -} - -const PolygonVertexType* PolygonVertexType::instance() -{ - static const PolygonVertexType t; - return &t; -} - -ObjectImp* PolygonVertexType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - const std::vector ppoints = static_cast( parents[0] )->points(); - const uint i = static_cast( parents[1] )->data(); - - if ( i >= ppoints.size() ) return new InvalidImp; - - return new PointImp( ppoints[i] ); -} - -const ObjectImpType* PolygonVertexType::resultId() const -{ - return PointImp::stype(); -} - -/* polygon sides */ - -static const ArgsParser::spec argsspecPolygonSide[] = -{ - { PolygonImp::stype(), I18N_NOOP( "Construct the sides of this polygon" ), - I18N_NOOP( "Select the polygon of which you want to construct the sides..." ), false }, - { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PolygonSideType ) - -PolygonSideType::PolygonSideType() - : ArgsParserObjectType( "PolygonSide", argsspecPolygonSide, 2 ) -{ -} - -PolygonSideType::~PolygonSideType() -{ -} - -const PolygonSideType* PolygonSideType::instance() -{ - static const PolygonSideType t; - return &t; -} - -ObjectImp* PolygonSideType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - const std::vector ppoints = static_cast( parents[0] )->points(); - const uint i = static_cast( parents[1] )->data(); - - if ( i >= ppoints.size() ) return new InvalidImp; - - uint nexti = i + 1; - if ( nexti >= ppoints.size() ) nexti = 0; - - return new SegmentImp( ppoints[i], ppoints[nexti] ); -} - -const ObjectImpType* PolygonSideType::resultId() const -{ - return SegmentImp::stype(); -} - -/* convex hull of a polygon */ - -static const ArgsParser::spec argsspecConvexHull[] = -{ - { PolygonImp::stype(), I18N_NOOP( "Construct the convex hull of this polygon" ), - I18N_NOOP( "Select the polygon of which you want to construct the convex hull..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConvexHullType ) - -ConvexHullType::ConvexHullType() - : ArgsParserObjectType( "ConvexHull", argsspecConvexHull, 1 ) -{ -} - -ConvexHullType::~ConvexHullType() -{ -} - -const ConvexHullType* ConvexHullType::instance() -{ - static const ConvexHullType t; - return &t; -} - -ObjectImp* ConvexHullType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - - const std::vector ppoints = static_cast( parents[0] )->points(); - - if ( ppoints.size() < 3 ) return new InvalidImp; - - std::vector hull = computeConvexHull( ppoints ); - if ( hull.size() < 3 ) return new InvalidImp; - return new PolygonImp( hull ); -} - -const ObjectImpType* ConvexHullType::resultId() const -{ - return PolygonImp::stype(); -} diff --git a/kig/objects/polygon_type.cpp b/kig/objects/polygon_type.cpp new file mode 100644 index 00000000..cd1fb544 --- /dev/null +++ b/kig/objects/polygon_type.cpp @@ -0,0 +1,669 @@ +// Copyright (C) 2003 Maurizio Paolini + +// 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 "polygon_type.h" + +#include "bogus_imp.h" +#include "line_imp.h" +#include "point_imp.h" +#include "polygon_imp.h" +#include "object_calcer.h" + +#include "../misc/common.h" + +#include +#include +#include + +/* + * triangle by its vertices + */ + +static const char triangle_constructstatement[] = I18N_NOOP( "Construct a triangle with this vertex" ); +static const char triangle_constructstatement2[] = I18N_NOOP( "Select a point to be a vertex of the new triangle..." ); + +static const struct ArgsParser::spec argsspecTriangleB3P[] = +{ + { PointImp::stype(), triangle_constructstatement, triangle_constructstatement2, true }, + { PointImp::stype(), triangle_constructstatement, triangle_constructstatement2, true }, + { PointImp::stype(), triangle_constructstatement, triangle_constructstatement2, true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( TriangleB3PType ) + +TriangleB3PType::TriangleB3PType() + : ArgsParserObjectType( "TriangleB3P", argsspecTriangleB3P, 3 ) +{ +} + +TriangleB3PType::~TriangleB3PType() +{ +} + +const TriangleB3PType* TriangleB3PType::instance() +{ + static const TriangleB3PType s; + return &s; +} + +ObjectImp* TriangleB3PType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents, 1 ) ) return new InvalidImp; + std::vector points; + + Coordinate centerofmass3 = Coordinate( 0, 0 ); + for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i ) + { + Coordinate point = static_cast( *i )->coordinate(); + centerofmass3 += point; + points.push_back( point ); + } + return new PolygonImp( 3, points, centerofmass3/3 ); +} + +const ObjectImpType* TriangleB3PType::resultId() const +{ + return PolygonImp::stype(); +} + +bool TriangleB3PType::canMove( const ObjectTypeCalcer& o ) const +{ + return isFreelyTranslatable( o ); +} + +bool TriangleB3PType::isFreelyTranslatable( const ObjectTypeCalcer& o ) const +{ + std::vector parents = o.parents(); + return parents[0]->isFreelyTranslatable() && + parents[1]->isFreelyTranslatable() && + parents[2]->isFreelyTranslatable(); +} + +void TriangleB3PType::move( ObjectTypeCalcer& o, const Coordinate& to, + const KigDocument& d ) const +{ + std::vector parents = o.parents(); + assert( margsparser.checkArgs( parents ) ); + const Coordinate a = static_cast( parents[0]->imp() )->coordinate(); + const Coordinate b = static_cast( parents[1]->imp() )->coordinate(); + const Coordinate c = static_cast( parents[2]->imp() )->coordinate(); + if ( parents[0]->canMove() ) + parents[0]->move( to, d ); + if ( parents[1]->canMove() ) + parents[1]->move( to + b - a, d ); + if ( parents[2]->canMove() ) + parents[2]->move( to + c - a, d ); +} + +const Coordinate TriangleB3PType::moveReferencePoint( const ObjectTypeCalcer& o ) const +{ + std::vector parents = o.parents(); + assert( margsparser.checkArgs( parents ) ); + return static_cast( parents[0]->imp() )->coordinate(); +} + +std::vector TriangleB3PType::movableParents( const ObjectTypeCalcer& ourobj ) const +{ + std::vector parents = ourobj.parents(); + std::set ret; + std::vector tmp = parents[0]->movableParents(); + ret.insert( tmp.begin(), tmp.end() ); + tmp = parents[1]->movableParents(); + ret.insert( tmp.begin(), tmp.end() ); + tmp = parents[2]->movableParents(); + ret.insert( tmp.begin(), tmp.end() ); + ret.insert( parents.begin(), parents.end() ); + return std::vector( ret.begin(), ret.end() ); +} + +/* + * generic polygon + */ + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PolygonBNPType ) + +PolygonBNPType::PolygonBNPType() + : ObjectType( "PolygonBNP" ) +{ +} + +PolygonBNPType::~PolygonBNPType() +{ +} + +const PolygonBNPType* PolygonBNPType::instance() +{ + static const PolygonBNPType s; + return &s; +} + +ObjectImp* PolygonBNPType::calc( const Args& parents, const KigDocument& ) const +{ + uint count = parents.size(); + assert (count >= 3); /* non sono ammessi poligoni con meno di tre lati */ +// if ( parents[0] != parents[count] ) return new InvalidImp; + std::vector points; + + uint npoints = 0; + Coordinate centerofmassn = Coordinate( 0, 0 ); + + for ( uint i = 0; i < count; ++i ) + { + npoints++; + if ( ! parents[i]->inherits( PointImp::stype() ) ) return new InvalidImp; + Coordinate point = static_cast( parents[i] )->coordinate(); + centerofmassn += point; + points.push_back( point ); + } + return new PolygonImp( npoints, points, centerofmassn/npoints ); +} + +const ObjectImpType* PolygonBNPType::resultId() const +{ + return PolygonImp::stype(); +} + +const ObjectImpType* PolygonBNPType::impRequirement( const ObjectImp*, const Args& ) const +{ + return PointImp::stype(); +} + +bool PolygonBNPType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const +{ + return false; /* should be true? */ +} + +std::vector PolygonBNPType::sortArgs( const std::vector& args ) const +{ + return args; /* should already be in correct order */ +} + +Args PolygonBNPType::sortArgs( const Args& args ) const +{ + return args; +} + +bool PolygonBNPType::canMove( const ObjectTypeCalcer& o ) const +{ + return isFreelyTranslatable( o ); +} + +bool PolygonBNPType::isFreelyTranslatable( const ObjectTypeCalcer& o ) const +{ + std::vector parents = o.parents(); + for ( uint i = 0; i < parents.size(); ++i ) + { + if ( !parents[i]->isFreelyTranslatable() ) return false; + } + return true; +} + +void PolygonBNPType::move( ObjectTypeCalcer& o, const Coordinate& to, + const KigDocument& d ) const +{ + std::vector parents = o.parents(); + const Coordinate ref = static_cast( parents[0]->imp() )->coordinate(); + for ( uint i = 0; i < parents.size(); ++i ) + { + const Coordinate a = static_cast( parents[i]->imp() )->coordinate(); + parents[i]->move( to + a - ref, d ); + } +} + +const Coordinate PolygonBNPType::moveReferencePoint( const ObjectTypeCalcer& o +) const +{ + std::vector parents = o.parents(); + return static_cast( parents[0]->imp() )->coordinate(); +} + +std::vector PolygonBNPType::movableParents( const ObjectTypeCalcer& ourobj ) const +{ + std::vector parents = ourobj.parents(); + std::set ret; + for ( uint i = 0; i < parents.size(); ++i ) + { + std::vector tmp = parents[i]->movableParents(); + ret.insert( tmp.begin(), tmp.end() ); + } + ret.insert( parents.begin(), parents.end() ); + return std::vector( ret.begin(), ret.end() ); +} + +/* + * regular polygon by center and vertex + */ + +//static const char constructpoligonthroughpointstat[] = I18N_NOOP( "Construct a polygon with this vertex" ); +// +//static const char constructpoligonwithcenterstat[] = I18N_NOOP( "Construct a polygon with this center" ); +// +//static const ArgsParser::spec argsspecPoligonBCV[] = +//{ +// { PointImp::stype(), constructpoligonwithcenterstat, +// I18N_NOOP( "Select the center of the new polygon..." ), false }, +// { PointImp::stype(), constructpoligonthroughpointstat, +// I18N_NOOP( "Select a vertex for the new polygon..." ), true }, +// { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } +//}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PolygonBCVType ) + +PolygonBCVType::PolygonBCVType() + : ObjectType( "PoligonBCV" ) +// we keep the name "PoligonBCV" although syntactically incorrect for +// compatibility reasons with old kig files +// : ArgsParserObjectType( "PoligonBCV", argsspecPoligonBCV, 3 ) +{ +} + +PolygonBCVType::~PolygonBCVType() +{ +} + +const PolygonBCVType* PolygonBCVType::instance() +{ + static const PolygonBCVType s; + return &s; +} + +ObjectImp* PolygonBCVType::calc( const Args& parents, const KigDocument& ) const +{ + if ( parents.size() < 3 || parents.size() > 4 ) return new InvalidImp; + + if ( ( ! parents[0]->inherits( PointImp::stype() ) ) || + ( ! parents[1]->inherits( PointImp::stype() ) ) || + ( ! parents[2]->inherits( IntImp::stype() ) ) ) + return new InvalidImp; + + const Coordinate center = + static_cast( parents[0] )->coordinate(); + const Coordinate vertex = + static_cast( parents[1] )->coordinate(); + const int sides = + static_cast( parents[2] )->data(); + int twist = 1; + if ( parents.size() == 4 ) + { + if ( ! parents[3]->inherits( IntImp::stype() ) ) return new InvalidImp; + twist = static_cast( parents[3] )->data(); + } + std::vector vertexes; + + double dx = vertex.x - center.x; + double dy = vertex.y - center.y; + + for ( int i = 1; i <= sides; i++ ) + { + double alfa = 2*twist*M_PI/sides; + double theta1 = alfa*i - alfa; + double ctheta1 = cos(theta1); + double stheta1 = sin(theta1); + + Coordinate v1 = center + Coordinate( ctheta1*dx - stheta1*dy, + stheta1*dx + ctheta1*dy ); + vertexes.push_back( v1 ); + } + return new PolygonImp( uint (sides), vertexes, center ); +} + +const ObjectImpType* PolygonBCVType::resultId() const +{ + return SegmentImp::stype(); +} + +const ObjectImpType* PolygonBCVType::impRequirement( const ObjectImp* obj, const Args& ) const +{ + if ( obj->inherits( PointImp::stype() ) ) + return PointImp::stype(); + + if ( obj->inherits( IntImp::stype() ) ) + return IntImp::stype(); + + return 0; +} + +bool PolygonBCVType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const +{ + return false; /* should be true? */ +} + +std::vector PolygonBCVType::sortArgs( const std::vector& args ) const +{ + return args; /* should already be in correct order */ +} + +Args PolygonBCVType::sortArgs( const Args& args ) const +{ + return args; +} + +bool PolygonBCVType::canMove( const ObjectTypeCalcer& o ) const +{ + return isFreelyTranslatable( o ); +} + +bool PolygonBCVType::isFreelyTranslatable( const ObjectTypeCalcer& o ) const +{ + std::vector parents = o.parents(); + return parents[0]->isFreelyTranslatable() && + parents[1]->isFreelyTranslatable(); +} + +void PolygonBCVType::move( ObjectTypeCalcer& o, const Coordinate& to, + const KigDocument& d ) const +{ + std::vector parents = o.parents(); + // assert( margsparser.checkArgs( parents ) ); + if ( ! parents[0]->imp()->inherits( PointImp::stype() ) || + ! parents[1]->imp()->inherits( PointImp::stype() ) ) return; + + const Coordinate a = static_cast( parents[0]->imp() )->coordinate(); + const Coordinate b = static_cast( parents[1]->imp() )->coordinate(); + parents[0]->move( to, d ); + parents[1]->move( to + b - a, d ); +} + +const Coordinate PolygonBCVType::moveReferencePoint( const ObjectTypeCalcer& o) const +{ + std::vector parents = o.parents(); + // assert( margsparser.checkArgs( parents ) ); + if ( ! parents[0]->imp()->inherits( PointImp::stype() ) ) return Coordinate::invalidCoord(); + + return static_cast( parents[0]->imp() )->coordinate(); +} + +std::vector PolygonBCVType::movableParents( const ObjectTypeCalcer& ourobj ) const +{ + std::vector parents = ourobj.parents(); + std::set ret; + std::vector tmp = parents[0]->movableParents(); + ret.insert( tmp.begin(), tmp.end() ); + tmp = parents[1]->movableParents(); + ret.insert( tmp.begin(), tmp.end() ); + ret.insert( &parents[0], &parents[1] ); + return std::vector( ret.begin(), ret.end() ); +} + +/* polygon-line intersection */ + +static const ArgsParser::spec argsspecPolygonLineIntersection[] = +{ + { PolygonImp::stype(), I18N_NOOP( "Intersect this polygon with a line" ), + I18N_NOOP( "Select the polygon of which you want the intersection with a line..." ), false }, + { AbstractLineImp::stype(), "Intersect this line with a polygon", "Select the line of which you want the intersection with a polygon...", false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PolygonLineIntersectionType ) + +PolygonLineIntersectionType::PolygonLineIntersectionType() + : ArgsParserObjectType( "PolygonLineIntersection", argsspecPolygonLineIntersection, 2 ) +{ +} + +PolygonLineIntersectionType::~PolygonLineIntersectionType() +{ +} + +const PolygonLineIntersectionType* PolygonLineIntersectionType::instance() +{ + static const PolygonLineIntersectionType t; + return &t; +} + +/* + * Intersection of a polygon and a line/ray/segment. + * + * geometrically speaking the result is always a collection of + * collinear nonintersecting open segments (at most one if the + * polygon is convex). Since we don't know in advance how many + * segments will result, the obvious choice is to return an + * InvalidImp in cases when the result is *not* a single segment + * + * computing the two ends of this segment is more tricky then one + * expects especially when intersecting segments/rays. + * + * particularly "difficult" situations are those where we intersect + * a segment/ray with an/the endpoint coinciding with a vertex of + * the polygon, especially if that vertex is a "reentrant" (concave) + * vertex of the polygon. + */ + +ObjectImp* PolygonLineIntersectionType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + const PolygonImp* polygon = static_cast( parents[0] ); + const std::vector ppoints = polygon->points(); + const LineData line = static_cast( parents[1] )->data(); + Coordinate intersections[2]; + uint whichintersection = 0; + + bool boundleft = false; + bool boundright = false; + if ( parents[1]->inherits( SegmentImp::stype() ) ) + { + boundleft = boundright = true; + } + if ( parents[1]->inherits( RayImp::stype() ) ) + { + boundleft = true; + } + Coordinate a = line.a; + double abx = line.b.x - a.x; + double aby = line.b.y - a.y; + + double leftendinside = false; + double rightendinside = false; + Coordinate prevpoint = ppoints.back() - a; + bool prevpointbelow = ( abx*prevpoint.y <= aby*prevpoint.x ); + for ( uint i = 0; i < ppoints.size(); ++i ) + { + Coordinate point = ppoints[i] - a; + bool pointbelow = ( abx*point.y <= aby*point.x ); + if ( pointbelow != prevpointbelow ) + { + /* found an intersection with the support line + * compute the value of the parameter... + */ + double dcx = point.x - prevpoint.x; + double dcy = point.y - prevpoint.y; + double num = point.x*dcy - point.y*dcx; + double den = abx*dcy - aby*dcx; + if ( std::fabs( den ) <= 1.e-6*std::fabs( num ) ) continue; //parallel + double t = num/den; + if ( boundleft && t <= 0 ) + { + leftendinside = !leftendinside; + } + else if ( boundright && t >= 1 ) + { + rightendinside = !rightendinside; + } + else + { + if ( whichintersection >= 2 ) return new InvalidImp; + intersections[whichintersection++] = a + t*Coordinate( abx, aby ); + } + } + prevpoint = point; + prevpointbelow = pointbelow; + } + + if ( leftendinside ) + { + if ( whichintersection >= 2 ) return new InvalidImp; + intersections[whichintersection++] = a; + } + + if ( rightendinside ) + { + if ( whichintersection >= 2 ) return new InvalidImp; + intersections[whichintersection++] = line.b; + } + + switch (whichintersection) + { + case 1: /* just for completeness: this should never happen */ + return new PointImp( intersections[0] ); + break; + case 2: + return new SegmentImp( intersections[0], intersections[1] ); + break; + case 0: + default: + return new InvalidImp; + break; + } +} + +const ObjectImpType* PolygonLineIntersectionType::resultId() const +{ + return SegmentImp::stype(); +} + +/* polygon vertices */ + +static const ArgsParser::spec argsspecPolygonVertex[] = +{ + { PolygonImp::stype(), I18N_NOOP( "Construct the vertices of this polygon" ), + I18N_NOOP( "Select the polygon of which you want to construct the vertices..." ), true }, + { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PolygonVertexType ) + +PolygonVertexType::PolygonVertexType() + : ArgsParserObjectType( "PolygonVertex", argsspecPolygonVertex, 2 ) +{ +} + +PolygonVertexType::~PolygonVertexType() +{ +} + +const PolygonVertexType* PolygonVertexType::instance() +{ + static const PolygonVertexType t; + return &t; +} + +ObjectImp* PolygonVertexType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + const std::vector ppoints = static_cast( parents[0] )->points(); + const uint i = static_cast( parents[1] )->data(); + + if ( i >= ppoints.size() ) return new InvalidImp; + + return new PointImp( ppoints[i] ); +} + +const ObjectImpType* PolygonVertexType::resultId() const +{ + return PointImp::stype(); +} + +/* polygon sides */ + +static const ArgsParser::spec argsspecPolygonSide[] = +{ + { PolygonImp::stype(), I18N_NOOP( "Construct the sides of this polygon" ), + I18N_NOOP( "Select the polygon of which you want to construct the sides..." ), false }, + { IntImp::stype(), "param", "SHOULD NOT BE SEEN", false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PolygonSideType ) + +PolygonSideType::PolygonSideType() + : ArgsParserObjectType( "PolygonSide", argsspecPolygonSide, 2 ) +{ +} + +PolygonSideType::~PolygonSideType() +{ +} + +const PolygonSideType* PolygonSideType::instance() +{ + static const PolygonSideType t; + return &t; +} + +ObjectImp* PolygonSideType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + const std::vector ppoints = static_cast( parents[0] )->points(); + const uint i = static_cast( parents[1] )->data(); + + if ( i >= ppoints.size() ) return new InvalidImp; + + uint nexti = i + 1; + if ( nexti >= ppoints.size() ) nexti = 0; + + return new SegmentImp( ppoints[i], ppoints[nexti] ); +} + +const ObjectImpType* PolygonSideType::resultId() const +{ + return SegmentImp::stype(); +} + +/* convex hull of a polygon */ + +static const ArgsParser::spec argsspecConvexHull[] = +{ + { PolygonImp::stype(), I18N_NOOP( "Construct the convex hull of this polygon" ), + I18N_NOOP( "Select the polygon of which you want to construct the convex hull..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConvexHullType ) + +ConvexHullType::ConvexHullType() + : ArgsParserObjectType( "ConvexHull", argsspecConvexHull, 1 ) +{ +} + +ConvexHullType::~ConvexHullType() +{ +} + +const ConvexHullType* ConvexHullType::instance() +{ + static const ConvexHullType t; + return &t; +} + +ObjectImp* ConvexHullType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + + const std::vector ppoints = static_cast( parents[0] )->points(); + + if ( ppoints.size() < 3 ) return new InvalidImp; + + std::vector hull = computeConvexHull( ppoints ); + if ( hull.size() < 3 ) return new InvalidImp; + return new PolygonImp( hull ); +} + +const ObjectImpType* ConvexHullType::resultId() const +{ + return PolygonImp::stype(); +} diff --git a/kig/objects/special_calcers.cc b/kig/objects/special_calcers.cc deleted file mode 100644 index e70bd4e9..00000000 --- a/kig/objects/special_calcers.cc +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (C) 2004 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_calcers.h" - -static const ArgsParser::spec argsspecMeasureTransport[] = -{ - { CircleImp::stype(), I18N_NOOP( "Transport a measure on this circle" ) }, - { PointImp::stype(), I18N_NOOP( "Project this point onto the circle" ) }, - { SegmentImp::stype(), I18N_NOOP( "Segment to transport" ) } -}; - -static ArgsParser measuretransportargsparser( argsspecMeasureTransport, 3 ); - -std::vector MeasureTransportCalcer::parents() const -{ - std::vector ret; - ret.push_back( mcircle ); - ret.push_back( mpoint ); - ret.push_back( msegment ); - return ret; -} - -MeasureTransportCalcer::MeasureTransportCalcer(ObjectCalcer* circle, ObjectCalcer* point, ObjectCalcer* segment ) - : mcircle( circle ), mpoint( point ), msegment( segment ), mimp( 0 ) -{ -} - -MeasureTransportCalcer::~MeasureTransportCalcer() -{ -} - -void MeasureTransportCalcer::calc( const KigDocument& ) -{ - if ( ! measuretransportargsparser.checkArgs( parents() ) ) - return new InvalidImp(); - - if ( ! isPointOnCurve( mpoint, mcircle ) ) - return new InvalidImp(); - - const CircleImp* c = static_cast( mcircle->imp() ); - const PointImp* p = static_cast( mpoint->imp() ); - const SegmentImp* s = static_cast( msegment->imp() ); - double param = c->getParam( p->coordinate(), doc ); - double measure = s->length(); - measure /= 2*c->radius()*M_PI; - param += measure; - while (param > 1) param -= 1; - - const Coordinate nc = c->getPoint( param, doc ); - if ( nc.valid() ) return new PointImp( nc ); - else return new InvalidImp; -} - -const ObjectImpType* MeasureTransportCalcer::impRequirement( - ObjectCalcer* o, const std::vector& os ) const -{ - if ( o->imp()->inherits( CircleImp::stype() ) ) - return CircleImp::stype(); - else if ( o->imp()->inherits( PointImp::stype() ) ) - return PointImp::stype(); - else if ( o->imp()->inherits( SegmentImp::stype() ) ) - return SegmentImp::stype(); - else - { - assert( false ); - return 0; - } -} - diff --git a/kig/objects/special_calcers.cpp b/kig/objects/special_calcers.cpp new file mode 100644 index 00000000..e70bd4e9 --- /dev/null +++ b/kig/objects/special_calcers.cpp @@ -0,0 +1,84 @@ +// Copyright (C) 2004 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_calcers.h" + +static const ArgsParser::spec argsspecMeasureTransport[] = +{ + { CircleImp::stype(), I18N_NOOP( "Transport a measure on this circle" ) }, + { PointImp::stype(), I18N_NOOP( "Project this point onto the circle" ) }, + { SegmentImp::stype(), I18N_NOOP( "Segment to transport" ) } +}; + +static ArgsParser measuretransportargsparser( argsspecMeasureTransport, 3 ); + +std::vector MeasureTransportCalcer::parents() const +{ + std::vector ret; + ret.push_back( mcircle ); + ret.push_back( mpoint ); + ret.push_back( msegment ); + return ret; +} + +MeasureTransportCalcer::MeasureTransportCalcer(ObjectCalcer* circle, ObjectCalcer* point, ObjectCalcer* segment ) + : mcircle( circle ), mpoint( point ), msegment( segment ), mimp( 0 ) +{ +} + +MeasureTransportCalcer::~MeasureTransportCalcer() +{ +} + +void MeasureTransportCalcer::calc( const KigDocument& ) +{ + if ( ! measuretransportargsparser.checkArgs( parents() ) ) + return new InvalidImp(); + + if ( ! isPointOnCurve( mpoint, mcircle ) ) + return new InvalidImp(); + + const CircleImp* c = static_cast( mcircle->imp() ); + const PointImp* p = static_cast( mpoint->imp() ); + const SegmentImp* s = static_cast( msegment->imp() ); + double param = c->getParam( p->coordinate(), doc ); + double measure = s->length(); + measure /= 2*c->radius()*M_PI; + param += measure; + while (param > 1) param -= 1; + + const Coordinate nc = c->getPoint( param, doc ); + if ( nc.valid() ) return new PointImp( nc ); + else return new InvalidImp; +} + +const ObjectImpType* MeasureTransportCalcer::impRequirement( + ObjectCalcer* o, const std::vector& os ) const +{ + if ( o->imp()->inherits( CircleImp::stype() ) ) + return CircleImp::stype(); + else if ( o->imp()->inherits( PointImp::stype() ) ) + return PointImp::stype(); + else if ( o->imp()->inherits( SegmentImp::stype() ) ) + return SegmentImp::stype(); + else + { + assert( false ); + return 0; + } +} + diff --git a/kig/objects/tangent_type.cc b/kig/objects/tangent_type.cc deleted file mode 100644 index 12ebda23..00000000 --- a/kig/objects/tangent_type.cc +++ /dev/null @@ -1,285 +0,0 @@ -// 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 "tangent_type.h" - -#include "bogus_imp.h" -#include "conic_imp.h" -#include "cubic_imp.h" -#include "curve_imp.h" -#include "other_imp.h" -#include "point_imp.h" -#include "line_imp.h" - -#include "../misc/common.h" -#include "../misc/conic-common.h" -//#include "../misc/calcpaths.h" -#include "../kig/kig_part.h" -#include "../kig/kig_view.h" - -static const char constructlinetangentpoint[] = "SHOULDNOTBESEEN"; -static const char selecttangent1[] = - I18N_NOOP( "Select the curve..." ); -static const char selecttangent2[] = - I18N_NOOP( "Select the point for the tangent to go through..." ); - -static const ArgsParser::spec argsspecTangentConic[] = -{ - { ConicImp::stype(), "SHOULDNOTBESEEN", selecttangent1, false }, - { PointImp::stype(), constructlinetangentpoint, selecttangent2, true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( TangentConicType ) - -TangentConicType::TangentConicType() - : ArgsParserObjectType( "TangentConic", argsspecTangentConic, 2 ) -{ -} - -TangentConicType::~TangentConicType() -{ -} - -const TangentConicType* TangentConicType::instance() -{ - static const TangentConicType t; - return &t; -} - -ObjectImp* TangentConicType::calc( const Args& args, const KigDocument& doc ) const -{ - if ( !margsparser.checkArgs( args ) ) - return new InvalidImp; - - const ConicImp* c = static_cast( args[0] ); - const Coordinate& p = static_cast( args[1] )->coordinate(); - - if ( !c->containsPoint( p, doc ) ) - return new InvalidImp; - - bool ok; - const LineData tangent = calcConicPolarLine( c->cartesianData(), p, ok ); - - if ( !ok ) - return new InvalidImp; - - return new LineImp( tangent ); -} - -const ObjectImpType* TangentConicType::resultId() const -{ - return LineImp::stype(); -} - -/*** Arc starts here ***/ - -static const ArgsParser::spec argsspecTangentArc[] = -{ - { ArcImp::stype(), "SHOULDNOTBESEEN", selecttangent1, false }, - { PointImp::stype(), constructlinetangentpoint, selecttangent2, true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( TangentArcType ) - -TangentArcType::TangentArcType() - : ArgsParserObjectType( "TangentArc", argsspecTangentArc, 2 ) -{ -} - -TangentArcType::~TangentArcType() -{ -} - -const TangentArcType* TangentArcType::instance() -{ - static const TangentArcType t; - return &t; -} - -ObjectImp* TangentArcType::calc( const Args& args, const KigDocument& doc ) const -{ - if ( !margsparser.checkArgs( args ) ) - return new InvalidImp; - - const ArcImp* arc = static_cast( args[0] ); - const Coordinate& p = static_cast( args[1] )->coordinate(); - - if ( !arc->containsPoint( p, doc ) ) - return new InvalidImp; - - Coordinate c = arc->center(); - double sqr = arc->radius(); - sqr *= sqr; - ConicCartesianData data( 1.0, 1.0, 0.0, -2*c.x, -2*c.y, c.x*c.x + c.y*c.y - sqr ); - - bool ok; - const LineData tangent = calcConicPolarLine( data, p, ok ); - - if ( !ok ) - return new InvalidImp; - - return new LineImp( tangent ); -} - -const ObjectImpType* TangentArcType::resultId() const -{ - return LineImp::stype(); -} - -/**** Cubic starts here ****/ - -static const ArgsParser::spec argsspecTangentCubic[] = -{ - { CubicImp::stype(), "SHOULDNOTBESEEN", selecttangent1, false }, - { PointImp::stype(), constructlinetangentpoint, selecttangent2, true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( TangentCubicType ) - -TangentCubicType::TangentCubicType() - : ArgsParserObjectType( "TangentCubic", argsspecTangentCubic, 2 ) -{ -} - -TangentCubicType::~TangentCubicType() -{ -} - -const TangentCubicType* TangentCubicType::instance() -{ - static const TangentCubicType t; - return &t; -} - -ObjectImp* TangentCubicType::calc( const Args& args, const KigDocument& doc ) const -{ - if ( !margsparser.checkArgs( args ) ) - return new InvalidImp; - - const CubicImp* cubic = static_cast( args[0] ); - const Coordinate& p = static_cast( args[1] )->coordinate(); - - if ( !cubic->containsPoint( p, doc ) ) - return new InvalidImp; - - double x = p.x; - double y = p.y; - CubicCartesianData data = cubic->data(); -// double aconst = data.coeffs[0]; - double ax = data.coeffs[1]; - double ay = data.coeffs[2]; - double axx = data.coeffs[3]; - double axy = data.coeffs[4]; - double ayy = data.coeffs[5]; - double axxx = data.coeffs[6]; - double axxy = data.coeffs[7]; - double axyy = data.coeffs[8]; - double ayyy = data.coeffs[9]; - - /* mp: the tangent vector (-gy,gx) is orthogonal to the gradient (gx,gy) - * which is easy to compute from the CartesianData - * - * note: same thing could be done for conics, which would be - * much more efficient... - */ - - Coordinate tangvec = Coordinate ( - - axxy*x*x - 2*axyy*x*y - 3*ayyy*y*y - axy*x - 2*ayy*y - ay, - 3*axxx*x*x + 2*axxy*x*y + axyy*y*y + 2*axx*x + axy*y + ax - ); - const LineData tangent = LineData( p, p + tangvec ); - - return new LineImp( tangent ); -} - -const ObjectImpType* TangentCubicType::resultId() const -{ - return LineImp::stype(); -} - -/**** Curve (locus) starts here ****/ - -static const ArgsParser::spec argsspecTangentCurve[] = -{ - { CurveImp::stype(), "SHOULDNOTBESEEN", selecttangent1, false }, - { PointImp::stype(), constructlinetangentpoint, selecttangent2, true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( TangentCurveType ) - -TangentCurveType::TangentCurveType() - : ArgsParserObjectType( "TangentCurve", argsspecTangentCurve, 2 ) -{ -} - -TangentCurveType::~TangentCurveType() -{ -} - -const TangentCurveType* TangentCurveType::instance() -{ - static const TangentCurveType t; - return &t; -} - -ObjectImp* TangentCurveType::calc( const Args& args, const KigDocument& doc ) const -{ - if ( !margsparser.checkArgs( args ) ) - return new InvalidImp; - - const CurveImp* curve = static_cast( args[0] ); - const Coordinate& p = static_cast( args[1] )->coordinate(); - if ( !curve->containsPoint( p, doc ) ) - return new InvalidImp; - - const double t = curve->getParam( p, doc ); - const double tau0 = 1e-3; - const double sigma = 1e-5; - const int maxiter = 20; - - double tau = tau0; - Coordinate tang, err; - double tplus = t + tau; - double tminus = t - tau; - if ( tplus > 1 ) {tplus = 1; tminus = 1 - 2*tau;} - if ( tminus < 0 ) {tminus = 0; tplus = 2*tau;} - Coordinate tangold = (curve->getPoint( tplus, doc ) - curve->getPoint( tminus, doc ))/(2*tau); - - for (int i = 0; i < maxiter; i++) - { - tau = tau/2; - tplus = t + tau; - tminus = t - tau; - if ( tplus > 1 ) {tplus = 1; tminus = 1 - 2*tau;} - if ( tminus < 0 ) {tminus = 0; tplus = 2*tau;} - tang = (curve->getPoint( tplus, doc ) - curve->getPoint( tminus, doc ))/(2*tau); - err = (tangold - tang)/3; - if (err.length() < sigma) - { - tang = (4*tang - tangold)/3; - const LineData tangent = LineData( p, p + tang ); - return new LineImp( tangent ); - } - tangold = tang; - } - return new InvalidImp; -} - -const ObjectImpType* TangentCurveType::resultId() const -{ - return LineImp::stype(); -} diff --git a/kig/objects/tangent_type.cpp b/kig/objects/tangent_type.cpp new file mode 100644 index 00000000..12ebda23 --- /dev/null +++ b/kig/objects/tangent_type.cpp @@ -0,0 +1,285 @@ +// 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 "tangent_type.h" + +#include "bogus_imp.h" +#include "conic_imp.h" +#include "cubic_imp.h" +#include "curve_imp.h" +#include "other_imp.h" +#include "point_imp.h" +#include "line_imp.h" + +#include "../misc/common.h" +#include "../misc/conic-common.h" +//#include "../misc/calcpaths.h" +#include "../kig/kig_part.h" +#include "../kig/kig_view.h" + +static const char constructlinetangentpoint[] = "SHOULDNOTBESEEN"; +static const char selecttangent1[] = + I18N_NOOP( "Select the curve..." ); +static const char selecttangent2[] = + I18N_NOOP( "Select the point for the tangent to go through..." ); + +static const ArgsParser::spec argsspecTangentConic[] = +{ + { ConicImp::stype(), "SHOULDNOTBESEEN", selecttangent1, false }, + { PointImp::stype(), constructlinetangentpoint, selecttangent2, true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( TangentConicType ) + +TangentConicType::TangentConicType() + : ArgsParserObjectType( "TangentConic", argsspecTangentConic, 2 ) +{ +} + +TangentConicType::~TangentConicType() +{ +} + +const TangentConicType* TangentConicType::instance() +{ + static const TangentConicType t; + return &t; +} + +ObjectImp* TangentConicType::calc( const Args& args, const KigDocument& doc ) const +{ + if ( !margsparser.checkArgs( args ) ) + return new InvalidImp; + + const ConicImp* c = static_cast( args[0] ); + const Coordinate& p = static_cast( args[1] )->coordinate(); + + if ( !c->containsPoint( p, doc ) ) + return new InvalidImp; + + bool ok; + const LineData tangent = calcConicPolarLine( c->cartesianData(), p, ok ); + + if ( !ok ) + return new InvalidImp; + + return new LineImp( tangent ); +} + +const ObjectImpType* TangentConicType::resultId() const +{ + return LineImp::stype(); +} + +/*** Arc starts here ***/ + +static const ArgsParser::spec argsspecTangentArc[] = +{ + { ArcImp::stype(), "SHOULDNOTBESEEN", selecttangent1, false }, + { PointImp::stype(), constructlinetangentpoint, selecttangent2, true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( TangentArcType ) + +TangentArcType::TangentArcType() + : ArgsParserObjectType( "TangentArc", argsspecTangentArc, 2 ) +{ +} + +TangentArcType::~TangentArcType() +{ +} + +const TangentArcType* TangentArcType::instance() +{ + static const TangentArcType t; + return &t; +} + +ObjectImp* TangentArcType::calc( const Args& args, const KigDocument& doc ) const +{ + if ( !margsparser.checkArgs( args ) ) + return new InvalidImp; + + const ArcImp* arc = static_cast( args[0] ); + const Coordinate& p = static_cast( args[1] )->coordinate(); + + if ( !arc->containsPoint( p, doc ) ) + return new InvalidImp; + + Coordinate c = arc->center(); + double sqr = arc->radius(); + sqr *= sqr; + ConicCartesianData data( 1.0, 1.0, 0.0, -2*c.x, -2*c.y, c.x*c.x + c.y*c.y - sqr ); + + bool ok; + const LineData tangent = calcConicPolarLine( data, p, ok ); + + if ( !ok ) + return new InvalidImp; + + return new LineImp( tangent ); +} + +const ObjectImpType* TangentArcType::resultId() const +{ + return LineImp::stype(); +} + +/**** Cubic starts here ****/ + +static const ArgsParser::spec argsspecTangentCubic[] = +{ + { CubicImp::stype(), "SHOULDNOTBESEEN", selecttangent1, false }, + { PointImp::stype(), constructlinetangentpoint, selecttangent2, true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( TangentCubicType ) + +TangentCubicType::TangentCubicType() + : ArgsParserObjectType( "TangentCubic", argsspecTangentCubic, 2 ) +{ +} + +TangentCubicType::~TangentCubicType() +{ +} + +const TangentCubicType* TangentCubicType::instance() +{ + static const TangentCubicType t; + return &t; +} + +ObjectImp* TangentCubicType::calc( const Args& args, const KigDocument& doc ) const +{ + if ( !margsparser.checkArgs( args ) ) + return new InvalidImp; + + const CubicImp* cubic = static_cast( args[0] ); + const Coordinate& p = static_cast( args[1] )->coordinate(); + + if ( !cubic->containsPoint( p, doc ) ) + return new InvalidImp; + + double x = p.x; + double y = p.y; + CubicCartesianData data = cubic->data(); +// double aconst = data.coeffs[0]; + double ax = data.coeffs[1]; + double ay = data.coeffs[2]; + double axx = data.coeffs[3]; + double axy = data.coeffs[4]; + double ayy = data.coeffs[5]; + double axxx = data.coeffs[6]; + double axxy = data.coeffs[7]; + double axyy = data.coeffs[8]; + double ayyy = data.coeffs[9]; + + /* mp: the tangent vector (-gy,gx) is orthogonal to the gradient (gx,gy) + * which is easy to compute from the CartesianData + * + * note: same thing could be done for conics, which would be + * much more efficient... + */ + + Coordinate tangvec = Coordinate ( + - axxy*x*x - 2*axyy*x*y - 3*ayyy*y*y - axy*x - 2*ayy*y - ay, + 3*axxx*x*x + 2*axxy*x*y + axyy*y*y + 2*axx*x + axy*y + ax + ); + const LineData tangent = LineData( p, p + tangvec ); + + return new LineImp( tangent ); +} + +const ObjectImpType* TangentCubicType::resultId() const +{ + return LineImp::stype(); +} + +/**** Curve (locus) starts here ****/ + +static const ArgsParser::spec argsspecTangentCurve[] = +{ + { CurveImp::stype(), "SHOULDNOTBESEEN", selecttangent1, false }, + { PointImp::stype(), constructlinetangentpoint, selecttangent2, true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( TangentCurveType ) + +TangentCurveType::TangentCurveType() + : ArgsParserObjectType( "TangentCurve", argsspecTangentCurve, 2 ) +{ +} + +TangentCurveType::~TangentCurveType() +{ +} + +const TangentCurveType* TangentCurveType::instance() +{ + static const TangentCurveType t; + return &t; +} + +ObjectImp* TangentCurveType::calc( const Args& args, const KigDocument& doc ) const +{ + if ( !margsparser.checkArgs( args ) ) + return new InvalidImp; + + const CurveImp* curve = static_cast( args[0] ); + const Coordinate& p = static_cast( args[1] )->coordinate(); + if ( !curve->containsPoint( p, doc ) ) + return new InvalidImp; + + const double t = curve->getParam( p, doc ); + const double tau0 = 1e-3; + const double sigma = 1e-5; + const int maxiter = 20; + + double tau = tau0; + Coordinate tang, err; + double tplus = t + tau; + double tminus = t - tau; + if ( tplus > 1 ) {tplus = 1; tminus = 1 - 2*tau;} + if ( tminus < 0 ) {tminus = 0; tplus = 2*tau;} + Coordinate tangold = (curve->getPoint( tplus, doc ) - curve->getPoint( tminus, doc ))/(2*tau); + + for (int i = 0; i < maxiter; i++) + { + tau = tau/2; + tplus = t + tau; + tminus = t - tau; + if ( tplus > 1 ) {tplus = 1; tminus = 1 - 2*tau;} + if ( tminus < 0 ) {tminus = 0; tplus = 2*tau;} + tang = (curve->getPoint( tplus, doc ) - curve->getPoint( tminus, doc ))/(2*tau); + err = (tangold - tang)/3; + if (err.length() < sigma) + { + tang = (4*tang - tangold)/3; + const LineData tangent = LineData( p, p + tang ); + return new LineImp( tangent ); + } + tangold = tang; + } + return new InvalidImp; +} + +const ObjectImpType* TangentCurveType::resultId() const +{ + return LineImp::stype(); +} diff --git a/kig/objects/tests_type.cc b/kig/objects/tests_type.cc deleted file mode 100644 index e85c111e..00000000 --- a/kig/objects/tests_type.cc +++ /dev/null @@ -1,382 +0,0 @@ -// Copyright (C) 2004 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 "tests_type.h" - -#include "line_imp.h" -#include "polygon_imp.h" -#include "point_imp.h" -#include "bogus_imp.h" -#include "other_imp.h" - -#include - -static const ArgsParser::spec argsspecAreParallel[] = -{ - { AbstractLineImp::stype(), I18N_NOOP( "Is this line parallel?" ), - I18N_NOOP( "Select the first of the two possibly parallel lines..." ), false }, - { AbstractLineImp::stype(), I18N_NOOP( "Parallel to this line?" ), - I18N_NOOP( "Select the other of the two possibly parallel lines..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( AreParallelType ) - -AreParallelType::AreParallelType() - : ArgsParserObjectType( "AreParallel", - argsspecAreParallel, 2 ) -{ -} - -AreParallelType::~AreParallelType() -{ -} - -const AreParallelType* AreParallelType::instance() -{ - static const AreParallelType t; - return &t; -} - -ObjectImp* AreParallelType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - const LineData& l1 = static_cast( parents[0] )->data(); - const LineData& l2 = static_cast( parents[1] )->data(); - - if ( l1.isParallelTo( l2 ) ) - return new TestResultImp( i18n( "These lines are parallel." ) ); - else - return new TestResultImp( i18n( "These lines are not parallel." ) ); - -} - -const ObjectImpType* AreParallelType::resultId() const -{ - return TestResultImp::stype(); -} - -static const ArgsParser::spec argsspecAreOrthogonal[] = -{ - { AbstractLineImp::stype(), I18N_NOOP( "Is this line orthogonal?" ), - I18N_NOOP( "Select the first of the two possibly orthogonal lines..." ), false }, - { AbstractLineImp::stype(), I18N_NOOP( "Orthogonal to this line?" ), - I18N_NOOP( "Select the other of the two possibly orthogonal lines..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( AreOrthogonalType ) - -AreOrthogonalType::AreOrthogonalType() - : ArgsParserObjectType( "AreOrthogonal", - argsspecAreOrthogonal, 2 ) -{ -} - -AreOrthogonalType::~AreOrthogonalType() -{ -} - -const AreOrthogonalType* AreOrthogonalType::instance() -{ - static const AreOrthogonalType t; - return &t; -} - -ObjectImp* AreOrthogonalType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - const LineData& l1 = static_cast( parents[0] )->data(); - const LineData& l2 = static_cast( parents[1] )->data(); - - if ( l1.isOrthogonalTo( l2 ) ) - return new TestResultImp( i18n( "These lines are orthogonal." ) ); - else - return new TestResultImp( i18n( "These lines are not orthogonal." ) ); - -} - -const ObjectImpType* AreOrthogonalType::resultId() const -{ - return TestResultImp::stype(); -} - -static const ArgsParser::spec argsspecAreCollinear[] = -{ - { PointImp::stype(), I18N_NOOP( "Check collinearity of this point" ), - I18N_NOOP( "Select the first of the three possibly collinear points..." ), false }, - { PointImp::stype(), I18N_NOOP( "and this second point" ), - I18N_NOOP( "Select the second of the three possibly collinear points..." ), false }, - { PointImp::stype(), I18N_NOOP( "with this third point" ), - I18N_NOOP( "Select the last of the three possibly collinear points..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( AreCollinearType ) - -AreCollinearType::AreCollinearType() - : ArgsParserObjectType( "AreCollinear", - argsspecAreCollinear, 3 ) -{ -} - -AreCollinearType::~AreCollinearType() -{ -} - -const AreCollinearType* AreCollinearType::instance() -{ - static const AreCollinearType t; - return &t; -} - -ObjectImp* AreCollinearType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - const Coordinate& p1 = static_cast( parents[0] )->coordinate(); - const Coordinate& p2 = static_cast( parents[1] )->coordinate(); - const Coordinate& p3 = static_cast( parents[2] )->coordinate(); - - if ( areCollinear( p1, p2, p3 ) ) - return new TestResultImp( i18n( "These points are collinear." ) ); - else - return new TestResultImp( i18n( "These points are not collinear." ) ); -} - -const ObjectImpType* AreCollinearType::resultId() const -{ - return TestResultImp::stype(); -} - -static const ArgsParser::spec containsTestArgsSpec[] = -{ - { PointImp::stype(), I18N_NOOP( "Check whether this point is on a curve" ), - I18N_NOOP( "Select the point you want to test..." ), false }, - { CurveImp::stype(), I18N_NOOP( "Check whether the point is on this curve" ), - I18N_NOOP( "Select the curve that the point might be on..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ContainsTestType ) - -ContainsTestType::ContainsTestType() - : ArgsParserObjectType( "ContainsTest", containsTestArgsSpec, 2 ) -{ -} - -ContainsTestType::~ContainsTestType() -{ -} - -const ContainsTestType* ContainsTestType::instance() -{ - static const ContainsTestType t; - return &t; -} - -ObjectImp* ContainsTestType::calc( const Args& parents, const KigDocument& doc ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - const Coordinate& p = static_cast( parents[0] )->coordinate(); - const CurveImp* c = static_cast( parents[1] ); - - if ( c->containsPoint( p, doc ) ) - return new TestResultImp( i18n( "This curve contains the point." ) ); - else - return new TestResultImp( i18n( "This curve does not contain the point." ) ); -} - -const ObjectImpType* ContainsTestType::resultId() const -{ - return TestResultImp::stype(); -} - -/* - * containment test of a point in a polygon - */ - -static const ArgsParser::spec InPolygonTestArgsSpec[] = -{ - { PointImp::stype(), I18N_NOOP( "Check whether this point is in a polygon" ), - I18N_NOOP( "Select the point you want to test..." ), false }, - { PolygonImp::stype(), I18N_NOOP( "Check whether the point is in this polygon" ), - I18N_NOOP( "Select the polygon that the point might be in..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InPolygonTestType ) - -InPolygonTestType::InPolygonTestType() - : ArgsParserObjectType( "InPolygonTest", InPolygonTestArgsSpec, 2 ) -{ -} - -InPolygonTestType::~InPolygonTestType() -{ -} - -const InPolygonTestType* InPolygonTestType::instance() -{ - static const InPolygonTestType t; - return &t; -} - -ObjectImp* InPolygonTestType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - const Coordinate& p = static_cast( parents[0] )->coordinate(); - const PolygonImp* pol = static_cast( parents[1] ); - - if ( pol->isInPolygon( p ) ) - return new TestResultImp( i18n( "This polygon contains the point." ) ); - else - return new TestResultImp( i18n( "This polygon does not contain the point." ) ); -} - -const ObjectImpType* InPolygonTestType::resultId() const -{ - return TestResultImp::stype(); -} - -/* - * test if a polygon is convex - */ - -static const ArgsParser::spec ConvexPolygonTestArgsSpec[] = -{ - { PolygonImp::stype(), I18N_NOOP( "Check whether this polygon is convex" ), - I18N_NOOP( "Select the polygon you want to test for convexity..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConvexPolygonTestType ) - -ConvexPolygonTestType::ConvexPolygonTestType() - : ArgsParserObjectType( "ConvexPolygonTest", ConvexPolygonTestArgsSpec, 1 ) -{ -} - -ConvexPolygonTestType::~ConvexPolygonTestType() -{ -} - -const ConvexPolygonTestType* ConvexPolygonTestType::instance() -{ - static const ConvexPolygonTestType t; - return &t; -} - -ObjectImp* ConvexPolygonTestType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - const PolygonImp* pol = static_cast( parents[0] ); - - if ( pol->isConvex() ) - return new TestResultImp( i18n( "This polygon is convex." ) ); - else - return new TestResultImp( i18n( "This polygon is not convex." ) ); -} - -const ObjectImpType* ConvexPolygonTestType::resultId() const -{ - return TestResultImp::stype(); -} - -/* - * same distance test - */ - -static const ArgsParser::spec argsspecSameDistanceType[] = -{ - { PointImp::stype(), I18N_NOOP( "Check if this point has the same distance" ), - I18N_NOOP( "Select the point which might have the same distance from two other points..." ), false }, - { PointImp::stype(), I18N_NOOP( "from this point" ), - I18N_NOOP( "Select the first of the two other points..." ), false }, - { PointImp::stype(), I18N_NOOP( "and from this second point" ), - I18N_NOOP( "Select the other of the two other points..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( SameDistanceType ) - -SameDistanceType::SameDistanceType() - : ArgsParserObjectType( "SameDistanceType", argsspecSameDistanceType, 3 ) -{ -} - -SameDistanceType::~SameDistanceType() -{ -} - -const SameDistanceType* SameDistanceType::instance() -{ - static const SameDistanceType t; - return &t; -} - -ObjectImp* SameDistanceType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - const Coordinate& p1 = static_cast( parents[0] )->coordinate(); - const Coordinate& p2 = static_cast( parents[1] )->coordinate(); - const Coordinate& p3 = static_cast( parents[2] )->coordinate(); - - if ( fabs( ( p1 - p2 ).length() - ( p1 - p3 ).length() ) < 10e-5 ) - return new TestResultImp( i18n( "The two distances are the same." ) ); - else - return new TestResultImp( i18n( "The two distances are not the same." ) ); -} - -const ObjectImpType* SameDistanceType::resultId() const -{ - return TestResultImp::stype(); -} - -static const ArgsParser::spec vectorEqualityArgsSpec[] = -{ - { VectorImp::stype(), I18N_NOOP( "Check whether this vector is equal to another vector" ), - I18N_NOOP( "Select the first of the two possibly equal vectors..." ), false }, - { VectorImp::stype(), I18N_NOOP( "Check whether this vector is equal to the other vector" ), - I18N_NOOP( "Select the other of the two possibly equal vectors..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( VectorEqualityTestType ) - -VectorEqualityTestType::VectorEqualityTestType() - : ArgsParserObjectType( "VectorEquality", vectorEqualityArgsSpec, 2 ) -{ -} - -VectorEqualityTestType::~VectorEqualityTestType() -{ -} - -const VectorEqualityTestType* VectorEqualityTestType::instance() -{ - static const VectorEqualityTestType t; - return &t; -} - -ObjectImp* VectorEqualityTestType::calc( const Args& parents, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; - const Coordinate& v1 = static_cast( parents[0] )->dir(); - const Coordinate& v2 = static_cast( parents[1] )->dir(); - - if ( ( v1 - v2 ).length() < 10e-5 ) - return new TestResultImp( i18n( "The two vectors are the same." ) ); - else - return new TestResultImp( i18n( "The two vectors are not the same." ) ); -} - -const ObjectImpType* VectorEqualityTestType::resultId() const -{ - return TestResultImp::stype(); -} diff --git a/kig/objects/tests_type.cpp b/kig/objects/tests_type.cpp new file mode 100644 index 00000000..e85c111e --- /dev/null +++ b/kig/objects/tests_type.cpp @@ -0,0 +1,382 @@ +// Copyright (C) 2004 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 "tests_type.h" + +#include "line_imp.h" +#include "polygon_imp.h" +#include "point_imp.h" +#include "bogus_imp.h" +#include "other_imp.h" + +#include + +static const ArgsParser::spec argsspecAreParallel[] = +{ + { AbstractLineImp::stype(), I18N_NOOP( "Is this line parallel?" ), + I18N_NOOP( "Select the first of the two possibly parallel lines..." ), false }, + { AbstractLineImp::stype(), I18N_NOOP( "Parallel to this line?" ), + I18N_NOOP( "Select the other of the two possibly parallel lines..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( AreParallelType ) + +AreParallelType::AreParallelType() + : ArgsParserObjectType( "AreParallel", + argsspecAreParallel, 2 ) +{ +} + +AreParallelType::~AreParallelType() +{ +} + +const AreParallelType* AreParallelType::instance() +{ + static const AreParallelType t; + return &t; +} + +ObjectImp* AreParallelType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + const LineData& l1 = static_cast( parents[0] )->data(); + const LineData& l2 = static_cast( parents[1] )->data(); + + if ( l1.isParallelTo( l2 ) ) + return new TestResultImp( i18n( "These lines are parallel." ) ); + else + return new TestResultImp( i18n( "These lines are not parallel." ) ); + +} + +const ObjectImpType* AreParallelType::resultId() const +{ + return TestResultImp::stype(); +} + +static const ArgsParser::spec argsspecAreOrthogonal[] = +{ + { AbstractLineImp::stype(), I18N_NOOP( "Is this line orthogonal?" ), + I18N_NOOP( "Select the first of the two possibly orthogonal lines..." ), false }, + { AbstractLineImp::stype(), I18N_NOOP( "Orthogonal to this line?" ), + I18N_NOOP( "Select the other of the two possibly orthogonal lines..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( AreOrthogonalType ) + +AreOrthogonalType::AreOrthogonalType() + : ArgsParserObjectType( "AreOrthogonal", + argsspecAreOrthogonal, 2 ) +{ +} + +AreOrthogonalType::~AreOrthogonalType() +{ +} + +const AreOrthogonalType* AreOrthogonalType::instance() +{ + static const AreOrthogonalType t; + return &t; +} + +ObjectImp* AreOrthogonalType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + const LineData& l1 = static_cast( parents[0] )->data(); + const LineData& l2 = static_cast( parents[1] )->data(); + + if ( l1.isOrthogonalTo( l2 ) ) + return new TestResultImp( i18n( "These lines are orthogonal." ) ); + else + return new TestResultImp( i18n( "These lines are not orthogonal." ) ); + +} + +const ObjectImpType* AreOrthogonalType::resultId() const +{ + return TestResultImp::stype(); +} + +static const ArgsParser::spec argsspecAreCollinear[] = +{ + { PointImp::stype(), I18N_NOOP( "Check collinearity of this point" ), + I18N_NOOP( "Select the first of the three possibly collinear points..." ), false }, + { PointImp::stype(), I18N_NOOP( "and this second point" ), + I18N_NOOP( "Select the second of the three possibly collinear points..." ), false }, + { PointImp::stype(), I18N_NOOP( "with this third point" ), + I18N_NOOP( "Select the last of the three possibly collinear points..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( AreCollinearType ) + +AreCollinearType::AreCollinearType() + : ArgsParserObjectType( "AreCollinear", + argsspecAreCollinear, 3 ) +{ +} + +AreCollinearType::~AreCollinearType() +{ +} + +const AreCollinearType* AreCollinearType::instance() +{ + static const AreCollinearType t; + return &t; +} + +ObjectImp* AreCollinearType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + const Coordinate& p1 = static_cast( parents[0] )->coordinate(); + const Coordinate& p2 = static_cast( parents[1] )->coordinate(); + const Coordinate& p3 = static_cast( parents[2] )->coordinate(); + + if ( areCollinear( p1, p2, p3 ) ) + return new TestResultImp( i18n( "These points are collinear." ) ); + else + return new TestResultImp( i18n( "These points are not collinear." ) ); +} + +const ObjectImpType* AreCollinearType::resultId() const +{ + return TestResultImp::stype(); +} + +static const ArgsParser::spec containsTestArgsSpec[] = +{ + { PointImp::stype(), I18N_NOOP( "Check whether this point is on a curve" ), + I18N_NOOP( "Select the point you want to test..." ), false }, + { CurveImp::stype(), I18N_NOOP( "Check whether the point is on this curve" ), + I18N_NOOP( "Select the curve that the point might be on..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ContainsTestType ) + +ContainsTestType::ContainsTestType() + : ArgsParserObjectType( "ContainsTest", containsTestArgsSpec, 2 ) +{ +} + +ContainsTestType::~ContainsTestType() +{ +} + +const ContainsTestType* ContainsTestType::instance() +{ + static const ContainsTestType t; + return &t; +} + +ObjectImp* ContainsTestType::calc( const Args& parents, const KigDocument& doc ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + const Coordinate& p = static_cast( parents[0] )->coordinate(); + const CurveImp* c = static_cast( parents[1] ); + + if ( c->containsPoint( p, doc ) ) + return new TestResultImp( i18n( "This curve contains the point." ) ); + else + return new TestResultImp( i18n( "This curve does not contain the point." ) ); +} + +const ObjectImpType* ContainsTestType::resultId() const +{ + return TestResultImp::stype(); +} + +/* + * containment test of a point in a polygon + */ + +static const ArgsParser::spec InPolygonTestArgsSpec[] = +{ + { PointImp::stype(), I18N_NOOP( "Check whether this point is in a polygon" ), + I18N_NOOP( "Select the point you want to test..." ), false }, + { PolygonImp::stype(), I18N_NOOP( "Check whether the point is in this polygon" ), + I18N_NOOP( "Select the polygon that the point might be in..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( InPolygonTestType ) + +InPolygonTestType::InPolygonTestType() + : ArgsParserObjectType( "InPolygonTest", InPolygonTestArgsSpec, 2 ) +{ +} + +InPolygonTestType::~InPolygonTestType() +{ +} + +const InPolygonTestType* InPolygonTestType::instance() +{ + static const InPolygonTestType t; + return &t; +} + +ObjectImp* InPolygonTestType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + const Coordinate& p = static_cast( parents[0] )->coordinate(); + const PolygonImp* pol = static_cast( parents[1] ); + + if ( pol->isInPolygon( p ) ) + return new TestResultImp( i18n( "This polygon contains the point." ) ); + else + return new TestResultImp( i18n( "This polygon does not contain the point." ) ); +} + +const ObjectImpType* InPolygonTestType::resultId() const +{ + return TestResultImp::stype(); +} + +/* + * test if a polygon is convex + */ + +static const ArgsParser::spec ConvexPolygonTestArgsSpec[] = +{ + { PolygonImp::stype(), I18N_NOOP( "Check whether this polygon is convex" ), + I18N_NOOP( "Select the polygon you want to test for convexity..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConvexPolygonTestType ) + +ConvexPolygonTestType::ConvexPolygonTestType() + : ArgsParserObjectType( "ConvexPolygonTest", ConvexPolygonTestArgsSpec, 1 ) +{ +} + +ConvexPolygonTestType::~ConvexPolygonTestType() +{ +} + +const ConvexPolygonTestType* ConvexPolygonTestType::instance() +{ + static const ConvexPolygonTestType t; + return &t; +} + +ObjectImp* ConvexPolygonTestType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + const PolygonImp* pol = static_cast( parents[0] ); + + if ( pol->isConvex() ) + return new TestResultImp( i18n( "This polygon is convex." ) ); + else + return new TestResultImp( i18n( "This polygon is not convex." ) ); +} + +const ObjectImpType* ConvexPolygonTestType::resultId() const +{ + return TestResultImp::stype(); +} + +/* + * same distance test + */ + +static const ArgsParser::spec argsspecSameDistanceType[] = +{ + { PointImp::stype(), I18N_NOOP( "Check if this point has the same distance" ), + I18N_NOOP( "Select the point which might have the same distance from two other points..." ), false }, + { PointImp::stype(), I18N_NOOP( "from this point" ), + I18N_NOOP( "Select the first of the two other points..." ), false }, + { PointImp::stype(), I18N_NOOP( "and from this second point" ), + I18N_NOOP( "Select the other of the two other points..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( SameDistanceType ) + +SameDistanceType::SameDistanceType() + : ArgsParserObjectType( "SameDistanceType", argsspecSameDistanceType, 3 ) +{ +} + +SameDistanceType::~SameDistanceType() +{ +} + +const SameDistanceType* SameDistanceType::instance() +{ + static const SameDistanceType t; + return &t; +} + +ObjectImp* SameDistanceType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + const Coordinate& p1 = static_cast( parents[0] )->coordinate(); + const Coordinate& p2 = static_cast( parents[1] )->coordinate(); + const Coordinate& p3 = static_cast( parents[2] )->coordinate(); + + if ( fabs( ( p1 - p2 ).length() - ( p1 - p3 ).length() ) < 10e-5 ) + return new TestResultImp( i18n( "The two distances are the same." ) ); + else + return new TestResultImp( i18n( "The two distances are not the same." ) ); +} + +const ObjectImpType* SameDistanceType::resultId() const +{ + return TestResultImp::stype(); +} + +static const ArgsParser::spec vectorEqualityArgsSpec[] = +{ + { VectorImp::stype(), I18N_NOOP( "Check whether this vector is equal to another vector" ), + I18N_NOOP( "Select the first of the two possibly equal vectors..." ), false }, + { VectorImp::stype(), I18N_NOOP( "Check whether this vector is equal to the other vector" ), + I18N_NOOP( "Select the other of the two possibly equal vectors..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( VectorEqualityTestType ) + +VectorEqualityTestType::VectorEqualityTestType() + : ArgsParserObjectType( "VectorEquality", vectorEqualityArgsSpec, 2 ) +{ +} + +VectorEqualityTestType::~VectorEqualityTestType() +{ +} + +const VectorEqualityTestType* VectorEqualityTestType::instance() +{ + static const VectorEqualityTestType t; + return &t; +} + +ObjectImp* VectorEqualityTestType::calc( const Args& parents, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; + const Coordinate& v1 = static_cast( parents[0] )->dir(); + const Coordinate& v2 = static_cast( parents[1] )->dir(); + + if ( ( v1 - v2 ).length() < 10e-5 ) + return new TestResultImp( i18n( "The two vectors are the same." ) ); + else + return new TestResultImp( i18n( "The two vectors are not the same." ) ); +} + +const ObjectImpType* VectorEqualityTestType::resultId() const +{ + return TestResultImp::stype(); +} diff --git a/kig/objects/text_imp.cc b/kig/objects/text_imp.cc deleted file mode 100644 index 32591c16..00000000 --- a/kig/objects/text_imp.cc +++ /dev/null @@ -1,173 +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 "text_imp.h" - -#include "bogus_imp.h" -#include "../misc/kigpainter.h" - -TextImp::TextImp( const TQString& text, const Coordinate& loc, bool frame ) - : mtext( text), mloc( loc ), mframe( frame ), mboundrect( Rect::invalidRect() ) -{ -} - -TextImp* TextImp::copy() const -{ - return new TextImp( mtext, mloc ); -} - -TextImp::~TextImp() -{ -} - -Coordinate TextImp::attachPoint() const -{ - return Coordinate::invalidCoord(); -} - -ObjectImp* TextImp::transform( const Transformation& t ) const -{ - Coordinate nloc = t.apply( mloc ); - return new TextImp( mtext, nloc, mframe ); -} - -void TextImp::draw( KigPainter& p ) const -{ - mboundrect = p.simpleBoundingRect( mloc, mtext ); - p.drawTextFrame( mboundrect, mtext, mframe ); -} - -bool TextImp::contains( const Coordinate& p, int, const KigWidget& ) const -{ - return mboundrect.contains( p ); -} - -bool TextImp::inRect( const Rect& r, int, const KigWidget& ) const -{ - return mboundrect.intersects( r ); -} - -bool TextImp::valid() const -{ - return true; -} - -const uint TextImp::numberOfProperties() const -{ - return Parent::numberOfProperties() + 1; -} - -const QCStringList TextImp::propertiesInternalNames() const -{ - QCStringList ret = Parent::propertiesInternalNames(); - ret << "kig_text"; - return ret; -} - -const QCStringList TextImp::properties() const -{ - QCStringList ret = Parent::properties(); - ret << I18N_NOOP( "Text" ); - return ret; -} - -const ObjectImpType* TextImp::impRequirementForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::impRequirementForProperty( which ); - return TextImp::stype(); -} - -const char* TextImp::iconForProperty( uint which ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::iconForProperty( which ); - else if ( which == Parent::numberOfProperties() ) - return "text"; // text - else assert( false ); - return ""; -} - -ObjectImp* TextImp::property( uint which, const KigDocument& w ) const -{ - if ( which < Parent::numberOfProperties() ) - return Parent::property( which, w ); - else if ( which == Parent::numberOfProperties() ) - return new StringImp( text() ); - else assert( false ); - return new InvalidImp; -} - -TQString TextImp::text() const -{ - return mtext; -} - -void TextImp::visit( ObjectImpVisitor* vtor ) const -{ - vtor->visit( this ); -} - -const Coordinate TextImp::coordinate() const -{ - return mloc; -} - -bool TextImp::equals( const ObjectImp& rhs ) const -{ - return rhs.inherits( TextImp::stype() ) && - static_cast( rhs ).coordinate() == coordinate() && - static_cast( rhs ).text() == text() && - static_cast( rhs ).hasFrame() == hasFrame(); -} - -bool TextImp::hasFrame() const -{ - return mframe; -} - -const ObjectImpType* TextImp::stype() -{ - static const ObjectImpType t( - Parent::stype(), "label", - I18N_NOOP( "label" ), - I18N_NOOP( "Select this label" ), - I18N_NOOP( "Select label %1" ), - I18N_NOOP( "Remove a Label" ), - I18N_NOOP( "Add a Label" ), - I18N_NOOP( "Move a Label" ), - I18N_NOOP( "Attach to this label" ), - I18N_NOOP( "Show a Label" ), - I18N_NOOP( "Hide a Label" ) - ); - return &t; -} - -const ObjectImpType* TextImp::type() const -{ - return TextImp::stype(); -} - -bool TextImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const -{ - return Parent::isPropertyDefinedOnOrThroughThisImp( which ); -} - -Rect TextImp::surroundingRect() const -{ - return mboundrect; -} diff --git a/kig/objects/text_imp.cpp b/kig/objects/text_imp.cpp new file mode 100644 index 00000000..32591c16 --- /dev/null +++ b/kig/objects/text_imp.cpp @@ -0,0 +1,173 @@ +// 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 "text_imp.h" + +#include "bogus_imp.h" +#include "../misc/kigpainter.h" + +TextImp::TextImp( const TQString& text, const Coordinate& loc, bool frame ) + : mtext( text), mloc( loc ), mframe( frame ), mboundrect( Rect::invalidRect() ) +{ +} + +TextImp* TextImp::copy() const +{ + return new TextImp( mtext, mloc ); +} + +TextImp::~TextImp() +{ +} + +Coordinate TextImp::attachPoint() const +{ + return Coordinate::invalidCoord(); +} + +ObjectImp* TextImp::transform( const Transformation& t ) const +{ + Coordinate nloc = t.apply( mloc ); + return new TextImp( mtext, nloc, mframe ); +} + +void TextImp::draw( KigPainter& p ) const +{ + mboundrect = p.simpleBoundingRect( mloc, mtext ); + p.drawTextFrame( mboundrect, mtext, mframe ); +} + +bool TextImp::contains( const Coordinate& p, int, const KigWidget& ) const +{ + return mboundrect.contains( p ); +} + +bool TextImp::inRect( const Rect& r, int, const KigWidget& ) const +{ + return mboundrect.intersects( r ); +} + +bool TextImp::valid() const +{ + return true; +} + +const uint TextImp::numberOfProperties() const +{ + return Parent::numberOfProperties() + 1; +} + +const QCStringList TextImp::propertiesInternalNames() const +{ + QCStringList ret = Parent::propertiesInternalNames(); + ret << "kig_text"; + return ret; +} + +const QCStringList TextImp::properties() const +{ + QCStringList ret = Parent::properties(); + ret << I18N_NOOP( "Text" ); + return ret; +} + +const ObjectImpType* TextImp::impRequirementForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::impRequirementForProperty( which ); + return TextImp::stype(); +} + +const char* TextImp::iconForProperty( uint which ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::iconForProperty( which ); + else if ( which == Parent::numberOfProperties() ) + return "text"; // text + else assert( false ); + return ""; +} + +ObjectImp* TextImp::property( uint which, const KigDocument& w ) const +{ + if ( which < Parent::numberOfProperties() ) + return Parent::property( which, w ); + else if ( which == Parent::numberOfProperties() ) + return new StringImp( text() ); + else assert( false ); + return new InvalidImp; +} + +TQString TextImp::text() const +{ + return mtext; +} + +void TextImp::visit( ObjectImpVisitor* vtor ) const +{ + vtor->visit( this ); +} + +const Coordinate TextImp::coordinate() const +{ + return mloc; +} + +bool TextImp::equals( const ObjectImp& rhs ) const +{ + return rhs.inherits( TextImp::stype() ) && + static_cast( rhs ).coordinate() == coordinate() && + static_cast( rhs ).text() == text() && + static_cast( rhs ).hasFrame() == hasFrame(); +} + +bool TextImp::hasFrame() const +{ + return mframe; +} + +const ObjectImpType* TextImp::stype() +{ + static const ObjectImpType t( + Parent::stype(), "label", + I18N_NOOP( "label" ), + I18N_NOOP( "Select this label" ), + I18N_NOOP( "Select label %1" ), + I18N_NOOP( "Remove a Label" ), + I18N_NOOP( "Add a Label" ), + I18N_NOOP( "Move a Label" ), + I18N_NOOP( "Attach to this label" ), + I18N_NOOP( "Show a Label" ), + I18N_NOOP( "Hide a Label" ) + ); + return &t; +} + +const ObjectImpType* TextImp::type() const +{ + return TextImp::stype(); +} + +bool TextImp::isPropertyDefinedOnOrThroughThisImp( uint which ) const +{ + return Parent::isPropertyDefinedOnOrThroughThisImp( which ); +} + +Rect TextImp::surroundingRect() const +{ + return mboundrect; +} diff --git a/kig/objects/text_type.cc b/kig/objects/text_type.cc deleted file mode 100644 index c82c2047..00000000 --- a/kig/objects/text_type.cc +++ /dev/null @@ -1,215 +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 "text_type.h" - -#include "text_imp.h" -#include "bogus_imp.h" -#include "point_imp.h" -#include "line_imp.h" - -#include "../kig/kig_view.h" -#include "../kig/kig_part.h" -#include "../kig/kig_commands.h" -#include "../modes/label.h" -#include "../misc/coordinate_system.h" - -#include - -#include -#include - -#include - -#include - -static const ArgsParser::spec arggspeccs[] = -{ - { IntImp::stype(), "UNUSED", "SHOULD NOT BE SEEN", false }, - { PointImp::stype(), "UNUSED", "SHOULD NOT BE SEEN", false }, - { StringImp::stype(), "UNUSED", "SHOULD NOT BE SEEN", false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( TextType ) - -TextType::TextType() - : ObjectType( "Label" ), mparser( arggspeccs, 3 ) -{ -} - -TextType::~TextType() -{ -} - -const TextType* TextType::instance() -{ - static const TextType t; - return &t; -} - -const ObjectImpType* TextType::resultId() const -{ - return TextImp::stype(); -} - -const ObjectImpType* TextType::impRequirement( const ObjectImp* o, const Args& args ) const -{ - assert( args.size() >= 3 ); - Args firstthree( args.begin(), args.begin() + 3 ); - if ( o == args[0] || o == args[1] || o == args[2] ) - return mparser.impRequirement( o, firstthree ); - else - return ObjectImp::stype(); -} - -ObjectImp* TextType::calc( const Args& parents, const KigDocument& doc ) const -{ - if( parents.size() < 3 ) return new InvalidImp; - Args firstthree( parents.begin(), parents.begin() + 3 ); - Args varargs( parents.begin() + 3, parents.end() ); - - if ( ! mparser.checkArgs( firstthree ) ) return new InvalidImp; - - int frame = static_cast( firstthree[0] )->data(); - bool needframe = frame != 0; - const Coordinate t = static_cast( firstthree[1] )->coordinate(); - TQString s = static_cast( firstthree[2] )->data(); - - for ( Args::iterator i = varargs.begin(); i != varargs.end(); ++i ) - (*i)->fillInNextEscape( s, doc ); - - return new TextImp( s, t, needframe ); -} - -bool TextType::canMove( const ObjectTypeCalcer& ) const -{ - return true; -} - -bool TextType::isFreelyTranslatable( const ObjectTypeCalcer& ) const -{ - return true; -} - -void TextType::move( ObjectTypeCalcer& ourobj, const Coordinate& to, - const KigDocument& d ) const -{ - const std::vector parents = ourobj.parents(); - assert( parents.size() >= 3 ); - const std::vector firstthree( parents.begin(), parents.begin() + 3 ); - if( dynamic_cast( firstthree[1] ) ) - { - ObjectConstCalcer* c = static_cast( firstthree[1] ); - c->setImp( new PointImp( to ) ); - } - else - firstthree[1]->move( to, d ); -} - -TQStringList TextType::specialActions() const -{ - TQStringList ret; - ret << i18n( "&Copy Text" ); - ret << i18n( "&Toggle Frame" ); - ret << i18n( "&Redefine..." ); - return ret; -} - -void TextType::executeAction( int i, ObjectHolder& o, ObjectTypeCalcer& c, - KigPart& doc, KigWidget&, - NormalMode& ) const -{ - std::vector parents = c.parents(); - assert( parents.size() >= 3 ); - - std::vector firstthree( parents.begin(), parents.begin() + 3 ); - - assert( mparser.checkArgs( firstthree ) ); - assert( dynamic_cast( firstthree[0] ) ); - assert( dynamic_cast( firstthree[2] ) ); - - if ( i == 0 ) - { - TQClipboard* cb = kapp->clipboard(); - - // copy the text into the clipboard - const TextImp* ti = static_cast( c.imp() ); - cb->setText( ti->text(), TQClipboard::Clipboard ); - } - else if ( i == 1 ) - { - // toggle label frame - int n = (static_cast( firstthree[0]->imp() )->data() + 1) % 2; - KigCommand* kc = new KigCommand( doc, i18n( "Toggle Label Frame" ) ); - kc->addTask( new ChangeObjectConstCalcerTask( - static_cast( firstthree[0] ), - new IntImp( n ) ) ); - doc.history()->addCommand( kc ); - } - else if ( i == 2 ) - { - assert( dynamic_cast( o.calcer() ) ); - // redefine.. - TextLabelRedefineMode m( doc, static_cast( o.calcer() ) ); - doc.runMode( &m ); - } - else assert( false ); -} - -const ArgsParser& TextType::argParser() const -{ - return mparser; -} - -const Coordinate TextType::moveReferencePoint( const ObjectTypeCalcer& ourobj ) const -{ - assert( ourobj.imp()->inherits( TextImp::stype() ) ); - return static_cast( ourobj.imp() )->coordinate(); -} - -std::vector TextType::sortArgs( const std::vector& os ) const -{ - assert( os.size() >= 3 ); - std::vector ret( os.begin(), os.begin() + 3 ); - ret = mparser.parse( ret ); - std::copy( os.begin() + 3, os.end(), std::back_inserter( ret ) ); - return ret; -} - -Args TextType::sortArgs( const Args& args ) const -{ - assert( args.size() >= 3 ); - Args ret( args.begin(), args.begin() + 3 ); - ret = mparser.parse( ret ); - std::copy( args.begin() + 3, args.end(), std::back_inserter( ret ) ); - return ret; -} - -std::vector TextType::movableParents( const ObjectTypeCalcer& ourobj ) const -{ - const std::vector parents = ourobj.parents(); - assert( parents.size() >= 3 ); - std::vector ret = parents[1]->movableParents(); - ret.push_back( parents[1] ); - return ret; -} - -bool TextType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const -{ - return false; -} - diff --git a/kig/objects/text_type.cpp b/kig/objects/text_type.cpp new file mode 100644 index 00000000..c82c2047 --- /dev/null +++ b/kig/objects/text_type.cpp @@ -0,0 +1,215 @@ +// 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 "text_type.h" + +#include "text_imp.h" +#include "bogus_imp.h" +#include "point_imp.h" +#include "line_imp.h" + +#include "../kig/kig_view.h" +#include "../kig/kig_part.h" +#include "../kig/kig_commands.h" +#include "../modes/label.h" +#include "../misc/coordinate_system.h" + +#include + +#include +#include + +#include + +#include + +static const ArgsParser::spec arggspeccs[] = +{ + { IntImp::stype(), "UNUSED", "SHOULD NOT BE SEEN", false }, + { PointImp::stype(), "UNUSED", "SHOULD NOT BE SEEN", false }, + { StringImp::stype(), "UNUSED", "SHOULD NOT BE SEEN", false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( TextType ) + +TextType::TextType() + : ObjectType( "Label" ), mparser( arggspeccs, 3 ) +{ +} + +TextType::~TextType() +{ +} + +const TextType* TextType::instance() +{ + static const TextType t; + return &t; +} + +const ObjectImpType* TextType::resultId() const +{ + return TextImp::stype(); +} + +const ObjectImpType* TextType::impRequirement( const ObjectImp* o, const Args& args ) const +{ + assert( args.size() >= 3 ); + Args firstthree( args.begin(), args.begin() + 3 ); + if ( o == args[0] || o == args[1] || o == args[2] ) + return mparser.impRequirement( o, firstthree ); + else + return ObjectImp::stype(); +} + +ObjectImp* TextType::calc( const Args& parents, const KigDocument& doc ) const +{ + if( parents.size() < 3 ) return new InvalidImp; + Args firstthree( parents.begin(), parents.begin() + 3 ); + Args varargs( parents.begin() + 3, parents.end() ); + + if ( ! mparser.checkArgs( firstthree ) ) return new InvalidImp; + + int frame = static_cast( firstthree[0] )->data(); + bool needframe = frame != 0; + const Coordinate t = static_cast( firstthree[1] )->coordinate(); + TQString s = static_cast( firstthree[2] )->data(); + + for ( Args::iterator i = varargs.begin(); i != varargs.end(); ++i ) + (*i)->fillInNextEscape( s, doc ); + + return new TextImp( s, t, needframe ); +} + +bool TextType::canMove( const ObjectTypeCalcer& ) const +{ + return true; +} + +bool TextType::isFreelyTranslatable( const ObjectTypeCalcer& ) const +{ + return true; +} + +void TextType::move( ObjectTypeCalcer& ourobj, const Coordinate& to, + const KigDocument& d ) const +{ + const std::vector parents = ourobj.parents(); + assert( parents.size() >= 3 ); + const std::vector firstthree( parents.begin(), parents.begin() + 3 ); + if( dynamic_cast( firstthree[1] ) ) + { + ObjectConstCalcer* c = static_cast( firstthree[1] ); + c->setImp( new PointImp( to ) ); + } + else + firstthree[1]->move( to, d ); +} + +TQStringList TextType::specialActions() const +{ + TQStringList ret; + ret << i18n( "&Copy Text" ); + ret << i18n( "&Toggle Frame" ); + ret << i18n( "&Redefine..." ); + return ret; +} + +void TextType::executeAction( int i, ObjectHolder& o, ObjectTypeCalcer& c, + KigPart& doc, KigWidget&, + NormalMode& ) const +{ + std::vector parents = c.parents(); + assert( parents.size() >= 3 ); + + std::vector firstthree( parents.begin(), parents.begin() + 3 ); + + assert( mparser.checkArgs( firstthree ) ); + assert( dynamic_cast( firstthree[0] ) ); + assert( dynamic_cast( firstthree[2] ) ); + + if ( i == 0 ) + { + TQClipboard* cb = kapp->clipboard(); + + // copy the text into the clipboard + const TextImp* ti = static_cast( c.imp() ); + cb->setText( ti->text(), TQClipboard::Clipboard ); + } + else if ( i == 1 ) + { + // toggle label frame + int n = (static_cast( firstthree[0]->imp() )->data() + 1) % 2; + KigCommand* kc = new KigCommand( doc, i18n( "Toggle Label Frame" ) ); + kc->addTask( new ChangeObjectConstCalcerTask( + static_cast( firstthree[0] ), + new IntImp( n ) ) ); + doc.history()->addCommand( kc ); + } + else if ( i == 2 ) + { + assert( dynamic_cast( o.calcer() ) ); + // redefine.. + TextLabelRedefineMode m( doc, static_cast( o.calcer() ) ); + doc.runMode( &m ); + } + else assert( false ); +} + +const ArgsParser& TextType::argParser() const +{ + return mparser; +} + +const Coordinate TextType::moveReferencePoint( const ObjectTypeCalcer& ourobj ) const +{ + assert( ourobj.imp()->inherits( TextImp::stype() ) ); + return static_cast( ourobj.imp() )->coordinate(); +} + +std::vector TextType::sortArgs( const std::vector& os ) const +{ + assert( os.size() >= 3 ); + std::vector ret( os.begin(), os.begin() + 3 ); + ret = mparser.parse( ret ); + std::copy( os.begin() + 3, os.end(), std::back_inserter( ret ) ); + return ret; +} + +Args TextType::sortArgs( const Args& args ) const +{ + assert( args.size() >= 3 ); + Args ret( args.begin(), args.begin() + 3 ); + ret = mparser.parse( ret ); + std::copy( args.begin() + 3, args.end(), std::back_inserter( ret ) ); + return ret; +} + +std::vector TextType::movableParents( const ObjectTypeCalcer& ourobj ) const +{ + const std::vector parents = ourobj.parents(); + assert( parents.size() >= 3 ); + std::vector ret = parents[1]->movableParents(); + ret.push_back( parents[1] ); + return ret; +} + +bool TextType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const +{ + return false; +} + diff --git a/kig/objects/transform_types.cc b/kig/objects/transform_types.cc deleted file mode 100644 index 3a8d32db..00000000 --- a/kig/objects/transform_types.cc +++ /dev/null @@ -1,874 +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 "transform_types.h" - -#include "bogus_imp.h" -#include "point_imp.h" -#include "line_imp.h" -#include "other_imp.h" -#include "polygon_imp.h" -#include "../misc/coordinate.h" -#include "../misc/kigtransform.h" - -#include - -static const ArgsParser::spec argsspecTranslation[] = -{ - { ObjectImp::stype(), I18N_NOOP("Translate this object"), - I18N_NOOP( "Select the object to translate..." ), false }, - { VectorImp::stype(), I18N_NOOP("Translate by this vector"), - I18N_NOOP( "Select the vector to translate by..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( TranslatedType ) - -TranslatedType::TranslatedType() - : ArgsParserObjectType( "Translation", argsspecTranslation, 2 ) -{ -} - -TranslatedType::~TranslatedType() -{ -} - -const TranslatedType* TranslatedType::instance() -{ - static const TranslatedType t; - return &t; -} - -ObjectImp* TranslatedType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - Coordinate dir = static_cast( args[1] )->dir(); - Transformation t = Transformation::translation( dir ); - - return args[0]->transform( t ); -} - -static const ArgsParser::spec argsspecPointReflection[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Reflect this object" ), - I18N_NOOP( "Select the object to reflect..." ), false }, - { PointImp::stype(), I18N_NOOP( "Reflect in this point" ), - I18N_NOOP( "Select the point to reflect in..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PointReflectionType ) - -PointReflectionType::PointReflectionType() - : ArgsParserObjectType( "PointReflection", argsspecPointReflection, 2 ) -{ -} - -PointReflectionType::~PointReflectionType() -{ -} - -const PointReflectionType* PointReflectionType::instance() -{ - static const PointReflectionType t; - return &t; -} - -ObjectImp* PointReflectionType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - Coordinate center = static_cast( args[1] )->coordinate(); - Transformation t = Transformation::pointReflection( center ); - - return args[0]->transform( t ); -} - -static const ArgsParser::spec argsspecLineReflection[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Reflect this object" ), - I18N_NOOP( "Select the object to reflect..." ), false }, - { AbstractLineImp::stype(), I18N_NOOP( "Reflect in this line" ), - I18N_NOOP( "Select the line to reflect in..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineReflectionType ) - -LineReflectionType::LineReflectionType() - : ArgsParserObjectType( "LineReflection", argsspecLineReflection, 2 ) -{ -} - -LineReflectionType::~LineReflectionType() -{ -} - -const LineReflectionType* LineReflectionType::instance() -{ - static const LineReflectionType t; - return &t; -} - -ObjectImp* LineReflectionType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - LineData d = static_cast( args[1] )->data(); - Transformation t = Transformation::lineReflection( d ); - - return args[0]->transform( t ); -} - -static const ArgsParser::spec argsspecRotation[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Rotate this object" ), - I18N_NOOP( "Select the object to rotate..." ), false }, - { PointImp::stype(), I18N_NOOP( "Rotate around this point" ), - I18N_NOOP( "Select the center point of the rotation..." ), false }, - { AngleImp::stype(), I18N_NOOP( "Rotate by this angle" ), - I18N_NOOP( "Select the angle of the rotation..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( RotationType ) - -RotationType::RotationType() - : ArgsParserObjectType( "Rotation", argsspecRotation, 3 ) -{ -} - -RotationType::~RotationType() -{ -} - -const RotationType* RotationType::instance() -{ - static const RotationType t; - return &t; -} - -ObjectImp* RotationType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - Coordinate center = static_cast( args[1] )->coordinate(); - double angle = static_cast( args[2] )->size(); - - return args[0]->transform( Transformation::rotation( angle, center ) ); -} - -static const ArgsParser::spec argsspecScalingOverCenter[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Scale this object" ), - I18N_NOOP( "Select the object to scale..." ), false }, - { PointImp::stype(), I18N_NOOP( "Scale with this center" ), - I18N_NOOP( "Select the center point of the scaling..." ), false }, - { SegmentImp::stype(), I18N_NOOP( "Scale by the length of this segment" ), - I18N_NOOP( "Select a segment whose length is the factor of the scaling..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ScalingOverCenterType ) - -ScalingOverCenterType::ScalingOverCenterType() - : ArgsParserObjectType( "ScalingOverCenter", argsspecScalingOverCenter, 3 ) -{ -} - -ScalingOverCenterType::~ScalingOverCenterType() -{ -} - -const ScalingOverCenterType* ScalingOverCenterType::instance() -{ - static const ScalingOverCenterType t; - return &t; -} - -ObjectImp* ScalingOverCenterType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - Coordinate center = static_cast( args[1] )->coordinate(); - double ratio = static_cast( args[2] )->length(); - - return args[0]->transform( Transformation::scalingOverPoint( ratio, center ) ); -} - -static const ArgsParser::spec argsspecScalingOverCenter2[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Scale this object" ), - I18N_NOOP( "Select the object to scale..." ), false }, - { PointImp::stype(), I18N_NOOP( "Scale with this center" ), - I18N_NOOP( "Select the center point of the scaling..." ), false }, - { SegmentImp::stype(), I18N_NOOP( "Scale the length of this segment..." ), - I18N_NOOP( "Select the first of two segments whose ratio is the factor of the scaling..." ), false }, - { SegmentImp::stype(), I18N_NOOP( "...to the length of this other segment" ), - I18N_NOOP( "Select the second of two segments whose ratio is the factor of the scaling..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ScalingOverCenter2Type ) - -ScalingOverCenter2Type::ScalingOverCenter2Type() - : ArgsParserObjectType( "ScalingOverCenter2", argsspecScalingOverCenter2, 4 ) -{ -} - -ScalingOverCenter2Type::~ScalingOverCenter2Type() -{ -} - -const ScalingOverCenter2Type* ScalingOverCenter2Type::instance() -{ - static const ScalingOverCenter2Type t; - return &t; -} - -ObjectImp* ScalingOverCenter2Type::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - Coordinate center = static_cast( args[1] )->coordinate(); - double ratio = static_cast( args[3] )->length()/ - static_cast( args[2] )->length(); - - return args[0]->transform( Transformation::scalingOverPoint( ratio, center ) ); -} - -static const ArgsParser::spec argsspecScalingOverLine[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Scale this object" ), I18N_NOOP( "Select the object to scale" ), false }, - { AbstractLineImp::stype(), I18N_NOOP( "Scale over this line" ), I18N_NOOP( "Select the line to scale over" ), false }, - { SegmentImp::stype(), I18N_NOOP( "Scale by the length of this segment" ), I18N_NOOP( "Select a segment whose length is the factor for the scaling" ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ScalingOverLineType ) - -ScalingOverLineType::ScalingOverLineType() - : ArgsParserObjectType( "ScalingOverLine", argsspecScalingOverLine, 3 ) -{ -} - -ScalingOverLineType::~ScalingOverLineType() -{ -} - -const ScalingOverLineType* ScalingOverLineType::instance() -{ - static const ScalingOverLineType t; - return &t; -} - -ObjectImp* ScalingOverLineType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - LineData line = static_cast( args[1] )->data(); - double ratio = static_cast( args[2] )->length(); - - return args[0]->transform( Transformation::scalingOverLine( ratio, line ) ); -} - -static const ArgsParser::spec argsspecScalingOverLine2[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Scale this object" ), I18N_NOOP( "Select the object to scale" ), false }, - { AbstractLineImp::stype(), I18N_NOOP( "Scale over this line" ), I18N_NOOP( "Select the line to scale over" ), false }, - { SegmentImp::stype(), I18N_NOOP( "Scale the length of this segment..." ), I18N_NOOP( "Select the first of two segments whose ratio is the factor for the scaling" ), false }, - { SegmentImp::stype(), I18N_NOOP( "...to the length of this segment" ), I18N_NOOP( "Select the second of two segments whose ratio is the factor for the scaling" ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ScalingOverLine2Type ) - -ScalingOverLine2Type::ScalingOverLine2Type() - : ArgsParserObjectType( "ScalingOverLine2", argsspecScalingOverLine2, 4 ) -{ -} - -ScalingOverLine2Type::~ScalingOverLine2Type() -{ -} - -const ScalingOverLine2Type* ScalingOverLine2Type::instance() -{ - static const ScalingOverLine2Type t; - return &t; -} - -ObjectImp* ScalingOverLine2Type::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - LineData line = static_cast( args[1] )->data(); - double ratio = static_cast( args[3] )->length()/ - static_cast( args[2] )->length(); - - return args[0]->transform( Transformation::scalingOverLine( ratio, line ) ); -} - -static const ArgsParser::spec argsspecProjectiveRotation[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Projectively rotate this object" ), I18N_NOOP( "Select the object to rotate projectively" ), false }, - { RayImp::stype(), I18N_NOOP( "Projectively rotate with this half-line" ), I18N_NOOP( "Select the half line of the projective rotation that you want to apply to the object" ), false }, - { AngleImp::stype(), I18N_NOOP( "Projectively rotate by this angle" ), I18N_NOOP( "Select the angle of the projective rotation that you want to apply to the object" ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ProjectiveRotationType ) - -ProjectiveRotationType::ProjectiveRotationType() - : ArgsParserObjectType( "ProjectiveRotation", argsspecProjectiveRotation, 3 ) -{ -} - -ProjectiveRotationType::~ProjectiveRotationType() -{ -} - -const ProjectiveRotationType* ProjectiveRotationType::instance() -{ - static const ProjectiveRotationType t; - return &t; -} - -ObjectImp* ProjectiveRotationType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - const RayImp* ray = static_cast( args[1] ); - Coordinate c1 = ray->data().a; - Coordinate dir = ray->data().dir().normalize(); - double alpha = static_cast( args[2] )->size(); - - return args[0]->transform( - Transformation::projectiveRotation( alpha, dir, c1 ) ); -} - -static const ArgsParser::spec argsspecHarmonicHomology[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Harmonic Homology of this object" ), - I18N_NOOP( "Select the object to transform..." ), false }, - { PointImp::stype(), I18N_NOOP( "Harmonic Homology with this center" ), - I18N_NOOP( "Select the center point of the harmonic homology..." ), false }, - { AbstractLineImp::stype(), I18N_NOOP( "Harmonic Homology with this axis" ), - I18N_NOOP( "Select the axis of the harmonic homology..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( HarmonicHomologyType ) - -HarmonicHomologyType::HarmonicHomologyType() - : ArgsParserObjectType( "HarmonicHomology", argsspecHarmonicHomology, 3 ) -{ -} - -HarmonicHomologyType::~HarmonicHomologyType() -{ -} - -const HarmonicHomologyType* HarmonicHomologyType::instance() -{ - static const HarmonicHomologyType t; - return &t; -} - -ObjectImp* HarmonicHomologyType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - Coordinate center = static_cast( args[1] )->coordinate(); - LineData axis = static_cast( args[2] )->data(); - return args[0]->transform( - Transformation::harmonicHomology( center, axis ) ); -} - -static const ArgsParser::spec argsspecAffinityB2Tr[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Generic affinity of this object" ), - I18N_NOOP( "Select the object to transform..." ), false }, - { PolygonImp::stype3(), I18N_NOOP( "Map this triangle" ), - I18N_NOOP( "Select the triangle that has to be transformed onto a given triangle..." ), false }, - { PolygonImp::stype3(), I18N_NOOP( "onto this other triangle" ), - I18N_NOOP( "Select the triangle that is the image by the affinity of the first triangle..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( AffinityB2TrType ) - -AffinityB2TrType::AffinityB2TrType() - : ArgsParserObjectType( "AffinityB2Tr", argsspecAffinityB2Tr, 3 ) -{ -} - -AffinityB2TrType::~AffinityB2TrType() -{ -} - -const AffinityB2TrType* AffinityB2TrType::instance() -{ - static const AffinityB2TrType t; - return &t; -} - -ObjectImp* AffinityB2TrType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - std::vector frompoints = static_cast( args[1] )->points(); - std::vector topoints = static_cast( args[2] )->points(); - - bool valid = true; - Transformation t = Transformation::affinityGI3P( frompoints, topoints, - valid ); - - if (valid == false) return new InvalidImp; - return args[0]->transform( t ); -} - -static const ArgsParser::spec argsspecAffinityGI3P[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Generic affinity of this object" ), - I18N_NOOP( "Select the object to transform..." ), false }, - { PointImp::stype(), I18N_NOOP( "First of 3 starting points" ), - I18N_NOOP( "Select the first of the three starting points of the generic affinity..." ), false }, - { PointImp::stype(), I18N_NOOP( "Second of 3 starting points" ), - I18N_NOOP( "Select the second of the three starting points of the generic affinity..." ), false }, - { PointImp::stype(), I18N_NOOP( "Third of 3 starting points" ), - I18N_NOOP( "Select the third of the three starting points of the generic affinity..." ), false }, - { PointImp::stype(), I18N_NOOP( "Transformed position of first point" ), - I18N_NOOP( "Select the first of the three end points of the generic affinity..." ), false }, - { PointImp::stype(), I18N_NOOP( "Transformed position of second point" ), - I18N_NOOP( "Select the second of the three end points of the generic affinity..." ), false }, - { PointImp::stype(), I18N_NOOP( "Transformed position of third point" ), - I18N_NOOP( "Select the third of the three end points of the generic affinity..." ), false }, -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( AffinityGI3PType ) - -AffinityGI3PType::AffinityGI3PType() - : ArgsParserObjectType( "AffinityGI3P", argsspecAffinityGI3P, 7 ) -{ -} - -AffinityGI3PType::~AffinityGI3PType() -{ -} - -const AffinityGI3PType* AffinityGI3PType::instance() -{ - static const AffinityGI3PType t; - return &t; -} - -ObjectImp* AffinityGI3PType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - std::vector frompoints; - std::vector topoints; - for ( uint i = 0; i < 3; ++i ) - { - frompoints.push_back( - static_cast( args[i+1] )->coordinate() ); - topoints.push_back( - static_cast( args[i+4] )->coordinate() ); - } - - bool valid = true; - Transformation t = Transformation::affinityGI3P( frompoints, topoints, - valid ); - - if (valid == false) return new InvalidImp; - return args[0]->transform( t ); -} - -static const ArgsParser::spec argsspecProjectivityB2Qu[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Generic projective transformation of this object" ), - I18N_NOOP( "Select the object to transform..." ), false }, - { PolygonImp::stype4(), I18N_NOOP( "Map this quadrilateral" ), - I18N_NOOP( "Select the quadrilateral that has to be transformed onto a given quadrilateral..." ), false }, - { PolygonImp::stype4(), I18N_NOOP( "onto this other quadrilateral" ), - I18N_NOOP( "Select the quadrilateral that is the image by the projective transformation of the first quadrilateral..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ProjectivityB2QuType ) - -ProjectivityB2QuType::ProjectivityB2QuType() - : ArgsParserObjectType( "ProjectivityB2Qu", argsspecProjectivityB2Qu, 3 ) -{ -} - -ProjectivityB2QuType::~ProjectivityB2QuType() -{ -} - -const ProjectivityB2QuType* ProjectivityB2QuType::instance() -{ - static const ProjectivityB2QuType t; - return &t; -} - -ObjectImp* ProjectivityB2QuType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - std::vector frompoints = static_cast( args[1] )->points(); - std::vector topoints = static_cast( args[2] )->points(); - - bool valid = true; - Transformation t = Transformation::projectivityGI4P( frompoints, topoints, - valid ); - - if (valid == false) return new InvalidImp; - return args[0]->transform( t ); -} - -static const ArgsParser::spec argsspecProjectivityGI4P[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Generic projective transformation of this object" ), - I18N_NOOP( "Select the object to transform..." ), false }, - { PointImp::stype(), I18N_NOOP( "First of 4 starting points" ), - I18N_NOOP( "Select the first of the four starting points of the generic projectivity..." ), false }, - { PointImp::stype(), I18N_NOOP( "Second of 4 starting points" ), - I18N_NOOP( "Select the second of the four starting points of the generic projectivity..." ), false }, - { PointImp::stype(), I18N_NOOP( "Third of 4 starting points" ), - I18N_NOOP( "Select the third of the four starting points of the generic projectivity..." ), false }, - { PointImp::stype(), I18N_NOOP( "Fourth of 4 starting points" ), - I18N_NOOP( "Select the fourth of the four starting points of the generic projectivity..." ), false }, - { PointImp::stype(), I18N_NOOP( "Transformed position of first point" ), - I18N_NOOP( "Select the first of the four end points of the generic projectivity..." ), false }, - { PointImp::stype(), I18N_NOOP( "Transformed position of second point" ), - I18N_NOOP( "Select the second of the four end points of the generic projectivity..." ), false }, - { PointImp::stype(), I18N_NOOP( "Transformed position of third point" ), - I18N_NOOP( "Select the third of the four end points of the generic projectivity..." ), false }, - { PointImp::stype(), I18N_NOOP( "Transformed position of fourth point" ), - I18N_NOOP( "Select the fourth of the four end points of the generic projectivity..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ProjectivityGI4PType ) - -ProjectivityGI4PType::ProjectivityGI4PType() - : ArgsParserObjectType( "ProjectivityGI4P", argsspecProjectivityGI4P, 9 ) -{ -} - -ProjectivityGI4PType::~ProjectivityGI4PType() -{ -} - -const ProjectivityGI4PType* ProjectivityGI4PType::instance() -{ - static const ProjectivityGI4PType t; - return &t; -} - -ObjectImp* ProjectivityGI4PType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - std::vector frompoints; - std::vector topoints; - for ( uint i = 0; i < 4; ++i ) - { - frompoints.push_back( - static_cast( args[i+1] )->coordinate() ); - topoints.push_back( - static_cast( args[i+5] )->coordinate() ); - } - - bool valid = true; - Transformation t = Transformation::projectivityGI4P( frompoints, topoints, - valid ); - - if (valid == false) return new InvalidImp; - return args[0]->transform( t ); -} - -static const ArgsParser::spec argsspecCastShadow[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Cast the shadow of this object" ), - I18N_NOOP( "Select the object of which you want to construct the shadow..." ), false }, - { PointImp::stype(), I18N_NOOP( "Cast a shadow from this light source" ), - I18N_NOOP( "Select the light source from which the shadow should originate..." ), false }, - { AbstractLineImp::stype(), - I18N_NOOP( "Cast a shadow on the horizon represented by this line" ), - I18N_NOOP( "Select the horizon for the shadow..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CastShadowType ) - -CastShadowType::CastShadowType() - : ArgsParserObjectType( "CastShadow", argsspecCastShadow, 3 ) -{ -} - -CastShadowType::~CastShadowType() -{ -} - -const CastShadowType* CastShadowType::instance() -{ - static const CastShadowType t; - return &t; -} - -ObjectImp* CastShadowType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - Coordinate lightsrc = static_cast( args[1] )->coordinate(); - LineData d = static_cast( args[2] )->data(); - return args[0]->transform( - Transformation::castShadow( lightsrc, d ) ); -} - -const ObjectImpType* TranslatedType::resultId() const -{ - return ObjectImp::stype(); -} - -const ObjectImpType* PointReflectionType::resultId() const -{ - return ObjectImp::stype(); -} - -const ObjectImpType* LineReflectionType::resultId() const -{ - return ObjectImp::stype(); -} - -const ObjectImpType* RotationType::resultId() const -{ - return ObjectImp::stype(); -} - -const ObjectImpType* ScalingOverCenterType::resultId() const -{ - return ObjectImp::stype(); -} - -const ObjectImpType* ScalingOverCenter2Type::resultId() const -{ - return ObjectImp::stype(); -} - -const ObjectImpType* ScalingOverLineType::resultId() const -{ - return ObjectImp::stype(); -} - -const ObjectImpType* ScalingOverLine2Type::resultId() const -{ - return ObjectImp::stype(); -} - -const ObjectImpType* ProjectiveRotationType::resultId() const -{ - return ObjectImp::stype(); -} - -const ObjectImpType* HarmonicHomologyType::resultId() const -{ - return ObjectImp::stype(); -} - -const ObjectImpType* AffinityB2TrType::resultId() const -{ - return ObjectImp::stype(); -} - -const ObjectImpType* AffinityGI3PType::resultId() const -{ - return ObjectImp::stype(); -} - -const ObjectImpType* ProjectivityB2QuType::resultId() const -{ - return ObjectImp::stype(); -} - -const ObjectImpType* ProjectivityGI4PType::resultId() const -{ - return ObjectImp::stype(); -} - -const ObjectImpType* CastShadowType::resultId() const -{ - return ObjectImp::stype(); -} - -bool TranslatedType::isTransform() const -{ - return true; -} - -bool PointReflectionType::isTransform() const -{ - return true; -} - -bool LineReflectionType::isTransform() const -{ - return true; -} - -bool RotationType::isTransform() const -{ - return true; -} - -bool ScalingOverCenterType::isTransform() const -{ - return true; -} - -bool ScalingOverCenter2Type::isTransform() const -{ - return true; -} - -bool ScalingOverLineType::isTransform() const -{ - return true; -} - -bool ScalingOverLine2Type::isTransform() const -{ - return true; -} - -bool ProjectiveRotationType::isTransform() const -{ - return true; -} - -bool HarmonicHomologyType::isTransform() const -{ - return true; -} - -bool AffinityB2TrType::isTransform() const -{ - return true; -} - -bool AffinityGI3PType::isTransform() const -{ - return true; -} - -bool ProjectivityB2QuType::isTransform() const -{ - return true; -} - -bool ProjectivityGI4PType::isTransform() const -{ - return true; -} - -bool CastShadowType::isTransform() const -{ - return true; -} - -static const ArgsParser::spec argsspecApplyTransformation[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Transform this object" ), "SHOULD NOT BE SEEN", false }, - { TransformationImp::stype(), I18N_NOOP( "Transform using this transformation" ), "SHOULD NOT BE SEEN", false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ApplyTransformationObjectType ) - -ApplyTransformationObjectType::ApplyTransformationObjectType() - : ArgsParserObjectType( "ApplyTransformation", argsspecApplyTransformation, 2 ) -{ -} - -ApplyTransformationObjectType::~ApplyTransformationObjectType() -{ -} - -const ApplyTransformationObjectType* ApplyTransformationObjectType::instance() -{ - static const ApplyTransformationObjectType t; - return &t; -} - -ObjectImp* ApplyTransformationObjectType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - return args[0]->transform( static_cast( args[1] )->data() ); -} - -const ObjectImpType* ApplyTransformationObjectType::resultId() const -{ - return ObjectImp::stype(); -} - -bool ApplyTransformationObjectType::isTransform() const -{ - return true; -} - -bool SimilitudeType::isTransform() const -{ - return true; -} - -const ObjectImpType* SimilitudeType::resultId() const -{ - return ObjectImp::stype(); -} - -const SimilitudeType* SimilitudeType::instance() -{ - static const SimilitudeType t; - return &t; -} - -ObjectImp* SimilitudeType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - Coordinate c = static_cast( args[1] )->coordinate(); - Coordinate a = static_cast( args[2] )->coordinate(); - Coordinate b = static_cast( args[3] )->coordinate(); - a -= c; - b -= c; - double factor = sqrt( b.squareLength()/a.squareLength() ); - double theta = atan2( b.y, b.x ) - atan2( a.y, a.x ); - - return args[0]->transform( Transformation::similitude( c, theta, factor ) ); -} - -SimilitudeType::~SimilitudeType() -{ -} - -static const ArgsParser::spec argsspecSimilitude[] = -{ - { ObjectImp::stype(), I18N_NOOP( "Apply a similitude to this object" ), - I18N_NOOP( "Select the object to transform..." ), false }, - { PointImp::stype(), I18N_NOOP( "Apply a similitude with this center" ), - I18N_NOOP( "Select the center for the similitude..." ), false }, - { PointImp::stype(), I18N_NOOP( "Apply a similitude mapping this point onto another point" ), - I18N_NOOP( "Select the point which the similitude should map onto another point..." ), false }, - { PointImp::stype(), I18N_NOOP( "Apply a similitude mapping a point onto this point" ), - I18N_NOOP( "Select the point onto which the similitude should map the first point..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( SimilitudeType ) - -SimilitudeType::SimilitudeType() - : ArgsParserObjectType( "Similitude", argsspecSimilitude, 4 ) -{ -} diff --git a/kig/objects/transform_types.cpp b/kig/objects/transform_types.cpp new file mode 100644 index 00000000..3a8d32db --- /dev/null +++ b/kig/objects/transform_types.cpp @@ -0,0 +1,874 @@ +// 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 "transform_types.h" + +#include "bogus_imp.h" +#include "point_imp.h" +#include "line_imp.h" +#include "other_imp.h" +#include "polygon_imp.h" +#include "../misc/coordinate.h" +#include "../misc/kigtransform.h" + +#include + +static const ArgsParser::spec argsspecTranslation[] = +{ + { ObjectImp::stype(), I18N_NOOP("Translate this object"), + I18N_NOOP( "Select the object to translate..." ), false }, + { VectorImp::stype(), I18N_NOOP("Translate by this vector"), + I18N_NOOP( "Select the vector to translate by..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( TranslatedType ) + +TranslatedType::TranslatedType() + : ArgsParserObjectType( "Translation", argsspecTranslation, 2 ) +{ +} + +TranslatedType::~TranslatedType() +{ +} + +const TranslatedType* TranslatedType::instance() +{ + static const TranslatedType t; + return &t; +} + +ObjectImp* TranslatedType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + Coordinate dir = static_cast( args[1] )->dir(); + Transformation t = Transformation::translation( dir ); + + return args[0]->transform( t ); +} + +static const ArgsParser::spec argsspecPointReflection[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Reflect this object" ), + I18N_NOOP( "Select the object to reflect..." ), false }, + { PointImp::stype(), I18N_NOOP( "Reflect in this point" ), + I18N_NOOP( "Select the point to reflect in..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PointReflectionType ) + +PointReflectionType::PointReflectionType() + : ArgsParserObjectType( "PointReflection", argsspecPointReflection, 2 ) +{ +} + +PointReflectionType::~PointReflectionType() +{ +} + +const PointReflectionType* PointReflectionType::instance() +{ + static const PointReflectionType t; + return &t; +} + +ObjectImp* PointReflectionType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + Coordinate center = static_cast( args[1] )->coordinate(); + Transformation t = Transformation::pointReflection( center ); + + return args[0]->transform( t ); +} + +static const ArgsParser::spec argsspecLineReflection[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Reflect this object" ), + I18N_NOOP( "Select the object to reflect..." ), false }, + { AbstractLineImp::stype(), I18N_NOOP( "Reflect in this line" ), + I18N_NOOP( "Select the line to reflect in..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( LineReflectionType ) + +LineReflectionType::LineReflectionType() + : ArgsParserObjectType( "LineReflection", argsspecLineReflection, 2 ) +{ +} + +LineReflectionType::~LineReflectionType() +{ +} + +const LineReflectionType* LineReflectionType::instance() +{ + static const LineReflectionType t; + return &t; +} + +ObjectImp* LineReflectionType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + LineData d = static_cast( args[1] )->data(); + Transformation t = Transformation::lineReflection( d ); + + return args[0]->transform( t ); +} + +static const ArgsParser::spec argsspecRotation[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Rotate this object" ), + I18N_NOOP( "Select the object to rotate..." ), false }, + { PointImp::stype(), I18N_NOOP( "Rotate around this point" ), + I18N_NOOP( "Select the center point of the rotation..." ), false }, + { AngleImp::stype(), I18N_NOOP( "Rotate by this angle" ), + I18N_NOOP( "Select the angle of the rotation..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( RotationType ) + +RotationType::RotationType() + : ArgsParserObjectType( "Rotation", argsspecRotation, 3 ) +{ +} + +RotationType::~RotationType() +{ +} + +const RotationType* RotationType::instance() +{ + static const RotationType t; + return &t; +} + +ObjectImp* RotationType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + Coordinate center = static_cast( args[1] )->coordinate(); + double angle = static_cast( args[2] )->size(); + + return args[0]->transform( Transformation::rotation( angle, center ) ); +} + +static const ArgsParser::spec argsspecScalingOverCenter[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Scale this object" ), + I18N_NOOP( "Select the object to scale..." ), false }, + { PointImp::stype(), I18N_NOOP( "Scale with this center" ), + I18N_NOOP( "Select the center point of the scaling..." ), false }, + { SegmentImp::stype(), I18N_NOOP( "Scale by the length of this segment" ), + I18N_NOOP( "Select a segment whose length is the factor of the scaling..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ScalingOverCenterType ) + +ScalingOverCenterType::ScalingOverCenterType() + : ArgsParserObjectType( "ScalingOverCenter", argsspecScalingOverCenter, 3 ) +{ +} + +ScalingOverCenterType::~ScalingOverCenterType() +{ +} + +const ScalingOverCenterType* ScalingOverCenterType::instance() +{ + static const ScalingOverCenterType t; + return &t; +} + +ObjectImp* ScalingOverCenterType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + Coordinate center = static_cast( args[1] )->coordinate(); + double ratio = static_cast( args[2] )->length(); + + return args[0]->transform( Transformation::scalingOverPoint( ratio, center ) ); +} + +static const ArgsParser::spec argsspecScalingOverCenter2[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Scale this object" ), + I18N_NOOP( "Select the object to scale..." ), false }, + { PointImp::stype(), I18N_NOOP( "Scale with this center" ), + I18N_NOOP( "Select the center point of the scaling..." ), false }, + { SegmentImp::stype(), I18N_NOOP( "Scale the length of this segment..." ), + I18N_NOOP( "Select the first of two segments whose ratio is the factor of the scaling..." ), false }, + { SegmentImp::stype(), I18N_NOOP( "...to the length of this other segment" ), + I18N_NOOP( "Select the second of two segments whose ratio is the factor of the scaling..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ScalingOverCenter2Type ) + +ScalingOverCenter2Type::ScalingOverCenter2Type() + : ArgsParserObjectType( "ScalingOverCenter2", argsspecScalingOverCenter2, 4 ) +{ +} + +ScalingOverCenter2Type::~ScalingOverCenter2Type() +{ +} + +const ScalingOverCenter2Type* ScalingOverCenter2Type::instance() +{ + static const ScalingOverCenter2Type t; + return &t; +} + +ObjectImp* ScalingOverCenter2Type::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + Coordinate center = static_cast( args[1] )->coordinate(); + double ratio = static_cast( args[3] )->length()/ + static_cast( args[2] )->length(); + + return args[0]->transform( Transformation::scalingOverPoint( ratio, center ) ); +} + +static const ArgsParser::spec argsspecScalingOverLine[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Scale this object" ), I18N_NOOP( "Select the object to scale" ), false }, + { AbstractLineImp::stype(), I18N_NOOP( "Scale over this line" ), I18N_NOOP( "Select the line to scale over" ), false }, + { SegmentImp::stype(), I18N_NOOP( "Scale by the length of this segment" ), I18N_NOOP( "Select a segment whose length is the factor for the scaling" ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ScalingOverLineType ) + +ScalingOverLineType::ScalingOverLineType() + : ArgsParserObjectType( "ScalingOverLine", argsspecScalingOverLine, 3 ) +{ +} + +ScalingOverLineType::~ScalingOverLineType() +{ +} + +const ScalingOverLineType* ScalingOverLineType::instance() +{ + static const ScalingOverLineType t; + return &t; +} + +ObjectImp* ScalingOverLineType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + LineData line = static_cast( args[1] )->data(); + double ratio = static_cast( args[2] )->length(); + + return args[0]->transform( Transformation::scalingOverLine( ratio, line ) ); +} + +static const ArgsParser::spec argsspecScalingOverLine2[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Scale this object" ), I18N_NOOP( "Select the object to scale" ), false }, + { AbstractLineImp::stype(), I18N_NOOP( "Scale over this line" ), I18N_NOOP( "Select the line to scale over" ), false }, + { SegmentImp::stype(), I18N_NOOP( "Scale the length of this segment..." ), I18N_NOOP( "Select the first of two segments whose ratio is the factor for the scaling" ), false }, + { SegmentImp::stype(), I18N_NOOP( "...to the length of this segment" ), I18N_NOOP( "Select the second of two segments whose ratio is the factor for the scaling" ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ScalingOverLine2Type ) + +ScalingOverLine2Type::ScalingOverLine2Type() + : ArgsParserObjectType( "ScalingOverLine2", argsspecScalingOverLine2, 4 ) +{ +} + +ScalingOverLine2Type::~ScalingOverLine2Type() +{ +} + +const ScalingOverLine2Type* ScalingOverLine2Type::instance() +{ + static const ScalingOverLine2Type t; + return &t; +} + +ObjectImp* ScalingOverLine2Type::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + LineData line = static_cast( args[1] )->data(); + double ratio = static_cast( args[3] )->length()/ + static_cast( args[2] )->length(); + + return args[0]->transform( Transformation::scalingOverLine( ratio, line ) ); +} + +static const ArgsParser::spec argsspecProjectiveRotation[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Projectively rotate this object" ), I18N_NOOP( "Select the object to rotate projectively" ), false }, + { RayImp::stype(), I18N_NOOP( "Projectively rotate with this half-line" ), I18N_NOOP( "Select the half line of the projective rotation that you want to apply to the object" ), false }, + { AngleImp::stype(), I18N_NOOP( "Projectively rotate by this angle" ), I18N_NOOP( "Select the angle of the projective rotation that you want to apply to the object" ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ProjectiveRotationType ) + +ProjectiveRotationType::ProjectiveRotationType() + : ArgsParserObjectType( "ProjectiveRotation", argsspecProjectiveRotation, 3 ) +{ +} + +ProjectiveRotationType::~ProjectiveRotationType() +{ +} + +const ProjectiveRotationType* ProjectiveRotationType::instance() +{ + static const ProjectiveRotationType t; + return &t; +} + +ObjectImp* ProjectiveRotationType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + const RayImp* ray = static_cast( args[1] ); + Coordinate c1 = ray->data().a; + Coordinate dir = ray->data().dir().normalize(); + double alpha = static_cast( args[2] )->size(); + + return args[0]->transform( + Transformation::projectiveRotation( alpha, dir, c1 ) ); +} + +static const ArgsParser::spec argsspecHarmonicHomology[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Harmonic Homology of this object" ), + I18N_NOOP( "Select the object to transform..." ), false }, + { PointImp::stype(), I18N_NOOP( "Harmonic Homology with this center" ), + I18N_NOOP( "Select the center point of the harmonic homology..." ), false }, + { AbstractLineImp::stype(), I18N_NOOP( "Harmonic Homology with this axis" ), + I18N_NOOP( "Select the axis of the harmonic homology..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( HarmonicHomologyType ) + +HarmonicHomologyType::HarmonicHomologyType() + : ArgsParserObjectType( "HarmonicHomology", argsspecHarmonicHomology, 3 ) +{ +} + +HarmonicHomologyType::~HarmonicHomologyType() +{ +} + +const HarmonicHomologyType* HarmonicHomologyType::instance() +{ + static const HarmonicHomologyType t; + return &t; +} + +ObjectImp* HarmonicHomologyType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + Coordinate center = static_cast( args[1] )->coordinate(); + LineData axis = static_cast( args[2] )->data(); + return args[0]->transform( + Transformation::harmonicHomology( center, axis ) ); +} + +static const ArgsParser::spec argsspecAffinityB2Tr[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Generic affinity of this object" ), + I18N_NOOP( "Select the object to transform..." ), false }, + { PolygonImp::stype3(), I18N_NOOP( "Map this triangle" ), + I18N_NOOP( "Select the triangle that has to be transformed onto a given triangle..." ), false }, + { PolygonImp::stype3(), I18N_NOOP( "onto this other triangle" ), + I18N_NOOP( "Select the triangle that is the image by the affinity of the first triangle..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( AffinityB2TrType ) + +AffinityB2TrType::AffinityB2TrType() + : ArgsParserObjectType( "AffinityB2Tr", argsspecAffinityB2Tr, 3 ) +{ +} + +AffinityB2TrType::~AffinityB2TrType() +{ +} + +const AffinityB2TrType* AffinityB2TrType::instance() +{ + static const AffinityB2TrType t; + return &t; +} + +ObjectImp* AffinityB2TrType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + std::vector frompoints = static_cast( args[1] )->points(); + std::vector topoints = static_cast( args[2] )->points(); + + bool valid = true; + Transformation t = Transformation::affinityGI3P( frompoints, topoints, + valid ); + + if (valid == false) return new InvalidImp; + return args[0]->transform( t ); +} + +static const ArgsParser::spec argsspecAffinityGI3P[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Generic affinity of this object" ), + I18N_NOOP( "Select the object to transform..." ), false }, + { PointImp::stype(), I18N_NOOP( "First of 3 starting points" ), + I18N_NOOP( "Select the first of the three starting points of the generic affinity..." ), false }, + { PointImp::stype(), I18N_NOOP( "Second of 3 starting points" ), + I18N_NOOP( "Select the second of the three starting points of the generic affinity..." ), false }, + { PointImp::stype(), I18N_NOOP( "Third of 3 starting points" ), + I18N_NOOP( "Select the third of the three starting points of the generic affinity..." ), false }, + { PointImp::stype(), I18N_NOOP( "Transformed position of first point" ), + I18N_NOOP( "Select the first of the three end points of the generic affinity..." ), false }, + { PointImp::stype(), I18N_NOOP( "Transformed position of second point" ), + I18N_NOOP( "Select the second of the three end points of the generic affinity..." ), false }, + { PointImp::stype(), I18N_NOOP( "Transformed position of third point" ), + I18N_NOOP( "Select the third of the three end points of the generic affinity..." ), false }, +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( AffinityGI3PType ) + +AffinityGI3PType::AffinityGI3PType() + : ArgsParserObjectType( "AffinityGI3P", argsspecAffinityGI3P, 7 ) +{ +} + +AffinityGI3PType::~AffinityGI3PType() +{ +} + +const AffinityGI3PType* AffinityGI3PType::instance() +{ + static const AffinityGI3PType t; + return &t; +} + +ObjectImp* AffinityGI3PType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + std::vector frompoints; + std::vector topoints; + for ( uint i = 0; i < 3; ++i ) + { + frompoints.push_back( + static_cast( args[i+1] )->coordinate() ); + topoints.push_back( + static_cast( args[i+4] )->coordinate() ); + } + + bool valid = true; + Transformation t = Transformation::affinityGI3P( frompoints, topoints, + valid ); + + if (valid == false) return new InvalidImp; + return args[0]->transform( t ); +} + +static const ArgsParser::spec argsspecProjectivityB2Qu[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Generic projective transformation of this object" ), + I18N_NOOP( "Select the object to transform..." ), false }, + { PolygonImp::stype4(), I18N_NOOP( "Map this quadrilateral" ), + I18N_NOOP( "Select the quadrilateral that has to be transformed onto a given quadrilateral..." ), false }, + { PolygonImp::stype4(), I18N_NOOP( "onto this other quadrilateral" ), + I18N_NOOP( "Select the quadrilateral that is the image by the projective transformation of the first quadrilateral..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ProjectivityB2QuType ) + +ProjectivityB2QuType::ProjectivityB2QuType() + : ArgsParserObjectType( "ProjectivityB2Qu", argsspecProjectivityB2Qu, 3 ) +{ +} + +ProjectivityB2QuType::~ProjectivityB2QuType() +{ +} + +const ProjectivityB2QuType* ProjectivityB2QuType::instance() +{ + static const ProjectivityB2QuType t; + return &t; +} + +ObjectImp* ProjectivityB2QuType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + std::vector frompoints = static_cast( args[1] )->points(); + std::vector topoints = static_cast( args[2] )->points(); + + bool valid = true; + Transformation t = Transformation::projectivityGI4P( frompoints, topoints, + valid ); + + if (valid == false) return new InvalidImp; + return args[0]->transform( t ); +} + +static const ArgsParser::spec argsspecProjectivityGI4P[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Generic projective transformation of this object" ), + I18N_NOOP( "Select the object to transform..." ), false }, + { PointImp::stype(), I18N_NOOP( "First of 4 starting points" ), + I18N_NOOP( "Select the first of the four starting points of the generic projectivity..." ), false }, + { PointImp::stype(), I18N_NOOP( "Second of 4 starting points" ), + I18N_NOOP( "Select the second of the four starting points of the generic projectivity..." ), false }, + { PointImp::stype(), I18N_NOOP( "Third of 4 starting points" ), + I18N_NOOP( "Select the third of the four starting points of the generic projectivity..." ), false }, + { PointImp::stype(), I18N_NOOP( "Fourth of 4 starting points" ), + I18N_NOOP( "Select the fourth of the four starting points of the generic projectivity..." ), false }, + { PointImp::stype(), I18N_NOOP( "Transformed position of first point" ), + I18N_NOOP( "Select the first of the four end points of the generic projectivity..." ), false }, + { PointImp::stype(), I18N_NOOP( "Transformed position of second point" ), + I18N_NOOP( "Select the second of the four end points of the generic projectivity..." ), false }, + { PointImp::stype(), I18N_NOOP( "Transformed position of third point" ), + I18N_NOOP( "Select the third of the four end points of the generic projectivity..." ), false }, + { PointImp::stype(), I18N_NOOP( "Transformed position of fourth point" ), + I18N_NOOP( "Select the fourth of the four end points of the generic projectivity..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ProjectivityGI4PType ) + +ProjectivityGI4PType::ProjectivityGI4PType() + : ArgsParserObjectType( "ProjectivityGI4P", argsspecProjectivityGI4P, 9 ) +{ +} + +ProjectivityGI4PType::~ProjectivityGI4PType() +{ +} + +const ProjectivityGI4PType* ProjectivityGI4PType::instance() +{ + static const ProjectivityGI4PType t; + return &t; +} + +ObjectImp* ProjectivityGI4PType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + std::vector frompoints; + std::vector topoints; + for ( uint i = 0; i < 4; ++i ) + { + frompoints.push_back( + static_cast( args[i+1] )->coordinate() ); + topoints.push_back( + static_cast( args[i+5] )->coordinate() ); + } + + bool valid = true; + Transformation t = Transformation::projectivityGI4P( frompoints, topoints, + valid ); + + if (valid == false) return new InvalidImp; + return args[0]->transform( t ); +} + +static const ArgsParser::spec argsspecCastShadow[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Cast the shadow of this object" ), + I18N_NOOP( "Select the object of which you want to construct the shadow..." ), false }, + { PointImp::stype(), I18N_NOOP( "Cast a shadow from this light source" ), + I18N_NOOP( "Select the light source from which the shadow should originate..." ), false }, + { AbstractLineImp::stype(), + I18N_NOOP( "Cast a shadow on the horizon represented by this line" ), + I18N_NOOP( "Select the horizon for the shadow..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CastShadowType ) + +CastShadowType::CastShadowType() + : ArgsParserObjectType( "CastShadow", argsspecCastShadow, 3 ) +{ +} + +CastShadowType::~CastShadowType() +{ +} + +const CastShadowType* CastShadowType::instance() +{ + static const CastShadowType t; + return &t; +} + +ObjectImp* CastShadowType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + Coordinate lightsrc = static_cast( args[1] )->coordinate(); + LineData d = static_cast( args[2] )->data(); + return args[0]->transform( + Transformation::castShadow( lightsrc, d ) ); +} + +const ObjectImpType* TranslatedType::resultId() const +{ + return ObjectImp::stype(); +} + +const ObjectImpType* PointReflectionType::resultId() const +{ + return ObjectImp::stype(); +} + +const ObjectImpType* LineReflectionType::resultId() const +{ + return ObjectImp::stype(); +} + +const ObjectImpType* RotationType::resultId() const +{ + return ObjectImp::stype(); +} + +const ObjectImpType* ScalingOverCenterType::resultId() const +{ + return ObjectImp::stype(); +} + +const ObjectImpType* ScalingOverCenter2Type::resultId() const +{ + return ObjectImp::stype(); +} + +const ObjectImpType* ScalingOverLineType::resultId() const +{ + return ObjectImp::stype(); +} + +const ObjectImpType* ScalingOverLine2Type::resultId() const +{ + return ObjectImp::stype(); +} + +const ObjectImpType* ProjectiveRotationType::resultId() const +{ + return ObjectImp::stype(); +} + +const ObjectImpType* HarmonicHomologyType::resultId() const +{ + return ObjectImp::stype(); +} + +const ObjectImpType* AffinityB2TrType::resultId() const +{ + return ObjectImp::stype(); +} + +const ObjectImpType* AffinityGI3PType::resultId() const +{ + return ObjectImp::stype(); +} + +const ObjectImpType* ProjectivityB2QuType::resultId() const +{ + return ObjectImp::stype(); +} + +const ObjectImpType* ProjectivityGI4PType::resultId() const +{ + return ObjectImp::stype(); +} + +const ObjectImpType* CastShadowType::resultId() const +{ + return ObjectImp::stype(); +} + +bool TranslatedType::isTransform() const +{ + return true; +} + +bool PointReflectionType::isTransform() const +{ + return true; +} + +bool LineReflectionType::isTransform() const +{ + return true; +} + +bool RotationType::isTransform() const +{ + return true; +} + +bool ScalingOverCenterType::isTransform() const +{ + return true; +} + +bool ScalingOverCenter2Type::isTransform() const +{ + return true; +} + +bool ScalingOverLineType::isTransform() const +{ + return true; +} + +bool ScalingOverLine2Type::isTransform() const +{ + return true; +} + +bool ProjectiveRotationType::isTransform() const +{ + return true; +} + +bool HarmonicHomologyType::isTransform() const +{ + return true; +} + +bool AffinityB2TrType::isTransform() const +{ + return true; +} + +bool AffinityGI3PType::isTransform() const +{ + return true; +} + +bool ProjectivityB2QuType::isTransform() const +{ + return true; +} + +bool ProjectivityGI4PType::isTransform() const +{ + return true; +} + +bool CastShadowType::isTransform() const +{ + return true; +} + +static const ArgsParser::spec argsspecApplyTransformation[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Transform this object" ), "SHOULD NOT BE SEEN", false }, + { TransformationImp::stype(), I18N_NOOP( "Transform using this transformation" ), "SHOULD NOT BE SEEN", false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ApplyTransformationObjectType ) + +ApplyTransformationObjectType::ApplyTransformationObjectType() + : ArgsParserObjectType( "ApplyTransformation", argsspecApplyTransformation, 2 ) +{ +} + +ApplyTransformationObjectType::~ApplyTransformationObjectType() +{ +} + +const ApplyTransformationObjectType* ApplyTransformationObjectType::instance() +{ + static const ApplyTransformationObjectType t; + return &t; +} + +ObjectImp* ApplyTransformationObjectType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + return args[0]->transform( static_cast( args[1] )->data() ); +} + +const ObjectImpType* ApplyTransformationObjectType::resultId() const +{ + return ObjectImp::stype(); +} + +bool ApplyTransformationObjectType::isTransform() const +{ + return true; +} + +bool SimilitudeType::isTransform() const +{ + return true; +} + +const ObjectImpType* SimilitudeType::resultId() const +{ + return ObjectImp::stype(); +} + +const SimilitudeType* SimilitudeType::instance() +{ + static const SimilitudeType t; + return &t; +} + +ObjectImp* SimilitudeType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + Coordinate c = static_cast( args[1] )->coordinate(); + Coordinate a = static_cast( args[2] )->coordinate(); + Coordinate b = static_cast( args[3] )->coordinate(); + a -= c; + b -= c; + double factor = sqrt( b.squareLength()/a.squareLength() ); + double theta = atan2( b.y, b.x ) - atan2( a.y, a.x ); + + return args[0]->transform( Transformation::similitude( c, theta, factor ) ); +} + +SimilitudeType::~SimilitudeType() +{ +} + +static const ArgsParser::spec argsspecSimilitude[] = +{ + { ObjectImp::stype(), I18N_NOOP( "Apply a similitude to this object" ), + I18N_NOOP( "Select the object to transform..." ), false }, + { PointImp::stype(), I18N_NOOP( "Apply a similitude with this center" ), + I18N_NOOP( "Select the center for the similitude..." ), false }, + { PointImp::stype(), I18N_NOOP( "Apply a similitude mapping this point onto another point" ), + I18N_NOOP( "Select the point which the similitude should map onto another point..." ), false }, + { PointImp::stype(), I18N_NOOP( "Apply a similitude mapping a point onto this point" ), + I18N_NOOP( "Select the point onto which the similitude should map the first point..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( SimilitudeType ) + +SimilitudeType::SimilitudeType() + : ArgsParserObjectType( "Similitude", argsspecSimilitude, 4 ) +{ +} diff --git a/kig/objects/vector_type.cc b/kig/objects/vector_type.cc deleted file mode 100644 index d96be07b..00000000 --- a/kig/objects/vector_type.cc +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (C) 2004 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 "vector_type.h" - -#include "point_imp.h" -#include "other_imp.h" -#include "bogus_imp.h" - -static const ArgsParser::spec argsspecVector[] = -{ - { PointImp::stype(), I18N_NOOP( "Construct a vector from this point" ), - I18N_NOOP( "Select the start point of the new vector..." ), true }, - { PointImp::stype(), I18N_NOOP( "Construct a vector to this point" ), - I18N_NOOP( "Select the end point of the new vector..." ), true } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( VectorType ) - -VectorType::VectorType() - : ObjectABType( "Vector", argsspecVector, 2 ) -{ -} - -VectorType::~VectorType() -{ -} - -const VectorType* VectorType::instance() -{ - static const VectorType t; - return &t; -} - -ObjectImp* VectorType::calc( const Coordinate& a, const Coordinate& b ) const -{ - return new VectorImp( a, b ); -} - -const ObjectImpType* VectorType::resultId() const -{ - return VectorImp::stype(); -} - -static const ArgsParser::spec argsspecVectorSum[] = -{ - { VectorImp::stype(), I18N_NOOP( "Construct the vector sum of this vector and another one." ), - I18N_NOOP( "Select the first of the two vectors of which you want to construct the sum..." ), false }, - { VectorImp::stype(), I18N_NOOP( "Construct the vector sum of this vector and the other one." ), - I18N_NOOP( "Select the other of the two vectors of which you want to construct the sum..." ), false }, - { PointImp::stype(), I18N_NOOP( "Construct the vector sum starting at this point." ), - I18N_NOOP( "Select the point to construct the sum vector in..." ), false } -}; - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( VectorSumType ) - -VectorSumType::VectorSumType() - : ArgsParserObjectType( "VectorSum", argsspecVectorSum, 3 ) -{ -} - -VectorSumType::~VectorSumType() -{ -} - -const VectorSumType* VectorSumType::instance() -{ - static const VectorSumType t; - return &t; -} - -ObjectImp* VectorSumType::calc( const Args& args, const KigDocument& ) const -{ - if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; - - const VectorImp& a = *static_cast( args[0] ); - const VectorImp& b = *static_cast( args[1] ); - const PointImp& p = *static_cast( args[2] ); - - return new VectorImp( p.coordinate(), p.coordinate() + a.dir() + b.dir() ); -} - -const ObjectImpType* VectorSumType::resultId() const -{ - return VectorImp::stype(); -} diff --git a/kig/objects/vector_type.cpp b/kig/objects/vector_type.cpp new file mode 100644 index 00000000..d96be07b --- /dev/null +++ b/kig/objects/vector_type.cpp @@ -0,0 +1,100 @@ +// Copyright (C) 2004 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 "vector_type.h" + +#include "point_imp.h" +#include "other_imp.h" +#include "bogus_imp.h" + +static const ArgsParser::spec argsspecVector[] = +{ + { PointImp::stype(), I18N_NOOP( "Construct a vector from this point" ), + I18N_NOOP( "Select the start point of the new vector..." ), true }, + { PointImp::stype(), I18N_NOOP( "Construct a vector to this point" ), + I18N_NOOP( "Select the end point of the new vector..." ), true } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( VectorType ) + +VectorType::VectorType() + : ObjectABType( "Vector", argsspecVector, 2 ) +{ +} + +VectorType::~VectorType() +{ +} + +const VectorType* VectorType::instance() +{ + static const VectorType t; + return &t; +} + +ObjectImp* VectorType::calc( const Coordinate& a, const Coordinate& b ) const +{ + return new VectorImp( a, b ); +} + +const ObjectImpType* VectorType::resultId() const +{ + return VectorImp::stype(); +} + +static const ArgsParser::spec argsspecVectorSum[] = +{ + { VectorImp::stype(), I18N_NOOP( "Construct the vector sum of this vector and another one." ), + I18N_NOOP( "Select the first of the two vectors of which you want to construct the sum..." ), false }, + { VectorImp::stype(), I18N_NOOP( "Construct the vector sum of this vector and the other one." ), + I18N_NOOP( "Select the other of the two vectors of which you want to construct the sum..." ), false }, + { PointImp::stype(), I18N_NOOP( "Construct the vector sum starting at this point." ), + I18N_NOOP( "Select the point to construct the sum vector in..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( VectorSumType ) + +VectorSumType::VectorSumType() + : ArgsParserObjectType( "VectorSum", argsspecVectorSum, 3 ) +{ +} + +VectorSumType::~VectorSumType() +{ +} + +const VectorSumType* VectorSumType::instance() +{ + static const VectorSumType t; + return &t; +} + +ObjectImp* VectorSumType::calc( const Args& args, const KigDocument& ) const +{ + if ( ! margsparser.checkArgs( args ) ) return new InvalidImp; + + const VectorImp& a = *static_cast( args[0] ); + const VectorImp& b = *static_cast( args[1] ); + const PointImp& p = *static_cast( args[2] ); + + return new VectorImp( p.coordinate(), p.coordinate() + a.dir() + b.dir() ); +} + +const ObjectImpType* VectorSumType::resultId() const +{ + return VectorImp::stype(); +} diff --git a/kig/scripting/CMakeLists.txt b/kig/scripting/CMakeLists.txt index ab158e89..ab53fef7 100644 --- a/kig/scripting/CMakeLists.txt +++ b/kig/scripting/CMakeLists.txt @@ -20,11 +20,11 @@ tde_add_library( kigscripting STATIC_PIC AUTOMOC SOURCES newscriptwizardbase.ui - python_type.cc - python_scripter.cc - script-common.cc - script_mode.cc - newscriptwizard.cc + python_type.cpp + python_scripter.cpp + script-common.cpp + script_mode.cpp + newscriptwizard.cpp LINK katepartinterfaces tdetexteditor-shared diff --git a/kig/scripting/Makefile.am b/kig/scripting/Makefile.am index c007a612..7f66791a 100644 --- a/kig/scripting/Makefile.am +++ b/kig/scripting/Makefile.am @@ -8,12 +8,12 @@ noinst_HEADERS = \ script_mode.h \ newscriptwizard.h libscripting_la_SOURCES = \ - python_type.cc \ - python_scripter.cc \ - script-common.cc \ - script_mode.cc \ + python_type.cpp \ + python_scripter.cpp \ + script-common.cpp \ + script_mode.cpp \ newscriptwizardbase.ui \ - newscriptwizard.cc + newscriptwizard.cpp libscripting_la_LIBADD = $(BOOST_PYTHON_LIBS) $(PYTHON_LIBS) -lkatepartinterfaces libscripting_la_LDFLAGS = $(all_libraries) $(PYTHON_LDFLAGS) METASOURCES=AUTO diff --git a/kig/scripting/newscriptwizard.cc b/kig/scripting/newscriptwizard.cc deleted file mode 100644 index 9cb4d9e2..00000000 --- a/kig/scripting/newscriptwizard.cc +++ /dev/null @@ -1,234 +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 "newscriptwizard.h" -#include "newscriptwizard.moc" - -#include "script_mode.h" - -#include -#include - -//#include -//#include -// make it still work on old kde 3.1... -#include -// -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -NewScriptWizard::~NewScriptWizard() -{ - if ( !document ) - { - delete textedit; - } - else - { - //restoring the state of the dynamic word wrap - dynamic_cast( editor )->setDynWordWrap( prevDynWordWrap ); - delete editor->document(); - } -} - -NewScriptWizard::NewScriptWizard( TQWidget* parent, ScriptModeBase* mode ) - : NewScriptWizardBase( parent, "New Script Wizard" ), - mmode( mode ) -{ - document = KTextEditor::EditorChooser::createDocument( 0, "KTextEditor::Document" ); -// document = 0; - - gridLayout->expand( 2, 1 ); - - if ( !document ) - { - // there is no KDE textditor component installed, so we'll use a - // simplier KTextEdit - textedit = new KTextEdit( mpcode, "textedit" ); - textedit->setFont( TDEGlobalSettings::fixedFont() ); - gridLayout->addWidget( textedit, 1, 0 ); - } - else - { - // creating the 'view', hat is what the user see and interact with - editor = document->createView( mpcode, "editor" ); - gridLayout->addWidget( editor, 1, 0 ); - - // casting to the interfaces we'll use often - hli = dynamic_cast( document ); - - // displaying the left border with line numbers - TDEToggleAction *a = dynamic_cast( editor->actionCollection()->action("view_line_numbers") ); - a->activate(); - - // saving the state of dynamic word wrap and disabling it - prevDynWordWrap = dynamic_cast( editor )->dynWordWrap(); - dynamic_cast( editor )->setDynWordWrap( false ); - - // saving the "no highlight" id - noHlStyle = hli->hlMode(); - - // creating the popup menu - TDEPopupMenu* pm = new TDEPopupMenu( editor ); - // creating the actions for the code editor... - TDEActionCollection* ac = new TDEActionCollection( editor ); - TDEAction* undoAction = KStdAction::undo( TQT_TQOBJECT(this), TQT_SLOT( slotUndo() ), ac ); - TDEAction* redoAction = KStdAction::redo( TQT_TQOBJECT(this), TQT_SLOT( slotRedo() ), ac ); - TDEAction* cutAction = KStdAction::cut( TQT_TQOBJECT(this), TQT_SLOT( slotCut() ), ac ); - TDEAction* copyAction = KStdAction::copy( TQT_TQOBJECT(this), TQT_SLOT( slotCopy() ), ac ); - TDEAction* pasteAction = KStdAction::paste( TQT_TQOBJECT(this), TQT_SLOT( slotPaste() ), ac ); - // ... and plugging them into the popup menu (to build it, of course :) ) - undoAction->plug( pm ); - redoAction->plug( pm ); - pm->insertSeparator(); - cutAction->plug( pm ); - copyAction->plug( pm ); - pasteAction->plug( pm ); - - // finally, we install the popup menu - dynamic_cast( editor )->installPopup( pm ); - } - - connect( this, TQT_SIGNAL( helpClicked() ), this, TQT_SLOT( slotHelpClicked() ) ); -} - -void NewScriptWizard::back() -{ - if ( currentPage() == mpcode ) - { - // currentPage() is not yet updated, so we're now entering the - // args page.. - mmode->argsPageEntered(); - } - else assert( false ); - NewScriptWizardBase::back(); -} - -void NewScriptWizard::next() -{ - if ( currentPage() == mpargs ) - mmode->codePageEntered(); - else assert( false ); - if ( !document ) - { - textedit->setFocus(); - } - else - { - editor->setFocus(); - } - NewScriptWizardBase::next(); -} - -void NewScriptWizard::reject() -{ - if ( mmode->queryCancel() ) - NewScriptWizardBase::reject(); -} - -void NewScriptWizard::accept() -{ - if ( mmode->queryFinish() ) - NewScriptWizardBase::accept(); -} - -void NewScriptWizard::slotHelpClicked() -{ - kapp->invokeHelp( TQString::fromLatin1( "scripting" ), - TQString::fromLatin1( "kig" ) ); -} - -void NewScriptWizard::setText( const TQString& text ) -{ - if ( !document ) - { - textedit->setText( text ); - } - else - { - dynamic_cast( document )->setText( text ); - } -} - -TQString NewScriptWizard::text() -{ - if ( !document ) - { - return textedit->text(); - } - else - { - return dynamic_cast( document )->text(); - } -} - -void NewScriptWizard::setType( ScriptType::Type type ) -{ - labelFillCode->setText( ScriptType::fillCodeStatement( type ) ); - - if ( !!document ) - { - if ( type != ScriptType::Unknown ) - { - for ( uint i = 0; i < hli->hlModeCount(); ++i ) - { - if ( hli->hlModeName( i ) == ScriptType::highlightStyle( type ) ) - { - // we found our highlight style, setting it - hli->setHlMode( i ); - return; - } - } - } - else - { - hli->setHlMode( noHlStyle ); - } - } -} - -void NewScriptWizard::slotUndo() -{ - dynamic_cast( document )->undo(); -} - -void NewScriptWizard::slotRedo() { - dynamic_cast( document )->redo(); -} - -void NewScriptWizard::slotCut() { - dynamic_cast( editor )->cut(); -} - -void NewScriptWizard::slotCopy() { - dynamic_cast( editor )->copy(); -} - -void NewScriptWizard::slotPaste() { - dynamic_cast( editor )->paste(); -} diff --git a/kig/scripting/newscriptwizard.cpp b/kig/scripting/newscriptwizard.cpp new file mode 100644 index 00000000..9cb4d9e2 --- /dev/null +++ b/kig/scripting/newscriptwizard.cpp @@ -0,0 +1,234 @@ +// 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 "newscriptwizard.h" +#include "newscriptwizard.moc" + +#include "script_mode.h" + +#include +#include + +//#include +//#include +// make it still work on old kde 3.1... +#include +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +NewScriptWizard::~NewScriptWizard() +{ + if ( !document ) + { + delete textedit; + } + else + { + //restoring the state of the dynamic word wrap + dynamic_cast( editor )->setDynWordWrap( prevDynWordWrap ); + delete editor->document(); + } +} + +NewScriptWizard::NewScriptWizard( TQWidget* parent, ScriptModeBase* mode ) + : NewScriptWizardBase( parent, "New Script Wizard" ), + mmode( mode ) +{ + document = KTextEditor::EditorChooser::createDocument( 0, "KTextEditor::Document" ); +// document = 0; + + gridLayout->expand( 2, 1 ); + + if ( !document ) + { + // there is no KDE textditor component installed, so we'll use a + // simplier KTextEdit + textedit = new KTextEdit( mpcode, "textedit" ); + textedit->setFont( TDEGlobalSettings::fixedFont() ); + gridLayout->addWidget( textedit, 1, 0 ); + } + else + { + // creating the 'view', hat is what the user see and interact with + editor = document->createView( mpcode, "editor" ); + gridLayout->addWidget( editor, 1, 0 ); + + // casting to the interfaces we'll use often + hli = dynamic_cast( document ); + + // displaying the left border with line numbers + TDEToggleAction *a = dynamic_cast( editor->actionCollection()->action("view_line_numbers") ); + a->activate(); + + // saving the state of dynamic word wrap and disabling it + prevDynWordWrap = dynamic_cast( editor )->dynWordWrap(); + dynamic_cast( editor )->setDynWordWrap( false ); + + // saving the "no highlight" id + noHlStyle = hli->hlMode(); + + // creating the popup menu + TDEPopupMenu* pm = new TDEPopupMenu( editor ); + // creating the actions for the code editor... + TDEActionCollection* ac = new TDEActionCollection( editor ); + TDEAction* undoAction = KStdAction::undo( TQT_TQOBJECT(this), TQT_SLOT( slotUndo() ), ac ); + TDEAction* redoAction = KStdAction::redo( TQT_TQOBJECT(this), TQT_SLOT( slotRedo() ), ac ); + TDEAction* cutAction = KStdAction::cut( TQT_TQOBJECT(this), TQT_SLOT( slotCut() ), ac ); + TDEAction* copyAction = KStdAction::copy( TQT_TQOBJECT(this), TQT_SLOT( slotCopy() ), ac ); + TDEAction* pasteAction = KStdAction::paste( TQT_TQOBJECT(this), TQT_SLOT( slotPaste() ), ac ); + // ... and plugging them into the popup menu (to build it, of course :) ) + undoAction->plug( pm ); + redoAction->plug( pm ); + pm->insertSeparator(); + cutAction->plug( pm ); + copyAction->plug( pm ); + pasteAction->plug( pm ); + + // finally, we install the popup menu + dynamic_cast( editor )->installPopup( pm ); + } + + connect( this, TQT_SIGNAL( helpClicked() ), this, TQT_SLOT( slotHelpClicked() ) ); +} + +void NewScriptWizard::back() +{ + if ( currentPage() == mpcode ) + { + // currentPage() is not yet updated, so we're now entering the + // args page.. + mmode->argsPageEntered(); + } + else assert( false ); + NewScriptWizardBase::back(); +} + +void NewScriptWizard::next() +{ + if ( currentPage() == mpargs ) + mmode->codePageEntered(); + else assert( false ); + if ( !document ) + { + textedit->setFocus(); + } + else + { + editor->setFocus(); + } + NewScriptWizardBase::next(); +} + +void NewScriptWizard::reject() +{ + if ( mmode->queryCancel() ) + NewScriptWizardBase::reject(); +} + +void NewScriptWizard::accept() +{ + if ( mmode->queryFinish() ) + NewScriptWizardBase::accept(); +} + +void NewScriptWizard::slotHelpClicked() +{ + kapp->invokeHelp( TQString::fromLatin1( "scripting" ), + TQString::fromLatin1( "kig" ) ); +} + +void NewScriptWizard::setText( const TQString& text ) +{ + if ( !document ) + { + textedit->setText( text ); + } + else + { + dynamic_cast( document )->setText( text ); + } +} + +TQString NewScriptWizard::text() +{ + if ( !document ) + { + return textedit->text(); + } + else + { + return dynamic_cast( document )->text(); + } +} + +void NewScriptWizard::setType( ScriptType::Type type ) +{ + labelFillCode->setText( ScriptType::fillCodeStatement( type ) ); + + if ( !!document ) + { + if ( type != ScriptType::Unknown ) + { + for ( uint i = 0; i < hli->hlModeCount(); ++i ) + { + if ( hli->hlModeName( i ) == ScriptType::highlightStyle( type ) ) + { + // we found our highlight style, setting it + hli->setHlMode( i ); + return; + } + } + } + else + { + hli->setHlMode( noHlStyle ); + } + } +} + +void NewScriptWizard::slotUndo() +{ + dynamic_cast( document )->undo(); +} + +void NewScriptWizard::slotRedo() { + dynamic_cast( document )->redo(); +} + +void NewScriptWizard::slotCut() { + dynamic_cast( editor )->cut(); +} + +void NewScriptWizard::slotCopy() { + dynamic_cast( editor )->copy(); +} + +void NewScriptWizard::slotPaste() { + dynamic_cast( editor )->paste(); +} diff --git a/kig/scripting/python_scripter.cc b/kig/scripting/python_scripter.cc deleted file mode 100644 index 00c7e162..00000000 --- a/kig/scripting/python_scripter.cc +++ /dev/null @@ -1,579 +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 "config.h" -#include "python_scripter.h" - -#include -#include -#include -#include -#include - -#include "../misc/common.h" -#include "../misc/coordinate.h" -#include "../misc/cubic-common.h" -#include "../misc/kigtransform.h" -#include "../objects/bogus_imp.h" -#include "../objects/common.h" -#include "../objects/circle_imp.h" -#include "../objects/cubic_imp.h" -#include "../objects/line_imp.h" -#include "../objects/other_imp.h" -#include "../objects/point_imp.h" - -using namespace boost::python; - -BOOST_PYTHON_MODULE_INIT( kig ) -{ - class_( "Coordinate" ) - .def( init() ) - .def( init() ) - .def( "invalidCoord", &Coordinate::invalidCoord ) - .staticmethod( "invalidCoord" ) - .def( "valid", &Coordinate::valid ) - .def( "distance", &Coordinate::distance ) - .def( "length", &Coordinate::length ) - .def( "squareLength", &Coordinate::squareLength ) - .def( "orthogonal", &Coordinate::orthogonal ) - .def( "round", &Coordinate::round ) - .def( "normalize", &Coordinate::normalize ) - .def( -self ) -// .def( self = self ) - .def( self += self ) - .def( self -= self ) - .def( self *= other() ) - .def( self *= other() ) - .def( self /= other() ) - .def( self / other() ) - .def( self + self ) - .def( self - self ) - .def( self * other() ) - .def( other() * self ) - .def( self * self ) - .def_readwrite( "x", &Coordinate::x ) - .def_readwrite( "y", &Coordinate::y ) - ; - - class_( "LineData" ) - .def( init() ) - .def( "dir", &LineData::dir ) - .def( "length", &LineData::length ) - .def( "isParallelTo", &LineData::isParallelTo ) - .def_readwrite( "a", &LineData::a ) - .def_readwrite( "b", &LineData::b ) - ; - - // we need this cause Transformation::apply is overloaded and - // otherwise using Transformation::apply would be ambiguous.. - const Coordinate (Transformation::*transformapplyfunc)( const Coordinate& ) const = &Transformation::apply; - class_( "Transformation", no_init ) - .def( "apply", transformapplyfunc ) - .def( "isHomothetic", &Transformation::isHomothetic ) - .def( "inverse", &Transformation::inverse ) - .def( "identity", &Transformation::identity ) - .def( "translation", &Transformation::translation ) - .def( "rotation", &Transformation::rotation ) - .def( "pointReflection", &Transformation::pointReflection ) - .def( "lineReflection", &Transformation::lineReflection ) - .def( "castShadow", &Transformation::castShadow ) - .def( "projectiveRotation", &Transformation::projectiveRotation ) - .def( "scalingOverPoint", &Transformation::scalingOverPoint ) - .def( "scalingOverLine", &Transformation::scalingOverLine ) - .def( self * self ) - .def( self == self ) - .staticmethod( "identity" ) - .staticmethod( "translation" ) - .staticmethod( "rotation" ) - .staticmethod( "pointReflection" ) - .staticmethod( "lineReflection" ) - .staticmethod( "castShadow" ) - .staticmethod( "projectiveRotation" ) - .staticmethod( "scalingOverPoint" ) - .staticmethod( "scalingOverLine" ) - ; - - class_( "ObjectType", no_init ) - .def( "fromInternalName", &ObjectImpType::typeFromInternalName, - return_value_policy() ) - .staticmethod( "fromInternalName" ) - .def( "inherits", &ObjectImpType::inherits ) - .def( "internalName", &ObjectImpType::internalName ) - .def( "translatedName", &ObjectImpType::translatedName ) - .def( "selectStatement", &ObjectImpType::selectStatement ) - .def( "removeAStatement", &ObjectImpType::removeAStatement ) - .def( "addAStatement", &ObjectImpType::addAStatement ) - .def( "moveAStatement", &ObjectImpType::moveAStatement ) - .def( "attachToThisStatement", &ObjectImpType::attachToThisStatement ) - ; - - class_( "Object", no_init ) - .def( "stype", &ObjectImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - .def( "inherits", &ObjectImp::inherits ) - .def( "transform", &ObjectImp::transform, - return_value_policy() ) - .def( "valid", &ObjectImp::valid ) - .def( "copy", &ObjectImp::copy, - return_value_policy() ) - .def( "equals", &ObjectImp::equals ) - ; - - class_, boost::noncopyable>( "Curve", no_init ) - .def( "stype", &CurveImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) -// .def( "getParam", &CurveImp::getParam ) -// .def( "getPoint", &CurveImp::getPoint ); - ; - class_ >( "Point", init() ) - .def( "stype", &PointImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - .def( "coordinate", &PointImp::coordinate, - return_internal_reference<1>() ) - .def( "setCoordinate", &PointImp::setCoordinate ) - ; - - class_, boost::noncopyable >( "AbstractLine", no_init ) - .def( "stype", &AbstractLineImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - .def( "slope", &AbstractLineImp::slope ) - .def( "equationString", &AbstractLineImp::equationString ) - .def( "data", &AbstractLineImp::data ) - ; - - class_ >( "Segment", init() ) - .def( "stype", &SegmentImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - .def( init() ) - .def( "length", &SegmentImp::length ) - ; - - class_ >( "Ray", init() ) - .def( "stype", &RayImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - .def( init() ) - ; - - class_ >( "Line", init() ) - .def( "stype", &LineImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - .def( init() ) - ; - - class_( "ConicCartesianData", init() ) - .def( init() ) - .def( "invalidData", &ConicCartesianData::invalidData ) - .staticmethod( "invalidData" ) - .def( "valid", &ConicCartesianData::valid ) -// .def( init() ) -// .def_readwrite( "coeffs", &ConicCartesianData::coeffs ) - ; - - class_( "ConicPolarData", init() ) - .def( init() ) - .def_readwrite( "focus1", &ConicPolarData::focus1 ) - .def_readwrite( "pdimen", &ConicPolarData::pdimen ) - .def_readwrite( "ecostheta0", &ConicPolarData::ecostheta0 ) - .def_readwrite( "esintheta0", &ConicPolarData::esintheta0 ) - ; - - class_, boost::noncopyable >( "Conic", no_init ) - .def( "stype", &ConicImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - .def( "conicType", &ConicImp::conicType ) -// .def( "conicTypeString", &ConicImp::conicTypeString ) -// .def( "cartesianEquationString", &ConicImp::cartesianEquationString ) -// .def( "polarEquationString", &ConicImp::polarEquationString ) - .def( "cartesianData", &ConicImp::cartesianData ) - .def( "polarData", &ConicImp::polarData ) - .def( "focus1", &ConicImp::focus1 ) - .def( "focus2", &ConicImp::focus2 ) - ; - - class_ >( "CartesianConic", init() ) - ; - class_ >( "PolarConic", init() ) - ; - - class_ >( "Circle", init() ) - .def( "stype", &CircleImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - .def( "center", &CircleImp::center ) - .def( "radius", &CircleImp::radius ) - .def( "squareRadius", &CircleImp::squareRadius ) - .def( "surface", &CircleImp::surface ) - .def( "circumference", &CircleImp::circumference ) - ; - - class_ >( "Vector", init() ) - .def( "stype", &VectorImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - .def( "length", &VectorImp::length ) - .def( "dir", &VectorImp::dir ) - .def( "data", &VectorImp::data ) - ; - - class_ >( "Angle", init() ) - .def( "stype", &AngleImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - .def( "size", &AngleImp::size ) - .def( "point", &AngleImp::point ) - .def( "startAngle", &AngleImp::startAngle ) - .def( "angle", &AngleImp::angle ) - ; - - class_ >( "Arc", init() ) - .def( "stype", &ArcImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - .def( "startAngle", &ArcImp::startAngle ) - .def( "angle", &ArcImp::angle ) - .def( "radius", &ArcImp::radius ) - .def( "center", &ArcImp::center ) - .def( "firstEndPoint", &ArcImp::firstEndPoint ) - .def( "secondEndPoint", &ArcImp::secondEndPoint ) - .def( "sectorSurface", &ArcImp::sectorSurface ) - ; - - class_, boost::noncopyable >( "BogusObject", no_init ) - .def( "stype", &BogusImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - ; - - class_ >( "InvalidObject", init<>() ) - .def( "stype", &InvalidImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - ; - - class_ >( "DoubleObject", init() ) - .def( "stype", &DoubleImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - .def( "data", &DoubleImp::data ) - .def( "setData", &DoubleImp::setData ) - ; - - class_ >( "IntObject", init() ) - .def( "stype", &IntImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - .def( "data", &IntImp::data ) - .def( "setData", &IntImp::setData ) - ; - - class_ >( "StringObject", no_init ) - .def( "stype", &StringImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) -// .def( "data", &StringImp::data ) -// .def( "setData", &StringImp::setData ) - ; - - class_ >( "TestResultObject", no_init ) - .def( "stype", &TestResultImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) -// .def( "data", &TestResultImp::data ) - ; - -// class_ >( "Text", init() ) -// .def( "stype", &TextImp::stype, -// return_value_policy() ) -// .staticmethod( "stype" ) -// .def( "text", &TextImp::text ) -// .def( "coordinate", &TextImp::coordinate ) -// .def( "hasFrame", &TextImp::hasFrame ) -// ; - - class_( "CubicCartesianData", init() ) - .def( "invalidData", &CubicCartesianData::invalidData ) - .staticmethod( "invalidData" ) - .def( "valid", &CubicCartesianData::valid ) -// .def( init() ) -// .def_readwrite( "coeffs", &CubicCartesianData::coeffs ) - ; - - class_ >( "Cubic", init() ) - .def( "stype", &CubicImp::stype, - return_value_policy() ) - .staticmethod( "stype" ) - .def( "data", &CubicImp::data ) - ; - -} - -PythonScripter* PythonScripter::instance() -{ - static PythonScripter t; - return &t; -} - -class PythonScripter::Private -{ -public: - dict mainnamespace; -}; - -// allocates a new string using new [], and copies contents into it.. -static char* newstring( const char* contents ) -{ - char* ret = new char[strlen( contents ) + 1]; - strcpy( ret, contents ); - return ret; -} - -PythonScripter::PythonScripter() -{ - d = new Private; - - // tell the python interpreter about our API.. - - // the newstring stuff is to prevent warnings about conversion from - // const char* to char*.. - char* s = newstring( "kig" ); - PyImport_AppendInittab( s, KIG_Python_init ); - // we can't delete this yet, since python keeps a pointer to it.. - // This means we have a small but harmless memory leak here, but it - // doesn't hurt at all, since it could only be freed at the end of - // the program, at which time it is freed by the system anyway if we - // don't do it.. - //delete [] s; - - Py_Initialize(); - - s = newstring( "import math; from math import *;" ); - PyRun_SimpleString( s ); - delete [] s; - s = newstring( "import kig; from kig import *;" ); - PyRun_SimpleString( s ); - delete [] s; - s = newstring( "import traceback;" ); - PyRun_SimpleString( s ); - delete [] s; - - // find the main namespace.. - - s = newstring( "__main__" ); - handle<> main_module( borrowed( PyImport_AddModule( s ) ) ); - delete [] s; - - handle<> mnh(borrowed( PyModule_GetDict(main_module.get()) )); - d->mainnamespace = extract( mnh.get() ); -} - -PythonScripter::~PythonScripter() -{ - PyErr_Clear(); - Py_Finalize(); - delete d; -} - -class CompiledPythonScript::Private -{ -public: - int ref; - object calcfunc; - // TODO -// object movefunc; -}; - -ObjectImp* CompiledPythonScript::calc( const Args& args, const KigDocument& ) -{ - return PythonScripter::instance()->calc( *this, args ); -} - -CompiledPythonScript::~CompiledPythonScript() -{ - --d->ref; - if ( d->ref == 0 ) - delete d; -} - -CompiledPythonScript::CompiledPythonScript( Private* ind ) - : d( ind ) -{ - ++d->ref; -} - -CompiledPythonScript PythonScripter::compile( const char* code ) -{ - clearErrors(); - dict retdict; - bool error = false; - try - { - (void) PyRun_String( const_cast( code ), Py_file_input, - d->mainnamespace.ptr(), retdict.ptr() ); - } - catch( ... ) - { - error = true; - }; - error |= static_cast( PyErr_Occurred() ); - if ( error ) - { - saveErrors(); - retdict.clear(); - } - - // debugging stuff, removed. -// std::string dictstring = extract( str( retdict ) ); - - CompiledPythonScript::Private* ret = new CompiledPythonScript::Private; - ret->ref = 0; - ret->calcfunc = retdict.get( "calc" ); - return CompiledPythonScript( ret ); -} - -CompiledPythonScript::CompiledPythonScript( const CompiledPythonScript& s ) - : d( s.d ) -{ - ++d->ref; -} - -std::string PythonScripter::lastErrorExceptionType() const -{ - return lastexceptiontype; -} - -std::string PythonScripter::lastErrorExceptionValue() const -{ - return lastexceptionvalue; -} - -std::string PythonScripter::lastErrorExceptionTraceback() const -{ - return lastexceptiontraceback; -} - -ObjectImp* PythonScripter::calc( CompiledPythonScript& script, const Args& args ) -{ - clearErrors(); - object calcfunc = script.d->calcfunc; - try - { - std::vector objectvect; - objectvect.reserve( args.size() ); - - for ( int i = 0; i < (int) args.size(); ++i ) - { - object o( boost::ref( *args[i] ) ); - objectvect.push_back( o ); - } - - handle<> argstuph( PyTuple_New( args.size() ) ); - for ( int i = 0; i < (int) objectvect.size(); ++i ) - { - PyTuple_SetItem( argstuph.get(), i, (objectvect.begin() +i)->ptr() ); - }; - tuple argstup( argstuph ); - - handle<> reth( PyEval_CallObject( calcfunc.ptr(), argstup.ptr() ) ); -// object resulto = calcfunc( argstup ); -// handle<> reth( PyEval_CallObject( calcfunc.ptr(), args ) ); - object resulto( reth ); - - extract result( resulto ); - if( ! result.check() ) return new InvalidImp; - else - { - ObjectImp& ret = result(); - return ret.copy(); - }; - } - catch( ... ) - { - saveErrors(); - - return new InvalidImp; - }; -} - -void PythonScripter::saveErrors() -{ - erroroccurred = true; - PyObject* poexctype; - PyObject* poexcvalue; - PyObject* poexctraceback; - PyErr_Fetch( &poexctype, &poexcvalue, &poexctraceback ); - handle<> exctypeh( poexctype ); - handle<> excvalueh( poexcvalue ); - - object exctype( exctypeh ); - object excvalue( excvalueh ); - object exctraceback; - if ( poexctraceback ) - { - handle<> exctracebackh( poexctraceback ); - exctraceback = object( exctracebackh ); - } - - lastexceptiontype = extract( str( exctype ) )(); - lastexceptionvalue = extract( str( excvalue ) )(); - - object printexcfunc = d->mainnamespace[ "traceback" ].attr( "format_exception" ); - - list tracebacklist = extract( printexcfunc( exctype, excvalue, exctraceback ) )(); - str tracebackstr( "" ); - while ( true ) - { - try { - str s = extract( tracebacklist.pop() ); - tracebackstr += s; - } - catch( ... ) - { - break; - } - } - - lastexceptiontraceback = extract( tracebackstr )(); - PyErr_Clear(); -} - -void PythonScripter::clearErrors() -{ - PyErr_Clear(); - lastexceptiontype.clear(); - lastexceptionvalue.clear(); - lastexceptiontraceback.clear(); - erroroccurred = false; -} - -bool CompiledPythonScript::valid() -{ - return !!d->calcfunc; -} - -bool PythonScripter::errorOccurred() const -{ - return erroroccurred; -} - diff --git a/kig/scripting/python_scripter.cpp b/kig/scripting/python_scripter.cpp new file mode 100644 index 00000000..00c7e162 --- /dev/null +++ b/kig/scripting/python_scripter.cpp @@ -0,0 +1,579 @@ +// 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 "config.h" +#include "python_scripter.h" + +#include +#include +#include +#include +#include + +#include "../misc/common.h" +#include "../misc/coordinate.h" +#include "../misc/cubic-common.h" +#include "../misc/kigtransform.h" +#include "../objects/bogus_imp.h" +#include "../objects/common.h" +#include "../objects/circle_imp.h" +#include "../objects/cubic_imp.h" +#include "../objects/line_imp.h" +#include "../objects/other_imp.h" +#include "../objects/point_imp.h" + +using namespace boost::python; + +BOOST_PYTHON_MODULE_INIT( kig ) +{ + class_( "Coordinate" ) + .def( init() ) + .def( init() ) + .def( "invalidCoord", &Coordinate::invalidCoord ) + .staticmethod( "invalidCoord" ) + .def( "valid", &Coordinate::valid ) + .def( "distance", &Coordinate::distance ) + .def( "length", &Coordinate::length ) + .def( "squareLength", &Coordinate::squareLength ) + .def( "orthogonal", &Coordinate::orthogonal ) + .def( "round", &Coordinate::round ) + .def( "normalize", &Coordinate::normalize ) + .def( -self ) +// .def( self = self ) + .def( self += self ) + .def( self -= self ) + .def( self *= other() ) + .def( self *= other() ) + .def( self /= other() ) + .def( self / other() ) + .def( self + self ) + .def( self - self ) + .def( self * other() ) + .def( other() * self ) + .def( self * self ) + .def_readwrite( "x", &Coordinate::x ) + .def_readwrite( "y", &Coordinate::y ) + ; + + class_( "LineData" ) + .def( init() ) + .def( "dir", &LineData::dir ) + .def( "length", &LineData::length ) + .def( "isParallelTo", &LineData::isParallelTo ) + .def_readwrite( "a", &LineData::a ) + .def_readwrite( "b", &LineData::b ) + ; + + // we need this cause Transformation::apply is overloaded and + // otherwise using Transformation::apply would be ambiguous.. + const Coordinate (Transformation::*transformapplyfunc)( const Coordinate& ) const = &Transformation::apply; + class_( "Transformation", no_init ) + .def( "apply", transformapplyfunc ) + .def( "isHomothetic", &Transformation::isHomothetic ) + .def( "inverse", &Transformation::inverse ) + .def( "identity", &Transformation::identity ) + .def( "translation", &Transformation::translation ) + .def( "rotation", &Transformation::rotation ) + .def( "pointReflection", &Transformation::pointReflection ) + .def( "lineReflection", &Transformation::lineReflection ) + .def( "castShadow", &Transformation::castShadow ) + .def( "projectiveRotation", &Transformation::projectiveRotation ) + .def( "scalingOverPoint", &Transformation::scalingOverPoint ) + .def( "scalingOverLine", &Transformation::scalingOverLine ) + .def( self * self ) + .def( self == self ) + .staticmethod( "identity" ) + .staticmethod( "translation" ) + .staticmethod( "rotation" ) + .staticmethod( "pointReflection" ) + .staticmethod( "lineReflection" ) + .staticmethod( "castShadow" ) + .staticmethod( "projectiveRotation" ) + .staticmethod( "scalingOverPoint" ) + .staticmethod( "scalingOverLine" ) + ; + + class_( "ObjectType", no_init ) + .def( "fromInternalName", &ObjectImpType::typeFromInternalName, + return_value_policy() ) + .staticmethod( "fromInternalName" ) + .def( "inherits", &ObjectImpType::inherits ) + .def( "internalName", &ObjectImpType::internalName ) + .def( "translatedName", &ObjectImpType::translatedName ) + .def( "selectStatement", &ObjectImpType::selectStatement ) + .def( "removeAStatement", &ObjectImpType::removeAStatement ) + .def( "addAStatement", &ObjectImpType::addAStatement ) + .def( "moveAStatement", &ObjectImpType::moveAStatement ) + .def( "attachToThisStatement", &ObjectImpType::attachToThisStatement ) + ; + + class_( "Object", no_init ) + .def( "stype", &ObjectImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + .def( "inherits", &ObjectImp::inherits ) + .def( "transform", &ObjectImp::transform, + return_value_policy() ) + .def( "valid", &ObjectImp::valid ) + .def( "copy", &ObjectImp::copy, + return_value_policy() ) + .def( "equals", &ObjectImp::equals ) + ; + + class_, boost::noncopyable>( "Curve", no_init ) + .def( "stype", &CurveImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) +// .def( "getParam", &CurveImp::getParam ) +// .def( "getPoint", &CurveImp::getPoint ); + ; + class_ >( "Point", init() ) + .def( "stype", &PointImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + .def( "coordinate", &PointImp::coordinate, + return_internal_reference<1>() ) + .def( "setCoordinate", &PointImp::setCoordinate ) + ; + + class_, boost::noncopyable >( "AbstractLine", no_init ) + .def( "stype", &AbstractLineImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + .def( "slope", &AbstractLineImp::slope ) + .def( "equationString", &AbstractLineImp::equationString ) + .def( "data", &AbstractLineImp::data ) + ; + + class_ >( "Segment", init() ) + .def( "stype", &SegmentImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + .def( init() ) + .def( "length", &SegmentImp::length ) + ; + + class_ >( "Ray", init() ) + .def( "stype", &RayImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + .def( init() ) + ; + + class_ >( "Line", init() ) + .def( "stype", &LineImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + .def( init() ) + ; + + class_( "ConicCartesianData", init() ) + .def( init() ) + .def( "invalidData", &ConicCartesianData::invalidData ) + .staticmethod( "invalidData" ) + .def( "valid", &ConicCartesianData::valid ) +// .def( init() ) +// .def_readwrite( "coeffs", &ConicCartesianData::coeffs ) + ; + + class_( "ConicPolarData", init() ) + .def( init() ) + .def_readwrite( "focus1", &ConicPolarData::focus1 ) + .def_readwrite( "pdimen", &ConicPolarData::pdimen ) + .def_readwrite( "ecostheta0", &ConicPolarData::ecostheta0 ) + .def_readwrite( "esintheta0", &ConicPolarData::esintheta0 ) + ; + + class_, boost::noncopyable >( "Conic", no_init ) + .def( "stype", &ConicImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + .def( "conicType", &ConicImp::conicType ) +// .def( "conicTypeString", &ConicImp::conicTypeString ) +// .def( "cartesianEquationString", &ConicImp::cartesianEquationString ) +// .def( "polarEquationString", &ConicImp::polarEquationString ) + .def( "cartesianData", &ConicImp::cartesianData ) + .def( "polarData", &ConicImp::polarData ) + .def( "focus1", &ConicImp::focus1 ) + .def( "focus2", &ConicImp::focus2 ) + ; + + class_ >( "CartesianConic", init() ) + ; + class_ >( "PolarConic", init() ) + ; + + class_ >( "Circle", init() ) + .def( "stype", &CircleImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + .def( "center", &CircleImp::center ) + .def( "radius", &CircleImp::radius ) + .def( "squareRadius", &CircleImp::squareRadius ) + .def( "surface", &CircleImp::surface ) + .def( "circumference", &CircleImp::circumference ) + ; + + class_ >( "Vector", init() ) + .def( "stype", &VectorImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + .def( "length", &VectorImp::length ) + .def( "dir", &VectorImp::dir ) + .def( "data", &VectorImp::data ) + ; + + class_ >( "Angle", init() ) + .def( "stype", &AngleImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + .def( "size", &AngleImp::size ) + .def( "point", &AngleImp::point ) + .def( "startAngle", &AngleImp::startAngle ) + .def( "angle", &AngleImp::angle ) + ; + + class_ >( "Arc", init() ) + .def( "stype", &ArcImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + .def( "startAngle", &ArcImp::startAngle ) + .def( "angle", &ArcImp::angle ) + .def( "radius", &ArcImp::radius ) + .def( "center", &ArcImp::center ) + .def( "firstEndPoint", &ArcImp::firstEndPoint ) + .def( "secondEndPoint", &ArcImp::secondEndPoint ) + .def( "sectorSurface", &ArcImp::sectorSurface ) + ; + + class_, boost::noncopyable >( "BogusObject", no_init ) + .def( "stype", &BogusImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + ; + + class_ >( "InvalidObject", init<>() ) + .def( "stype", &InvalidImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + ; + + class_ >( "DoubleObject", init() ) + .def( "stype", &DoubleImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + .def( "data", &DoubleImp::data ) + .def( "setData", &DoubleImp::setData ) + ; + + class_ >( "IntObject", init() ) + .def( "stype", &IntImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + .def( "data", &IntImp::data ) + .def( "setData", &IntImp::setData ) + ; + + class_ >( "StringObject", no_init ) + .def( "stype", &StringImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) +// .def( "data", &StringImp::data ) +// .def( "setData", &StringImp::setData ) + ; + + class_ >( "TestResultObject", no_init ) + .def( "stype", &TestResultImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) +// .def( "data", &TestResultImp::data ) + ; + +// class_ >( "Text", init() ) +// .def( "stype", &TextImp::stype, +// return_value_policy() ) +// .staticmethod( "stype" ) +// .def( "text", &TextImp::text ) +// .def( "coordinate", &TextImp::coordinate ) +// .def( "hasFrame", &TextImp::hasFrame ) +// ; + + class_( "CubicCartesianData", init() ) + .def( "invalidData", &CubicCartesianData::invalidData ) + .staticmethod( "invalidData" ) + .def( "valid", &CubicCartesianData::valid ) +// .def( init() ) +// .def_readwrite( "coeffs", &CubicCartesianData::coeffs ) + ; + + class_ >( "Cubic", init() ) + .def( "stype", &CubicImp::stype, + return_value_policy() ) + .staticmethod( "stype" ) + .def( "data", &CubicImp::data ) + ; + +} + +PythonScripter* PythonScripter::instance() +{ + static PythonScripter t; + return &t; +} + +class PythonScripter::Private +{ +public: + dict mainnamespace; +}; + +// allocates a new string using new [], and copies contents into it.. +static char* newstring( const char* contents ) +{ + char* ret = new char[strlen( contents ) + 1]; + strcpy( ret, contents ); + return ret; +} + +PythonScripter::PythonScripter() +{ + d = new Private; + + // tell the python interpreter about our API.. + + // the newstring stuff is to prevent warnings about conversion from + // const char* to char*.. + char* s = newstring( "kig" ); + PyImport_AppendInittab( s, KIG_Python_init ); + // we can't delete this yet, since python keeps a pointer to it.. + // This means we have a small but harmless memory leak here, but it + // doesn't hurt at all, since it could only be freed at the end of + // the program, at which time it is freed by the system anyway if we + // don't do it.. + //delete [] s; + + Py_Initialize(); + + s = newstring( "import math; from math import *;" ); + PyRun_SimpleString( s ); + delete [] s; + s = newstring( "import kig; from kig import *;" ); + PyRun_SimpleString( s ); + delete [] s; + s = newstring( "import traceback;" ); + PyRun_SimpleString( s ); + delete [] s; + + // find the main namespace.. + + s = newstring( "__main__" ); + handle<> main_module( borrowed( PyImport_AddModule( s ) ) ); + delete [] s; + + handle<> mnh(borrowed( PyModule_GetDict(main_module.get()) )); + d->mainnamespace = extract( mnh.get() ); +} + +PythonScripter::~PythonScripter() +{ + PyErr_Clear(); + Py_Finalize(); + delete d; +} + +class CompiledPythonScript::Private +{ +public: + int ref; + object calcfunc; + // TODO +// object movefunc; +}; + +ObjectImp* CompiledPythonScript::calc( const Args& args, const KigDocument& ) +{ + return PythonScripter::instance()->calc( *this, args ); +} + +CompiledPythonScript::~CompiledPythonScript() +{ + --d->ref; + if ( d->ref == 0 ) + delete d; +} + +CompiledPythonScript::CompiledPythonScript( Private* ind ) + : d( ind ) +{ + ++d->ref; +} + +CompiledPythonScript PythonScripter::compile( const char* code ) +{ + clearErrors(); + dict retdict; + bool error = false; + try + { + (void) PyRun_String( const_cast( code ), Py_file_input, + d->mainnamespace.ptr(), retdict.ptr() ); + } + catch( ... ) + { + error = true; + }; + error |= static_cast( PyErr_Occurred() ); + if ( error ) + { + saveErrors(); + retdict.clear(); + } + + // debugging stuff, removed. +// std::string dictstring = extract( str( retdict ) ); + + CompiledPythonScript::Private* ret = new CompiledPythonScript::Private; + ret->ref = 0; + ret->calcfunc = retdict.get( "calc" ); + return CompiledPythonScript( ret ); +} + +CompiledPythonScript::CompiledPythonScript( const CompiledPythonScript& s ) + : d( s.d ) +{ + ++d->ref; +} + +std::string PythonScripter::lastErrorExceptionType() const +{ + return lastexceptiontype; +} + +std::string PythonScripter::lastErrorExceptionValue() const +{ + return lastexceptionvalue; +} + +std::string PythonScripter::lastErrorExceptionTraceback() const +{ + return lastexceptiontraceback; +} + +ObjectImp* PythonScripter::calc( CompiledPythonScript& script, const Args& args ) +{ + clearErrors(); + object calcfunc = script.d->calcfunc; + try + { + std::vector objectvect; + objectvect.reserve( args.size() ); + + for ( int i = 0; i < (int) args.size(); ++i ) + { + object o( boost::ref( *args[i] ) ); + objectvect.push_back( o ); + } + + handle<> argstuph( PyTuple_New( args.size() ) ); + for ( int i = 0; i < (int) objectvect.size(); ++i ) + { + PyTuple_SetItem( argstuph.get(), i, (objectvect.begin() +i)->ptr() ); + }; + tuple argstup( argstuph ); + + handle<> reth( PyEval_CallObject( calcfunc.ptr(), argstup.ptr() ) ); +// object resulto = calcfunc( argstup ); +// handle<> reth( PyEval_CallObject( calcfunc.ptr(), args ) ); + object resulto( reth ); + + extract result( resulto ); + if( ! result.check() ) return new InvalidImp; + else + { + ObjectImp& ret = result(); + return ret.copy(); + }; + } + catch( ... ) + { + saveErrors(); + + return new InvalidImp; + }; +} + +void PythonScripter::saveErrors() +{ + erroroccurred = true; + PyObject* poexctype; + PyObject* poexcvalue; + PyObject* poexctraceback; + PyErr_Fetch( &poexctype, &poexcvalue, &poexctraceback ); + handle<> exctypeh( poexctype ); + handle<> excvalueh( poexcvalue ); + + object exctype( exctypeh ); + object excvalue( excvalueh ); + object exctraceback; + if ( poexctraceback ) + { + handle<> exctracebackh( poexctraceback ); + exctraceback = object( exctracebackh ); + } + + lastexceptiontype = extract( str( exctype ) )(); + lastexceptionvalue = extract( str( excvalue ) )(); + + object printexcfunc = d->mainnamespace[ "traceback" ].attr( "format_exception" ); + + list tracebacklist = extract( printexcfunc( exctype, excvalue, exctraceback ) )(); + str tracebackstr( "" ); + while ( true ) + { + try { + str s = extract( tracebacklist.pop() ); + tracebackstr += s; + } + catch( ... ) + { + break; + } + } + + lastexceptiontraceback = extract( tracebackstr )(); + PyErr_Clear(); +} + +void PythonScripter::clearErrors() +{ + PyErr_Clear(); + lastexceptiontype.clear(); + lastexceptionvalue.clear(); + lastexceptiontraceback.clear(); + erroroccurred = false; +} + +bool CompiledPythonScript::valid() +{ + return !!d->calcfunc; +} + +bool PythonScripter::errorOccurred() const +{ + return erroroccurred; +} + diff --git a/kig/scripting/python_type.cc b/kig/scripting/python_type.cc deleted file mode 100644 index cc5a00ea..00000000 --- a/kig/scripting/python_type.cc +++ /dev/null @@ -1,195 +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 "python_type.h" - -#include "python_scripter.h" - -#include "../objects/object_imp.h" -#include "../objects/bogus_imp.h" - -class PythonCompiledScriptImp - : public BogusImp -{ - mutable CompiledPythonScript mscript; -public: - typedef BogusImp Parent; - static const ObjectImpType* stype(); - const ObjectImpType* type() const; - - PythonCompiledScriptImp( const CompiledPythonScript& s ); - - void visit( ObjectImpVisitor* vtor ) const; - ObjectImp* copy() const; - bool equals( const ObjectImp& rhs ) const; - - bool isCache() const; - - CompiledPythonScript& data() const { return mscript; }; -}; - -PythonCompiledScriptImp::PythonCompiledScriptImp( const CompiledPythonScript& s ) - : BogusImp(), mscript( s ) -{ - -} - -const ObjectImpType* PythonCompiledScriptImp::stype() -{ - static const ObjectImpType t( BogusImp::stype(), "python-compiled-script-imp", - 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - return &t; -} - -const ObjectImpType* PythonCompiledScriptImp::type() const -{ - return PythonCompiledScriptImp::stype(); -} - -void PythonCompiledScriptImp::visit( ObjectImpVisitor* ) const -{ - // TODO ? -} - -ObjectImp* PythonCompiledScriptImp::copy() const -{ - return new PythonCompiledScriptImp( mscript ); -} - -bool PythonCompiledScriptImp::equals( const ObjectImp& ) const -{ - // problem ? - return true; -} - -bool PythonCompiledScriptImp::isCache() const -{ - return true; -} - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PythonCompileType ) - -PythonCompileType::PythonCompileType() - : ObjectType( "PythonCompileType" ) -{ -} - -PythonCompileType::~PythonCompileType() -{ -} - -const PythonCompileType* PythonCompileType::instance() -{ - static const PythonCompileType t; - return &t; -} - -const ObjectImpType* PythonCompileType::impRequirement( const ObjectImp*, const Args& ) const -{ - return StringImp::stype(); -} - -const ObjectImpType* PythonCompileType::resultId() const -{ - return PythonCompiledScriptImp::stype(); -} - -ObjectImp* PythonCompileType::calc( const Args& parents, const KigDocument& ) const -{ - assert( parents.size() == 1 ); - if ( !parents[0]->inherits( StringImp::stype() ) ) return new InvalidImp; - - const StringImp* si = static_cast( parents[0] ); - TQString s = si->data(); - - CompiledPythonScript cs = PythonScripter::instance()->compile( s.latin1() ); - - if ( cs.valid() ) - return new PythonCompiledScriptImp( cs ); - else - return new InvalidImp(); -} - -KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PythonExecuteType ) - -PythonExecuteType::PythonExecuteType() - : ObjectType( "PythonExecuteType" ) -{ -} - -PythonExecuteType::~PythonExecuteType() -{ -} - -const PythonExecuteType* PythonExecuteType::instance() -{ - static const PythonExecuteType t; - return &t; -} - -ObjectImp* PythonExecuteType::calc( const Args& parents, const KigDocument& d ) const -{ - assert( parents.size() >= 1 ); - if( !parents[0]->inherits( PythonCompiledScriptImp::stype() ) ) return new InvalidImp; - - CompiledPythonScript& script = static_cast( parents[0] )->data(); - - Args args( parents.begin() + 1, parents.end() ); - return script.calc( args, d ); -} - -const ObjectImpType* PythonExecuteType::impRequirement( const ObjectImp* o, const Args& parents ) const -{ - if ( o == parents[0] ) return PythonCompiledScriptImp::stype(); - else return ObjectImp::stype(); -} - -const ObjectImpType* PythonExecuteType::resultId() const -{ - return ObjectImp::stype(); -} - -std::vector PythonCompileType::sortArgs( const std::vector& args ) const -{ - return args; -} - -Args PythonCompileType::sortArgs( const Args& args ) const -{ - return args; -} - -std::vector PythonExecuteType::sortArgs( const std::vector& args ) const -{ - return args; -} - -Args PythonExecuteType::sortArgs( const Args& args ) const -{ - return args; -} - -bool PythonCompileType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const -{ - return false; -} - -bool PythonExecuteType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const -{ - return false; -} - diff --git a/kig/scripting/python_type.cpp b/kig/scripting/python_type.cpp new file mode 100644 index 00000000..cc5a00ea --- /dev/null +++ b/kig/scripting/python_type.cpp @@ -0,0 +1,195 @@ +// 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 "python_type.h" + +#include "python_scripter.h" + +#include "../objects/object_imp.h" +#include "../objects/bogus_imp.h" + +class PythonCompiledScriptImp + : public BogusImp +{ + mutable CompiledPythonScript mscript; +public: + typedef BogusImp Parent; + static const ObjectImpType* stype(); + const ObjectImpType* type() const; + + PythonCompiledScriptImp( const CompiledPythonScript& s ); + + void visit( ObjectImpVisitor* vtor ) const; + ObjectImp* copy() const; + bool equals( const ObjectImp& rhs ) const; + + bool isCache() const; + + CompiledPythonScript& data() const { return mscript; }; +}; + +PythonCompiledScriptImp::PythonCompiledScriptImp( const CompiledPythonScript& s ) + : BogusImp(), mscript( s ) +{ + +} + +const ObjectImpType* PythonCompiledScriptImp::stype() +{ + static const ObjectImpType t( BogusImp::stype(), "python-compiled-script-imp", + 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + return &t; +} + +const ObjectImpType* PythonCompiledScriptImp::type() const +{ + return PythonCompiledScriptImp::stype(); +} + +void PythonCompiledScriptImp::visit( ObjectImpVisitor* ) const +{ + // TODO ? +} + +ObjectImp* PythonCompiledScriptImp::copy() const +{ + return new PythonCompiledScriptImp( mscript ); +} + +bool PythonCompiledScriptImp::equals( const ObjectImp& ) const +{ + // problem ? + return true; +} + +bool PythonCompiledScriptImp::isCache() const +{ + return true; +} + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PythonCompileType ) + +PythonCompileType::PythonCompileType() + : ObjectType( "PythonCompileType" ) +{ +} + +PythonCompileType::~PythonCompileType() +{ +} + +const PythonCompileType* PythonCompileType::instance() +{ + static const PythonCompileType t; + return &t; +} + +const ObjectImpType* PythonCompileType::impRequirement( const ObjectImp*, const Args& ) const +{ + return StringImp::stype(); +} + +const ObjectImpType* PythonCompileType::resultId() const +{ + return PythonCompiledScriptImp::stype(); +} + +ObjectImp* PythonCompileType::calc( const Args& parents, const KigDocument& ) const +{ + assert( parents.size() == 1 ); + if ( !parents[0]->inherits( StringImp::stype() ) ) return new InvalidImp; + + const StringImp* si = static_cast( parents[0] ); + TQString s = si->data(); + + CompiledPythonScript cs = PythonScripter::instance()->compile( s.latin1() ); + + if ( cs.valid() ) + return new PythonCompiledScriptImp( cs ); + else + return new InvalidImp(); +} + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PythonExecuteType ) + +PythonExecuteType::PythonExecuteType() + : ObjectType( "PythonExecuteType" ) +{ +} + +PythonExecuteType::~PythonExecuteType() +{ +} + +const PythonExecuteType* PythonExecuteType::instance() +{ + static const PythonExecuteType t; + return &t; +} + +ObjectImp* PythonExecuteType::calc( const Args& parents, const KigDocument& d ) const +{ + assert( parents.size() >= 1 ); + if( !parents[0]->inherits( PythonCompiledScriptImp::stype() ) ) return new InvalidImp; + + CompiledPythonScript& script = static_cast( parents[0] )->data(); + + Args args( parents.begin() + 1, parents.end() ); + return script.calc( args, d ); +} + +const ObjectImpType* PythonExecuteType::impRequirement( const ObjectImp* o, const Args& parents ) const +{ + if ( o == parents[0] ) return PythonCompiledScriptImp::stype(); + else return ObjectImp::stype(); +} + +const ObjectImpType* PythonExecuteType::resultId() const +{ + return ObjectImp::stype(); +} + +std::vector PythonCompileType::sortArgs( const std::vector& args ) const +{ + return args; +} + +Args PythonCompileType::sortArgs( const Args& args ) const +{ + return args; +} + +std::vector PythonExecuteType::sortArgs( const std::vector& args ) const +{ + return args; +} + +Args PythonExecuteType::sortArgs( const Args& args ) const +{ + return args; +} + +bool PythonCompileType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const +{ + return false; +} + +bool PythonExecuteType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const +{ + return false; +} + diff --git a/kig/scripting/script-common.cc b/kig/scripting/script-common.cc deleted file mode 100644 index e2c15786..00000000 --- a/kig/scripting/script-common.cc +++ /dev/null @@ -1,95 +0,0 @@ -// 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 "script-common.h" - -#include - -#include -#include - -struct script_prop -{ - const char* fillCodeStatement; - const char* icon; - const char* highlightStyle; -}; - -static const script_prop scripts_properties[] = -{ - { I18N_NOOP( "Now fill in the code:" ), "text-x-script", "" }, - { I18N_NOOP( "Now fill in the Python code:" ), "text-x-python", "Python-Kig" } -}; - -TQString ScriptType::fillCodeStatement( ScriptType::Type type ) -{ - return i18n( scripts_properties[type].fillCodeStatement ); -} - -TQString ScriptType::templateCode( ScriptType::Type type, std::list args ) -{ - if ( type == Python ) - { - TQString tempcode = TQString::fromLatin1( "def calc( " ); - bool firstarg = true; - TQString temparg = i18n( "Note to translators: this should be a default " - "name for an argument in a Python function. The " - "default is \"arg%1\" which would become arg1, " - "arg2, etc. Give something which seems " - "appropriate for your language.", "arg%1" ); - - uint id = 1; - for ( std::list::const_iterator i = args.begin(); i != args.end(); ++i ) - { - if ( !firstarg ) tempcode += ", "; - else firstarg = false; - TQString n = ( *i )->name(); - tempcode += n.isEmpty() ? temparg.arg( id ) : n; - id++; - }; - tempcode += - " ):\n" - "\t# Calculate whatever you want to show here, and return it.\n" - "\t# For example, to implement a mid point, you would put\n" - "\t# this code here:\n" - "\t#\treturn Point( ( arg1.coordinate() + arg2.coordinate() ) / 2 )\n" - "\t# Please refer to the manual for more information.\n" - "\n"; - return tempcode; - } - - kdDebug() << "No such script type: " << type << endl; - return ""; -} - -const char* ScriptType::icon( ScriptType::Type type ) -{ - return scripts_properties[type].icon; -} - -TQString ScriptType::highlightStyle( ScriptType::Type type ) -{ - return TQString( scripts_properties[type].highlightStyle ); -} - -ScriptType::Type ScriptType::intToType( int type ) -{ - if ( type == 1 ) - return Python; - - return Unknown; -} diff --git a/kig/scripting/script-common.cpp b/kig/scripting/script-common.cpp new file mode 100644 index 00000000..e2c15786 --- /dev/null +++ b/kig/scripting/script-common.cpp @@ -0,0 +1,95 @@ +// 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 "script-common.h" + +#include + +#include +#include + +struct script_prop +{ + const char* fillCodeStatement; + const char* icon; + const char* highlightStyle; +}; + +static const script_prop scripts_properties[] = +{ + { I18N_NOOP( "Now fill in the code:" ), "text-x-script", "" }, + { I18N_NOOP( "Now fill in the Python code:" ), "text-x-python", "Python-Kig" } +}; + +TQString ScriptType::fillCodeStatement( ScriptType::Type type ) +{ + return i18n( scripts_properties[type].fillCodeStatement ); +} + +TQString ScriptType::templateCode( ScriptType::Type type, std::list args ) +{ + if ( type == Python ) + { + TQString tempcode = TQString::fromLatin1( "def calc( " ); + bool firstarg = true; + TQString temparg = i18n( "Note to translators: this should be a default " + "name for an argument in a Python function. The " + "default is \"arg%1\" which would become arg1, " + "arg2, etc. Give something which seems " + "appropriate for your language.", "arg%1" ); + + uint id = 1; + for ( std::list::const_iterator i = args.begin(); i != args.end(); ++i ) + { + if ( !firstarg ) tempcode += ", "; + else firstarg = false; + TQString n = ( *i )->name(); + tempcode += n.isEmpty() ? temparg.arg( id ) : n; + id++; + }; + tempcode += + " ):\n" + "\t# Calculate whatever you want to show here, and return it.\n" + "\t# For example, to implement a mid point, you would put\n" + "\t# this code here:\n" + "\t#\treturn Point( ( arg1.coordinate() + arg2.coordinate() ) / 2 )\n" + "\t# Please refer to the manual for more information.\n" + "\n"; + return tempcode; + } + + kdDebug() << "No such script type: " << type << endl; + return ""; +} + +const char* ScriptType::icon( ScriptType::Type type ) +{ + return scripts_properties[type].icon; +} + +TQString ScriptType::highlightStyle( ScriptType::Type type ) +{ + return TQString( scripts_properties[type].highlightStyle ); +} + +ScriptType::Type ScriptType::intToType( int type ) +{ + if ( type == 1 ) + return Python; + + return Unknown; +} diff --git a/kig/scripting/script_mode.cc b/kig/scripting/script_mode.cc deleted file mode 100644 index 1fd88405..00000000 --- a/kig/scripting/script_mode.cc +++ /dev/null @@ -1,362 +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 "script_mode.h" - -#include "newscriptwizard.h" -#include "python_type.h" -#include "python_scripter.h" - -#include "../kig/kig_commands.h" -#include "../kig/kig_part.h" -#include "../kig/kig_view.h" -#include "../misc/calcpaths.h" -#include "../misc/kigpainter.h" -#include "../modes/dragrectmode.h" -#include "../objects/bogus_imp.h" -#include "../objects/object_imp.h" - -#include -#include - -#include -#include -#include - -void ScriptModeBase::dragRect( const TQPoint& p, KigWidget& w ) -{ - if ( mwawd != SelectingArgs ) return; - - DragRectMode dm( p, mdoc, w ); - mdoc.runMode( &dm ); - std::vector ret = dm.ret(); - - KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.stillPix), mdoc.document() ); - if ( dm.needClear() ) - { - std::vector tmp( margs.begin(), margs.begin() ); - pter.drawObjects( tmp, false ); - margs.clear(); - } - - std::copy( ret.begin(), ret.end(), std::inserter( margs, margs.begin() ) ); - pter.drawObjects( ret, true ); - - w.updateCurPix( pter.overlay() ); - w.updateWidget(); -} - -void ScriptModeBase::leftClickedObject( ObjectHolder* o, const TQPoint&, - KigWidget& w, bool ) -{ - std::list::iterator dup_o; - - if ( mwawd != SelectingArgs ) return; - - KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.stillPix), mdoc.document() ); - - if ( (dup_o = std::find( margs.begin(), margs.end(), o )) != margs.end() ) - { - margs.erase( dup_o ); - pter.drawObject( o, false ); - } - else - { - margs.push_back( o ); - pter.drawObject( o, true ); - }; - w.updateCurPix( pter.overlay() ); - w.updateWidget(); -} - -void ScriptModeBase::mouseMoved( const std::vector& os, - const TQPoint& pt, KigWidget& w, bool ) -{ - if ( mwawd != SelectingArgs ) return; - - w.updateCurPix(); - if ( os.empty() ) - { - w.setCursor( KCursor::arrowCursor() ); - mdoc.emitStatusBarText( 0 ); - w.updateWidget(); - } - else - { - // the cursor is over an object, show object type next to cursor - // and set statusbar text - - w.setCursor( KCursor::handCursor() ); - TQString selectstat = os.front()->selectStatement(); - - // statusbar text - mdoc.emitStatusBarText( selectstat ); - KigPainter p( w.screenInfo(), TQT_TQPAINTDEVICE(&w.curPix), mdoc.document() ); - - // set the text next to the arrow cursor - TQPoint point = pt; - point.setX(point.x()+15); - - p.drawTextStd( point, selectstat ); - w.updateWidget( p.overlay() ); - } -} - -ScriptModeBase::ScriptModeBase( KigPart& doc ) - : BaseMode( doc ), mwizard( 0 ), mpart( doc ), - mwawd( SelectingArgs ) -{ - mwizard = new NewScriptWizard( doc.widget(), this ); - - doc.redrawScreen(); -} - -ScriptModeBase::~ScriptModeBase() -{ -} - -void ScriptModeBase::killMode() -{ - mdoc.doneMode( this ); -} - -bool ScriptCreationMode::queryCancel() -{ - killMode(); - return true; -} - -void ScriptModeBase::argsPageEntered() -{ - mwawd = SelectingArgs; - mdoc.redrawScreen(); -} - -void ScriptModeBase::enableActions() -{ - KigMode::enableActions(); - // we don't enable any actions.. -} - -void ScriptModeBase::codePageEntered() -{ - if ( mwizard->text().isEmpty() ) - { - // insert template code.. - TQString tempcode = ScriptType::templateCode( mtype, margs ); - mwizard->setText( tempcode ); - }; - mwizard->setFinishEnabled( mwizard->mpcode, true ); - mwawd = EnteringCode; - mdoc.redrawScreen(); -} - -void ScriptModeBase::redrawScreen( KigWidget* w ) -{ - std::vector sel; - if ( mwawd == SelectingArgs ) - sel = std::vector( margs.begin(), margs.end() ); - w->redrawScreen( sel ); - w->updateScrollBars(); -} - -bool ScriptCreationMode::queryFinish() -{ - std::vector args; - - TQString script = mwizard->text(); - args.push_back( new ObjectConstCalcer( new StringImp( script ) ) ); - - ObjectTypeCalcer* compiledscript = - new ObjectTypeCalcer( PythonCompileType::instance(), args ); - compiledscript->calc( mdoc.document() ); - - args.clear(); - args.push_back( compiledscript ); - for ( std::list::iterator i = margs.begin(); - i != margs.end(); ++i ) - args.push_back( ( *i )->calcer() ); - - ObjectTypeCalcer::shared_ptr reto = - new ObjectTypeCalcer( PythonExecuteType::instance(), args ); - reto->calc( mdoc.document() ); - - if ( reto->imp()->inherits( InvalidImp::stype() ) ) - { - PythonScripter* inst = PythonScripter::instance(); - TQCString errtrace = inst->lastErrorExceptionTraceback().c_str(); - if ( inst->errorOccurred() ) - { - KMessageBox::detailedSorry( - mwizard, i18n( "The Python interpreter caught an error during the execution of your " - "script. Please fix the script and click the Finish button again." ), - i18n( "The Python Interpreter generated the following error output:\n%1").arg( errtrace.data() ) ); - } - else - { - KMessageBox::sorry( - mwizard, i18n( "There seems to be an error in your script. The Python interpreter " - "reported no errors, but the script does not generate " - "a valid object. Please fix the script, and click the Finish button " - "again." ) ); - } - return false; - } - else - { - mdoc.addObject( new ObjectHolder( reto.get() ) ); - killMode(); - return true; - } -} - -void ScriptModeBase::midClicked( const TQPoint&, KigWidget& ) -{ -} - -void ScriptModeBase::rightClicked( const std::vector&, - const TQPoint&, KigWidget& ) -{ -} - -void ScriptModeBase::setScriptType( ScriptType::Type type ) -{ - mtype = type; - mwizard->setType( mtype ); - if ( mtype != ScriptType::Unknown ) - { - TDEIconLoader* il = mpart.instance()->iconLoader(); - mwizard->setIcon( il->loadIcon( ScriptType::icon( mtype ), TDEIcon::Small ) ); - } -} - -void ScriptModeBase::addArgs( const std::vector& obj, KigWidget& w ) -{ - KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.stillPix), mdoc.document() ); - - std::copy( obj.begin(), obj.end(), std::inserter( margs, margs.begin() ) ); - pter.drawObjects( obj, true ); - - w.updateCurPix( pter.overlay() ); - w.updateWidget(); -} - -void ScriptModeBase::goToCodePage() -{ - mwizard->next(); -} - -ScriptCreationMode::ScriptCreationMode( KigPart& doc ) - : ScriptModeBase( doc ) -{ - mwizard->show(); -} - -ScriptCreationMode::~ScriptCreationMode() -{ -} - -ScriptEditMode::ScriptEditMode( ObjectTypeCalcer* exec_calc, KigPart& doc ) - : ScriptModeBase( doc ), mexecuted( exec_calc ) -{ - mwawd = EnteringCode; - - mexecargs = mexecuted->parents(); - assert( mexecargs.size() >= 1 ); - - mcompiledargs = mexecargs[0]->parents(); - assert( mcompiledargs.size() == 1 ); - - const ObjectImp* imp = static_cast( mcompiledargs[0] )->imp(); - assert( dynamic_cast( imp ) ); - // save the original script text, in case the user modifies the text - // in the editor and aborts the editing - morigscript = static_cast( imp )->data(); - - mwizard->setCaption( i18n( "'Edit' is a verb", "Edit Script" ) ); - mwizard->setText( morigscript ); - mwizard->show(); - mwizard->next(); - mwizard->backButton()->setEnabled( false ); - mwizard->finishButton()->setEnabled( true ); -} - -ScriptEditMode::~ScriptEditMode() -{ -} - -bool ScriptEditMode::queryFinish() -{ - MonitorDataObjects mon( mcompiledargs ); - - static_cast( mcompiledargs[0] )->switchImp( new StringImp( mwizard->text() ) ); - mexecargs[0]->calc( mpart.document() ); - - mexecuted->calc( mpart.document() ); - - mpart.redrawScreen(); - - KigCommand* comm = new KigCommand( mpart, i18n( "Edit Python Script" ) ); - mon.finish( comm ); - - if ( mexecuted->imp()->inherits( InvalidImp::stype() ) ) - { - PythonScripter* inst = PythonScripter::instance(); - TQCString errtrace = inst->lastErrorExceptionTraceback().c_str(); - if ( inst->errorOccurred() ) - { - KMessageBox::detailedSorry( - mpart.widget(), i18n( "The Python interpreter caught an error during the execution of your " - "script. Please fix the script." ), - i18n( "The Python Interpreter generated the following error output:\n%1").arg( errtrace.data() ) ); - } - else - { - KMessageBox::sorry( - mpart.widget(), i18n( "There seems to be an error in your script. The Python interpreter " - "reported no errors, but the script does not generate " - "a valid object. Please fix the script." ) ); - } - delete comm; - return false; - } - - mpart.history()->addCommand( comm ); - mpart.setModified( true ); - - killMode(); - return true; -} - -bool ScriptEditMode::queryCancel() -{ - // reverting the original script text - static_cast( mcompiledargs[0] )->switchImp( new StringImp( morigscript ) ); - mexecargs[0]->calc( mpart.document() ); - - mexecuted->calc( mpart.document() ); - // paranoic check - assert( !mexecuted->imp()->inherits( InvalidImp::stype() ) ); - - mpart.redrawScreen(); - - // no need to further checks here, as the original script text is ok - - killMode(); - return true; -} - diff --git a/kig/scripting/script_mode.cpp b/kig/scripting/script_mode.cpp new file mode 100644 index 00000000..1fd88405 --- /dev/null +++ b/kig/scripting/script_mode.cpp @@ -0,0 +1,362 @@ +// 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 "script_mode.h" + +#include "newscriptwizard.h" +#include "python_type.h" +#include "python_scripter.h" + +#include "../kig/kig_commands.h" +#include "../kig/kig_part.h" +#include "../kig/kig_view.h" +#include "../misc/calcpaths.h" +#include "../misc/kigpainter.h" +#include "../modes/dragrectmode.h" +#include "../objects/bogus_imp.h" +#include "../objects/object_imp.h" + +#include +#include + +#include +#include +#include + +void ScriptModeBase::dragRect( const TQPoint& p, KigWidget& w ) +{ + if ( mwawd != SelectingArgs ) return; + + DragRectMode dm( p, mdoc, w ); + mdoc.runMode( &dm ); + std::vector ret = dm.ret(); + + KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.stillPix), mdoc.document() ); + if ( dm.needClear() ) + { + std::vector tmp( margs.begin(), margs.begin() ); + pter.drawObjects( tmp, false ); + margs.clear(); + } + + std::copy( ret.begin(), ret.end(), std::inserter( margs, margs.begin() ) ); + pter.drawObjects( ret, true ); + + w.updateCurPix( pter.overlay() ); + w.updateWidget(); +} + +void ScriptModeBase::leftClickedObject( ObjectHolder* o, const TQPoint&, + KigWidget& w, bool ) +{ + std::list::iterator dup_o; + + if ( mwawd != SelectingArgs ) return; + + KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.stillPix), mdoc.document() ); + + if ( (dup_o = std::find( margs.begin(), margs.end(), o )) != margs.end() ) + { + margs.erase( dup_o ); + pter.drawObject( o, false ); + } + else + { + margs.push_back( o ); + pter.drawObject( o, true ); + }; + w.updateCurPix( pter.overlay() ); + w.updateWidget(); +} + +void ScriptModeBase::mouseMoved( const std::vector& os, + const TQPoint& pt, KigWidget& w, bool ) +{ + if ( mwawd != SelectingArgs ) return; + + w.updateCurPix(); + if ( os.empty() ) + { + w.setCursor( KCursor::arrowCursor() ); + mdoc.emitStatusBarText( 0 ); + w.updateWidget(); + } + else + { + // the cursor is over an object, show object type next to cursor + // and set statusbar text + + w.setCursor( KCursor::handCursor() ); + TQString selectstat = os.front()->selectStatement(); + + // statusbar text + mdoc.emitStatusBarText( selectstat ); + KigPainter p( w.screenInfo(), TQT_TQPAINTDEVICE(&w.curPix), mdoc.document() ); + + // set the text next to the arrow cursor + TQPoint point = pt; + point.setX(point.x()+15); + + p.drawTextStd( point, selectstat ); + w.updateWidget( p.overlay() ); + } +} + +ScriptModeBase::ScriptModeBase( KigPart& doc ) + : BaseMode( doc ), mwizard( 0 ), mpart( doc ), + mwawd( SelectingArgs ) +{ + mwizard = new NewScriptWizard( doc.widget(), this ); + + doc.redrawScreen(); +} + +ScriptModeBase::~ScriptModeBase() +{ +} + +void ScriptModeBase::killMode() +{ + mdoc.doneMode( this ); +} + +bool ScriptCreationMode::queryCancel() +{ + killMode(); + return true; +} + +void ScriptModeBase::argsPageEntered() +{ + mwawd = SelectingArgs; + mdoc.redrawScreen(); +} + +void ScriptModeBase::enableActions() +{ + KigMode::enableActions(); + // we don't enable any actions.. +} + +void ScriptModeBase::codePageEntered() +{ + if ( mwizard->text().isEmpty() ) + { + // insert template code.. + TQString tempcode = ScriptType::templateCode( mtype, margs ); + mwizard->setText( tempcode ); + }; + mwizard->setFinishEnabled( mwizard->mpcode, true ); + mwawd = EnteringCode; + mdoc.redrawScreen(); +} + +void ScriptModeBase::redrawScreen( KigWidget* w ) +{ + std::vector sel; + if ( mwawd == SelectingArgs ) + sel = std::vector( margs.begin(), margs.end() ); + w->redrawScreen( sel ); + w->updateScrollBars(); +} + +bool ScriptCreationMode::queryFinish() +{ + std::vector args; + + TQString script = mwizard->text(); + args.push_back( new ObjectConstCalcer( new StringImp( script ) ) ); + + ObjectTypeCalcer* compiledscript = + new ObjectTypeCalcer( PythonCompileType::instance(), args ); + compiledscript->calc( mdoc.document() ); + + args.clear(); + args.push_back( compiledscript ); + for ( std::list::iterator i = margs.begin(); + i != margs.end(); ++i ) + args.push_back( ( *i )->calcer() ); + + ObjectTypeCalcer::shared_ptr reto = + new ObjectTypeCalcer( PythonExecuteType::instance(), args ); + reto->calc( mdoc.document() ); + + if ( reto->imp()->inherits( InvalidImp::stype() ) ) + { + PythonScripter* inst = PythonScripter::instance(); + TQCString errtrace = inst->lastErrorExceptionTraceback().c_str(); + if ( inst->errorOccurred() ) + { + KMessageBox::detailedSorry( + mwizard, i18n( "The Python interpreter caught an error during the execution of your " + "script. Please fix the script and click the Finish button again." ), + i18n( "The Python Interpreter generated the following error output:\n%1").arg( errtrace.data() ) ); + } + else + { + KMessageBox::sorry( + mwizard, i18n( "There seems to be an error in your script. The Python interpreter " + "reported no errors, but the script does not generate " + "a valid object. Please fix the script, and click the Finish button " + "again." ) ); + } + return false; + } + else + { + mdoc.addObject( new ObjectHolder( reto.get() ) ); + killMode(); + return true; + } +} + +void ScriptModeBase::midClicked( const TQPoint&, KigWidget& ) +{ +} + +void ScriptModeBase::rightClicked( const std::vector&, + const TQPoint&, KigWidget& ) +{ +} + +void ScriptModeBase::setScriptType( ScriptType::Type type ) +{ + mtype = type; + mwizard->setType( mtype ); + if ( mtype != ScriptType::Unknown ) + { + TDEIconLoader* il = mpart.instance()->iconLoader(); + mwizard->setIcon( il->loadIcon( ScriptType::icon( mtype ), TDEIcon::Small ) ); + } +} + +void ScriptModeBase::addArgs( const std::vector& obj, KigWidget& w ) +{ + KigPainter pter( w.screenInfo(), TQT_TQPAINTDEVICE(&w.stillPix), mdoc.document() ); + + std::copy( obj.begin(), obj.end(), std::inserter( margs, margs.begin() ) ); + pter.drawObjects( obj, true ); + + w.updateCurPix( pter.overlay() ); + w.updateWidget(); +} + +void ScriptModeBase::goToCodePage() +{ + mwizard->next(); +} + +ScriptCreationMode::ScriptCreationMode( KigPart& doc ) + : ScriptModeBase( doc ) +{ + mwizard->show(); +} + +ScriptCreationMode::~ScriptCreationMode() +{ +} + +ScriptEditMode::ScriptEditMode( ObjectTypeCalcer* exec_calc, KigPart& doc ) + : ScriptModeBase( doc ), mexecuted( exec_calc ) +{ + mwawd = EnteringCode; + + mexecargs = mexecuted->parents(); + assert( mexecargs.size() >= 1 ); + + mcompiledargs = mexecargs[0]->parents(); + assert( mcompiledargs.size() == 1 ); + + const ObjectImp* imp = static_cast( mcompiledargs[0] )->imp(); + assert( dynamic_cast( imp ) ); + // save the original script text, in case the user modifies the text + // in the editor and aborts the editing + morigscript = static_cast( imp )->data(); + + mwizard->setCaption( i18n( "'Edit' is a verb", "Edit Script" ) ); + mwizard->setText( morigscript ); + mwizard->show(); + mwizard->next(); + mwizard->backButton()->setEnabled( false ); + mwizard->finishButton()->setEnabled( true ); +} + +ScriptEditMode::~ScriptEditMode() +{ +} + +bool ScriptEditMode::queryFinish() +{ + MonitorDataObjects mon( mcompiledargs ); + + static_cast( mcompiledargs[0] )->switchImp( new StringImp( mwizard->text() ) ); + mexecargs[0]->calc( mpart.document() ); + + mexecuted->calc( mpart.document() ); + + mpart.redrawScreen(); + + KigCommand* comm = new KigCommand( mpart, i18n( "Edit Python Script" ) ); + mon.finish( comm ); + + if ( mexecuted->imp()->inherits( InvalidImp::stype() ) ) + { + PythonScripter* inst = PythonScripter::instance(); + TQCString errtrace = inst->lastErrorExceptionTraceback().c_str(); + if ( inst->errorOccurred() ) + { + KMessageBox::detailedSorry( + mpart.widget(), i18n( "The Python interpreter caught an error during the execution of your " + "script. Please fix the script." ), + i18n( "The Python Interpreter generated the following error output:\n%1").arg( errtrace.data() ) ); + } + else + { + KMessageBox::sorry( + mpart.widget(), i18n( "There seems to be an error in your script. The Python interpreter " + "reported no errors, but the script does not generate " + "a valid object. Please fix the script." ) ); + } + delete comm; + return false; + } + + mpart.history()->addCommand( comm ); + mpart.setModified( true ); + + killMode(); + return true; +} + +bool ScriptEditMode::queryCancel() +{ + // reverting the original script text + static_cast( mcompiledargs[0] )->switchImp( new StringImp( morigscript ) ); + mexecargs[0]->calc( mpart.document() ); + + mexecuted->calc( mpart.document() ); + // paranoic check + assert( !mexecuted->imp()->inherits( InvalidImp::stype() ) ); + + mpart.redrawScreen(); + + // no need to further checks here, as the original script text is ok + + killMode(); + return true; +} + -- cgit v1.2.3