summaryrefslogtreecommitdiffstats
path: root/karbon/tools
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
commit8362bf63dea22bbf6736609b0f49c152f975eb63 (patch)
tree0eea3928e39e50fae91d4e68b21b1e6cbae25604 /karbon/tools
downloadkoffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz
koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'karbon/tools')
-rw-r--r--karbon/tools/Makefile.am63
-rw-r--r--karbon/tools/gradienttoolplugin.rc3
-rw-r--r--karbon/tools/karbondefaulttools.desktop55
-rw-r--r--karbon/tools/patterntoolplugin.rc3
-rw-r--r--karbon/tools/vcurvefit.cc565
-rw-r--r--karbon/tools/vcurvefit.h11
-rw-r--r--karbon/tools/vdefaulttools.cc87
-rw-r--r--karbon/tools/vdefaulttools.h41
-rw-r--r--karbon/tools/vellipsetool.cc279
-rw-r--r--karbon/tools/vellipsetool.h91
-rw-r--r--karbon/tools/vgradienttool.cc526
-rw-r--r--karbon/tools/vgradienttool.h98
-rw-r--r--karbon/tools/vpatterntool.cc509
-rw-r--r--karbon/tools/vpatterntool.h116
-rw-r--r--karbon/tools/vpenciltool.cc411
-rw-r--r--karbon/tools/vpenciltool.h160
-rw-r--r--karbon/tools/vpolygontool.cc165
-rw-r--r--karbon/tools/vpolygontool.h70
-rw-r--r--karbon/tools/vpolylinetool.cc504
-rw-r--r--karbon/tools/vpolylinetool.h129
-rw-r--r--karbon/tools/vrectangletool.cc143
-rw-r--r--karbon/tools/vrectangletool.h70
-rw-r--r--karbon/tools/vrotatetool.cc175
-rw-r--r--karbon/tools/vrotatetool.h63
-rw-r--r--karbon/tools/vroundrecttool.cc179
-rw-r--r--karbon/tools/vroundrecttool.h81
-rw-r--r--karbon/tools/vselectnodestool.cc443
-rw-r--r--karbon/tools/vselectnodestool.h72
-rw-r--r--karbon/tools/vselecttool.cc613
-rw-r--r--karbon/tools/vselecttool.h110
-rw-r--r--karbon/tools/vshapetool.cc274
-rw-r--r--karbon/tools/vshapetool.h83
-rw-r--r--karbon/tools/vsheartool.cc219
-rw-r--r--karbon/tools/vsheartool.h62
-rw-r--r--karbon/tools/vsinustool.cc162
-rw-r--r--karbon/tools/vsinustool.h72
-rw-r--r--karbon/tools/vspiraltool.cc213
-rw-r--r--karbon/tools/vspiraltool.h81
-rw-r--r--karbon/tools/vstartool.cc249
-rw-r--r--karbon/tools/vstartool.h87
-rw-r--r--karbon/tools/vtexttool.cc1159
-rw-r--r--karbon/tools/vtexttool.h287
42 files changed, 8783 insertions, 0 deletions
diff --git a/karbon/tools/Makefile.am b/karbon/tools/Makefile.am
new file mode 100644
index 00000000..71ba99b8
--- /dev/null
+++ b/karbon/tools/Makefile.am
@@ -0,0 +1,63 @@
+kde_services_DATA = karbondefaulttools.desktop
+
+INCLUDES = $(KOFFICE_INCLUDES) $(KOPAINTER_INCLUDES) \
+ -I$(srcdir)/.. \
+ -I$(srcdir)/../commands \
+ -I$(srcdir)/../core \
+ -I$(srcdir)/../dialogs \
+ -I$(srcdir)/../widgets \
+ -I$(srcdir)/../dockers \
+ -I$(srcdir)/../render \
+ -I$(srcdir)/../shapes \
+ -I$(srcdir)/../visitors \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = karbon_defaulttools.la
+
+noinst_HEADERS = \
+ vcurvefit.h \
+ vrotatetool.h \
+ vselectnodestool.h \
+ vselecttool.h \
+ vsheartool.h \
+ vellipsetool.h \
+ vgradienttool.h \
+ vpatterntool.h \
+ vpenciltool.h \
+ vpolygontool.h \
+ vpolylinetool.h \
+ vrectangletool.h \
+ vroundrecttool.h \
+ vshapetool.h \
+ vsinustool.h \
+ vspiraltool.h \
+ vstartool.h \
+ vtexttool.h \
+ vdefaulttools.h
+
+karbon_defaulttools_la_SOURCES = \
+ vcurvefit.cc \
+ vrotatetool.cc \
+ vselectnodestool.cc \
+ vselecttool.cc \
+ vsheartool.cc \
+ vellipsetool.cc \
+ vgradienttool.cc \
+ vpatterntool.cc \
+ vpenciltool.cc \
+ vpolygontool.cc \
+ vpolylinetool.cc \
+ vrectangletool.cc \
+ vroundrecttool.cc \
+ vshapetool.cc \
+ vsinustool.cc \
+ vspiraltool.cc \
+ vstartool.cc \
+ vtexttool.cc \
+ vdefaulttools.cc
+
+karbon_defaulttools_la_LIBADD = $(LIB_KPARTS) $(LIB_KOFFICEUI) ../libkarboncommon.la
+karbon_defaulttools_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+
+karbon_defaulttools_la_METASOURCES = \
+ AUTO
diff --git a/karbon/tools/gradienttoolplugin.rc b/karbon/tools/gradienttoolplugin.rc
new file mode 100644
index 00000000..ba3746e9
--- /dev/null
+++ b/karbon/tools/gradienttoolplugin.rc
@@ -0,0 +1,3 @@
+<!DOCTYPE kpartgui>
+<kpartplugin name="gradienttoolplugin" library="karbon_gradienttoolplugin">
+</kpartplugin>
diff --git a/karbon/tools/karbondefaulttools.desktop b/karbon/tools/karbondefaulttools.desktop
new file mode 100644
index 00000000..193c5d6c
--- /dev/null
+++ b/karbon/tools/karbondefaulttools.desktop
@@ -0,0 +1,55 @@
+[Desktop Entry]
+Name=Default Tools
+Name[bg]=Инструменти по подразбиране
+Name[br]=Ostilhoù dre ziouer
+Name[ca]=Eines per defecte
+Name[cy]=Offer Rhagosodol
+Name[da]=Standardværktøjer
+Name[de]=Standardwerkzeuge
+Name[el]=Προκαθορισμένα εργαλεία
+Name[eo]=Aprioraj Iloj
+Name[es]=Herramientas predefinidas
+Name[et]=Vaiketööriistad
+Name[eu]=Tresna lehenetsiak
+Name[fa]=ابزارهای پیش‌فرض
+Name[fi]=Oletustyökalut
+Name[fr]=Outils par défaut
+Name[fy]=Standert ark
+Name[ga]=Uirlisí Réamhshocraithe
+Name[gl]=Ferramentas Predefinidas
+Name[he]=כלים המוגדרים כברירת מחדל
+Name[hi]=डिफ़ॉल्ट औज़ार
+Name[hr]=Zadani alati
+Name[hu]=Alapértelmezett eszközök
+Name[is]=Sjálfgefin tól
+Name[it]=Strumenti predefiniti
+Name[ja]=標準ツール
+Name[km]=ឧបករណ៍​លំនាំដើម
+Name[lt]=Numatyti įrankiai
+Name[lv]=Noklusējuma rīks
+Name[ms]=Alat Piawai
+Name[nb]=Standardverktøy
+Name[nds]=Standardwarktüüch
+Name[ne]=पूर्वनिर्धारित उपकरणहरू
+Name[nl]=Standaardgereedschappen
+Name[nn]=Standardverktøy
+Name[pl]=Domyślne narzędzia
+Name[pt]=Ferramentas Predefinidas
+Name[pt_BR]=Ferramentas Padrão
+Name[ru]=Стандартный инструментарий
+Name[se]=Standárdreaiddut
+Name[sk]=Štandardné nástroje
+Name[sl]=Privzeta orodja
+Name[sr]=Подразумевани алати
+Name[sr@Latn]=Podrazumevani alati
+Name[sv]=Standardverktyg
+Name[ta]=முன்னிருப்பு கருவிகள்
+Name[tr]=Öntanımlı Araçlar
+Name[uk]=Типові інструменти
+Name[uz]=Andoza vositalar
+Name[uz@cyrillic]=Андоза воситалар
+Name[zh_CN]=默认工具
+Name[zh_TW]=預設工具
+ServiceTypes=Karbon/CoreModule
+Type=Service
+X-KDE-Library=karbon_defaulttools
diff --git a/karbon/tools/patterntoolplugin.rc b/karbon/tools/patterntoolplugin.rc
new file mode 100644
index 00000000..b1019eab
--- /dev/null
+++ b/karbon/tools/patterntoolplugin.rc
@@ -0,0 +1,3 @@
+<!DOCTYPE kpartgui>
+<kpartplugin name="patterntoolplugin" library="karbon_patterntoolplugin">
+</kpartplugin>
diff --git a/karbon/tools/vcurvefit.cc b/karbon/tools/vcurvefit.cc
new file mode 100644
index 00000000..08dbda44
--- /dev/null
+++ b/karbon/tools/vcurvefit.cc
@@ -0,0 +1,565 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <karbon_part.h>
+#include <karbon_view.h>
+#include <core/vcolor.h>
+#include <core/vcomposite.h>
+#include <core/vfill.h>
+#include <core/vstroke.h>
+#include <core/vglobal.h>
+#include <render/vpainter.h>
+#include <render/vpainterfactory.h>
+#include <commands/vshapecmd.h>
+
+/*
+ An Algorithm for Automatically Fitting Digitized Curves
+ by Philip J. Schneider
+ from "Graphics Gems", Academic Press, 1990
+
+ http://www.acm.org/pubs/tog/GraphicsGems/gems/FitCurves.c
+ http://www.acm.org/pubs/tog/GraphicsGems/gems/README
+*/
+
+
+#include "vcurvefit.h"
+
+#define MAXPOINTS 1000 /* The most points you can have */
+
+
+class FitVector {
+ public:
+ FitVector(KoPoint &p){
+ m_X=p.x();
+ m_Y=p.y();
+ }
+
+ FitVector(){
+ m_X=0;
+ m_Y=0;
+ }
+
+ FitVector(KoPoint &a,KoPoint &b){
+ m_X=a.x()-b.x();
+ m_Y=a.y()-b.y();
+ }
+
+ void normalize(){
+ double len=length();
+ if(len==0.0f)
+ return;
+ m_X/=len; m_Y/=len;
+ }
+
+ void negate(){
+ m_X = -m_X;
+ m_Y = -m_Y;
+ }
+
+ void scale(double s){
+ double len = length();
+ if(len==0.0f)
+ return;
+ m_X *= s/len;
+ m_Y *= s/len;
+ }
+
+ double dot(FitVector &v){
+ return ((m_X*v.m_X)+(m_Y*v.m_Y));
+ }
+
+ double length(){
+ return (double) sqrt(m_X*m_X+m_Y*m_Y);
+ }
+
+ KoPoint operator+(KoPoint &p){
+ KoPoint b(p.x()+m_X,p.y()+m_Y);
+ return b;
+ }
+
+ public:
+ double m_X,m_Y;
+};
+
+double distance(KoPoint *p1,KoPoint *p2){
+ double dx = (p1->x()-p2->x());
+ double dy = (p1->y()-p2->y());
+ return sqrt( dx*dx + dy*dy );
+}
+
+
+FitVector ComputeLeftTangent(QPtrList<KoPoint> &points,int end){
+ FitVector tHat1(*points.at(end+1),*points.at(end));
+
+ tHat1.normalize();
+
+ return tHat1;
+}
+
+FitVector ComputeRightTangent(QPtrList<KoPoint> &points,int end){
+ FitVector tHat1(*points.at(end-1),*points.at(end));
+
+ tHat1.normalize();
+
+ return tHat1;
+}
+
+/*
+ * ChordLengthParameterize :
+ * Assign parameter values to digitized points
+ * using relative distances between points.
+ */
+static double *ChordLengthParameterize(QPtrList<KoPoint> points,int first,int last)
+{
+ int i;
+ double *u; /* Parameterization */
+
+ u = new double[(last-first+1)];
+
+ u[0] = 0.0;
+ for (i = first+1; i <= last; i++) {
+ u[i-first] = u[i-first-1] +
+ distance(points.at(i), points.at(i-1));
+ }
+
+ for (i = first + 1; i <= last; i++) {
+ u[i-first] = u[i-first] / u[last-first];
+ }
+
+ return(u);
+}
+
+static FitVector VectorAdd(FitVector a,FitVector b)
+{
+ FitVector c;
+ c.m_X = a.m_X + b.m_X; c.m_Y = a.m_Y + b.m_Y;
+ return (c);
+}
+static FitVector VectorScale(FitVector v,double s)
+{
+ FitVector result;
+ result.m_X = v.m_X * s; result.m_Y = v.m_Y * s;
+ return (result);
+}
+
+static FitVector VectorSub(FitVector a,FitVector b)
+{
+ FitVector c;
+ c.m_X = a.m_X - b.m_X; c.m_Y = a.m_Y - b.m_Y;
+ return (c);
+}
+
+static FitVector ComputeCenterTangent(QPtrList<KoPoint> points,int center)
+{
+ FitVector V1, V2, tHatCenter;
+
+ FitVector cpointb = *points.at(center-1);
+ FitVector cpoint = *points.at(center);
+ FitVector cpointa = *points.at(center+1);
+
+ V1 = VectorSub(cpointb,cpoint);
+ V2 = VectorSub(cpoint,cpointa);
+ tHatCenter.m_X= ((V1.m_X + V2.m_X)/2.0);
+ tHatCenter.m_Y= ((V1.m_Y + V2.m_Y)/2.0);
+ tHatCenter.normalize();
+ return tHatCenter;
+}
+
+/*
+ * B0, B1, B2, B3 :
+ * Bezier multipliers
+ */
+static double B0(double u)
+{
+ double tmp = 1.0 - u;
+ return (tmp * tmp * tmp);
+}
+
+
+static double B1(double u)
+{
+ double tmp = 1.0 - u;
+ return (3 * u * (tmp * tmp));
+}
+
+static double B2(double u)
+{
+ double tmp = 1.0 - u;
+ return (3 * u * u * tmp);
+}
+
+static double B3(double u)
+{
+ return (u * u * u);
+}
+
+/*
+ * GenerateBezier :
+ * Use least-squares method to find Bezier control points for region.
+ *
+ */
+KoPoint* GenerateBezier(QPtrList<KoPoint> &points, int first, int last, double *uPrime,FitVector tHat1,FitVector tHat2)
+{
+ int i;
+ FitVector A[MAXPOINTS][2]; /* Precomputed rhs for eqn */
+ int nPts; /* Number of pts in sub-curve */
+ double C[2][2]; /* Matrix C */
+ double X[2]; /* Matrix X */
+ double det_C0_C1, /* Determinants of matrices */
+ det_C0_X,
+ det_X_C1;
+ double alpha_l, /* Alpha values, left and right */
+ alpha_r;
+ FitVector tmp; /* Utility variable */
+ KoPoint *curve;
+
+ curve = new KoPoint[4];
+ nPts = last - first + 1;
+
+
+ /* Compute the A's */
+ for (i = 0; i < nPts; i++) {
+ FitVector v1, v2;
+ v1 = tHat1;
+ v2 = tHat2;
+ v1.scale(B1(uPrime[i]));
+ v2.scale(B2(uPrime[i]));
+ A[i][0] = v1;
+ A[i][1] = v2;
+ }
+
+ /* Create the C and X matrices */
+ C[0][0] = 0.0;
+ C[0][1] = 0.0;
+ C[1][0] = 0.0;
+ C[1][1] = 0.0;
+ X[0] = 0.0;
+ X[1] = 0.0;
+
+ for (i = 0; i < nPts; i++) {
+ C[0][0] += (A[i][0]).dot(A[i][0]);
+ C[0][1] += A[i][0].dot(A[i][1]);
+ /* C[1][0] += V2Dot(&A[i][0], &A[i][1]);*/
+ C[1][0] = C[0][1];
+ C[1][1] += A[i][1].dot(A[i][1]);
+
+ FitVector vfirstp1(*points.at(first+i));
+ FitVector vfirst(*points.at(first));
+ FitVector vlast(*points.at(last));
+
+ tmp = VectorSub(vfirstp1,
+ VectorAdd(
+ VectorScale(vfirst, B0(uPrime[i])),
+ VectorAdd(
+ VectorScale(vfirst, B1(uPrime[i])),
+ VectorAdd(
+ VectorScale(vlast, B2(uPrime[i])),
+ VectorScale(vlast, B3(uPrime[i])) ))));
+
+
+ X[0] += A[i][0].dot(tmp);
+ X[1] += A[i][1].dot(tmp);
+ }
+
+ /* Compute the determinants of C and X */
+ det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
+ det_C0_X = C[0][0] * X[1] - C[0][1] * X[0];
+ det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1];
+
+ /* Finally, derive alpha values */
+ if (det_C0_C1 == 0.0) {
+ det_C0_C1 = (C[0][0] * C[1][1]) * 10e-12;
+ }
+ alpha_l = det_X_C1 / det_C0_C1;
+ alpha_r = det_C0_X / det_C0_C1;
+
+
+ /* If alpha negative, use the Wu/Barsky heuristic (see text) */
+ /* (if alpha is 0, you get coincident control points that lead to
+ * divide by zero in any subsequent NewtonRaphsonRootFind() call. */
+ if (alpha_l < 1.0e-6 || alpha_r < 1.0e-6) {
+ double dist = distance(points.at(last),points.at(first)) /
+ 3.0;
+
+ curve[0] = *points.at(first);
+ curve[3] = *points.at(last);
+
+ tHat1.scale(dist);
+ tHat2.scale(dist);
+
+ curve[1] = tHat1 + curve[0];
+ curve[2] = tHat2 + curve[3];
+ return curve;
+ }
+
+ /* First and last control points of the Bezier curve are */
+ /* positioned exactly at the first and last data points */
+ /* Control points 1 and 2 are positioned an alpha distance out */
+ /* on the tangent vectors, left and right, respectively */
+ curve[0] = *points.at(first);
+ curve[3] = *points.at(last);
+
+ tHat1.scale(alpha_l);
+ tHat2.scale(alpha_r);
+
+ curve[1] = tHat1 + curve[0];
+ curve[2] = tHat2 + curve[3];
+
+ return (curve);
+}
+
+/*
+ * Bezier :
+ * Evaluate a Bezier curve at a particular parameter value
+ *
+ */
+static KoPoint BezierII(int degree,KoPoint *V, double t)
+{
+ int i, j;
+ KoPoint Q; /* Point on curve at parameter t */
+ KoPoint *Vtemp; /* Local copy of control points */
+
+ Vtemp = new KoPoint[degree+1];
+
+ for (i = 0; i <= degree; i++) {
+ Vtemp[i] = V[i];
+ }
+
+ /* Triangle computation */
+ for (i = 1; i <= degree; i++) {
+ for (j = 0; j <= degree-i; j++) {
+ Vtemp[j].setX((1.0 - t) * Vtemp[j].x() + t * Vtemp[j+1].x());
+ Vtemp[j].setY((1.0 - t) * Vtemp[j].y() + t * Vtemp[j+1].y());
+ }
+ }
+
+ Q = Vtemp[0];
+ delete[] Vtemp;
+ return Q;
+}
+
+/*
+ * ComputeMaxError :
+ * Find the maximum squared distance of digitized points
+ * to fitted curve.
+*/
+static double ComputeMaxError(QPtrList<KoPoint> points,int first,int last,KoPoint *curve,double *u,int *splitPoint)
+{
+ int i;
+ double maxDist; /* Maximum error */
+ double dist; /* Current error */
+ KoPoint P; /* Point on curve */
+ FitVector v; /* Vector from point to curve */
+
+ *splitPoint = (last - first + 1)/2;
+ maxDist = 0.0;
+ for (i = first + 1; i < last; i++) {
+ P = BezierII(3, curve, u[i-first]);
+ v = VectorSub(P, *points.at(i));
+ dist = v.length();
+ if (dist >= maxDist) {
+ maxDist = dist;
+ *splitPoint = i;
+ }
+ }
+ return (maxDist);
+}
+
+
+/*
+ * NewtonRaphsonRootFind :
+ * Use Newton-Raphson iteration to find better root.
+ */
+static double NewtonRaphsonRootFind(KoPoint *Q,KoPoint P,double u)
+{
+ double numerator, denominator;
+ KoPoint Q1[3], Q2[2]; /* Q' and Q'' */
+ KoPoint Q_u, Q1_u, Q2_u; /*u evaluated at Q, Q', & Q'' */
+ double uPrime; /* Improved u */
+ int i;
+
+ /* Compute Q(u) */
+ Q_u = BezierII(3,Q, u);
+
+ /* Generate control vertices for Q' */
+ for (i = 0; i <= 2; i++) {
+ Q1[i].setX((Q[i+1].x() - Q[i].x()) * 3.0);
+ Q1[i].setY((Q[i+1].y() - Q[i].y()) * 3.0);
+ }
+
+ /* Generate control vertices for Q'' */
+ for (i = 0; i <= 1; i++) {
+ Q2[i].setX((Q1[i+1].x() - Q1[i].x()) * 2.0);
+ Q2[i].setY((Q1[i+1].y() - Q1[i].y()) * 2.0);
+ }
+
+ /* Compute Q'(u) and Q''(u) */
+ Q1_u = BezierII(2, Q1, u);
+ Q2_u = BezierII(1, Q2, u);
+
+ /* Compute f(u)/f'(u) */
+ numerator = (Q_u.x() - P.x()) * (Q1_u.x()) + (Q_u.y() - P.y()) * (Q1_u.y());
+ denominator = (Q1_u.x()) * (Q1_u.x()) + (Q1_u.y()) * (Q1_u.y()) +
+ (Q_u.x() - P.x()) * (Q2_u.x()) + (Q_u.y() - P.y()) * (Q2_u.y());
+
+ /* u = u - f(u)/f'(u) */
+ uPrime = u - (numerator/denominator);
+ return (uPrime);
+}
+
+/*
+ * Reparameterize:
+ * Given set of points and their parameterization, try to find
+ * a better parameterization.
+ *
+ */
+static double *Reparameterize(QPtrList<KoPoint> points,int first,int last,double *u,KoPoint *curve)
+{
+ int nPts = last-first+1;
+ int i;
+ double *uPrime; /* New parameter values */
+
+ uPrime = new double[nPts];
+ for (i = first; i <= last; i++) {
+ uPrime[i-first] = NewtonRaphsonRootFind(curve, *points.at(i), u[i-
+ first]);
+ }
+ return (uPrime);
+}
+
+KoPoint *FitCubic(QPtrList<KoPoint> &points,int first,int last,FitVector tHat1,FitVector tHat2,float error,int &width){
+ double *u;
+ double *uPrime;
+ double maxError;
+ int splitPoint;
+ int nPts;
+ double iterationError;
+ int maxIterations=4;
+ FitVector tHatCenter;
+ KoPoint *curve;
+ int i;
+
+ width=0;
+
+
+ iterationError=error*error;
+ nPts = last-first+1;
+
+ if(nPts == 2){
+ double dist = distance(points.at(last), points.at(first)) / 3.0;
+
+ curve = new KoPoint[4];
+
+ curve[0] = *points.at(first);
+ curve[3] = *points.at(last);
+
+ tHat1.scale(dist);
+ tHat2.scale(dist);
+
+ curve[1] = tHat1 + curve[0];
+ curve[2] = tHat2 + curve[3];
+
+ width=4;
+ return curve;
+ }
+
+ /* Parameterize points, and attempt to fit curve */
+ u = ChordLengthParameterize(points, first, last);
+ curve = GenerateBezier(points, first, last, u, tHat1, tHat2);
+
+
+ /* Find max deviation of points to fitted curve */
+ maxError = ComputeMaxError(points, first, last, curve, u, &splitPoint);
+ if (maxError < error) {
+ delete[] u;
+ width=4;
+ return curve;
+ }
+
+
+ /* If error not too large, try some reparameterization */
+ /* and iteration */
+ if (maxError < iterationError) {
+ for (i = 0; i < maxIterations; i++) {
+ uPrime = Reparameterize(points, first, last, u, curve);
+ curve = GenerateBezier(points, first, last, uPrime, tHat1, tHat2);
+ maxError = ComputeMaxError(points, first, last,
+ curve, uPrime, &splitPoint);
+ if (maxError < error) {
+ delete[] u;
+ width=4;
+ return curve;
+ }
+ delete[] u;
+ u = uPrime;
+ }
+ }
+
+ /* Fitting failed -- split at max error point and fit recursively */
+ delete[] u;
+ delete[] curve;
+ tHatCenter = ComputeCenterTangent(points, splitPoint);
+
+ int w1,w2;
+ KoPoint *cu1=NULL, *cu2=NULL;
+ cu1 = FitCubic(points, first, splitPoint, tHat1, tHatCenter, error,w1);
+
+ tHatCenter.negate();
+ cu2 = FitCubic(points, splitPoint, last, tHatCenter, tHat2, error,w2);
+
+ KoPoint *newcurve = new KoPoint[w1+w2];
+ for(int i=0;i<w1;i++){
+ newcurve[i]=cu1[i];
+ }
+ for(int i=0;i<w2;i++){
+ newcurve[i+w1]=cu2[i];
+ }
+
+ delete[] cu1;
+ delete[] cu2;
+ width=w1+w2;
+ return newcurve;
+}
+
+
+VPath *bezierFit(QPtrList<KoPoint> &points,float error){
+ FitVector tHat1, tHat2;
+
+ tHat1 = ComputeLeftTangent(points,0);
+ tHat2 = ComputeRightTangent(points,points.count()-1);
+
+ int width=0;
+ KoPoint *curve;
+ curve = FitCubic(points,0,points.count()-1,tHat1,tHat2,error,width);
+
+ VPath *path = new VPath(NULL);
+
+ if(width>3){
+ path->moveTo(curve[0]);
+ path->curveTo(curve[1],curve[2],curve[3]);
+ for(int i=4;i<width;i+=4){
+ path->curveTo(curve[i+1],curve[i+2],curve[i+3]);
+ }
+ }
+
+
+ delete[] curve;
+ return path;
+}
+
diff --git a/karbon/tools/vcurvefit.h b/karbon/tools/vcurvefit.h
new file mode 100644
index 00000000..b9e54d1d
--- /dev/null
+++ b/karbon/tools/vcurvefit.h
@@ -0,0 +1,11 @@
+#ifndef __VCURVEFIT_H__
+#define __VCURVEFIT_H__
+
+#include <qstring.h>
+#include <qptrlist.h>
+#include "KoPoint.h"
+
+VPath *bezierFit(QPtrList<KoPoint> &points,float error);
+
+#endif
+
diff --git a/karbon/tools/vdefaulttools.cc b/karbon/tools/vdefaulttools.cc
new file mode 100644
index 00000000..c3a713ec
--- /dev/null
+++ b/karbon/tools/vdefaulttools.cc
@@ -0,0 +1,87 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+*/
+
+#include <kgenericfactory.h>
+
+#include "karbon_factory.h"
+#include "karbon_tool_factory.h"
+#include "karbon_tool_registry.h"
+
+#include "vdefaulttools.h"
+
+#include "vellipsetool.h"
+#include "vgradienttool.h"
+#include "vpatterntool.h"
+#include "vpenciltool.h"
+#include "vpolygontool.h"
+#include "vpolylinetool.h"
+#include "vrectangletool.h"
+#include "vrotatetool.h"
+#include "vroundrecttool.h"
+#include "vselectnodestool.h"
+#include "vselecttool.h"
+#include "vshapetool.h"
+#include "vsheartool.h"
+#include "vsinustool.h"
+#include "vspiraltool.h"
+#include "vstartool.h"
+#include "vtexttool.h"
+
+typedef KGenericFactory<VDefaultTools> VDefaultToolsFactory;
+K_EXPORT_COMPONENT_FACTORY( karbon_defaulttools, VDefaultToolsFactory( "karbon_defaulttools" ) )
+
+VDefaultTools::VDefaultTools(QObject *parent, const char *name, const QStringList &)
+ : KParts::Plugin(parent, name)
+{
+ setInstance(VDefaultToolsFactory::instance());
+
+ kdDebug() << "VDefaultTools. Class: "
+ << className()
+ << ", Parent: "
+ << parent -> className()
+ << "\n";
+
+ if ( parent->inherits("KarbonFactory") )
+ {
+ KarbonToolRegistry* r = KarbonToolRegistry::instance();
+ r->add(new KarbonToolFactory<VSelectTool>());
+ r->add(new KarbonToolFactory<VSelectNodesTool>());
+ r->add(new KarbonToolFactory<VRotateTool>());
+ r->add(new KarbonToolFactory<VShearTool>());
+ r->add(new KarbonToolFactory<VEllipseTool>());
+ r->add(new KarbonToolFactory<VGradientTool>());
+ r->add(new KarbonToolFactory<VPatternTool>());
+ r->add(new KarbonToolFactory<VPencilTool>());
+ r->add(new KarbonToolFactory<VPolygonTool>());
+ r->add(new KarbonToolFactory<VPolylineTool>());
+ r->add(new KarbonToolFactory<VRectangleTool>());
+ r->add(new KarbonToolFactory<VRoundRectTool>());
+ r->add(new KarbonToolFactory<VSinusTool>());
+ r->add(new KarbonToolFactory<VSpiralTool>());
+ r->add(new KarbonToolFactory<VStarTool>());
+ r->add(new KarbonToolFactory<VTextTool>());
+ }
+}
+
+VDefaultTools::~VDefaultTools()
+{
+}
+
+#include "vdefaulttools.moc"
diff --git a/karbon/tools/vdefaulttools.h b/karbon/tools/vdefaulttools.h
new file mode 100644
index 00000000..bb58bd8f
--- /dev/null
+++ b/karbon/tools/vdefaulttools.h
@@ -0,0 +1,41 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef __DEFAULTTOOLS_H__
+#define __DEFAULTTOOLS_H__
+
+#include <qstring.h>
+
+#include <kparts/plugin.h>
+
+/**
+ * A module that provides the default tools
+ */
+class VDefaultTools : public KParts::Plugin
+{
+ Q_OBJECT
+public:
+ VDefaultTools(QObject *parent, const char *name, const QStringList &);
+ virtual ~VDefaultTools();
+};
+
+#endif // __DEFAULTTOOLS_H__
+
+
diff --git a/karbon/tools/vellipsetool.cc b/karbon/tools/vellipsetool.cc
new file mode 100644
index 00000000..87528f4a
--- /dev/null
+++ b/karbon/tools/vellipsetool.cc
@@ -0,0 +1,279 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+
+#include <klocale.h>
+#include "KoUnitWidgets.h"
+#include <KoUnit.h>
+#include <kcombobox.h>
+#include <knuminput.h>
+
+#include <karbon_view.h>
+#include <karbon_part.h>
+#include <shapes/vellipse.h>
+#include "vellipsetool.h"
+#include "vglobal.h"
+
+
+VEllipseOptionsWidget::VEllipseOptionsWidget( KarbonPart *part, QWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, i18n( "Insert Ellipse" ), Ok | Cancel ), m_part( part )
+{
+ QGroupBox *group = new QGroupBox( 2, Qt::Horizontal, i18n( "Properties" ), this );
+ new QLabel( i18n( "Type:" ), group );
+ m_type = new KComboBox( false, group );
+ m_type->insertItem( i18n( "Full" ), VEllipse::full );
+ m_type->insertItem( i18n( "Section" ), VEllipse::section );
+ m_type->insertItem( i18n( "Pie" ), VEllipse::cut );
+ m_type->insertItem( i18n( "Arc" ), VEllipse::arc );
+ connect( m_type, SIGNAL( activated( int ) ), this, SLOT( typeChanged( int ) ) );
+
+ // add width/height-input:
+ m_widthLabel = new QLabel( i18n( "object width", "Width:" ), group );
+ m_width = new KoUnitDoubleSpinBox( group, 0.0, 1000.0, 0.5, 100.0, KoUnit::U_MM );
+ m_heightLabel = new QLabel( i18n( "Height:" ), group );
+ m_height = new KoUnitDoubleSpinBox( group, 0.0, 1000.0, 0.5, 100.0, KoUnit::U_MM );
+
+ new QLabel( i18n( "Start angle:" ), group );
+ m_startAngle = new KIntSpinBox( group );
+ m_startAngle->setMinValue( 0 );
+ m_startAngle->setMaxValue( 360 );
+
+ new QLabel( i18n( "End angle:" ), group );
+ m_endAngle = new KIntSpinBox( group );
+ m_endAngle->setMinValue( 0 );
+ m_endAngle->setMaxValue( 360 );
+
+ typeChanged( VEllipse::full );
+
+ refreshUnit();
+
+ group->setInsideMargin( 4 );
+ group->setInsideSpacing( 2 );
+
+ setMainWidget( group );
+ setFixedSize( baseSize() );
+}
+
+void
+VEllipseOptionsWidget::typeChanged( int type )
+{
+ m_startAngle->setEnabled( type != VEllipse::full );
+ m_endAngle->setEnabled( type != VEllipse::full );
+}
+
+uint
+VEllipseOptionsWidget::type() const
+{
+ return m_type->currentItem();
+}
+
+uint
+VEllipseOptionsWidget::startAngle() const
+{
+ return m_startAngle->value();
+}
+
+uint
+VEllipseOptionsWidget::endAngle() const
+{
+ return m_endAngle->value();
+}
+
+double
+VEllipseOptionsWidget::width() const
+{
+ return m_width->value();
+}
+
+double
+VEllipseOptionsWidget::height() const
+{
+ return m_height->value();
+}
+
+void
+VEllipseOptionsWidget::setWidth( double value )
+{
+ m_width->changeValue( value );
+}
+
+void
+VEllipseOptionsWidget::setHeight( double value )
+{
+ m_height->changeValue( value );
+}
+
+void
+VEllipseOptionsWidget::refreshUnit ()
+{
+ m_width->setUnit( m_part->unit() );
+ m_height->setUnit( m_part->unit() );
+}
+
+VEllipseTool::VEllipseTool( KarbonView *view )
+ : VShapeTool( view, "tool_ellipse" )
+{
+ // create config dialog:
+ m_optionsWidget = new VEllipseOptionsWidget( view->part() );
+ registerTool( this );
+
+ m_startAngle = m_endAngle = 0;
+ m_state = normal;
+}
+
+VEllipseTool::~VEllipseTool()
+{
+ delete( m_optionsWidget );
+}
+
+void
+VEllipseTool::refreshUnit()
+{
+ m_optionsWidget->refreshUnit();
+}
+
+VPath*
+VEllipseTool::shape( bool interactive ) const
+{
+ if( interactive )
+ {
+ double d1 = m_optionsWidget->width() / 2.0;
+ double d2 = m_optionsWidget->height() / 2.0;
+ return
+ new VEllipse(
+ 0L,
+ KoPoint( m_center.x() - d1, m_center.y() - d2 ),
+ d1 * 2.0, d2 * 2.0,
+ (VEllipse::VEllipseType)m_optionsWidget->type(),
+ m_optionsWidget->startAngle(),
+ m_optionsWidget->endAngle() );
+ }
+ else
+ return
+ new VEllipse(
+ 0L,
+ KoPoint( m_center.x() - m_d1, m_center.y() - m_d2 ),
+ m_d1 * 2.0,
+ m_d2 * 2.0,
+ (VEllipse::VEllipseType)m_optionsWidget->type(),
+ m_startAngle, m_endAngle );
+}
+
+void
+VEllipseTool::mouseMove()
+{
+ if( m_state == normal )
+ return;
+
+ draw();
+
+ //recalc();
+
+ if( m_state == startangle )
+ {
+ m_startAngle = atan2( last().y() - m_center.y(), last().x() - m_center.x() );
+ m_startAngle = ( m_startAngle / VGlobal::pi_2 ) * 90.0;
+ if( m_startAngle < 0 )
+ m_startAngle += 360.0;
+ }
+ else
+ {
+ m_endAngle = atan2( last().y() - m_center.y(), last().x() - m_center.x() );
+ m_endAngle = ( m_endAngle / VGlobal::pi_2 ) * 90.0;
+ if( m_endAngle < 0 )
+ m_endAngle += 360.0;
+ }
+
+ draw();
+}
+
+void
+VEllipseTool::mouseDragRelease()
+{
+ if( m_optionsWidget->type() == VEllipse::full )
+ VShapeTool::mouseDragRelease();
+
+ if( m_state == normal )
+ if( m_optionsWidget->type() != VEllipse::full )
+ m_state = startangle;
+}
+
+void
+VEllipseTool::mouseButtonPress()
+{
+ if( m_state == normal )
+ {
+ VShapeTool::mouseButtonPress();
+ m_center = first();
+ }
+}
+
+void
+VEllipseTool::mouseButtonRelease()
+{
+ if( m_optionsWidget->type() == VEllipse::full || m_state == normal )
+ VShapeTool::mouseButtonRelease();
+
+ if( m_state == startangle )
+ m_state = endangle;
+ else if( m_state == endangle )
+ {
+ VShapeTool::mouseDragRelease();
+ m_startAngle = m_endAngle = 0;
+ m_state = normal;
+ }
+}
+
+void
+VEllipseTool::cancel()
+{
+ if( isDragging() )
+ VShapeTool::cancel();
+ else
+ draw();
+
+ m_startAngle = m_endAngle = 0;
+ m_state = normal;
+}
+
+bool
+VEllipseTool::showDialog() const
+{
+ return m_optionsWidget->exec() == QDialog::Accepted;
+}
+
+void
+VEllipseTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ m_action = new KRadioAction( i18n( "Ellipse Tool" ), "14_ellipse", Qt::SHIFT+Qt::Key_H, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Ellipse" ) );
+ m_action->setExclusiveGroup( "shapes" );
+ //m_ownAction = true;
+ }
+}
+
+#include "vellipsetool.moc"
+
diff --git a/karbon/tools/vellipsetool.h b/karbon/tools/vellipsetool.h
new file mode 100644
index 00000000..d30e3411
--- /dev/null
+++ b/karbon/tools/vellipsetool.h
@@ -0,0 +1,91 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VELLIPSETOOL_H__
+#define __VELLIPSETOOL_H__
+
+#include <kdialogbase.h>
+
+#include "vshapetool.h"
+
+class KoUnitDoubleSpinBox;
+class KComboBox;
+class KIntSpinBox;
+class KarbonView;
+class QLabel;
+class QWidget;
+
+class VEllipseOptionsWidget : public KDialogBase
+{
+Q_OBJECT
+public:
+ VEllipseOptionsWidget( KarbonPart *part, QWidget *parent = 0L, const char *name = 0L );
+
+ double width() const;
+ double height() const;
+ uint startAngle() const;
+ uint endAngle() const;
+ uint type() const;
+ void setWidth( double value );
+ void setHeight( double value );
+ void refreshUnit();
+
+public slots:
+ void typeChanged( int );
+
+private:
+ KComboBox *m_type;
+ KIntSpinBox *m_startAngle;
+ KIntSpinBox *m_endAngle;
+ KoUnitDoubleSpinBox *m_width;
+ KoUnitDoubleSpinBox *m_height;
+ KarbonPart *m_part;
+ QLabel *m_heightLabel;
+ QLabel *m_widthLabel;
+};
+
+class VEllipseTool : public VShapeTool
+{
+public:
+ VEllipseTool( KarbonView *view );
+ virtual ~VEllipseTool();
+
+ virtual void setup(KActionCollection *collection);
+ virtual bool showDialog() const;
+ virtual QString uiname() { return i18n( "Ellipse Tool" ); }
+ virtual VPath *shape( bool interactive = false ) const;
+ void refreshUnit();
+
+protected:
+ void mouseDragRelease();
+ void mouseMove();
+ void mouseButtonPress();
+ void mouseButtonRelease();
+ void cancel();
+
+private:
+ enum { normal, startangle, endangle } m_state;
+ VEllipseOptionsWidget *m_optionsWidget;
+ double m_startAngle;
+ double m_endAngle;
+ KoPoint m_center;
+};
+
+#endif
+
diff --git a/karbon/tools/vgradienttool.cc b/karbon/tools/vgradienttool.cc
new file mode 100644
index 00000000..dbd82720
--- /dev/null
+++ b/karbon/tools/vgradienttool.cc
@@ -0,0 +1,526 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <qcursor.h>
+#include <qlabel.h>
+
+#include <klocale.h>
+
+#include <karbon_part.h>
+#include <karbon_view.h>
+#include <karbon_factory.h>
+#include <render/vpainter.h>
+#include <render/vpainterfactory.h>
+#include "vgradienttool.h"
+#include <widgets/vgradienttabwidget.h>
+#include <commands/vfillcmd.h>
+#include <commands/vstrokecmd.h>
+#include <core/vstroke.h>
+#include <core/vselection.h>
+#include <widgets/vstrokefillpreview.h>
+
+#include <kdebug.h>
+
+VGradientTool::VGradientOptionsWidget::VGradientOptionsWidget( VGradient& gradient )
+ : KDialogBase( 0L, "", true, i18n( "Edit Gradient" ), Ok | Cancel )
+{
+ m_gradientWidget = new VGradientTabWidget( gradient, KarbonFactory::rServer(), this );
+ setMainWidget( m_gradientWidget );
+ setFixedSize( baseSize() );
+}
+
+VGradientTool::VGradientTool( KarbonView *view )
+ : VTool( view, "gradienttool" ), m_state( normal ), m_handleSize( 3 ), m_active( false )
+{
+ setName( "tool_gradient" );
+ m_optionsWidget = new VGradientOptionsWidget( m_gradient );
+ registerTool( this );
+}
+
+VGradientTool::~VGradientTool()
+{
+ delete m_optionsWidget;
+}
+
+void
+VGradientTool::activate()
+{
+ m_active = true;
+ m_state = normal;
+ view()->statusMessage()->setText( i18n( "Gradient" ) );
+ view()->setCursor( QCursor( Qt::crossCursor ) );
+ VTool::activate();
+
+ if( view() )
+ {
+ // disable selection handles
+ view()->part()->document().selection()->showHandle( false );
+ // connect to the stroke-fill-preview to get notice when the stroke or fill gets selected
+ VStrokeFillPreview* preview = view()->strokeFillPreview();
+ if( preview )
+ {
+ connect( preview, SIGNAL( fillSelected() ), this, SLOT( targetChanged() ) );
+ connect( preview, SIGNAL( strokeSelected() ), this, SLOT( targetChanged() ) );
+ }
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+ }
+}
+
+void
+VGradientTool::deactivate()
+{
+ m_active = false;
+
+ if( view() )
+ {
+ // enable selection handles
+ view()->part()->document().selection()->showHandle( true );
+ VStrokeFillPreview* preview = view()->strokeFillPreview();
+ if( preview )
+ {
+ disconnect( preview, SIGNAL( fillSelected() ), this, SLOT( targetChanged() ) );
+ disconnect( preview, SIGNAL( strokeSelected() ), this, SLOT( targetChanged() ) );
+ }
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+ }
+}
+
+QString
+VGradientTool::statusText()
+{
+ return i18n( "Gradient Tool" );
+}
+
+QString
+VGradientTool::contextHelp()
+{
+ QString s = i18n( "<qt><b>Gradient tool:</b><br>" );
+ s += i18n( "<i>Click and drag</i> to choose the gradient vector.<br>" );
+ s += i18n( "<i>Click and drag</i> a gradient vector handle to change the gradient vector.<br>" );
+ s += i18n( "<i>Shift click and drag</i> to move the radial gradient focal point.<br>" );
+ s += i18n( "<i>Press i or Shift+i</i> to decrease or increase the handle size.<br>" );
+ s += i18n( "<br><b>Gradient editing:</b><br>" );
+ s += i18n( "<i>Click and drag</i> to move points.<br>" );
+ s += i18n( "<i>Double click</i> on a color point to edit it.<br>" );
+ s += i18n( "<i>Right click</i> on a color point to remove it.</qt>" );
+ return s;
+}
+
+bool
+VGradientTool::getGradient( VGradient &gradient )
+{
+ if( ! view() )
+ return false;
+
+ // determine if stroke of fill is selected for editing
+ VStrokeFillPreview *preview = view()->strokeFillPreview();
+ bool strokeSelected = ( preview && preview->strokeIsSelected() );
+
+ VSelection* selection = view()->part()->document().selection();
+ if( selection->objects().count() != 1 )
+ return false;
+
+ VObject *obj = selection->objects().getFirst();
+ // get the gradient of the first selected object, if any
+ if( strokeSelected && obj->stroke()->type() == VStroke::grad )
+ gradient = obj->stroke()->gradient();
+ else if( ! strokeSelected && obj->fill()->type() == VFill::grad )
+ gradient = obj->fill()->gradient();
+ else
+ return false;
+
+ return true;
+}
+
+bool
+VGradientTool::getOpacity( double &opacity )
+{
+ if( ! view() )
+ return false;
+
+ // determine if stroke of fill is selected for editing
+ VStrokeFillPreview *preview = view()->strokeFillPreview();
+ bool strokeSelected = ( preview && preview->strokeIsSelected() );
+
+ VSelection* selection = view()->part()->document().selection();
+ if( selection->objects().count() != 1 )
+ return false;
+
+ VObject *obj = selection->objects().getFirst();
+ // get the opacity of the first selected object, if any
+ if( strokeSelected && obj->stroke()->type() == VStroke::grad )
+ opacity = obj->stroke()->color().opacity();
+ else if( ! strokeSelected && obj->fill()->type() == VFill::grad )
+ opacity = obj->fill()->color().opacity();
+ else return false;
+
+ return true;
+}
+
+void
+VGradientTool::draw( VPainter* painter )
+{
+ if( ! m_active )
+ return;
+
+ if( m_state != normal )
+ return;
+
+ if( ! getGradient( m_gradient ) )
+ return;
+
+ KoPoint s = m_gradient.origin();
+ KoPoint e = m_gradient.vector();
+ KoPoint f = m_gradient.focalPoint();
+
+ // save the handle rects for later inside testing
+ m_origin = KoRect( s.x()-m_handleSize, s.y()-m_handleSize, 2*m_handleSize, 2*m_handleSize );
+ m_vector = KoRect( e.x()-m_handleSize, e.y()-m_handleSize, 2*m_handleSize, 2*m_handleSize );
+ m_center = KoRect( f.x()-m_handleSize, f.y()-m_handleSize, 2*m_handleSize, 2*m_handleSize );
+
+ painter->setPen( Qt::blue.light() );
+ painter->setBrush( Qt::blue.light() );
+ painter->setRasterOp( Qt::XorROP );
+
+ // draw the gradient vector
+ painter->newPath();
+ painter->moveTo( s );
+ painter->lineTo( e );
+ painter->strokePath();
+
+ if( m_gradient.type() == VGradient::radial )
+ {
+ // draw the focal point cross
+ double size = (double)m_handleSize / view()->zoom();
+ KoPoint focal = m_center.center();
+ KoRect cross = KoRect( focal.x()-3*size, focal.y()-3*size, 6*size, 6*size );
+ painter->newPath();
+ painter->moveTo( cross.topLeft() );
+ painter->lineTo( cross.bottomRight() );
+ painter->strokePath();
+ painter->newPath();
+ painter->moveTo( cross.bottomLeft() );
+ painter->lineTo( cross.topRight() );
+ painter->strokePath();
+ }
+ // draw the handle rects
+ painter->drawNode( m_origin.center(), m_handleSize );
+ painter->drawNode( m_vector.center(), m_handleSize );
+}
+
+void
+VGradientTool::draw()
+{
+ if( ! view() || view()->part()->document().selection()->objects().count() == 0 )
+ return;
+
+ VPainter *painter = view()->painterFactory()->editpainter();
+ painter->setRasterOp( Qt::NotROP );
+
+ painter->setPen( Qt::DotLine );
+ painter->newPath();
+
+ // differentiate between moving a handle and creating a complete new vector
+ if( m_state == moveOrigin || m_state == moveVector )
+ {
+ painter->moveTo( m_fixed );
+ painter->lineTo( m_current );
+ // draw the handle rects
+ painter->drawNode( m_fixed, m_handleSize );
+ painter->drawNode( m_current, m_handleSize );
+ }
+ else if( m_state == createNew )
+ {
+ painter->moveTo( first() );
+ painter->lineTo( m_current );
+ // draw the handle rects
+ painter->drawNode( first(), m_handleSize );
+ painter->drawNode( m_current, m_handleSize );
+ }
+ else if( m_state == moveCenter )
+ {
+ // draw the focal point cross
+ double size = (double)m_handleSize / view()->zoom();
+ KoRect cross = KoRect( m_current.x()-3*size, m_current.y()-3*size, 6*size, 6*size );
+ painter->moveTo( cross.topLeft() );
+ painter->lineTo( cross.bottomRight() );
+ painter->strokePath();
+ painter->newPath();
+ painter->moveTo( cross.bottomLeft() );
+ painter->lineTo( cross.topRight() );
+ }
+
+ painter->strokePath();
+}
+
+void
+VGradientTool::mouseDrag()
+{
+ if( m_state == normal )
+ return;
+
+ // undo old line
+ draw();
+
+ m_current = last();
+
+ draw();
+}
+
+void
+VGradientTool::mouseButtonPress()
+{
+ m_current = first();
+
+ // set the apropriate editing state
+ if( m_center.contains( m_current ) && shiftPressed())
+ {
+ m_state = moveCenter;
+ }
+ else if( m_origin.contains( m_current ) )
+ {
+ m_state = moveOrigin;
+ m_fixed = m_vector.center();
+ }
+ else if( m_vector.contains( m_current ) )
+ {
+ m_state = moveVector;
+ m_fixed = m_origin.center();
+ }
+ else
+ m_state = createNew;
+}
+
+void
+VGradientTool::mouseButtonRelease()
+{
+ m_state = normal;
+
+ if( ! view() || view()->part()->document().selection()->objects().count() == 0 )
+ return;
+
+ // save old gradient position
+ VGradient oldGradient = m_gradient;
+
+ bool strokeSelected = false;
+
+ // determine the target from the stroke-fill-preview-widget
+ VStrokeFillPreview* preview = view()->strokeFillPreview();
+ if( preview && preview->strokeIsSelected() )
+ strokeSelected = true;
+
+ if( first() == last() )
+ {
+ m_optionsWidget->gradientWidget()->setGradient( m_gradient );
+ if( strokeSelected )
+ {
+ m_optionsWidget->gradientWidget()->setTarget( VGradientTabWidget::STROKE );
+ m_optionsWidget->gradientWidget()->setOpacity( 1.0 );
+ }
+ else
+ {
+ m_optionsWidget->gradientWidget()->setTarget( VGradientTabWidget::FILL );
+ double opacity;
+ if( getOpacity( opacity ) )
+ m_optionsWidget->gradientWidget()->setOpacity( opacity );
+ }
+
+ if( ! showDialog() )
+ return;
+
+ m_gradient = m_optionsWidget->gradientWidget()->gradient();
+
+ // if the gradient dialog was shown and accepted, determine the target from the dialog
+ strokeSelected = ( m_optionsWidget->gradientWidget()->target() == VGradientTabWidget::STROKE );
+ }
+
+ // calculate a sane intial position for the new gradient
+ if( view()->part()->document().selection()->objects().count() == 1 )
+ {
+ VObject *obj = view()->part()->document().selection()->objects().getFirst();
+
+ if( ( ! strokeSelected && obj->fill()->type() != VFill::grad )
+ || ( strokeSelected && obj->stroke()->type() != VStroke::grad ) )
+ {
+ KoRect bbox = obj->boundingBox();
+ switch( m_gradient.type() )
+ {
+ case VGradient::linear:
+ oldGradient.setOrigin( bbox.bottomLeft() + 0.5*(bbox.bottomRight()-bbox.bottomLeft()) );
+ oldGradient.setVector( bbox.topLeft() + 0.5*(bbox.topRight()-bbox.topLeft()) );
+ oldGradient.setFocalPoint( bbox.center() );
+ break;
+ case VGradient::radial:
+ oldGradient.setOrigin( bbox.center() );
+ oldGradient.setVector( bbox.topLeft() + 0.5*(bbox.topRight()-bbox.topLeft()) );
+ oldGradient.setFocalPoint( bbox.center() );
+ break;
+ case VGradient::conic:
+ oldGradient.setOrigin( bbox.center() );
+ oldGradient.setVector( bbox.topLeft() + 0.5*(bbox.topRight()-bbox.topLeft()) );
+ oldGradient.setFocalPoint( bbox.center() );
+ break;
+ }
+ }
+ }
+
+ // workaround for a libart 2.3.10 bug
+ if( oldGradient.origin() == oldGradient.vector() )
+ oldGradient.vector().rx()+=1;
+
+ // use the old gradient position
+ m_gradient.setVector( oldGradient.vector() );
+ m_gradient.setOrigin( oldGradient.origin() );
+ m_gradient.setFocalPoint( oldGradient.focalPoint() );
+
+ if( ! strokeSelected )
+ {
+ VFill fill;
+ fill.gradient() = m_gradient;
+ fill.setType( VFill::grad );
+ VColor c = fill.color();
+ c.setOpacity( m_optionsWidget->gradientWidget()->opacity() );
+ fill.setColor( c, false );
+ view()->part()->addCommand(
+ new VFillCmd( &view()->part()->document(), fill, "14_gradient" ), true );
+ }
+ else
+ {
+ view()->part()->addCommand(
+ new VStrokeCmd( &view()->part()->document(), &m_gradient ), true );
+ }
+}
+
+void
+VGradientTool::mouseDragRelease()
+{
+ if( ! view() || m_state == normal )
+ return;
+
+ if( view()->part()->document().selection()->objects().count() == 0 )
+ {
+ draw();
+ return;
+ }
+
+ if( m_state == moveOrigin )
+ m_gradient.setOrigin( last() );
+ else if( m_state == moveVector )
+ m_gradient.setVector( last() );
+ else if( m_state == moveCenter )
+ m_gradient.setFocalPoint( last() );
+ else if( m_state == createNew )
+ {
+ m_gradient.setOrigin( first() );
+ m_gradient.setFocalPoint( first() );
+ m_gradient.setVector( last() );
+ }
+
+ m_state = normal;
+
+ VStrokeFillPreview* preview = view()->strokeFillPreview();
+ if( ! preview )
+ return;
+
+ if( ! preview->strokeIsSelected() )
+ {
+ VFill fill;
+ fill.gradient() = m_gradient;
+ fill.setType( VFill::grad );
+ VColor c = fill.color();
+ c.setOpacity( m_optionsWidget->gradientWidget()->opacity() );
+ fill.setColor( c, false );
+ view()->part()->addCommand(
+ new VFillCmd( &view()->part()->document(), fill, "14_gradient" ), true );
+ }
+ else
+ view()->part()->addCommand(
+ new VStrokeCmd( &view()->part()->document(), &m_gradient ), true );
+}
+
+void
+VGradientTool::cancel()
+{
+ // Erase old object:
+ if( isDragging() )
+ draw();
+ m_state = normal;
+}
+
+bool
+VGradientTool::showDialog() const
+{
+ return m_optionsWidget->exec() == QDialog::Accepted;
+}
+
+void
+VGradientTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ m_action = new KRadioAction( i18n( "Gradient Tool" ), "14_gradient", Qt::Key_G, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Gradient" ) );
+ m_action->setExclusiveGroup( "misc" );
+ //m_ownAction = true;
+ }
+}
+
+void
+VGradientTool::setCursor() const
+{
+ if( !view() ) return;
+
+ // set a different cursor if mouse is inside the handle rects
+ if( m_origin.contains( last() ) || m_vector.contains( last() ) || m_center.contains( last() ) )
+ view()->setCursor( QCursor( Qt::SizeAllCursor ) );
+ else
+ view()->setCursor( QCursor( Qt::arrowCursor ) );
+}
+
+bool
+VGradientTool::keyReleased( Qt::Key key )
+{
+ // increase/decrease the handle size
+ switch( key )
+ {
+ case Qt::Key_I:
+ if( shiftPressed() )
+ m_handleSize++;
+ else if( m_handleSize > 3 )
+ m_handleSize--;
+ break;
+ default: return false;
+ }
+
+ if( view() )
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+
+ return true;
+}
+
+void
+VGradientTool::targetChanged()
+{
+ if( view() )
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+}
+
+#include "vgradienttool.moc"
diff --git a/karbon/tools/vgradienttool.h b/karbon/tools/vgradienttool.h
new file mode 100644
index 00000000..7e78d510
--- /dev/null
+++ b/karbon/tools/vgradienttool.h
@@ -0,0 +1,98 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VGRADIENTTOOL_H__
+#define __VGRADIENTTOOL_H__
+
+#include <kdialogbase.h>
+
+#include "vtool.h"
+#include "vgradient.h"
+#include "KoRect.h"
+
+class VGradientTabWidget;
+
+class VGradientTool : public VTool
+{
+ Q_OBJECT
+
+public:
+ VGradientTool( KarbonView *view );
+ virtual ~VGradientTool();
+
+ virtual void activate();
+ virtual void deactivate();
+
+ virtual void setup(KActionCollection *collection);
+ virtual QString uiname() { return i18n( "Gradient Tool" ); }
+ virtual QString statusText();
+
+ virtual QString contextHelp();
+ virtual bool showDialog() const;
+
+ virtual void draw( VPainter* painter );
+
+protected:
+
+ virtual void draw();
+ virtual void mouseButtonRelease();
+ virtual void mouseButtonPress();
+ virtual void mouseDragRelease();
+ virtual void mouseDrag();
+ virtual void cancel();
+ virtual void setCursor() const;
+ virtual bool keyReleased( Qt::Key key );
+
+ /**
+ * Determines the actual gradient to be edited.
+ *
+ * @param gradient the found gradient
+ * @return true if gradient was found, else false
+ */
+ bool getGradient( VGradient &gradient );
+
+ bool getOpacity( double &opacity );
+
+protected slots:
+ void targetChanged();
+
+private:
+ enum { normal, moveOrigin, moveVector, moveCenter, createNew } m_state;
+
+ class VGradientOptionsWidget : public KDialogBase
+ {
+ public:
+ VGradientOptionsWidget( VGradient& gradient );
+ VGradientTabWidget *gradientWidget() { return m_gradientWidget; }
+ private:
+ VGradientTabWidget *m_gradientWidget;
+ };
+ VGradient m_gradient; /**< the actual gradient */
+ KoPoint m_current; /**< the current position when dragging */
+ KoPoint m_fixed; /**< the fixed point when only dragging one point of the gradient vector */
+ VGradientOptionsWidget* m_optionsWidget; /**< the options dialog, for editing gradients */
+ KoRect m_origin; /**< the handle of the gradient origin */
+ KoRect m_vector; /**< the handle of the gradient vector */
+ KoRect m_center; /**< the handle of the radial gradient focal point */
+ int m_handleSize; /**< the handle's size */
+ bool m_active; /**< holds active state of the tool, which is used for drawing of the gradient vector */
+};
+
+#endif
+
diff --git a/karbon/tools/vpatterntool.cc b/karbon/tools/vpatterntool.cc
new file mode 100644
index 00000000..0143d0bc
--- /dev/null
+++ b/karbon/tools/vpatterntool.cc
@@ -0,0 +1,509 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "vpatterntool.h"
+
+#include <qtoolbutton.h>
+#include <qframe.h>
+#include <qhbuttongroup.h>
+#include <qlayout.h>
+#include <qfileinfo.h>
+#include <qlabel.h>
+#include <qcursor.h>
+
+#include <kiconloader.h>
+#include <koIconChooser.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+
+#include <karbon_factory.h>
+#include <karbon_resourceserver.h>
+#include <karbon_view.h>
+#include <karbon_part.h>
+#include <render/vpainter.h>
+#include <render/vpainterfactory.h>
+#include <core/vselection.h>
+#include <core/vfill.h>
+#include <core/vstroke.h>
+#include <commands/vfillcmd.h>
+#include <commands/vstrokecmd.h>
+#include <widgets/vstrokefillpreview.h>
+
+VPatternWidget::VPatternWidget( QPtrList<KoIconItem>* patterns, VTool*, QWidget* parent )
+ : KDialogBase( parent, "", true, i18n( "Choose Pattern" ), Ok | Cancel ), m_pattern( 0 )
+{
+ QWidget *base = new QWidget( this );
+ QVBoxLayout* layout = new QVBoxLayout( base );
+ layout->addWidget( m_patternChooser = new KoIconChooser( QSize( 32, 32 ), base ) );
+ layout->addWidget( m_buttonGroup = new QHButtonGroup( base ) );
+ m_buttonGroup->insert( m_importPatternButton = new QToolButton( m_buttonGroup ) );
+ m_buttonGroup->insert( m_deletePatternButton = new QToolButton( m_buttonGroup ) );
+ m_patternChooser->setFixedSize( 180, 120 );
+ m_importPatternButton->setIconSet( SmallIconSet( "14_layer_newlayer" ) );
+ m_importPatternButton->setTextLabel( i18n( "Import" ) );
+ m_deletePatternButton->setIconSet( SmallIconSet("14_layer_deletelayer" ) );
+ m_deletePatternButton->setTextLabel( i18n( "Delete" ) );
+
+ m_buttonGroup->setInsideMargin( 3 );
+ m_importPatternButton->setEnabled( true );
+ m_deletePatternButton->setEnabled( false );
+
+ //setFrameStyle( Box | Sunken );
+ layout->setMargin( 3 );
+
+ connect( m_buttonGroup, SIGNAL( clicked( int ) ), this, SLOT( slotButtonClicked( int ) ) );
+ connect( m_patternChooser, SIGNAL( selected( KoIconItem* ) ), this, SLOT( patternSelected( KoIconItem* ) ) );
+
+ KoIconItem* item;
+ for( item = patterns->first(); item; item = patterns->next() )
+ m_patternChooser->addItem( item );
+ m_pattern = (VPattern*)patterns->first();
+
+ setMainWidget( base );
+} // VPatternWidget::VPatternWidget
+
+VPatternWidget::~VPatternWidget()
+{
+} // VPatternWidget::~VPatternWidget
+
+VPattern* VPatternWidget::selectedPattern()
+{
+ return m_pattern;
+} // VPatternWidget::selectedPattern
+
+void VPatternWidget::importPattern()
+{
+ VPattern* pattern = KarbonFactory::rServer()->addPattern( KFileDialog::getOpenFileName( QString::null,
+ "*.jpg *.gif *.png *.tif *.xpm *.bmp", this, i18n( "Choose Pattern to Add" ) ) );
+ if( pattern )
+ m_patternChooser->addItem( pattern );
+} // VPatternWidget::importPattern
+
+void VPatternWidget::deletePattern()
+{
+ m_patternChooser->removeItem( m_pattern );
+ KarbonFactory::rServer()->removePattern( m_pattern );
+ m_patternChooser->updateContents();
+ m_pattern = static_cast<VPattern*>( m_patternChooser->currentItem() );
+} // VPatternWidget::deletePattern
+
+void VPatternWidget::slotButtonClicked( int id )
+{
+ switch( id )
+ {
+ case 0: importPattern();
+ break;
+ case 1: deletePattern();
+ break;
+ }
+} // VPatternWidget::slotButtonClicked
+
+void VPatternWidget::patternSelected( KoIconItem* item )
+{
+ m_pattern = (VPattern*)item;
+ m_deletePatternButton->setEnabled( QFileInfo( m_pattern->tilename() ).isWritable() );
+} // VPatternWidget::patternSelected
+
+VPatternTool::VPatternTool( KarbonView *view )
+ : VTool( view, "tool_pattern" ), m_state( normal ), m_handleSize( 3 ), m_active( false )
+{
+ QPtrList<KoIconItem> patterns = KarbonFactory::rServer()->patterns();
+ m_optionsWidget = new VPatternWidget( &patterns, this );
+ registerTool( this );
+} // VPatternTool::VPatternTool
+
+VPatternTool::~VPatternTool()
+{
+ delete m_optionsWidget;
+} // VPatternTool::~VPatternTool
+
+void
+VPatternTool::activate()
+{
+ m_active = true;
+ m_state = normal;
+ VTool::activate();
+ view()->statusMessage()->setText( i18n( "Pattern" ) );
+ view()->setCursor( QCursor( Qt::crossCursor ) );
+
+ if( view() )
+ {
+ // disable selection handles
+ view()->part()->document().selection()->showHandle( false );
+ // connect to the stroke-fill-preview to get notice when the stroke or fill gets selected
+ VStrokeFillPreview* preview = view()->strokeFillPreview();
+ if( preview )
+ {
+ connect( preview, SIGNAL( fillSelected() ), this, SLOT( targetChanged() ) );
+ connect( preview, SIGNAL( strokeSelected() ), this, SLOT( targetChanged() ) );
+ }
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+ }
+}
+
+void
+VPatternTool::deactivate()
+{
+ m_active = false;
+
+ if( view() )
+ {
+ // enable selection handles
+ view()->part()->document().selection()->showHandle( true );
+ VStrokeFillPreview* preview = view()->strokeFillPreview();
+ if( preview )
+ {
+ disconnect( preview, SIGNAL( fillSelected() ), this, SLOT( targetChanged() ) );
+ disconnect( preview, SIGNAL( strokeSelected() ), this, SLOT( targetChanged() ) );
+ }
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+ }
+}
+
+
+QString
+VPatternTool::contextHelp()
+{
+ QString s = i18n( "<qt><b>Pattern tool:</b><br>" );
+ s += i18n( "<i>Click</i> on the pattern you want in the chooser.<br>" );
+ s += i18n( "<i>Click and drag</i> to choose the pattern vector.</qt>" );
+ s += i18n( "<i>Press i or Shift+i</i> to decrease or increase the handle size.<br>" );
+ return s;
+} // VPatternTool::contextHelp
+
+void VPatternTool::draw()
+{
+ if( ! view() || view()->part()->document().selection()->objects().count() == 0 )
+ return;
+
+ VPainter *painter = view()->painterFactory()->editpainter();
+ painter->setRasterOp( Qt::NotROP );
+
+ painter->setPen( Qt::DotLine );
+
+ // differentiate between moving a handle and creating a complete new vector
+ if( m_state == moveOrigin || m_state == moveVector )
+ {
+ painter->newPath();
+ painter->moveTo( m_fixed );
+ painter->lineTo( m_current );
+ painter->strokePath();
+ // draw the handle rects
+ painter->drawNode( m_fixed, m_handleSize );
+ painter->drawNode( m_current, m_handleSize );
+ }
+ else if( m_state == createNew )
+ {
+ painter->newPath();
+ painter->moveTo( first() );
+ painter->lineTo( m_current );
+ painter->strokePath();
+ // draw the handle rects
+ painter->drawNode( first(), m_handleSize );
+ painter->drawNode( m_current, m_handleSize );
+ }
+} // VPatternTool::draw
+
+bool
+VPatternTool::getPattern( VPattern &pattern )
+{
+ if( ! view() )
+ return false;
+
+ // determine if stroke of fill is selected for editing
+ //VStrokeFillPreview *preview = view()->strokeFillPreview();
+ //bool strokeSelected = ( preview && preview->strokeIsSelected() );
+ bool strokeSelected = false; // FIXME: stroke patterns don't work
+
+ VSelection* selection = view()->part()->document().selection();
+ if( selection->objects().count() != 1 )
+ return false;
+
+ VObject *obj = selection->objects().getFirst();
+ // get the pattern of the first selected object, if any
+ if( strokeSelected && obj->stroke()->type() == VStroke::patt )
+ pattern = obj->stroke()->pattern();
+ else if( ! strokeSelected && obj->fill()->type() == VFill::patt )
+ pattern = obj->fill()->pattern();
+ else
+ return false;
+
+ return true;
+}
+
+void
+VPatternTool::draw( VPainter* painter )
+{
+ if( ! m_active )
+ return;
+
+ if( m_state != normal )
+ return;
+
+ if( ! getPattern( m_pattern ) )
+ return;
+
+ KoPoint s = m_pattern.origin();
+ KoPoint e = m_pattern.vector();
+
+ // save the handle rects for later inside testing
+ m_origin = KoRect( s.x()-m_handleSize, s.y()-m_handleSize, 2*m_handleSize, 2*m_handleSize );
+ m_vector = KoRect( e.x()-m_handleSize, e.y()-m_handleSize, 2*m_handleSize, 2*m_handleSize );
+
+ painter->setPen( Qt::blue.light() );
+ painter->setBrush( Qt::blue.light() );
+ painter->setRasterOp( Qt::XorROP );
+
+ // draw the pattern vector
+ painter->newPath();
+ painter->moveTo( s );
+ painter->lineTo( e );
+ painter->strokePath();
+
+ // draw the handle rects
+ painter->drawNode( m_origin.center(), m_handleSize );
+ painter->drawNode( m_vector.center(), m_handleSize );
+}
+
+void
+VPatternTool::mouseDrag()
+{
+ if( m_state == normal )
+ return;
+
+ draw();
+
+ m_current = last();
+
+ draw();
+} // VPatternTool::mouseDrag
+
+void
+VPatternTool::mouseButtonPress()
+{
+ m_current = first();
+
+ // set the apropriate editing state
+ if( m_origin.contains( m_current ) )
+ {
+ m_state = moveOrigin;
+ m_fixed = m_vector.center();
+ }
+ else if( m_vector.contains( m_current ) )
+ {
+ m_state = moveVector;
+ m_fixed = m_origin.center();
+ }
+ else
+ m_state = createNew;
+} // VPatternTool::mouseButtonPress
+
+void
+VPatternTool::mouseButtonRelease()
+{
+ m_state = normal;
+
+ if( view()->part()->document().selection()->objects().count() == 0 )
+ return;
+
+ // save old pattern position
+ VPattern oldPattern = m_pattern;
+
+ if( first() == last() )
+ {
+ if( showDialog() != QDialog::Accepted )
+ return;
+ }
+
+ if( !m_optionsWidget->selectedPattern() )
+ {
+ KMessageBox::error( 0L, i18n( "Please select a pattern." ), "" );
+ return;
+ }
+
+ bool strokeSelected = false;
+
+ // determine the target from the stroke-fill-preview-widget
+ //VStrokeFillPreview* preview = view()->strokeFillPreview();
+ //if( preview && preview->strokeIsSelected() ) // FIXME: stroke patterns don't work
+ // strokeSelected = true;
+
+ // calculate a sane intial position for the new pattern
+ if( view()->part()->document().selection()->objects().count() == 1 )
+ {
+ VObject *obj = view()->part()->document().selection()->objects().getFirst();
+
+ if( ( ! strokeSelected && obj->fill()->type() != VFill::patt ) || (strokeSelected && obj->stroke()->type() != VStroke::patt ) )
+ {
+ KoRect bbox = obj->boundingBox();
+ oldPattern.setOrigin( bbox.bottomLeft() + 0.5*(bbox.topLeft()-bbox.bottomLeft()) );
+ oldPattern.setVector( bbox.bottomRight() + 0.5*(bbox.topRight()-bbox.bottomRight()) );
+ }
+ }
+
+ m_pattern = *m_optionsWidget->selectedPattern();
+
+ // use the old pattern position
+ m_pattern.setOrigin( oldPattern.origin() );
+ m_pattern.setVector( oldPattern.vector() );
+
+ if( ! strokeSelected )
+ {
+ VFill fill;
+ fill.pattern() = m_pattern;
+ fill.setType( VFill::patt );
+ view()->part()->addCommand(
+ new VFillCmd( &view()->part()->document(), fill, "14_pattern" ), true );
+ }
+ else
+ {
+ VStroke stroke;
+ stroke.pattern() = m_pattern;
+ stroke.setType( VStroke::patt );
+ view()->part()->addCommand(
+ new VStrokeCmd( &view()->part()->document(), &stroke, "14_pattern" ), true );
+ }
+} // VPatternTool::mouseButtonRelease
+
+void
+VPatternTool::mouseDragRelease()
+{
+ if( ! view() || m_state == normal )
+ return;
+
+ if( view()->part()->document().selection()->objects().count() == 0 )
+ {
+ draw();
+ return;
+ }
+
+ if( !m_optionsWidget->selectedPattern() )
+ {
+ draw();
+ KMessageBox::error( 0L, i18n( "Please select a pattern." ), "" );
+ return;
+ }
+ //m_pattern = *m_optionsWidget->selectedPattern();
+
+ if( m_state == moveOrigin )
+ m_pattern.setOrigin( last() );
+ else if( m_state == moveVector )
+ m_pattern.setVector( last() );
+ else if( m_state == createNew )
+ {
+ m_pattern.setOrigin( first() );
+ m_pattern.setVector( last() );
+ }
+
+ m_state = normal;
+
+ VStrokeFillPreview* preview = view()->strokeFillPreview();
+ if( ! preview )
+ return;
+
+ //if( ! preview->strokeIsSelected() ) // FIXME: stroke patterns don't work
+ {
+ VFill fill;
+ fill.pattern() = m_pattern;
+ fill.setType( VFill::patt );
+ view()->part()->addCommand(
+ new VFillCmd( &view()->part()->document(), fill, "14_pattern" ), true );
+ }
+ /*
+ else
+ {
+ VStroke stroke;
+ stroke.pattern() = m_pattern;
+ stroke.setType( VStroke::patt );
+ view()->part()->addCommand(
+ new VStrokeCmd( &view()->part()->document(), &stroke, "14_pattern" ), true );
+ }
+ */
+} // VPatternTool::mouseDragRelease
+
+void
+VPatternTool::cancel()
+{
+ // Erase old object:
+ if( isDragging() )
+ draw();
+ m_state = normal;
+}
+
+bool
+VPatternTool::showDialog() const
+{
+ return m_optionsWidget->exec() == QDialog::Accepted;
+}
+
+void
+VPatternTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ m_action = new KRadioAction( i18n( "Pattern Tool" ), "14_pattern", Qt::SHIFT+Qt::Key_H, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Pattern" ) );
+ m_action->setExclusiveGroup( "misc" );
+ //m_ownAction = true;
+ }
+}
+
+void
+VPatternTool::setCursor() const
+{
+ if( !view() ) return;
+
+ // set a different cursor if mouse is inside the handle rects
+ if( m_origin.contains( last() ) || m_vector.contains( last() ) )
+ view()->setCursor( QCursor( Qt::SizeAllCursor ) );
+ else
+ view()->setCursor( QCursor( Qt::arrowCursor ) );
+}
+
+bool
+VPatternTool::keyReleased( Qt::Key key )
+{
+ // increase/decrease the handle size
+ switch( key )
+ {
+ case Qt::Key_I:
+ if( shiftPressed() )
+ m_handleSize++;
+ else if( m_handleSize > 3 )
+ m_handleSize--;
+ break;
+ default: return false;
+ }
+
+ if( view() )
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+
+ return true;
+}
+
+void
+VPatternTool::targetChanged()
+{
+ if( view() )
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+}
+
+#include "vpatterntool.moc"
diff --git a/karbon/tools/vpatterntool.h b/karbon/tools/vpatterntool.h
new file mode 100644
index 00000000..0a89a4d4
--- /dev/null
+++ b/karbon/tools/vpatterntool.h
@@ -0,0 +1,116 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VPATTERNTOOL_H__
+#define __VPATTERNTOOL_H__
+
+#include <kdialogbase.h>
+
+#include "vtool.h"
+#include "vpattern.h"
+#include "KoRect.h"
+
+class QHButtonGroup;
+class QToolButton;
+class KoIconChooser;
+
+class VPatternWidget : public KDialogBase
+{
+Q_OBJECT
+
+public:
+ VPatternWidget( QPtrList<KoIconItem>* patterns, VTool* tool, QWidget* parent = 0L );
+ ~VPatternWidget();
+
+ VPattern* selectedPattern();
+
+public slots:
+ void importPattern();
+ void deletePattern();
+
+ void slotButtonClicked( int id );
+ void patternSelected( KoIconItem* );
+
+private:
+ KoIconChooser* m_patternChooser;
+ QHButtonGroup* m_buttonGroup;
+ QToolButton* m_importPatternButton;
+ QToolButton* m_deletePatternButton;
+ VTool* m_tool;
+ VPattern* m_pattern;
+}; // VPatternWidget
+
+
+class VPatternTool : public VTool
+{
+ Q_OBJECT
+
+public:
+ VPatternTool( KarbonView *view );
+ virtual ~VPatternTool();
+
+ virtual void activate();
+ virtual void deactivate();
+
+ virtual void setup(KActionCollection *collection);
+ virtual QString uiname() { return i18n( "Pattern Tool" ); }
+ virtual QString contextHelp();
+ virtual bool showDialog() const;
+
+ virtual void draw( VPainter* painter );
+
+protected:
+ virtual void draw();
+
+ virtual void mouseButtonRelease();
+ virtual void mouseButtonPress();
+ virtual void mouseDragRelease();
+ virtual void mouseDrag();
+ /*virtual void mouseDragShiftPressed(); // To use to scale the pattern.
+ virtual void mouseDragShiftReleased(); */
+ virtual void cancel();
+ virtual void setCursor() const;
+ virtual bool keyReleased( Qt::Key key );
+
+ /**
+ * Determines the actual pattern to be edited.
+ *
+ * @param pattern the found pattern
+ * @return true if pattern was found, else false
+ */
+ bool getPattern( VPattern &pattern );
+
+protected slots:
+ void targetChanged();
+
+private:
+ enum { normal, moveOrigin, moveVector, createNew } m_state;
+
+ VPattern m_pattern;
+ KoPoint m_current; /**< the current position when dragging */
+ KoPoint m_fixed; /**< the fixed point when only dragging one point of the gradient vector */
+ VPatternWidget* m_optionsWidget; /**< the options dialog, for selecting patterns */
+ KoRect m_origin; /**< the handle of the pattern origin */
+ KoRect m_vector; /**< the handle of the pattern vector */
+ int m_handleSize; /**< the handle's size */
+ bool m_active; /**< holds active state of the tool, which is used for drawing of the pattern vector */
+}; // VPatternTool
+
+#endif /* __VPATTERNTOOL_H__ */
+
diff --git a/karbon/tools/vpenciltool.cc b/karbon/tools/vpenciltool.cc
new file mode 100644
index 00000000..3a18fcb0
--- /dev/null
+++ b/karbon/tools/vpenciltool.cc
@@ -0,0 +1,411 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+*/
+#include <math.h>
+
+#include <qcursor.h>
+#include <qevent.h>
+#include <qlabel.h>
+#include <qgroupbox.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <qvbox.h>
+#include <qwidgetstack.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+//#include <KoUnitWidgets.h>
+
+#include <karbon_part.h>
+#include <karbon_view.h>
+
+#include <core/vcolor.h>
+#include <core/vcomposite.h>
+#include <core/vfill.h>
+#include <core/vstroke.h>
+#include <core/vglobal.h>
+#include <core/vselection.h>
+#include <core/vcursor.h>
+#include <render/vpainter.h>
+#include <render/vpainterfactory.h>
+#include "vpenciltool.h"
+#include <commands/vshapecmd.h>
+
+#include "vcurvefit.h"
+
+#include "vpenciltool.moc"
+
+VPencilOptionsWidget::VPencilOptionsWidget( KarbonView*view, QWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, i18n( "Pencil Settings" ), Ok | Cancel ), m_view( view )
+{
+ QVBox *vbox = new QVBox( this );
+
+ m_combo = new QComboBox( vbox );
+
+ m_combo->insertItem( i18n( "Raw" ) );
+ m_combo->insertItem( i18n( "Curve" ) );
+ m_combo->insertItem( i18n( "Straight" ) );
+
+ m_widgetStack = new QWidgetStack( vbox );
+
+ QGroupBox *group1 = new QGroupBox( 2, Qt::Horizontal, i18n( "Properties" ), m_widgetStack );
+ m_widgetStack->addWidget( group1, 1 );
+ m_optimizeRaw = new QCheckBox( i18n( "Optimize" ), group1 );
+
+ group1->setInsideMargin( 4 );
+ group1->setInsideSpacing( 2 );
+
+ QGroupBox *group2 = new QGroupBox( 2, Qt::Horizontal, i18n( "Properties" ), m_widgetStack );
+ m_widgetStack->addWidget( group2, 2 );
+
+ QVBox *vbox2 = new QVBox( group2 );
+
+ m_optimizeCurve = new QCheckBox( i18n( "Optimize" ), vbox2 );
+ m_fittingError = new KDoubleNumInput( 0.0, 400.0, 4.00, 0.50, 3, vbox2 );
+ m_fittingError->setLabel( i18n( "Exactness:" ) );
+
+ group2->setInsideMargin( 4 );
+ group2->setInsideSpacing( 2 );
+
+ QGroupBox *group3 = new QGroupBox( 2, Qt::Horizontal, i18n( "Properties" ), m_widgetStack );
+ m_widgetStack->addWidget( group3, 3 );
+
+ m_combineAngle = new KDoubleNumInput( 0.0, 360.0, 0.10, 0.50, 3, group3 );
+ m_combineAngle->setSuffix( " deg" );
+ m_combineAngle->setLabel( i18n( "Combine angle:" ) );
+
+ group3->setInsideMargin( 4 );
+ group3->setInsideSpacing( 2 );
+
+ connect( m_combo, SIGNAL( activated( int ) ), this, SLOT( selectMode() ) );
+
+ //Set the default settings
+ m_mode = VPencilTool::CURVE;
+ selectMode();
+
+ m_optimizeCurve->setChecked( true );
+ m_optimizeRaw->setChecked( true );
+
+ setMainWidget( vbox );
+}
+
+float VPencilOptionsWidget::combineAngle()
+{
+ return m_combineAngle->value();
+}
+
+bool VPencilOptionsWidget::optimize()
+{
+ return ( m_optimizeRaw->isChecked() || m_optimizeCurve->isChecked() );
+}
+
+float VPencilOptionsWidget::fittingError()
+{
+ return m_fittingError->value();
+}
+
+void VPencilOptionsWidget::selectMode()
+{
+ m_widgetStack->raiseWidget( m_combo->currentItem() + 1 );
+
+ switch( m_combo->currentItem() )
+ {
+ case 0: m_mode = VPencilTool::RAW; break;
+ case 1: m_mode = VPencilTool::CURVE; break;
+ case 2: m_mode = VPencilTool::STRAIGHT; break;
+ }
+}
+
+int VPencilOptionsWidget::currentMode(){
+ return m_mode;
+}
+
+/* ------------------------------------------------------------------------------------------------------------------------*/
+
+VPencilTool::VPencilTool( KarbonView *view )
+ : VTool( view, "tool_pencil" )
+{
+ m_Points.setAutoDelete( true );
+ m_optionWidget = new VPencilOptionsWidget( view );
+ registerTool( this );
+ m_mode = CURVE;
+ m_optimize = true;
+ m_combineAngle = 3.0f;
+ m_cursor = new QCursor( VCursor::createCursor( VCursor::CrossHair ) );
+}
+
+VPencilTool::~VPencilTool()
+{
+ delete m_cursor;
+}
+
+QString
+VPencilTool::contextHelp()
+{
+ QString s = i18n( "<qt><b>Pencil tool:</b><br>" );
+ s += i18n( "- <i>Click</i> to begin drawing, release when you have finished.");
+ s += i18n( "- Press <i>Enter</i> or <i>double click</i> to end the polyline.</qt>" );
+
+ return s;
+}
+
+void
+VPencilTool::activate()
+{
+ VTool::activate();
+ view()->statusMessage()->setText( i18n( "Pencil Tool" ) );
+ view()->setCursor( *m_cursor );
+ view()->part()->document().selection()->showHandle( false );
+
+ m_Points.clear();
+ m_close = false;
+}
+
+void
+VPencilTool::deactivate()
+{
+ m_Points.removeLast();
+ m_Points.removeLast();
+
+ VPath* line = 0L;
+
+ QPtrList<KoPoint> complete;
+ QPtrList<KoPoint> *points = &m_Points;
+
+ if( m_Points.count() > 1 )
+ {
+ if( m_optimize || m_mode == STRAIGHT )
+ {
+ complete.setAutoDelete( true );
+ m_Points.setAutoDelete( false );
+
+ float cangle;
+
+ if( m_mode == STRAIGHT )
+ cangle = m_combineAngle;
+ else
+ cangle = 0.50f;
+
+ #define ANGLE(P0,P1)\
+ atan((P1)->y()-(P0)->y())/((P1)->x()-(P0)->x())*(180/M_PI)
+
+ //Add the first point
+ complete.append( m_Points.first() );
+ complete.append( m_Points.next() );
+
+ //Now we need to get the angle of the first line
+ float langle = ANGLE( complete.at( 0 ), complete.at( 1 ) );
+
+ KoPoint *nextp = NULL;
+ while( ( nextp = m_Points.next() ) )
+ {
+ float angle = ANGLE( complete.last(), nextp );
+ if( QABS( angle - langle ) < cangle )
+ complete.removeLast();
+ complete.append(nextp);
+ langle=angle;
+ }
+ m_Points.clear();
+ m_Points.setAutoDelete(true);
+
+ points = &complete;
+ }
+
+ switch(m_mode)
+ {
+ case CURVE:
+ {
+ line = bezierFit( *points, m_optionWidget->fittingError() );
+ break;
+ }
+ case STRAIGHT:
+ case RAW:
+ {
+ line = new VPath( 0L );
+ KoPoint* p1 = (*points).first();
+ KoPoint* plast = p1;
+ line->moveTo( *p1 );
+
+ KoPoint* pnext = 0L;
+
+ while( ( pnext = (*points).next() ) )
+ {
+ line->lineTo( *pnext );
+ plast = pnext;
+ }
+ break;
+ }
+ }
+
+ if( shiftPressed() )
+ line->close();
+ }
+
+ if( line )
+ {
+ VShapeCmd* cmd = new VShapeCmd(
+ &view()->part()->document(),
+ i18n( "Pencil" ),
+ line,
+ "14_pencil" );
+
+ view()->part()->addCommand( cmd, true );
+ }
+}
+
+void
+VPencilTool::draw()
+{
+ VPainter* painter = view()->painterFactory()->editpainter();
+ painter->setRasterOp( Qt::NotROP );
+
+ m_mode = m_optionWidget->currentMode();
+ m_optimize = m_optionWidget->optimize();
+ m_combineAngle = m_optionWidget->combineAngle();
+
+ if( m_Points.count() > 1 )
+ {
+ VPath line( 0L );
+ line.moveTo( *m_Points.first() );
+
+ KoPoint *pnext;
+ while((pnext=m_Points.next())){
+ line.lineTo( *pnext );
+ }
+
+ line.setState( VObject::edit );
+ line.draw( painter, &line.boundingBox() );
+ }
+
+}
+
+
+void
+VPencilTool::mouseMove()
+{
+}
+
+void
+VPencilTool::mouseButtonPress()
+{
+ m_Points.append( new KoPoint( last() ) );
+
+ draw();
+}
+
+void
+VPencilTool::mouseButtonRelease()
+{
+ m_Points.append( new KoPoint( last() ) );
+ draw();
+ accept();
+ return;
+}
+
+void
+VPencilTool::mouseButtonDblClick()
+{
+ accept();
+}
+
+void
+VPencilTool::mouseDrag()
+{
+ if( m_Points.count() != 0 )
+ {
+ draw();
+
+ m_Points.append( new KoPoint( last() ) );
+
+ draw();
+ }
+}
+
+void
+VPencilTool::mouseDragRelease()
+{
+ mouseButtonRelease();
+}
+
+void
+VPencilTool::mouseDragShiftPressed()
+{
+}
+
+void
+VPencilTool::mouseDragCtrlPressed()
+{
+
+}
+
+void
+VPencilTool::mouseDragShiftReleased()
+{
+}
+
+void
+VPencilTool::mouseDragCtrlReleased()
+{
+}
+
+void
+VPencilTool::cancel()
+{
+ draw();
+
+ m_Points.clear();
+}
+
+void
+VPencilTool::cancelStep()
+{
+ draw();
+
+ m_Points.clear();
+
+ draw();
+}
+
+void
+VPencilTool::accept()
+{
+ deactivate();
+ activate();
+}
+
+bool
+VPencilTool::showDialog() const
+{
+ return m_optionWidget->exec() == QDialog::Accepted;
+}
+
+void
+VPencilTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ m_action = new KRadioAction( i18n( "Pencil Tool" ), "14_pencil", Qt::SHIFT+Qt::Key_P, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Pencil" ) );
+ m_action->setExclusiveGroup( "freehand" );
+ //m_ownAction = true;
+ }
+}
+
diff --git a/karbon/tools/vpenciltool.h b/karbon/tools/vpenciltool.h
new file mode 100644
index 00000000..d8eeb77a
--- /dev/null
+++ b/karbon/tools/vpenciltool.h
@@ -0,0 +1,160 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef __VPENCILTOOL_H__
+#define __VPENCILTOOL_H__
+
+
+#include <qptrlist.h>
+#include <qstring.h>
+
+#include <klocale.h>
+#include <kdialogbase.h>
+#include "KoPoint.h"
+
+#include "vtool.h"
+
+
+class QLabel;
+class QWidget;
+class VPath;
+class KarbonView;
+class QCheckBox;
+class QWidgetStack;
+class QComboBox;
+class KDoubleNumInput;
+class QCursor;
+
+class VPencilOptionsWidget : public KDialogBase
+{
+ Q_OBJECT
+ public:
+ VPencilOptionsWidget( KarbonView*view, QWidget* parent = 0L, const char* name = 0L );
+
+ int currentMode();
+ bool optimize();
+ float combineAngle();
+ float fittingError();
+
+ public slots:
+ void selectMode();
+
+ private:
+ KarbonView *m_view;
+ QCheckBox *m_optimizeRaw;
+ QCheckBox *m_optimizeCurve;
+ KDoubleNumInput *m_combineAngle;
+ KDoubleNumInput *m_fittingError;
+ QWidgetStack *m_widgetStack;
+ QComboBox *m_combo;
+ int m_mode;
+};
+
+
+/**
+ * The pencil tool.
+ *
+ * This tool has three modes of operation
+ * * Raw - exactly what is drawn by the user is what is captured
+ * * Straightend - captured data is straightended
+ * * Smooth - captured data is converted to a bezier curve
+ *
+ */
+
+class VPencilTool : public VTool
+{
+ public:
+ VPencilTool( KarbonView *view );
+ ~VPencilTool();
+
+ virtual void activate();
+ virtual void deactivate();
+
+ virtual void setup(KActionCollection *collection);
+ virtual QString uiname() { return i18n( "Pencil Tool" ); }
+ virtual QString contextHelp();
+ virtual enumToolType toolType() { return TOOL_FREEHAND; }
+
+ virtual bool showDialog() const;
+
+ enum {
+ RAW,
+ STRAIGHT,
+ CURVE
+ };
+
+ protected:
+ /**
+ * Helper method: draws the polyline.
+ */
+ void draw();
+
+ virtual void mouseMove();
+ virtual void mouseButtonPress();
+ virtual void mouseButtonRelease();
+ virtual void mouseButtonDblClick();
+ virtual void mouseDrag();
+ virtual void mouseDragRelease();
+ virtual void mouseDragShiftPressed();
+ virtual void mouseDragCtrlPressed();
+ virtual void mouseDragShiftReleased();
+ virtual void mouseDragCtrlReleased();
+
+ virtual void cancel();
+ virtual void cancelStep();
+ virtual void accept();
+
+ /**
+ * The list of this polyline points.
+ */
+ QPtrList<KoPoint> m_Points;
+
+ /**
+ * The start of the last drawn vector.
+ */
+ KoPoint m_lastVectorStart;
+
+ /**
+ * The end of the last drawn vector.
+ */
+ KoPoint m_lastVectorEnd;
+
+ /**
+ * Indicates if the Line is to close.
+ */
+ bool m_close;
+
+ /**
+ * The mode of the pencile
+ */
+
+ short m_mode;
+
+ bool m_optimize;
+
+ float m_combineAngle;
+
+ VPencilOptionsWidget *m_optionWidget;
+
+ private:
+ QCursor* m_cursor;
+};
+
+#endif
diff --git a/karbon/tools/vpolygontool.cc b/karbon/tools/vpolygontool.cc
new file mode 100644
index 00000000..fcd0faeb
--- /dev/null
+++ b/karbon/tools/vpolygontool.cc
@@ -0,0 +1,165 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+
+#include <qlabel.h>
+#include <qgroupbox.h>
+
+#include <kdialogbase.h>
+#include <klocale.h>
+#include <KoUnitWidgets.h>
+
+#include <karbon_view.h>
+#include <karbon_part.h>
+#include <shapes/vstar.h>
+#include "vpolygontool.h"
+
+VPolygonTool::VPolygonOptionsWidget::VPolygonOptionsWidget( KarbonView *view, QWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, i18n( "Insert Polygon" ), Ok | Cancel ), m_view(view)
+{
+ QGroupBox *group = new QGroupBox( 2, Qt::Horizontal, i18n( "Properties" ), this );
+
+ new QLabel( i18n( "Radius:" ), group );
+ m_radius = new KoUnitDoubleSpinBox( group, 0.0, 1000.0, 0.5, 50.0, KoUnit::U_MM );
+ refreshUnit();
+ new QLabel( i18n( "Edges:" ), group );
+ m_edges = new KIntSpinBox( group );
+ m_edges->setMinValue( 3 );
+
+ group->setInsideMargin( 4 );
+ group->setInsideSpacing( 2 );
+
+ setMainWidget( group );
+ //setFixedSize( baseSize() );
+}
+
+double
+VPolygonTool::VPolygonOptionsWidget::radius() const
+{
+ return m_radius->value();
+}
+
+uint
+VPolygonTool::VPolygonOptionsWidget::edges() const
+{
+ return m_edges->value();
+}
+
+void
+VPolygonTool::VPolygonOptionsWidget::setRadius( double value )
+{
+ m_radius->changeValue( value );
+}
+
+void
+VPolygonTool::VPolygonOptionsWidget::setEdges( uint value )
+{
+ m_edges->setValue( value );
+}
+
+void
+VPolygonTool::VPolygonOptionsWidget::refreshUnit()
+{
+ m_radius->setUnit( m_view->part()->unit() );
+}
+
+VPolygonTool::VPolygonTool( KarbonView *view )
+ : VShapeTool( view, "tool_polygon", true )
+{
+ // create config dialog:
+ m_optionsWidget = new VPolygonOptionsWidget( view );
+ m_optionsWidget->setEdges( 5 );
+ registerTool( this );
+}
+
+VPolygonTool::~VPolygonTool()
+{
+ delete( m_optionsWidget );
+}
+
+void
+VPolygonTool::refreshUnit()
+{
+ m_optionsWidget->refreshUnit();
+}
+
+void
+VPolygonTool::arrowKeyReleased( Qt::Key key )
+{
+ int change = 0;
+ if( key == Qt::Key_Up )
+ change = 1;
+ else if( key == Qt::Key_Down )
+ change = -1;
+
+ if( change != 0 )
+ {
+ draw();
+
+ m_optionsWidget->setEdges( m_optionsWidget->edges() + change );
+
+ draw();
+ }
+}
+
+VPath*
+VPolygonTool::shape( bool interactive ) const
+{
+ if( interactive )
+ {
+ return
+ new VStar(
+ 0L,
+ m_p,
+ m_optionsWidget->radius(),
+ m_optionsWidget->radius(),
+ m_optionsWidget->edges(), 0, 0, 0, VStar::polygon );
+ }
+ else
+ return
+ new VStar(
+ 0L,
+ m_p,
+ m_d1, m_d1,
+ m_optionsWidget->edges(),
+ m_d2, 0, 0, VStar::polygon );
+}
+
+bool
+VPolygonTool::showDialog() const
+{
+ return m_optionsWidget->exec() == QDialog::Accepted;
+}
+
+void
+VPolygonTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ KShortcut shortcut( Qt::Key_Plus );
+ shortcut.append(KShortcut( Qt::Key_F9 ) );
+ m_action = new KRadioAction( i18n( "Polygon Tool" ), "14_polygon", shortcut, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Polygon" ) );
+ m_action->setExclusiveGroup( "shapes" );
+ //m_ownAction = true;
+ }
+}
+
diff --git a/karbon/tools/vpolygontool.h b/karbon/tools/vpolygontool.h
new file mode 100644
index 00000000..028565db
--- /dev/null
+++ b/karbon/tools/vpolygontool.h
@@ -0,0 +1,70 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VPOLYGONTOOL_H__
+#define __VPOLYGONTOOL_H__
+
+#include <kdialogbase.h>
+
+#include "vshapetool.h"
+
+class KoUnitDoubleSpinBox;
+class KIntSpinBox;
+
+
+class VPolygonTool : public VShapeTool
+{
+public:
+ VPolygonTool( KarbonView *view );
+ virtual ~VPolygonTool();
+
+ virtual void setup(KActionCollection *collection);
+ virtual bool showDialog() const;
+ virtual QString uiname() { return i18n( "Polygon Tool" ); }
+
+ virtual VPath *shape( bool interactive = false ) const;
+
+ void refreshUnit();
+
+ virtual void arrowKeyReleased( Qt::Key );
+
+private:
+ class VPolygonOptionsWidget : public KDialogBase
+ {
+ public:
+ VPolygonOptionsWidget( KarbonView *view, QWidget *parent = 0L, const char *name = 0L );
+
+ double radius() const;
+ uint edges() const;
+ void setRadius( double value );
+ void setEdges( uint value );
+
+ void refreshUnit();
+
+ private:
+ KoUnitDoubleSpinBox *m_radius;
+ KIntSpinBox *m_edges;
+ KarbonView *m_view;
+ };
+
+ VPolygonOptionsWidget* m_optionsWidget;
+};
+
+#endif
+
diff --git a/karbon/tools/vpolylinetool.cc b/karbon/tools/vpolylinetool.cc
new file mode 100644
index 00000000..59b72a0e
--- /dev/null
+++ b/karbon/tools/vpolylinetool.cc
@@ -0,0 +1,504 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+*/
+
+#include <qcursor.h>
+#include <qevent.h>
+#include <qlabel.h>
+
+#include <klocale.h>
+
+#include <karbon_part.h>
+#include <karbon_view.h>
+#include <core/vcolor.h>
+#include <core/vcomposite.h>
+#include <core/vfill.h>
+#include <core/vstroke.h>
+#include <core/vglobal.h>
+#include <core/vcursor.h>
+#include <render/vpainter.h>
+#include <render/vpainterfactory.h>
+#include "vpolylinetool.h"
+#include <commands/vshapecmd.h>
+#include <commands/vcommand.h>
+#include <widgets/vcanvas.h>
+
+VPolylineTool::VPolylineTool( KarbonView *view )
+ : VTool( view, "tool_polyline" )
+{
+ m_bezierPoints.setAutoDelete( true );
+ registerTool( this );
+ m_crossCursor = new QCursor( VCursor::createCursor( VCursor::CrossHair ) );
+}
+
+VPolylineTool::~VPolylineTool()
+{
+ delete m_crossCursor;
+}
+
+QString
+VPolylineTool::contextHelp()
+{
+ QString s = i18n( "<qt><b>Polyline tool:</b><br>" );
+ s += i18n( "- <i>Click</i> to add a node and <i>drag</i> to set its bezier vector.<br>" );
+ s += i18n( "- Press <i>Ctrl</i> while dragging to edit the previous bezier vector.<br>" );
+ s += i18n( "- Press <i>Shift</i> while dragging to change the curve in a straight line.<br>" );
+ s += i18n( "- Press <i>Backspace</i> to cancel the last curve.<br>" );
+ s += i18n( "- Press <i>Esc</i> to cancel the whole polyline.<br>" );
+ s += i18n( "- Press <i>Enter</i> or <i>double click</i> to end the polyline.</qt>" );
+
+ return s;
+}
+
+void
+VPolylineTool::activate()
+{
+ VTool::activate();
+ view()->statusMessage()->setText( i18n( "Polyline Tool" ) );
+ view()->setCursor( *m_crossCursor );
+
+ m_bezierPoints.clear();
+ m_close = false;
+
+ connect( view()->part()->commandHistory(), SIGNAL(commandExecuted()), this, SLOT(commandExecuted()) );
+}
+
+void
+VPolylineTool::initializePath( VPath &path )
+{
+ KoPoint* p1 = m_bezierPoints.first();
+ KoPoint* p2;
+ KoPoint* p3;
+ KoPoint* p4;
+
+ path.moveTo( *p1 );
+
+ while(
+ ( p2 = m_bezierPoints.next() ) &&
+ ( p3 = m_bezierPoints.next() ) &&
+ ( p4 = m_bezierPoints.next() ) )
+ {
+ if ( *p1 == *p2 )
+ if ( *p3 == *p4 )
+ path.lineTo( *p4 );
+ else
+ //polyline->curve1To( *p3, *p4 );
+ path.curveTo( *p3, *p4, *p4 );
+ else
+ if ( *p3 == *p4 )
+ //polyline->curve2To( *p2, *p4 );
+ path.curveTo( *p2, *p2, *p4 );
+ else
+ path.curveTo( *p2, *p3, *p4 );
+ p1 = p4;
+ }
+}
+
+void
+VPolylineTool::createObject()
+{
+ VPath* polyline = 0L;
+ if( m_bezierPoints.count() > 2 )
+ {
+ polyline = new VPath( 0L );
+ if( polyline )
+ {
+ initializePath( *polyline );
+ if( m_close )
+ polyline->close();
+
+ VShapeCmd* cmd = new VShapeCmd(
+ &view()->part()->document(),
+ i18n( "Polyline" ),
+ polyline,
+ "14_polyline" );
+
+ view()->part()->addCommand( cmd, true );
+ }
+ }
+
+ m_bezierPoints.clear();
+ m_close = false;
+}
+
+void
+VPolylineTool::deactivate()
+{
+ m_bezierPoints.removeLast();
+ m_bezierPoints.removeLast();
+
+ createObject();
+
+ disconnect( view()->part()->commandHistory(), SIGNAL(commandExecuted()), this, SLOT(commandExecuted()) );
+}
+
+void
+VPolylineTool::draw()
+{
+ VPainter* painter = view()->painterFactory()->editpainter();
+ painter->setRasterOp( Qt::NotROP );
+
+ if( m_bezierPoints.count() > 2 )
+ {
+ VPath polyline( 0L );
+ initializePath( polyline );
+
+ polyline.setState( VObject::edit );
+ polyline.draw( painter, &polyline.boundingBox() );
+ }
+}
+
+void
+VPolylineTool::drawBezierVector( KoPoint& start, KoPoint& end )
+{
+ VPainter* painter = view()->painterFactory()->editpainter();
+
+ painter->save();
+
+ float zoomFactor = view()->zoom();
+
+ painter->setRasterOp( Qt::NotROP );
+ painter->newPath();
+/* VStroke stroke( Qt::blue, 0L, 1.0 );
+ QValueList<float> array;
+ array << 2.0 << 3.0;
+ stroke.dashPattern().setArray( array );*/
+ painter->setPen( Qt::DotLine /*stroke*/ );
+ painter->setBrush( Qt::NoBrush );
+
+ painter->moveTo( start );
+ painter->lineTo( end );
+ painter->strokePath();
+ painter->setRasterOp( Qt::XorROP );
+ painter->newPath();
+ painter->setPen( Qt::yellow );
+
+ float width = 2.0;
+
+ painter->moveTo( KoPoint(
+ end.x() - width / zoomFactor,
+ end.y() - width / zoomFactor ) );
+ painter->lineTo( KoPoint(
+ end.x() + width / zoomFactor,
+ end.y() - width / zoomFactor ) );
+ painter->lineTo( KoPoint(
+ end.x() + width / zoomFactor,
+ end.y() + width / zoomFactor ) );
+ painter->lineTo( KoPoint(
+ end.x() - width / zoomFactor,
+ end.y() + width / zoomFactor ) );
+ painter->lineTo( KoPoint(
+ end.x() - width / zoomFactor,
+ end.y() - width / zoomFactor ) );
+
+ painter->strokePath();
+ painter->restore();
+}
+
+void
+VPolylineTool::mouseMove()
+{
+ if( m_bezierPoints.count() != 0 )
+ {
+ KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
+ draw();
+
+ m_bezierPoints.removeLast();
+ m_bezierPoints.removeLast();
+ m_bezierPoints.append( new KoPoint( _last ) );
+ m_bezierPoints.append( new KoPoint( _last ) );
+
+ draw();
+ }
+}
+
+void
+VPolylineTool::mouseButtonPress()
+{
+ KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
+ if( m_bezierPoints.count() != 0 )
+ {
+ draw();
+ m_bezierPoints.removeLast();
+ m_bezierPoints.removeLast();
+ m_bezierPoints.append( new KoPoint( _last ) );
+ }
+
+ m_lastVectorEnd = m_lastVectorStart = _last;
+
+ m_bezierPoints.append( new KoPoint( _last ) );
+ m_bezierPoints.append( new KoPoint( _last ) );
+ drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
+ draw();
+}
+
+void
+VPolylineTool::mouseButtonRelease()
+{
+ KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
+ if( m_bezierPoints.count() == 2 )
+ {
+ drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
+
+ m_bezierPoints.removeLast();
+ m_bezierPoints.append( new KoPoint( _last ) );
+
+ VPainter* painter = view()->painterFactory()->editpainter();
+ painter->save();
+ painter->setZoomFactor( view()->zoom() );
+ painter->setRasterOp( Qt::XorROP );
+ VStroke stroke( Qt::yellow, 0L, 1.0 );
+ painter->setPen( stroke );
+ painter->setBrush( Qt::yellow );
+ painter->newPath();
+ painter->drawNode( m_lastVectorStart, 2 );
+ painter->strokePath();
+ painter->restore();
+ }
+ else
+ {
+ drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
+ draw();
+ m_bezierPoints.removeLast();
+ KoPoint* p = new KoPoint( *m_bezierPoints.last() );
+ m_bezierPoints.removeLast();
+ KoPoint* b = new KoPoint( *m_bezierPoints.last() );
+ m_bezierPoints.removeLast();
+
+ if( shiftPressed() )
+ {
+ m_bezierPoints.removeLast();
+ m_bezierPoints.append( new KoPoint( *m_bezierPoints.last() ) );
+ m_bezierPoints.append( new KoPoint( *p ) );
+ m_bezierPoints.append( new KoPoint( *p ) );
+ m_bezierPoints.append( new KoPoint( *p ) );
+ m_lastVectorStart = m_lastVectorEnd = *p;
+ }
+ else if( ctrlPressed() )
+ {
+ m_bezierPoints.removeLast();
+ m_lastVectorStart = *m_bezierPoints.last();
+ m_bezierPoints.append( new KoPoint( _last ) );
+ m_bezierPoints.append( new KoPoint( *b ) );
+ m_bezierPoints.append( new KoPoint( *p ) );
+ m_bezierPoints.append( new KoPoint( *p - ( *b - *p ) ) );
+ m_lastVectorEnd = _last;
+ }
+ else
+ {
+ m_bezierPoints.append( new KoPoint( _last ) );
+ m_bezierPoints.append( new KoPoint( *p ) );
+ m_bezierPoints.append( new KoPoint( *p - ( _last - *p ) ) );
+ m_lastVectorStart = *p;
+ m_lastVectorEnd = _last;
+ }
+ if( m_bezierPoints.count() > 2 && p->isNear( *m_bezierPoints.first(), 3 ) )
+ {
+ m_bezierPoints.append( new KoPoint( _last ) );
+ m_close = true;
+ createObject();
+ return;
+ }
+ }
+
+ m_bezierPoints.append( new KoPoint( _last ) );
+ m_bezierPoints.append( new KoPoint( _last ) );
+
+ draw();
+}
+
+void
+VPolylineTool::rightMouseButtonRelease()
+{
+ // end line without adding new points
+ m_bezierPoints.removeLast();
+ m_bezierPoints.removeLast();
+
+ createObject();
+}
+
+void
+VPolylineTool::mouseButtonDblClick()
+{
+ createObject();
+}
+
+void
+VPolylineTool::mouseDrag()
+{
+ KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
+
+ if( m_bezierPoints.count() == 2 )
+ {
+ drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
+
+ m_bezierPoints.removeLast();
+ m_bezierPoints.append( new KoPoint( _last ) );
+ m_lastVectorEnd = _last;
+
+ drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
+ }
+ else
+ {
+ drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
+ draw();
+
+ m_bezierPoints.removeLast();
+ KoPoint* p = new KoPoint( *m_bezierPoints.last() );
+ m_bezierPoints.removeLast();
+ KoPoint* b = new KoPoint( *m_bezierPoints.last() );
+ m_bezierPoints.removeLast();
+
+ if( shiftPressed() )
+ {
+ m_bezierPoints.removeLast();
+ m_bezierPoints.append( new KoPoint( *m_bezierPoints.last() ) );
+ m_bezierPoints.append( new KoPoint( *p ) );
+ m_bezierPoints.append( new KoPoint( *p ) );
+ m_bezierPoints.append( new KoPoint( *p ) );
+ m_lastVectorStart = m_lastVectorEnd = *p;
+ }
+ else if( ctrlPressed() )
+ {
+ m_bezierPoints.removeLast();
+ m_lastVectorStart = *m_bezierPoints.last();
+ m_bezierPoints.append( new KoPoint( _last ) );
+ m_bezierPoints.append( new KoPoint( *b ) );
+ m_bezierPoints.append( new KoPoint( *p ) );
+ m_bezierPoints.append( new KoPoint( *p - ( *b - *p ) ) );
+ m_lastVectorEnd = _last;
+ }
+ else
+ {
+ m_bezierPoints.append( new KoPoint( _last ) );
+ m_bezierPoints.append( new KoPoint( *p ) );
+ m_bezierPoints.append( new KoPoint( *p - ( _last - *p ) ) );
+ m_lastVectorStart = *p;
+ m_lastVectorEnd = _last;
+ }
+
+ draw();
+ drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
+ }
+}
+
+void
+VPolylineTool::mouseDragRelease()
+{
+ mouseButtonRelease();
+}
+
+void
+VPolylineTool::mouseDragShiftPressed()
+{
+}
+
+void
+VPolylineTool::mouseDragCtrlPressed()
+{
+ // Moves the mouse to the other bezier vector position.
+ if( m_bezierPoints.count() > 3 )
+ {
+ KoPoint p;
+ p = *m_bezierPoints.at( m_bezierPoints.count() - 4) - *m_bezierPoints.at( m_bezierPoints.count() - 3 );
+
+ view()->setPos( p );
+ }
+}
+
+void
+VPolylineTool::mouseDragShiftReleased()
+{
+}
+
+void
+VPolylineTool::mouseDragCtrlReleased()
+{
+ if( m_bezierPoints.count() > 3 )
+ {
+ KoPoint p;
+ p = *m_bezierPoints.at( m_bezierPoints.count() - 3) - *m_bezierPoints.at( m_bezierPoints.count() - 4 );
+
+ view()->setPos( p );
+ }
+}
+
+void
+VPolylineTool::cancel()
+{
+ draw();
+
+ m_bezierPoints.clear();
+}
+
+void
+VPolylineTool::cancelStep()
+{
+ draw();
+
+ if ( m_bezierPoints.count() > 6 )
+ {
+ m_bezierPoints.removeLast();
+ m_bezierPoints.removeLast();
+ m_bezierPoints.removeLast();
+ KoPoint p1 = *m_bezierPoints.last();
+ m_bezierPoints.removeLast();
+ m_bezierPoints.removeLast();
+ m_bezierPoints.append( new KoPoint( p1 ) );
+ m_bezierPoints.append( new KoPoint( p1 ) );
+
+ view()->setPos( p1 );
+ }
+ else
+ {
+ m_bezierPoints.clear();
+ }
+
+ draw();
+}
+
+void
+VPolylineTool::accept()
+{
+ activate();
+}
+
+void
+VPolylineTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ KShortcut shortcut( Qt::Key_Plus );
+ shortcut.append( KShortcut( Qt::Key_F9 ) );
+ m_action = new KRadioAction( i18n( "Polyline Tool" ), "14_polyline", shortcut, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Polyline" ) );
+ m_action->setExclusiveGroup( "freehand" );
+ //m_ownAction = true;
+ }
+}
+
+void
+VPolylineTool::commandExecuted()
+{
+ cancel();
+}
+
+#include "vpolylinetool.moc"
diff --git a/karbon/tools/vpolylinetool.h b/karbon/tools/vpolylinetool.h
new file mode 100644
index 00000000..83e4a562
--- /dev/null
+++ b/karbon/tools/vpolylinetool.h
@@ -0,0 +1,129 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef __VPOLYLINETOOL_H__
+#define __VPOLYLINETOOL_H__
+
+
+#include <qptrlist.h>
+#include <qstring.h>
+
+#include "KoPoint.h"
+
+#include "vtool.h"
+
+
+class QLabel;
+class QWidget;
+class VPath;
+class QCursor;
+
+/**
+ * The polyline tool.
+ *
+ * When the tool is activated, you draw your polyline until the tool is
+ * deactivated.
+ * When the mouse button is pressed, you add a Bezier node and sets the vector by
+ * dragging it.
+ * While dragging, when you press on CTRL, you edit the other vector, and when
+ * you press on SHIFT the current segment, the segment becames a line.
+ */
+
+class VPolylineTool : public VTool
+{
+ Q_OBJECT
+
+ public:
+ VPolylineTool( KarbonView *view );
+ ~VPolylineTool();
+
+ virtual void setup(KActionCollection *collection);
+ virtual void activate();
+ virtual void deactivate();
+
+ virtual QString uiname() { return i18n( "Polyline Tool" ); }
+ virtual QString contextHelp();
+ virtual enumToolType toolType() { return TOOL_FREEHAND; }
+
+ protected:
+ /**
+ * Helper method: draws the polyline.
+ */
+ void draw();
+
+ /**
+ * Helper method: draws a bezier vector.
+ */
+ void drawBezierVector( KoPoint& start, KoPoint& end );
+
+ /**
+ * Creates the polyline from the bezier points.
+ */
+ void createObject();
+
+ /**
+ * Initializes the specified path with the actual bezier points.
+ */
+ void initializePath( VPath &path );
+
+ virtual void mouseMove();
+ virtual void mouseButtonPress();
+ virtual void mouseButtonRelease();
+ virtual void rightMouseButtonRelease();
+ virtual void mouseButtonDblClick();
+ virtual void mouseDrag();
+ virtual void mouseDragRelease();
+ virtual void mouseDragShiftPressed();
+ virtual void mouseDragCtrlPressed();
+ virtual void mouseDragShiftReleased();
+ virtual void mouseDragCtrlReleased();
+
+ virtual void cancel();
+ virtual void cancelStep();
+ virtual void accept();
+
+ /**
+ * The list of this polyline points.
+ */
+ QPtrList<KoPoint> m_bezierPoints;
+
+ /**
+ * The start of the last drawn vector.
+ */
+ KoPoint m_lastVectorStart;
+
+ /**
+ * The end of the last drawn vector.
+ */
+ KoPoint m_lastVectorEnd;
+
+ /**
+ * Indicates if the polyline is to close.
+ */
+ bool m_close;
+ protected slots:
+ void commandExecuted();
+
+ private:
+ QCursor* m_crossCursor;
+};
+
+#endif
+
diff --git a/karbon/tools/vrectangletool.cc b/karbon/tools/vrectangletool.cc
new file mode 100644
index 00000000..e65f3e88
--- /dev/null
+++ b/karbon/tools/vrectangletool.cc
@@ -0,0 +1,143 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <qlabel.h>
+#include <qgroupbox.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+
+#include <karbon_view.h>
+#include <karbon_part.h>
+#include <shapes/vrectangle.h>
+#include "vrectangletool.h"
+#include <KoUnitWidgets.h>
+
+
+VRectangleTool::VRectangleOptionsWidget::VRectangleOptionsWidget( KarbonPart *part, QWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, i18n( "Insert Rectangle" ), Ok | Cancel ), m_part( part )
+{
+ QGroupBox *group = new QGroupBox( 2, Qt::Horizontal, i18n( "Properties" ), this );
+ // add width/height-input:
+ m_widthLabel = new QLabel( i18n( "object width", "Width:" ), group );
+ m_width = new KoUnitDoubleSpinBox( group, 0.0, 1000.0, 0.5, 100.0, KoUnit::U_MM );
+
+ m_heightLabel = new QLabel( i18n( "Height:" ), group );
+ m_height = new KoUnitDoubleSpinBox( group, 0.0, 1000.0, 0.5, 100.0, KoUnit::U_MM );
+
+ refreshUnit();
+
+ group->setInsideMargin( 4 );
+ group->setInsideSpacing( 2 );
+
+ setMainWidget( group );
+ //setFixedSize( baseSize() );
+}
+
+double
+VRectangleTool::VRectangleOptionsWidget::width() const
+{
+ return m_width->value();
+}
+
+double
+VRectangleTool::VRectangleOptionsWidget::height() const
+{
+ return m_height->value();
+}
+
+void
+VRectangleTool::VRectangleOptionsWidget::setWidth( double value )
+{
+ m_width->setValue( value );
+}
+
+void
+VRectangleTool::VRectangleOptionsWidget::setHeight( double value )
+{
+ m_height->setValue( value );
+}
+
+void
+VRectangleTool::VRectangleOptionsWidget::refreshUnit()
+{
+ m_width->setUnit( m_part->unit() );
+ m_height->setUnit( m_part->unit() );
+}
+
+VRectangleTool::VRectangleTool( KarbonView *view )
+ : VShapeTool( view, "tool_rectangle" )
+{
+ // Create config dialog:
+ m_optionWidget = new VRectangleOptionsWidget( view->part() );
+ registerTool( this );
+}
+
+VRectangleTool::~VRectangleTool()
+{
+ delete( m_optionWidget );
+}
+
+void
+VRectangleTool::refreshUnit()
+{
+ m_optionWidget->refreshUnit();
+}
+
+VPath *
+VRectangleTool::shape( bool interactive ) const
+{
+ if( interactive )
+ {
+ return
+ new VRectangle(
+ 0L,
+ m_p,
+ m_optionWidget->width(),
+ m_optionWidget->height() );
+ }
+ else
+ return
+ new VRectangle(
+ 0L,
+ m_p,
+ m_d1,
+ m_d2 );
+}
+
+bool
+VRectangleTool::showDialog() const
+{
+ return m_optionWidget->exec() == QDialog::Accepted;
+}
+
+void
+VRectangleTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ m_action = new KRadioAction( i18n( "Rectangle Tool" ), "14_rectangle", Qt::Key_Plus+Qt::Key_F9, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Rectangle" ) );
+ m_action->setExclusiveGroup( "shapes" );
+ //m_ownAction = true;
+ }
+}
+
diff --git a/karbon/tools/vrectangletool.h b/karbon/tools/vrectangletool.h
new file mode 100644
index 00000000..d5e45c30
--- /dev/null
+++ b/karbon/tools/vrectangletool.h
@@ -0,0 +1,70 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VRECTANGLETOOL_H__
+#define __VRECTANGLETOOL_H__
+
+
+#include <klocale.h>
+#include <kdialogbase.h>
+
+#include "vshapetool.h"
+
+class KarbonView;
+class QLabel;
+class KoUnitDoubleSpinBox;
+
+class VRectangleTool : public VShapeTool
+{
+public:
+ VRectangleTool( KarbonView *view );
+ virtual ~VRectangleTool();
+
+ virtual void setup(KActionCollection *collection);
+ virtual bool showDialog() const;
+ virtual QString uiname() { return i18n( "Rectangle Tool" ); }
+ virtual VPath* shape( bool interactive = false ) const;
+
+ void refreshUnit();
+
+private:
+ class VRectangleOptionsWidget : public KDialogBase
+ {
+ public:
+ VRectangleOptionsWidget( KarbonPart *part, QWidget* parent = 0L, const char* name = 0L );
+
+ double width() const;
+ double height() const;
+ void setWidth( double value );
+ void setHeight( double value );
+ void refreshUnit();
+
+ private:
+ KoUnitDoubleSpinBox *m_width;
+ KoUnitDoubleSpinBox *m_height;
+ KarbonPart *m_part;
+ QLabel *m_heightLabel;
+ QLabel *m_widthLabel;
+ };
+
+ VRectangleOptionsWidget *m_optionWidget;
+};
+
+#endif
+
diff --git a/karbon/tools/vrotatetool.cc b/karbon/tools/vrotatetool.cc
new file mode 100644
index 00000000..987a7b60
--- /dev/null
+++ b/karbon/tools/vrotatetool.cc
@@ -0,0 +1,175 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <math.h>
+
+#include <qcursor.h>
+#include <qlabel.h>
+
+#include <klocale.h>
+#include <KoRect.h>
+
+#include <karbon_part.h>
+#include <karbon_view.h>
+#include <core/vglobal.h>
+#include "vrotatetool.h"
+#include <render/vpainter.h>
+#include <render/vpainterfactory.h>
+#include <commands/vtransformcmd.h>
+
+#include <kdebug.h>
+
+VRotateTool::VRotateTool( KarbonView *view )
+ : VTool( view, "tool_rotate" )
+{
+ m_objects.setAutoDelete( true );
+ registerTool( this );
+}
+
+VRotateTool::~VRotateTool()
+{
+ m_objects.clear();
+}
+
+void
+VRotateTool::activate()
+{
+ view()->setCursor( QCursor( Qt::arrowCursor ) );
+ view()->part()->document().selection()->setState( VObject::selected );
+ view()->part()->document().selection()->showHandle( false );
+ VTool::activate();
+}
+
+QString
+VRotateTool::statusText()
+{
+ return i18n( "Rotate" );
+}
+
+void
+VRotateTool::draw()
+{
+ VPainter* painter = view()->painterFactory()->editpainter();
+ //painter->setZoomFactor( view()->zoom() );
+ painter->setRasterOp( Qt::NotROP );
+
+ VObjectListIterator itr = m_objects;
+ for( ; itr.current(); ++itr )
+ {
+ itr.current()->draw( painter, &itr.current()->boundingBox() );
+ }
+}
+
+void
+VRotateTool::mouseButtonPress()
+{
+ //view()->painterFactory()->painter()->end();
+
+ recalc();
+
+ // Draw new object:
+ draw();
+}
+
+void
+VRotateTool::mouseDrag()
+{
+ // Erase old object:
+ draw();
+
+ recalc();
+
+ // Draw new object:
+ draw();
+}
+
+void
+VRotateTool::mouseDragRelease()
+{
+ view()->part()->addCommand(
+ new VRotateCmd(
+ &view()->part()->document(),
+ m_center,
+ m_angle, altPressed() ),
+ true );
+}
+
+void
+VRotateTool::cancel()
+{
+ // Erase old object:
+ if ( isDragging() )
+ {
+ draw();
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+ }
+}
+
+void
+VRotateTool::recalc()
+{
+ // Get center:
+ m_center = view()->part()->document().selection()->boundingBox().center();
+
+ // Calculate angle between vector (last - center) and (first - center):
+ m_angle = VGlobal::one_pi_180 * (
+ atan2(
+ last().y() - m_center.y(),
+ last().x() - m_center.x() )
+ -
+ atan2(
+ first().y() - m_center.y(),
+ first().x() - m_center.x() ) );
+
+ VRotateCmd cmd( 0L, m_center, m_angle );
+
+ // Copy selected objects and transform:
+ m_objects.clear();
+ VObject* copy;
+
+ VObjectListIterator itr = view()->part()->document().selection()->objects();
+ for ( ; itr.current() ; ++itr )
+ {
+ if( itr.current()->state() != VObject::deleted )
+ {
+ copy = itr.current()->clone();
+
+ cmd.visit( *copy );
+
+ copy->setState( VObject::edit );
+
+ m_objects.append( copy );
+ }
+ }
+}
+
+void
+VRotateTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ m_action = new KRadioAction( i18n( "Rotate Tool" ), "14_rotate", Qt::SHIFT+Qt::Key_H, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Rotate" ) );
+ m_action->setExclusiveGroup( "manipulation" );
+ //m_ownAction = true;
+ }
+}
+
diff --git a/karbon/tools/vrotatetool.h b/karbon/tools/vrotatetool.h
new file mode 100644
index 00000000..46e2c98b
--- /dev/null
+++ b/karbon/tools/vrotatetool.h
@@ -0,0 +1,63 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VROTATETOOL_H__
+#define __VROTATETOOL_H__
+
+#include "vselection.h"
+#include "vtool.h"
+
+
+class VRotateTool : public VTool
+{
+public:
+ VRotateTool( KarbonView *view );
+ virtual ~VRotateTool();
+
+ virtual void activate();
+
+ virtual void setup(KActionCollection *collection);
+ virtual QString uiname() { return i18n( "Rotate Tool" ); }
+ virtual enumToolType toolType() { return TOOL_MANIPULATION; }
+ virtual QString statusText();
+ virtual uint priority() { return 0; }
+
+protected:
+ virtual void draw();
+
+ virtual void mouseButtonPress();
+ virtual void mouseDrag();
+ virtual void mouseDragRelease();
+
+ virtual void cancel();
+
+private:
+ void recalc();
+
+ KoPoint m_center;
+ double m_angle;
+
+ VHandleNode m_activeNode;
+
+ // A list of temporary objects:
+ VObjectList m_objects;
+};
+
+#endif
+
diff --git a/karbon/tools/vroundrecttool.cc b/karbon/tools/vroundrecttool.cc
new file mode 100644
index 00000000..af21d4d9
--- /dev/null
+++ b/karbon/tools/vroundrecttool.cc
@@ -0,0 +1,179 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+
+#include <knuminput.h>
+
+#include <karbon_view.h>
+#include <karbon_part.h>
+#include <shapes/vrectangle.h>
+#include "vroundrecttool.h"
+#include "KoUnitWidgets.h"
+
+#include <kgenericfactory.h>
+
+VRoundRectTool::VRoundRectOptionsWidget::VRoundRectOptionsWidget( KarbonPart *part, QWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, i18n( "Insert Round Rect" ), Ok | Cancel ), m_part( part )
+{
+ QGroupBox *group = new QGroupBox( 2, Qt::Horizontal, i18n( "Properties" ), this );
+ new QLabel( i18n( "object width", "Width:" ), group );
+
+ KoUnit::Unit unit = KoUnit::U_CM;
+ m_width = new KoUnitDoubleSpinBox( group, 0.0, KoUnit::fromUserValue( 1000.0, unit ), KoUnit::fromUserValue( 0.5, unit ), KoUnit::fromUserValue( 10.0, unit ), unit );
+
+ new QLabel( i18n( "Height (%1):" ).arg(KoUnit::unitName( m_part->unit() )), group );
+ m_height = new KoUnitDoubleSpinBox( group, 0.0, KoUnit::fromUserValue( 1000.0, unit ), KoUnit::fromUserValue( 0.5, unit ), KoUnit::fromUserValue( 10.0, unit ), unit );
+
+ new QLabel( i18n( "Edge radius X:" ), group );
+ m_roundx = new KoUnitDoubleSpinBox( group, 0.0, KoUnit::fromUserValue( 100.0, unit ), KoUnit::fromUserValue( 0.1, unit ), KoUnit::fromUserValue( 1.0, unit ), unit );
+
+ new QLabel( i18n( "Edge radius Y:" ), group );
+ m_roundy = new KoUnitDoubleSpinBox( group, 0.0, KoUnit::fromUserValue( 100.0, unit ), KoUnit::fromUserValue( 0.1, unit ), KoUnit::fromUserValue( 1.0, unit ), unit );
+
+ group->setInsideMargin( 4 );
+ group->setInsideSpacing( 2 );
+
+ setMainWidget( group );
+ setFixedSize( baseSize() );
+}
+
+double
+VRoundRectTool::VRoundRectOptionsWidget::width() const
+{
+ return m_width->value();
+}
+
+double
+VRoundRectTool::VRoundRectOptionsWidget::height() const
+{
+ return m_height->value();
+}
+
+double
+VRoundRectTool::VRoundRectOptionsWidget::roundx() const
+{
+ return m_roundx->value();
+}
+
+double
+VRoundRectTool::VRoundRectOptionsWidget::roundy() const
+{
+ return m_roundy->value();
+}
+
+void
+VRoundRectTool::VRoundRectOptionsWidget::setWidth( double value )
+{
+ m_width->changeValue( value );
+}
+
+void
+VRoundRectTool::VRoundRectOptionsWidget::setHeight( double value )
+{
+ m_height->changeValue( value );
+}
+
+void
+VRoundRectTool::VRoundRectOptionsWidget::setRoundX( double value )
+{
+ m_roundx->changeValue( value );
+}
+
+void
+VRoundRectTool::VRoundRectOptionsWidget::setRoundY( double value )
+{
+ m_roundy->changeValue( value );
+}
+
+void
+VRoundRectTool::VRoundRectOptionsWidget::refreshUnit ()
+{
+ m_width->setUnit( m_part->unit() );
+ m_height->setUnit( m_part->unit() );
+ m_roundx->setUnit( m_part->unit() );
+ m_roundy->setUnit( m_part->unit() );
+}
+
+VRoundRectTool::VRoundRectTool( KarbonView *view )
+ : VShapeTool( view, "tool_round_rectangle" )
+{
+ // Create config dialog:
+ m_optionsWidget = new VRoundRectOptionsWidget( view->part() );
+ registerTool( this );
+}
+
+VRoundRectTool::~VRoundRectTool()
+{
+ delete( m_optionsWidget );
+}
+
+void VRoundRectTool::refreshUnit()
+{
+ m_optionsWidget->refreshUnit();
+}
+
+VPath*
+VRoundRectTool::shape( bool interactive ) const
+{
+ if( interactive )
+ {
+ return
+ new VRectangle(
+ 0L,
+ m_p,
+ m_optionsWidget->width(),
+ m_optionsWidget->height(),
+ m_optionsWidget->roundx(),
+ m_optionsWidget->roundy() );
+ }
+ else {
+ return
+ new VRectangle(
+ 0L,
+ m_p,
+ m_d1,
+ m_d2,
+ m_optionsWidget->roundx(),
+ m_optionsWidget->roundy() );
+ }
+}
+
+bool
+VRoundRectTool::showDialog() const
+{
+ return m_optionsWidget->exec() == QDialog::Accepted;
+}
+
+void
+VRoundRectTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ m_action = new KRadioAction( i18n( "Round Rectangle Tool" ), "14_roundrect", Qt::SHIFT+Qt::Key_H, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Round Rectangle" ) );
+ m_action->setExclusiveGroup( "shapes" );
+ //m_ownAction = true;
+ }
+}
+
diff --git a/karbon/tools/vroundrecttool.h b/karbon/tools/vroundrecttool.h
new file mode 100644
index 00000000..75e86796
--- /dev/null
+++ b/karbon/tools/vroundrecttool.h
@@ -0,0 +1,81 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VROUNDRECTTOOL_H__
+#define __VROUNDRECTTOOL_H__
+
+#include <klocale.h>
+#include <kdialogbase.h>
+#include <knuminput.h>
+
+
+#include "vshapetool.h"
+
+class KarbonView;
+class KarbonPart;
+class QLabel;
+class KoUnitDoubleSpinBox;
+
+
+class VRoundRectTool : public VShapeTool
+{
+public:
+ VRoundRectTool( KarbonView *view );
+ virtual ~VRoundRectTool();
+
+ virtual bool showDialog() const;
+ virtual void setup(KActionCollection *collection);
+ virtual QString uiname() { return i18n( "Round Rectangle Tool" ); }
+
+ virtual VPath* shape( bool interactive = false ) const;
+
+ void refreshUnit();
+
+private:
+ class VRoundRectOptionsWidget : public KDialogBase
+ {
+ public:
+ VRoundRectOptionsWidget( KarbonPart *part, QWidget *parent = 0L, const char *name = 0L );
+
+ double width() const;
+ double height() const;
+ double roundx() const;
+ double roundy() const;
+ void setWidth( double value );
+ void setHeight( double value );
+ void setRoundX( double value );
+ void setRoundY( double value );
+ void refreshUnit ();
+
+ private:
+
+ KoUnitDoubleSpinBox* m_width;
+ KoUnitDoubleSpinBox* m_height;
+ KoUnitDoubleSpinBox* m_roundx;
+ KoUnitDoubleSpinBox* m_roundy;
+
+ KarbonPart* m_part;
+
+ };
+
+ VRoundRectOptionsWidget* m_optionsWidget;
+};
+
+#endif
+
diff --git a/karbon/tools/vselectnodestool.cc b/karbon/tools/vselectnodestool.cc
new file mode 100644
index 00000000..1c628faa
--- /dev/null
+++ b/karbon/tools/vselectnodestool.cc
@@ -0,0 +1,443 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <math.h>
+
+#include <qcursor.h>
+#include <qlabel.h>
+
+#include <klocale.h>
+#include <KoPoint.h>
+#include <KoRect.h>
+
+#include <karbon_part.h>
+#include <karbon_view.h>
+
+#include <render/vpainter.h>
+#include <render/vpainterfactory.h>
+#include <visitors/vselectnodes.h>
+#include <commands/vtransformcmd.h>
+#include <visitors/vdrawselection.h>
+#include <core/vselection.h>
+#include <core/vcursor.h>
+#include "vselectnodestool.h"
+#include <vtransformnodes.h>
+#include <commands/vdeletenodescmd.h>
+#include <widgets/vcanvas.h>
+
+#include <kdebug.h>
+
+VSelectNodesTool::VSelectNodesTool( KarbonView* view )
+ : VTool( view, "tool_select_nodes" ), m_state( normal ), m_select( true )
+{
+ registerTool( this );
+}
+
+VSelectNodesTool::~VSelectNodesTool()
+{
+}
+
+void
+VSelectNodesTool::activate()
+{
+ if( view() )
+ {
+ view()->setCursor( VCursor::needleArrow() );
+ view()->part()->document().selection()->showHandle( false );
+ view()->part()->document().selection()->setSelectObjects( false );
+ // deselect all nodes
+ view()->part()->document().selection()->selectNodes( false );
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+ }
+ VTool::activate();
+}
+
+QString
+VSelectNodesTool::statusText()
+{
+ if( m_state == normal )
+ return i18n( "Editing Nodes" );
+ else
+ return QString( "" );
+}
+
+void
+VSelectNodesTool::draw()
+{
+ VPainter *painter = view()->painterFactory()->editpainter();
+ painter->setZoomFactor( view()->zoom() );
+ painter->setRasterOp( Qt::NotROP );
+
+ if( m_state == dragging )
+ {
+ painter->setPen( Qt::DotLine );
+ painter->newPath();
+ painter->moveTo( KoPoint( m_first.x(), m_first.y() ) );
+ painter->lineTo( KoPoint( m_current.x(), m_first.y() ) );
+ painter->lineTo( KoPoint( m_current.x(), m_current.y() ) );
+ painter->lineTo( KoPoint( m_first.x(), m_current.y() ) );
+ painter->lineTo( KoPoint( m_first.x(), m_first.y() ) );
+ painter->strokePath();
+ }
+ else
+ {
+ VDrawSelection op( m_objects, painter, true, VSelection::handleSize() );
+ VObjectListIterator itr = m_objects;
+ for( ; itr.current(); ++itr )
+ op.visit( *( itr.current() ) );
+ }
+}
+
+void
+VSelectNodesTool::setCursor() const
+{
+ if( m_state >= moving )
+ {
+ view()->setCursor( VCursor::needleMoveArrow() );
+ return;
+ }
+
+ KoRect selrect = calcSelRect( last() );
+
+ QPtrList<VSegment> segments = view()->part()->document().selection()->getSegments( selrect );
+ if( segments.count() > 0 )
+ {
+ VSegment* seg = segments.at( 0 );
+ for( int i = 0; i < seg->degree(); ++i )
+ if( seg->pointIsSelected( i ) && selrect.contains( seg->point( i ) ) )
+ {
+ view()->setCursor( VCursor::needleMoveArrow() );
+ break;
+ }
+ }
+ else
+ view()->setCursor( VCursor::needleArrow() );
+}
+
+void
+VSelectNodesTool::mouseButtonPress()
+{
+ m_first = m_current = first();
+
+ m_state = normal;
+ m_select = true;
+
+ recalc();
+
+ view()->part()->document().selection()->setState( VObject::edit );
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+ view()->part()->document().selection()->setState( VObject::selected );
+
+ VSelection* selection = view()->part()->document().selection();
+
+ KoRect selrect = calcSelRect( m_current );
+
+ // get segments with control points inside selection rect
+ QPtrList<VSegment> segments = selection->getSegments( selrect );
+ if( segments.count() > 0 )
+ {
+ VSegment *seg = segments.at( 0 );
+ VSegment* prev = seg->prev();
+ VSegment* next = seg->next();
+
+ // allow moving bezier points only if one of the bezier points is within the selection rect
+ // and no neighboring knot is selected
+ if( segments.count() == 1 && ! selrect.contains( seg->knot() ) && ! seg->knotIsSelected()
+ && ( prev && ! prev->knotIsSelected() ) )
+ {
+ if( selrect.contains( seg->point( 1 ) ) )
+ {
+ m_state = movingbezier1;
+ if( next )
+ next->selectPoint( 0, false );
+ }
+ else if( selrect.contains( seg->point( 0 ) ) )
+ {
+ m_state = movingbezier2;
+ if( prev )
+ prev->selectPoint( 1, false );
+ }
+ }
+ else
+ {
+ for( VSegment *seg = segments.first(); seg; seg = segments.next() )
+ {
+ for( int i = 0; i < seg->degree(); ++i )
+ {
+ if( seg->pointIsSelected( i ) && selrect.contains( seg->point( i ) ) )
+ {
+ m_state = moving;
+ break;
+ }
+ }
+ if( m_state == moving )
+ break;
+ }
+ }
+
+ double minDist = -1.0;
+ // use the nearest control point of all the segments as starting point
+ for( VSegment *seg = segments.first(); seg; seg = segments.next() )
+ {
+ for( int i = 0; i < seg->degree(); ++i )
+ {
+ if( selrect.contains( seg->point( i ) ) )
+ {
+ KoPoint vDist = seg->point( i ) - m_current;
+ double dist = vDist.x()*vDist.x() + vDist.y()*vDist.y();
+ if( minDist < 0.0 || dist < minDist )
+ {
+ m_first = seg->point( i );
+ minDist = dist;
+ }
+ }
+ }
+ }
+ recalc();
+ }
+ else
+ m_state = dragging;
+
+ draw();
+}
+
+void
+VSelectNodesTool::rightMouseButtonPress()
+{
+ m_first = m_current = first();
+
+ m_state = normal;
+ m_select = false;
+
+ recalc();
+
+ view()->part()->document().selection()->setState( VObject::edit );
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+ view()->part()->document().selection()->setState( VObject::selected );
+
+ draw();
+}
+
+bool
+VSelectNodesTool::keyReleased( Qt::Key key )
+{
+ VSelection* selection = view()->part()->document().selection();
+
+ switch( key )
+ {
+ // increase/decrease the handle size
+ case Qt::Key_I:
+ {
+ uint handleSize = selection->handleSize();
+ if( shiftPressed() )
+ selection->setHandleSize( ++handleSize );
+ else if( handleSize > 1 )
+ selection->setHandleSize( --handleSize );
+ }
+ break;
+ case Qt::Key_Delete:
+ if( selection->objects().count() > 0 )
+ view()->part()->addCommand( new VDeleteNodeCmd( &view()->part()->document() ), true );
+ break;
+ default: return false;
+ }
+
+ if( view() )
+ view()->repaintAll( selection->boundingBox() );
+
+ return true;
+}
+
+void
+VSelectNodesTool::mouseButtonRelease()
+{
+ // erase old object:
+ draw();
+
+ VSelection* selection = view()->part()->document().selection();
+
+ KoRect selrect = calcSelRect( last() );
+
+ if( ctrlPressed() )
+ selection->append( selrect.normalize(), false, false );
+ else
+ selection->append( selrect.normalize(), false, true );
+
+ view()->selectionChanged();
+ view()->part()->repaintAllViews();
+ m_state = normal;
+}
+
+void
+VSelectNodesTool::rightMouseButtonRelease()
+{
+ // erase old object:
+ draw();
+
+ VSelection* selection = view()->part()->document().selection();
+
+ KoRect selrect = calcSelRect( last() );
+
+ selection->take( selrect.normalize(), false, false );
+
+ view()->selectionChanged();
+ view()->part()->repaintAllViews();
+ m_state = normal;
+}
+
+void
+VSelectNodesTool::mouseDrag()
+{
+ draw();
+
+ recalc();
+
+ draw();
+}
+
+void
+VSelectNodesTool::mouseDragRelease()
+{
+ if( m_state >= moving )
+ {
+ view()->part()->document().selection()->setState( VObject::selected );
+ VCommand *cmd;
+ QPtrList<VSegment> segments;
+ KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
+ if( m_state == movingbezier1 || m_state == movingbezier2 )
+ {
+ KoRect selrect = calcSelRect( m_first );
+ segments = view()->part()->document().selection()->getSegments( selrect );
+ cmd = new VTranslateBezierCmd( &view()->part()->document(), segments.at( 0 ),
+ qRound( ( _last.x() - m_first.x() ) ),
+ qRound( ( _last.y() - m_first.y() ) ),
+ m_state == movingbezier2 );
+ }
+ else
+ {
+ cmd = new VTranslatePointCmd(
+ &view()->part()->document(),
+ qRound( ( _last.x() - m_first.x() ) ),
+ qRound( ( _last.y() - m_first.y() ) ) );
+ }
+ view()->part()->addCommand( cmd, true );
+ m_state = normal;
+ }
+ else
+ {
+ KoPoint fp = m_first;
+ KoPoint lp = last();
+
+ if ( (fabs(lp.x() - fp.x()) + fabs(lp.y()-fp.y())) < 3.0 )
+ {
+ // AK - should take the middle point here
+ fp = last() - KoPoint(8.0, 8.0);
+ lp = last() + KoPoint(8.0, 8.0);
+ }
+
+ // erase old object:
+ draw();
+
+ if( m_select )
+ {
+ view()->part()->document().selection()->append(); // select all
+ view()->part()->document().selection()->append(
+ KoRect( fp.x(), fp.y(), lp.x() - fp.x(), lp.y() - fp.y() ).normalize(),
+ false, true );
+ }
+ else
+ {
+ view()->part()->document().selection()->take(
+ KoRect( fp.x(), fp.y(), lp.x() - fp.x(), lp.y() - fp.y() ).normalize(),
+ false, false );
+ }
+ view()->selectionChanged();
+ view()->part()->repaintAllViews();
+ m_state = normal;
+ }
+}
+
+void
+VSelectNodesTool::cancel()
+{
+ // Erase old object:
+ if ( isDragging() )
+ {
+ draw();
+ m_state = normal;
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+ }
+}
+
+void
+VSelectNodesTool::recalc()
+{
+ if( m_state == dragging )
+ {
+ m_current = last();
+ }
+ else if( m_state == moving || m_state == movingbezier1 || m_state == movingbezier2 )
+ {
+ KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
+ double distx = _last.x() - m_first.x();
+ double disty = _last.y() - m_first.y();
+ // move operation
+ QWMatrix mat;
+ mat.translate( distx, disty );
+
+ // Copy selected objects and transform:
+ m_objects.clear();
+ VObject* copy;
+
+ VTransformNodes op( mat );
+
+ VObjectListIterator itr = view()->part()->document().selection()->objects();
+ for ( ; itr.current() ; ++itr )
+ {
+ if( itr.current()->state() != VObject::deleted )
+ {
+ copy = itr.current()->clone();
+ copy->setState( VObject::edit );
+ op.visit( *copy );
+ m_objects.append( copy );
+ }
+ }
+ }
+}
+
+void
+VSelectNodesTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ m_action = new KRadioAction( i18n( "Select Nodes Tool" ), "14_selectnodes", Qt::SHIFT+Qt::Key_H, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Select Nodes" ) );
+ m_action->setExclusiveGroup( "select" );
+ //m_ownAction = true;
+ }
+}
+
+KoRect
+VSelectNodesTool::calcSelRect( const KoPoint &pos ) const
+{
+ double tolerance = view()->part()->document().selection()->handleSize() / view()->zoom();
+ return KoRect( pos.x() - tolerance, pos.y() - tolerance, 2 * tolerance + 1.0, 2 * tolerance + 1.0 );
+}
diff --git a/karbon/tools/vselectnodestool.h b/karbon/tools/vselectnodestool.h
new file mode 100644
index 00000000..d0a5b296
--- /dev/null
+++ b/karbon/tools/vselectnodestool.h
@@ -0,0 +1,72 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VSELECTNODESTOOL_H__
+#define __VSELECTNODESTOOL_H__
+
+#include "vtool.h"
+
+class VSelectNodesTool : public VTool
+{
+public:
+ VSelectNodesTool( KarbonView *view );
+ virtual ~VSelectNodesTool();
+
+ virtual void activate();
+
+ virtual void setup(KActionCollection *collection);
+ virtual QString uiname() { return i18n( "Select Nodes Tool" ); }
+ virtual enumToolType toolType() { return TOOL_SELECT; }
+ virtual QString statusText();
+ virtual uint priority() { return 1; }
+
+protected:
+ virtual void draw();
+
+ virtual void setCursor() const;
+
+ virtual void mouseButtonPress();
+ virtual void mouseButtonRelease();
+ virtual void mouseDragRelease();
+ virtual void mouseDrag();
+ virtual void rightMouseButtonPress();
+ virtual void rightMouseButtonRelease();
+
+ virtual bool keyReleased( Qt::Key );
+
+ virtual void cancel();
+
+private:
+ enum { normal, dragging, moving, movingbezier1, movingbezier2 } m_state;
+
+ void recalc();
+
+ KoRect calcSelRect( const KoPoint &pos ) const;
+
+ // A list of temporary objects:
+ VObjectList m_objects;
+
+ KoPoint m_current;
+ KoPoint m_first;
+
+ bool m_select;
+};
+
+#endif
+
diff --git a/karbon/tools/vselecttool.cc b/karbon/tools/vselecttool.cc
new file mode 100644
index 00000000..19338038
--- /dev/null
+++ b/karbon/tools/vselecttool.cc
@@ -0,0 +1,613 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <math.h>
+#include <stdlib.h>
+
+#include <qcursor.h>
+#include <qlabel.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+
+#include <KoPoint.h>
+#include <KoRect.h>
+#include <kdebug.h>
+
+#include <karbon_part.h>
+#include <karbon_view.h>
+#include <render/vpainter.h>
+#include <render/vpainterfactory.h>
+#include <core/vselection.h>
+#include "vselecttool.h"
+#include <commands/vtransformcmd.h>
+#include <visitors/vselectiondesc.h>
+#include <visitors/vselectobjects.h>
+#include <widgets/vcanvas.h>
+
+VSelectOptionsWidget::VSelectOptionsWidget( KarbonPart *part )
+ : KDialogBase( 0L, "", true, i18n( "Selection" ), Ok | Cancel ), m_part( part )
+{
+ QButtonGroup *group = new QButtonGroup( 1, Qt::Horizontal, i18n( "Selection Mode" ), this );
+
+ new QRadioButton( i18n( "Select in current layer" ), group );
+ new QRadioButton( i18n( "Select in visible layers" ), group );
+ new QRadioButton( i18n( "Select in selected layers" ), group );
+
+ group->setRadioButtonExclusive( true );
+ group->setButton( part->document().selectionMode() );
+
+ connect( group, SIGNAL( clicked( int ) ), this, SLOT( modeChange( int ) ) );
+
+ group->setInsideMargin( 4 );
+ group->setInsideSpacing( 2 );
+
+ setMainWidget( group );
+ setFixedSize( baseSize() );
+} // VSelectOptionsWidget::VSelectOptionsWidget
+
+void VSelectOptionsWidget::modeChange( int mode )
+{
+ m_part->document().setSelectionMode( (VDocument::VSelectionMode)mode );
+} // VSelectOptionsWidget::modeChanged
+
+VSelectTool::VSelectTool( KarbonView *view )
+ : VTool( view, "tool_select" ), m_state( normal )
+{
+ m_lock = false;
+ m_add = true;
+ m_objects.setAutoDelete( true );
+ m_optionsWidget = new VSelectOptionsWidget( view->part() );
+ registerTool( this );
+ connect( view, SIGNAL( selectionChange() ), this, SLOT( updateStatusBar() ) );
+}
+
+VSelectTool::~VSelectTool()
+{
+ delete m_optionsWidget;
+}
+
+void
+VSelectTool::activate()
+{
+ VTool::activate();
+ view()->setCursor( QCursor( Qt::arrowCursor ) );
+ view()->part()->document().selection()->showHandle();
+ view()->part()->document().selection()->setSelectObjects();
+ view()->part()->document().selection()->setState( VObject::selected );
+ view()->part()->document().selection()->selectNodes();
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+ updateStatusBar();
+}
+
+QString
+VSelectTool::statusText()
+{
+ return i18n( "Select" );
+}
+
+QString VSelectTool::contextHelp()
+{
+ QString s = i18n( "<qt><b>Selection tool:</b><br>" );
+ s += i18n( "<i>Select in current layer:</i><br>The selection is made in the layer selected in the layers docker.<br><br>" );
+ s += i18n( "<i>Select in visible layers:</i><br>The selection is made in the visible layers (eye in the layers docker).<br><br>" );
+ s += i18n( "<i>Select in selected layers:</i><br>The selection is made in the checked layers in the layers docker.<br><br>" );
+ s += i18n( "<i>Position using arrow keys</i><br>The selection can be positioned up, down, left and right using the corresponding arrow keys." );
+ return s;
+} // VSelectTool::contextHelp
+
+void
+VSelectTool::draw()
+{
+ VPainter *painter = view()->painterFactory()->editpainter();
+ //painter->setZoomFactor( view()->zoom() );
+ painter->setRasterOp( Qt::NotROP );
+
+ KoRect rect = view()->part()->document().selection()->boundingBox();
+
+ if( m_state != normal )
+ {
+ VObjectListIterator itr = m_objects;
+ for( ; itr.current(); ++itr )
+ {
+ itr.current()->draw( painter, &itr.current()->boundingBox() );
+ }
+ }
+ else if( m_state == normal )
+ {
+ painter->setPen( Qt::DotLine );
+ painter->newPath();
+ painter->moveTo( KoPoint( first().x(), first().y() ) );
+ painter->lineTo( KoPoint( m_current.x(), first().y() ) );
+ painter->lineTo( KoPoint( m_current.x(), m_current.y() ) );
+ painter->lineTo( KoPoint( first().x(), m_current.y() ) );
+ painter->lineTo( KoPoint( first().x(), first().y() ) );
+ painter->strokePath();
+
+ m_state = normal;
+ }
+}
+
+void
+VSelectTool::setCursor() const
+{
+ if( m_state != normal || !view() ) return;
+ switch( view()->part()->document().selection()->handleNode( last() ) )
+ {
+ case node_lt:
+ case node_rb:
+ view()->setCursor( QCursor( Qt::SizeFDiagCursor ) );
+ break;
+ case node_rt:
+ case node_lb:
+ view()->setCursor( QCursor( Qt::SizeBDiagCursor ) );
+ break;
+ case node_lm:
+ case node_rm:
+ view()->setCursor( QCursor( Qt::SizeHorCursor ) );
+ break;
+ case node_mt:
+ case node_mb:
+ view()->setCursor( QCursor( Qt::SizeVerCursor ) );
+ break;
+ default:
+ view()->setCursor( QCursor( Qt::arrowCursor ) );
+ }
+}
+
+void
+VSelectTool::mouseButtonPress()
+{
+ // we are adding to the selection
+ m_add = true;
+
+ m_current = first();
+
+ m_activeNode = view()->part()->document().selection()->handleNode( first() );
+ KoRect rect = view()->part()->document().selection()->boundingBox();
+
+ if( m_activeNode != node_none )
+ m_state = scaling;
+ else if( rect.contains( m_current ) && m_state == normal )
+ m_state = moving;
+
+ recalc();
+
+ // undraw selection bounding box
+ view()->part()->document().selection()->setState( VObject::edit );
+ view()->repaintAll( rect );
+ view()->part()->document().selection()->setState( VObject::selected );
+
+ draw();
+}
+
+void
+VSelectTool::rightMouseButtonPress()
+{
+ // we are removing from the selection
+ m_add = false;
+
+ m_current = first();
+
+ recalc();
+
+ // undraw selection bounding box
+ view()->part()->document().selection()->setState( VObject::edit );
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+ view()->part()->document().selection()->setState( VObject::selected );
+
+ draw();
+}
+
+void
+VSelectTool::mouseDrag()
+{
+ draw();
+
+ recalc();
+
+ draw();
+}
+
+void
+VSelectTool::rightMouseButtonRelease()
+{
+ m_state = normal;
+ m_add = true;
+
+ if( ctrlPressed() )
+ {
+ // unselect the topmost object under the mouse cursor
+ VObjectList newSelection;
+ VSelectObjects selector( newSelection, first() );
+ if( selector.visit( view()->part()->document() ) )
+ view()->part()->document().selection()->take( *newSelection.last() );
+
+ view()->part()->repaintAllViews( view()->part()->document().selection()->boundingBox() );
+ view()->selectionChanged();
+
+ updateStatusBar();
+ }
+ else if( view()->part()->document().selection()->objects().count() > 0 )
+ {
+ view()->showSelectionPopupMenu( QCursor::pos() );
+ }
+}
+
+void
+VSelectTool::mouseButtonRelease()
+{
+ m_state = normal;
+ m_add = true;
+
+ // selection of next underlying object
+ if( shiftPressed() )
+ {
+ VObjectList newSelection;
+ VObjectList oldSelection = view()->part()->document().selection()->objects();
+
+ // clear selection if not in multi-slection-mode
+ if( ! ctrlPressed() )
+ view()->part()->document().selection()->clear();
+
+ // get a list of all object under the mouse cursor
+ VSelectObjects selector( newSelection, first(), true, true );
+ if( selector.visit( view()->part()->document() ) )
+ {
+ // determine the last selected object of the object stack
+ VObject *lastMatched = 0L;
+ VObjectListIterator it( newSelection );
+ for( ; it.current(); ++it )
+ {
+ if( oldSelection.contains( it.current() ) )
+ lastMatched = it.current();
+ }
+
+ // select the next underlying object or the first if:
+ // - none is selected
+ // - the stack's bottom object was the last selected object
+ if( lastMatched && lastMatched != newSelection.first() )
+ view()->part()->document().selection()->append( newSelection.at( newSelection.find( lastMatched )-1 ) );
+ else
+ view()->part()->document().selection()->append( newSelection.last() );
+ }
+ }
+ else
+ {
+ // clear selection if not in multi-slection-mode
+ if( ! ctrlPressed() )
+ view()->part()->document().selection()->clear();
+
+ // append the topmost object under the mouse cursor to the selection
+ VObjectList newSelection;
+ VSelectObjects selector( newSelection, first() );
+ if( selector.visit( view()->part()->document() ) )
+ view()->part()->document().selection()->append( newSelection.last() );
+ }
+
+ view()->part()->repaintAllViews( view()->part()->document().selection()->boundingBox() );
+ view()->selectionChanged();
+
+ updateStatusBar();
+}
+
+void
+VSelectTool::mouseDragRelease()
+{
+ if( m_state == normal )
+ {
+ // Y mirroring
+ KoPoint fp = first();
+ KoPoint lp = last();
+ if( ! ctrlPressed() )
+ view()->part()->document().selection()->clear();
+
+ KoRect selRect = KoRect( fp.x(), fp.y(), lp.x() - fp.x(), lp.y() - fp.y() ).normalize();
+ if( m_add )
+ view()->part()->document().selection()->append( selRect );
+ else
+ view()->part()->document().selection()->take( selRect );
+ view()->part()->repaintAllViews( selRect );
+ }
+ else if( m_state == moving )
+ {
+ m_state = normal;
+ recalc();
+ if( m_lock )
+ view()->part()->addCommand(
+ new VTranslateCmd(
+ &view()->part()->document(),
+ abs( int( m_distx ) ) >= abs( int( m_disty ) ) ? qRound( m_distx ) : 0,
+ abs( int( m_distx ) ) <= abs( int( m_disty ) ) ? qRound( m_disty ) : 0, altPressed() ),
+ true );
+ else
+ view()->part()->addCommand(
+ new VTranslateCmd( &view()->part()->document(), qRound( m_distx ), qRound( m_disty ), altPressed() ),
+ true );
+ }
+ else if( m_state == scaling )
+ {
+ m_state = normal;
+ view()->part()->addCommand(
+ new VScaleCmd( &view()->part()->document(), m_sp, m_s1, m_s2, altPressed() ),
+ true );
+ m_s1 = m_s2 = 1;
+ }
+
+ view()->selectionChanged();
+ m_lock = false;
+ updateStatusBar();
+}
+
+void
+VSelectTool::arrowKeyReleased( Qt::Key key )
+{
+ int dx = 0;
+ int dy = 0;
+ switch( key )
+ {
+ case Qt::Key_Up: dy = 10; break;
+ case Qt::Key_Down: dy = -10; break;
+ case Qt::Key_Right: dx = 10; break;
+ case Qt::Key_Left: dx = -10; break;
+ default: return;
+ }
+ m_state = normal;
+ view()->part()->addCommand(
+ new VTranslateCmd(
+ &view()->part()->document(),
+ dx, dy ),
+ true );
+ view()->selectionChanged();
+ updateStatusBar();
+}
+
+bool
+VSelectTool::keyReleased( Qt::Key key )
+{
+
+ VSelection* selection = view()->part()->document().selection();
+
+ switch( key )
+ {
+ // increase/decrease the handle size
+ case Qt::Key_I:
+ {
+ uint handleSize = selection->handleSize();
+ if( shiftPressed() )
+ selection->setHandleSize( ++handleSize );
+ else if( handleSize > 1 )
+ selection->setHandleSize( --handleSize );
+ }
+ break;
+ default: return false;
+ }
+
+ if( view() )
+ view()->repaintAll( selection->boundingBox() );
+
+ return true;
+}
+
+void
+VSelectTool::updateStatusBar() const
+{
+ if( ! view() )
+ return;
+
+ if( ! view()->part() )
+ return;
+
+ int objcount = view()->part()->document().selection()->objects().count();
+ if( objcount > 0 )
+ {
+ KoRect rect = view()->part()->document().selection()->boundingBox();
+
+ double x = KoUnit::toUserValue( rect.x(), view()->part()->unit() );
+ double y = KoUnit::toUserValue( rect.y(), view()->part()->unit() );
+ double r = KoUnit::toUserValue( rect.right(), view()->part()->unit() );
+ double b = KoUnit::toUserValue( rect.bottom(), view()->part()->unit() );
+
+ // print bottom-left (%1,%2), top-right (%3,%4) corner of selection bounding box and document unit (%5)
+ QString selectMessage = i18n( "[(left,bottom), (right,top)] (actual unit)", "Selection [(%1, %2), (%3, %4)] (%5)").arg( x, 0, 'f', 1 ).arg( y, 0, 'f', 1 ).arg( r, 0, 'f', 1 ).arg( b, 0, 'f', 1 ).arg( view()->part()->unitName() );
+
+ VSelectionDescription selectionDesc;
+ selectionDesc.visit( *view()->part()->document().selection() );
+ selectMessage += QString( "(%1)" ).arg( selectionDesc.description() );
+
+ view()->statusMessage()->setText( selectMessage );
+ }
+ else
+ view()->statusMessage()->setText( i18n( "No selection" ) );
+}
+
+void
+VSelectTool::mouseDragCtrlPressed()
+{
+ m_lock = true;
+}
+
+void
+VSelectTool::mouseDragCtrlReleased()
+{
+ m_lock = false;
+}
+
+void
+VSelectTool::mouseDragShiftPressed()
+{
+ draw();
+
+ recalc();
+
+ draw();
+}
+
+void
+VSelectTool::mouseDragShiftReleased()
+{
+ draw();
+
+ recalc();
+
+ draw();
+}
+
+void
+VSelectTool::cancel()
+{
+ // Erase old object:
+ if ( isDragging() )
+ {
+ draw();
+ m_state = normal;
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+ }
+}
+
+void
+VSelectTool::recalc()
+{
+ if( m_state == normal )
+ {
+ m_current = last();
+ }
+ else
+ {
+ VTransformCmd* cmd;
+ KoPoint _first = view()->canvasWidget()->snapToGrid( first() );
+ KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
+ KoRect rect = view()->part()->document().selection()->boundingBox();
+
+ if( m_state == moving )
+ {
+ KoPoint p( rect.x() + last().x() - first().x(), rect.bottom() + last().y() - first().y() );
+ p = view()->canvasWidget()->snapToGrid( p );
+ m_distx = p.x() - rect.x();
+ m_disty = p.y() - rect.bottom();
+ if( m_lock )
+ cmd = new VTranslateCmd( 0L, abs( int( m_distx ) ) >= abs( int( m_disty ) ) ? m_distx : 0,
+ abs( int( m_distx ) ) <= abs( int( m_disty ) ) ? m_disty : 0 );
+ else
+ cmd = new VTranslateCmd( 0L, m_distx, m_disty );
+ }
+ else
+ {
+ if( m_activeNode == node_lb )
+ {
+ m_sp = KoPoint( rect.right(), rect.bottom() );
+ m_s1 = ( rect.right() - _last.x() ) / double( rect.width() );
+ m_s2 = ( rect.bottom() - _last.y() ) / double( rect.height() );
+ }
+ else if( m_activeNode == node_mb )
+ {
+ m_sp = KoPoint( ( ( rect.right() + rect.left() ) / 2 ), rect.bottom() );
+ m_s1 = 1;
+ m_s2 = ( rect.bottom() - _last.y() ) / double( rect.height() );
+ }
+ else if( m_activeNode == node_rb )
+ {
+ m_sp = KoPoint( rect.x(), rect.bottom() );
+ m_s1 = ( _last.x() - rect.x() ) / double( rect.width() );
+ m_s2 = ( rect.bottom() - _last.y() ) / double( rect.height() );
+ }
+ else if( m_activeNode == node_rm)
+ {
+ m_sp = KoPoint( rect.x(), ( rect.bottom() + rect.top() ) / 2 );
+ m_s1 = ( _last.x() - rect.x() ) / double( rect.width() );
+ m_s2 = 1;
+ }
+ else if( m_activeNode == node_rt )
+ {
+ m_sp = KoPoint( rect.x(), rect.y() );
+ m_s1 = ( _last.x() - rect.x() ) / double( rect.width() );
+ m_s2 = ( _last.y() - rect.y() ) / double( rect.height() );
+ }
+ else if( m_activeNode == node_mt )
+ {
+ m_sp = KoPoint( ( ( rect.right() + rect.left() ) / 2 ), rect.y() );
+ m_s1 = 1;
+ m_s2 = ( _last.y() - rect.y() ) / double( rect.height() );
+ }
+ else if( m_activeNode == node_lt )
+ {
+ m_sp = KoPoint( rect.right(), rect.y() );
+ m_s1 = ( rect.right() - _last.x() ) / double( rect.width() );
+ m_s2 = ( _last.y() - rect.y() ) / double( rect.height() );
+ }
+ else if( m_activeNode == node_lm )
+ {
+ m_sp = KoPoint( rect.right(), ( rect.bottom() + rect.top() ) / 2 );
+ m_s1 = ( rect.right() - _last.x() ) / double( rect.width() );
+ m_s2 = 1;
+ }
+
+ if( shiftPressed() )
+ m_s1 = m_s2 = kMax( m_s1, m_s2 );
+ cmd = new VScaleCmd( 0L, m_sp, m_s1, m_s2 );
+ }
+
+ // Copy selected objects and transform:
+ m_objects.clear();
+ VObject* copy;
+
+ VObjectListIterator itr = view()->part()->document().selection()->objects();
+ for( ; itr.current() ; ++itr )
+ {
+ if( itr.current()->state() != VObject::deleted )
+ {
+ copy = itr.current()->clone();
+ copy->setState( VObject::edit );
+
+ cmd->visit( *copy );
+
+ m_objects.append( copy );
+ }
+ }
+
+ delete( cmd );
+ }
+}
+
+bool
+VSelectTool::showDialog() const
+{
+ return m_optionsWidget->exec() == QDialog::Accepted;
+}
+
+void
+VSelectTool::refreshUnit()
+{
+ updateStatusBar();
+}
+
+void
+VSelectTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ m_action = new KRadioAction( i18n( "Select Tool" ), "14_select", Qt::SHIFT+Qt::Key_H, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Select" ) );
+ m_action->setExclusiveGroup( "select" );
+ //m_ownAction = true;
+ }
+}
+
+#include "vselecttool.moc"
diff --git a/karbon/tools/vselecttool.h b/karbon/tools/vselecttool.h
new file mode 100644
index 00000000..3ef50cab
--- /dev/null
+++ b/karbon/tools/vselecttool.h
@@ -0,0 +1,110 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VSELECTTOOL_H__
+#define __VSELECTTOOL_H__
+
+#include <kdialogbase.h>
+#include <klocale.h>
+
+#include "vtool.h"
+
+class KarbonView;
+
+class VSelectOptionsWidget : public KDialogBase
+{
+Q_OBJECT
+
+public:
+ VSelectOptionsWidget( KarbonPart* part );
+
+public slots:
+ void modeChange( int mode );
+
+private:
+ KarbonPart* m_part;
+}; // VSelectOptionsWidget
+
+class VSelectTool : public VTool
+{
+Q_OBJECT
+
+public:
+ VSelectTool( KarbonView *view );
+ virtual ~VSelectTool();
+
+ virtual void setup(KActionCollection *collection);
+ virtual bool showDialog() const;
+ virtual QString uiname() { return i18n( "Select Tool" ); }
+ virtual enumToolType toolType() { return TOOL_SELECT; }
+ virtual QString statusText();
+ virtual uint priority() { return 0; }
+ virtual QString contextHelp();
+
+ virtual void refreshUnit();
+
+ virtual void activate();
+
+protected:
+ virtual void draw();
+
+ virtual void setCursor() const;
+
+ virtual void mouseButtonPress();
+ virtual void rightMouseButtonPress();
+ virtual void mouseButtonRelease();
+ virtual void rightMouseButtonRelease();
+ virtual void mouseDrag();
+ virtual void mouseDragRelease();
+ virtual void mouseDragCtrlPressed();
+ virtual void mouseDragCtrlReleased();
+ virtual void mouseDragShiftPressed();
+ virtual void mouseDragShiftReleased();
+ virtual void arrowKeyReleased( Qt::Key );
+ virtual bool keyReleased( Qt::Key );
+
+ virtual void cancel();
+
+protected slots:
+ void updateStatusBar() const;
+
+private:
+ enum { normal, moving, scaling, rotating } m_state;
+ bool m_lock;
+ // controls if objects are added to or removed from the selection
+ bool m_add;
+ double m_s1;
+ double m_s2;
+ double m_distx;
+ double m_disty;
+ KoPoint m_sp;
+ KoPoint m_current;
+
+ VHandleNode m_activeNode;
+
+ void recalc();
+
+ // A list of temporary objects:
+ VObjectList m_objects;
+ // The options widget.
+ VSelectOptionsWidget *m_optionsWidget;
+};
+
+#endif
+
diff --git a/karbon/tools/vshapetool.cc b/karbon/tools/vshapetool.cc
new file mode 100644
index 00000000..5ec04084
--- /dev/null
+++ b/karbon/tools/vshapetool.cc
@@ -0,0 +1,274 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <qcursor.h>
+#include <qevent.h>
+#include <qlabel.h>
+
+#include "karbon_part.h"
+#include "karbon_view.h"
+#include "vcanvas.h"
+#include "vcomposite.h"
+#include "vglobal.h"
+#include "vpainter.h"
+#include "vpainterfactory.h"
+#include "vshapecmd.h"
+#include "vshapetool.h"
+#include "vselection.h"
+#include "vcursor.h"
+
+VShapeTool::VShapeTool( KarbonView *view, const char *name, bool polar )
+ : VTool( view, name )
+{
+ m_cursor = new QCursor( VCursor::createCursor( VCursor::CrossHair ) );
+
+ m_isPolar = polar;
+ m_isSquare = false;
+ m_isCentered = false;
+}
+
+VShapeTool::~VShapeTool()
+{
+ delete m_cursor;
+}
+
+QString
+VShapeTool::contextHelp()
+{
+ QString s = i18n( "<qt><b>Shape tool</b><br>" );
+ s += i18n( "<i>Click and drag</i> to place your own shape.<br>" );
+ s += i18n( "<i>Click</i> to place a shape using the tool properties values.</qt>" );
+ return s;
+}
+
+void
+VShapeTool::activate()
+{
+ VTool::activate();
+ view()->setCursor( *m_cursor );
+ view()->part()->document().selection()->showHandle( true );
+}
+
+QString
+VShapeTool::statusText()
+{
+ return uiname();
+}
+
+void
+VShapeTool::draw()
+{
+ VPainter* painter = view()->painterFactory()->editpainter();
+ painter->setRasterOp( Qt::NotROP );
+
+ VPath* composite = shape();
+ composite->setState( VPath::edit );
+ composite->draw( painter, &composite->boundingBox() );
+ delete( composite );
+}
+
+void
+VShapeTool::mouseButtonPress()
+{
+ recalc();
+
+ // Draw new object:
+ draw();
+}
+
+void
+VShapeTool::mouseButtonRelease()
+{
+ draw();
+
+ recalc();
+
+ if( showDialog() )
+ {
+ VPath* composite = shape( true );
+
+ if( composite )
+ {
+ VShapeCmd* cmd = new VShapeCmd(
+ &view()->part()->document(),
+ uiname(), composite, icon() );
+
+ view()->part()->addCommand( cmd, true );
+ }
+ }
+
+ m_isSquare = false;
+ m_isCentered = false;
+}
+
+void
+VShapeTool::mouseDrag()
+{
+ // Erase old object:
+ draw();
+
+ recalc();
+
+ // Draw new object:
+ draw();
+}
+
+void
+VShapeTool::mouseDragRelease()
+{
+ //recalc();
+
+ VShapeCmd* cmd = new VShapeCmd(
+ &view()->part()->document(),
+ uiname(), shape(), icon() );
+
+ view()->part()->addCommand( cmd, true );
+
+ m_isSquare = false;
+ m_isCentered = false;
+}
+
+void
+VShapeTool::mouseDragShiftPressed()
+{
+ // Erase old object:
+ draw();
+
+ m_isSquare = true;
+ recalc();
+
+ // Draw new object:
+ draw();
+}
+
+void
+VShapeTool::mouseDragCtrlPressed()
+{
+ // Erase old object:
+ draw();
+
+ m_isCentered = true;
+ recalc();
+
+ // Draw new object:
+ draw();
+}
+
+void
+VShapeTool::mouseDragShiftReleased()
+{
+ // Erase old object:
+ draw();
+
+ m_isSquare = false;
+ recalc();
+
+ // Draw new object:
+ draw();
+}
+
+void
+VShapeTool::mouseDragCtrlReleased()
+{
+ // Erase old object:
+ draw();
+
+ m_isCentered = false;
+ recalc();
+
+ // Draw new object:
+ draw();
+}
+
+void
+VShapeTool::cancel()
+{
+ // Erase old object:
+ if ( isDragging() )
+ {
+ draw();
+ m_isSquare = false;
+ m_isCentered = false;
+ }
+}
+
+void
+VShapeTool::recalc()
+{
+ m_isSquare = shiftPressed();
+ m_isCentered = ctrlPressed();
+
+ KoPoint _first = view()->canvasWidget()->snapToGrid( first() );
+ KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
+
+ // Calculate radius and angle:
+ if( m_isPolar )
+ {
+ // Radius:
+ m_d1 = sqrt(
+ ( _last.x() - _first.x() ) * ( _last.x() - _first.x() ) +
+ ( _last.y() - _first.y() ) * ( _last.y() - _first.y() ) );
+
+ // Angle:
+ m_d2 = atan2( _last.y() - _first.y(), _last.x() - _first.x() );
+
+ // Define pi/2 as "0.0":
+ m_d2 -= VGlobal::pi_2;
+
+ m_p = _first;
+ }
+ else
+ // Calculate width and height:
+ {
+ m_d1 = _last.x() - _first.x();
+ m_d2 = _last.y() - _first.y();
+
+ const int m_sign1 = VGlobal::sign( m_d1 );
+// TODO: revert when we introduce y-mirroring:
+ const int m_sign2 = VGlobal::sign( -m_d2 );
+
+ // Make unsigned:
+ if( m_d1 < 0.0 )
+ m_d1 = -m_d1;
+
+ if( m_d2 < 0.0 )
+ m_d2 = -m_d2;
+
+ if ( m_isSquare )
+ {
+ if ( m_d1 > m_d2 )
+ m_d2 = m_d1;
+ else
+ m_d1 = m_d2;
+ }
+
+ m_p.setX(
+ _first.x() - ( m_sign1 == -1 ? m_d1 : 0.0 ) );
+// TODO: revert when we introduce y-mirroring:
+ m_p.setY(
+ _first.y() + ( m_sign2 == -1 ? m_d2 : 0.0 ) );
+
+ if ( m_isCentered )
+ {
+ m_p.setX( m_p.x() - m_sign1 * qRound( m_d1 * 0.5 ) );
+ m_p.setY( m_p.y() + m_sign2 * qRound( m_d2 * 0.5 ) );
+ }
+ }
+}
+
diff --git a/karbon/tools/vshapetool.h b/karbon/tools/vshapetool.h
new file mode 100644
index 00000000..48cfa4c7
--- /dev/null
+++ b/karbon/tools/vshapetool.h
@@ -0,0 +1,83 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VSHAPETOOL_H__
+#define __VSHAPETOOL_H__
+
+#include <qstring.h>
+
+#include <KoPoint.h>
+
+#include "vtool.h"
+
+
+class VPath;
+class VCursor;
+
+class VShapeTool : public VTool
+{
+public:
+ VShapeTool( KarbonView *view, const char *name, bool polar = false );
+
+ virtual enumToolType toolType() { return TOOL_SHAPE; }
+ virtual QString statusText();
+ virtual QString contextHelp();
+
+ virtual void activate();
+
+protected:
+ virtual void draw();
+
+ virtual void mouseButtonPress();
+ virtual void mouseButtonRelease();
+ virtual void mouseDrag();
+ virtual void mouseDragRelease();
+ virtual void mouseDragShiftPressed();
+ virtual void mouseDragCtrlPressed();
+ virtual void mouseDragShiftReleased();
+ virtual void mouseDragCtrlReleased();
+
+ virtual void cancel();
+
+ // Make it "abstract":
+ virtual ~VShapeTool();
+
+ virtual VPath* shape( bool interactive = false ) const = 0;
+
+ /**
+ * Output coordinates.
+ */
+ KoPoint m_p;
+ double m_d1;
+ double m_d2;
+
+private:
+ void recalc();
+
+ /// Calculate width/height or radius/angle?
+ bool m_isPolar;
+
+ /// States:
+ bool m_isSquare;
+ bool m_isCentered;
+
+ QCursor* m_cursor;
+};
+
+#endif
diff --git a/karbon/tools/vsheartool.cc b/karbon/tools/vsheartool.cc
new file mode 100644
index 00000000..e38336b1
--- /dev/null
+++ b/karbon/tools/vsheartool.cc
@@ -0,0 +1,219 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <math.h>
+
+#include <qcursor.h>
+#include <qlabel.h>
+
+#include <klocale.h>
+#include <KoRect.h>
+
+#include <karbon_part.h>
+#include <karbon_view.h>
+#include <render/vpainter.h>
+#include <render/vpainterfactory.h>
+#include <vselection.h>
+#include "vsheartool.h"
+#include <commands/vtransformcmd.h>
+
+VShearTool::VShearTool( KarbonView *view ) : VTool( view, "sheartool" )
+{
+ setName( "tool_shear" );
+ m_objects.setAutoDelete( true );
+ registerTool( this );
+}
+
+VShearTool::~VShearTool()
+{
+}
+
+void
+VShearTool::activate()
+{
+ view()->setCursor( QCursor( Qt::arrowCursor ) );
+ view()->part()->document().selection()->showHandle( true );
+ view()->part()->document().selection()->setState( VObject::selected );
+ VTool::activate();
+}
+
+QString
+VShearTool::statusText()
+{
+ return i18n( "Shear" );
+}
+
+void
+VShearTool::draw()
+{
+ VPainter* painter = view()->painterFactory()->editpainter();
+ painter->setRasterOp( Qt::NotROP );
+
+ VObjectListIterator itr = m_objects;
+ for( ; itr.current(); ++itr )
+ itr.current()->draw( painter, &itr.current()->boundingBox() );
+}
+
+void
+VShearTool::setCursor() const
+{
+ if( isDragging() ) return;
+ switch( view()->part()->document().selection()->handleNode( last() ) )
+ {
+ case node_lt:
+ case node_rb:
+ view()->setCursor( QCursor( Qt::SizeFDiagCursor ) );
+ break;
+ case node_rt:
+ case node_lb:
+ view()->setCursor( QCursor( Qt::SizeBDiagCursor ) );
+ break;
+ case node_lm:
+ case node_rm:
+ view()->setCursor( QCursor( Qt::SizeHorCursor ) );
+ break;
+ case node_mt:
+ case node_mb:
+ view()->setCursor( QCursor( Qt::SizeVerCursor ) );
+ break;
+ default:
+ view()->setCursor( QCursor( Qt::arrowCursor ) );
+ }
+}
+
+void
+VShearTool::mouseButtonPress()
+{
+ view()->painterFactory()->painter()->end();
+ m_activeNode = view()->part()->document().selection()->handleNode( first() );
+ recalc();
+
+ // Draw new object:
+ draw();
+}
+
+void
+VShearTool::mouseDrag( )
+{
+ // Erase old object:
+ draw();
+
+ recalc();
+
+ // Draw new object:
+ draw();
+}
+
+
+void
+VShearTool::mouseDragRelease()
+{
+ view()->part()->addCommand(
+ new VShearCmd( &view()->part()->document(), m_center, m_s1, m_s2, altPressed() ),
+ true );
+}
+
+void
+VShearTool::cancel()
+{
+ // Erase old object:
+ if ( isDragging() )
+ {
+ draw();
+ view()->repaintAll( view()->part()->document().selection()->boundingBox() );
+ }
+}
+
+void
+VShearTool::recalc()
+{
+ KoRect rect = view()->part()->document().selection()->boundingBox();
+
+ if( m_activeNode == node_lt )
+ {
+ }
+ else if( m_activeNode == node_mt )
+ {
+ m_s1 = 0;
+ m_s2 = ( last().y() - first().y() ) / double( ( rect.height() / 2 ) );
+ }
+ else if( m_activeNode == node_rt )
+ {
+ }
+ else if( m_activeNode == node_rm)
+ {
+ m_s1 = ( last().x() - first().x() ) / double( ( rect.width() / 2 ) );
+ m_s2 = 0;
+ }
+ else if( m_activeNode == node_rb )
+ {
+ }
+ else if( m_activeNode == node_mb )
+ {
+ m_s1 = 0;
+ m_s2 = ( last().y() - first().y() ) / double( ( rect.height() / 2 ) );
+ }
+ else if( m_activeNode == node_lb )
+ {
+ }
+ else if( m_activeNode == node_lm )
+ {
+ m_s1 = ( last().x() - first().x() ) / double( ( rect.width() / 2 ) );
+ m_s2 = 0;
+ }
+
+ // Get center:
+ m_center = view()->part()->document().selection()->boundingBox().center();
+
+ VShearCmd cmd( 0L, m_center, m_s1, m_s2 );
+
+ // Copy selected objects and transform:
+ m_objects.clear();
+ VObject* copy;
+
+ VObjectListIterator itr = view()->part()->document().selection()->objects();
+ for ( ; itr.current() ; ++itr )
+ {
+ if( itr.current()->state() != VObject::deleted )
+ {
+ copy = itr.current()->clone();
+
+ cmd.visit( *copy );
+
+ copy->setState( VObject::edit );
+
+ m_objects.append( copy );
+ }
+ }
+}
+
+void
+VShearTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ m_action = new KRadioAction( i18n( "Shear Tool" ), "14_shear", Qt::SHIFT+Qt::Key_H, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Shear" ) );
+ m_action->setExclusiveGroup( "manipulation" );
+ //m_ownAction = true;
+ }
+}
+
diff --git a/karbon/tools/vsheartool.h b/karbon/tools/vsheartool.h
new file mode 100644
index 00000000..eb3be26c
--- /dev/null
+++ b/karbon/tools/vsheartool.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VSHEARTOOL_H__
+#define __VSHEARTOOL_H__
+
+#include "vtool.h"
+
+class VShearTool : public VTool
+{
+public:
+ VShearTool( KarbonView *view );
+ virtual ~VShearTool();
+
+ virtual void activate();
+
+ virtual void setup(KActionCollection *collection);
+ virtual QString uiname() { return i18n( "Shear Tool" ); }
+ virtual enumToolType toolType() { return TOOL_MANIPULATION; }
+ virtual uint priority() { return 1; }
+ virtual QString statusText();
+
+protected:
+ virtual void draw();
+
+ virtual void setCursor() const;
+ virtual void mouseButtonPress();
+ virtual void mouseDrag();
+ virtual void mouseDragRelease();
+
+ virtual void cancel();
+
+private:
+ void recalc();
+
+ KoPoint m_center;
+ double m_s1, m_s2;
+
+ VHandleNode m_activeNode;
+
+ // A list of temporary objects:
+ VObjectList m_objects;
+};
+
+#endif
+
diff --git a/karbon/tools/vsinustool.cc b/karbon/tools/vsinustool.cc
new file mode 100644
index 00000000..056b88c9
--- /dev/null
+++ b/karbon/tools/vsinustool.cc
@@ -0,0 +1,162 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+
+#include <karbon_view.h>
+#include <karbon_part.h>
+#include <shapes/vsinus.h>
+#include "vsinustool.h"
+#include "KoUnitWidgets.h"
+
+
+VSinusTool::VSinusOptionsWidget::VSinusOptionsWidget( KarbonPart *part, QWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, i18n( "Insert Sinus" ), Ok | Cancel ), m_part( part )
+{
+ QGroupBox *group = new QGroupBox( 2, Qt::Horizontal, i18n( "Properties" ), this );
+
+ // add width/height-input:
+ m_widthLabel = new QLabel( i18n( "object width", "Width:" ), group );
+ m_width = new KoUnitDoubleSpinBox( group, 0.0, 1000.0, 0.5, 100.0, KoUnit::U_MM );
+ m_heightLabel = new QLabel( i18n( "Height:" ), group );
+ m_height = new KoUnitDoubleSpinBox( group, 0.0, 1000.0, 0.5, 100.0, KoUnit::U_MM );
+
+ refreshUnit();
+
+ new QLabel( i18n( "Periods:" ), group );
+ m_periods = new KIntSpinBox( group );
+ m_periods->setMinValue( 1 );
+
+ group->setInsideMargin( 4 );
+ group->setInsideSpacing( 2 );
+
+ setMainWidget( group );
+ setFixedSize( baseSize() );
+}
+
+double
+VSinusTool::VSinusOptionsWidget::width() const
+{
+ return m_width->value();
+}
+
+double
+VSinusTool::VSinusOptionsWidget::height() const
+{
+ return m_height->value();
+}
+
+uint
+VSinusTool::VSinusOptionsWidget::periods() const
+{
+ return m_periods->value();
+}
+
+void
+VSinusTool::VSinusOptionsWidget::setWidth( double value )
+{
+ m_width->changeValue( value );
+}
+
+void
+VSinusTool::VSinusOptionsWidget::setHeight( double value )
+{
+ m_height->changeValue( value );
+}
+
+void
+VSinusTool::VSinusOptionsWidget::setPeriods( uint value )
+{
+ m_periods->setValue( value );
+}
+
+void
+VSinusTool::VSinusOptionsWidget::refreshUnit ()
+{
+ m_width->setUnit( m_part->unit() );
+ m_height->setUnit( m_part->unit() );
+}
+
+VSinusTool::VSinusTool( KarbonView *view )
+ : VShapeTool( view, "tool_sinus" )
+{
+ // create config widget:
+ m_optionsWidget = new VSinusOptionsWidget( view->part() );
+ m_optionsWidget->setPeriods( 1 );
+ registerTool( this );
+}
+
+VSinusTool::~VSinusTool()
+{
+ delete( m_optionsWidget );
+}
+
+void
+VSinusTool::refreshUnit()
+{
+ m_optionsWidget->refreshUnit();
+}
+
+VPath*
+VSinusTool::shape( bool interactive ) const
+{
+ if( interactive )
+ return
+ new VSinus(
+ 0L,
+ m_p,
+ m_optionsWidget->width(),
+ m_optionsWidget->height(),
+ m_optionsWidget->periods() );
+ else
+ return
+ new VSinus(
+ 0L,
+ m_p,
+ m_d1,
+ m_d2,
+ m_optionsWidget->periods() );
+}
+
+bool
+VSinusTool::showDialog() const
+{
+ return m_optionsWidget->exec() == QDialog::Accepted;
+}
+
+void
+VSinusTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ m_action = new KRadioAction( i18n( "Sinus Tool" ), "14_sinus", Qt::SHIFT+Qt::Key_S, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Sinus" ) );
+ m_action->setExclusiveGroup( "shapes" );
+ //m_ownAction = true;
+ }
+}
+
diff --git a/karbon/tools/vsinustool.h b/karbon/tools/vsinustool.h
new file mode 100644
index 00000000..6fcfd45c
--- /dev/null
+++ b/karbon/tools/vsinustool.h
@@ -0,0 +1,72 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VSINUSTOOL_H__
+#define __VSINUSTOOL_H__
+
+#include <kdialogbase.h>
+#include "vshapetool.h"
+
+class KoUnitDoubleSpinBox;
+class KIntSpinBox;
+class KarbonView;
+class QLabel;
+
+class VSinusTool : public VShapeTool
+{
+public:
+ VSinusTool( KarbonView *view );
+ virtual ~VSinusTool();
+
+ virtual void setup(KActionCollection *collection);
+ virtual bool showDialog() const;
+ virtual QString uiname() { return i18n( "Sinus Tool" ); }
+
+ virtual VPath *shape( bool interactive = false ) const;
+
+ void refreshUnit();
+
+private:
+ class VSinusOptionsWidget : public KDialogBase
+ {
+ public:
+ VSinusOptionsWidget( KarbonPart *part, QWidget *parent = 0L, const char *name = 0L );
+
+ double width() const;
+ double height() const;
+ uint periods() const;
+ void setWidth( double value );
+ void setHeight( double value );
+ void setPeriods( uint value );
+ void refreshUnit();
+
+ private:
+ KoUnitDoubleSpinBox *m_width;
+ KoUnitDoubleSpinBox *m_height;
+ KIntSpinBox *m_periods;
+ KarbonPart *m_part;
+ QLabel *m_heightLabel;
+ QLabel *m_widthLabel;
+ };
+
+ VSinusOptionsWidget *m_optionsWidget;
+};
+
+#endif
+
diff --git a/karbon/tools/vspiraltool.cc b/karbon/tools/vspiraltool.cc
new file mode 100644
index 00000000..f4c3fff6
--- /dev/null
+++ b/karbon/tools/vspiraltool.cc
@@ -0,0 +1,213 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <qlabel.h>
+#include <qgroupbox.h>
+
+#include <klocale.h>
+#include <kcombobox.h>
+#include <knuminput.h>
+
+#include <karbon_view.h>
+#include <karbon_part.h>
+#include <shapes/vspiral.h>
+#include "vspiraltool.h"
+#include "KoUnitWidgets.h"
+
+
+VSpiralTool::VSpiralOptionsWidget::VSpiralOptionsWidget( KarbonPart *part, QWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, i18n( "Insert Spiral" ), Ok | Cancel ), m_part( part )
+{
+ QGroupBox *group = new QGroupBox( 2, Qt::Horizontal, i18n( "Properties" ), this );
+
+ new QLabel( i18n( "Type:" ), group );
+ m_type = new KComboBox( false, group );
+ m_type->insertItem( i18n( "Round" ), 0 );
+ m_type->insertItem( i18n( "Rectangular" ), 1 );
+
+ new QLabel( i18n( "Radius:" ), group );
+ m_radius = new KoUnitDoubleSpinBox( group, 0.0, 1000.0, 0.5, 50.0, KoUnit::U_MM );
+ refreshUnit();
+ new QLabel( i18n( "Segments:" ), group );
+ m_segments = new KIntSpinBox( group );
+ m_segments->setMinValue( 1 );
+ new QLabel( i18n( "Fade:" ), group );
+ m_fade = new KDoubleNumInput( group );
+ m_fade->setRange( 0.0, 1.0, 0.05 );
+
+ new QLabel( i18n( "Orientation:" ), group );
+ m_clockwise = new KComboBox( false, group );
+ m_clockwise->insertItem( i18n( "Clockwise" ), 0 );
+ m_clockwise->insertItem( i18n( "Counter Clockwise" ), 1 );
+
+ group->setInsideMargin( 4 );
+ group->setInsideSpacing( 2 );
+
+ setMainWidget( group );
+ //setFixedSize( baseSize() );
+}
+
+double
+VSpiralTool::VSpiralOptionsWidget::radius() const
+{
+ return m_radius->value();
+}
+
+uint
+VSpiralTool::VSpiralOptionsWidget::segments() const
+{
+ return m_segments->value();
+}
+
+double
+VSpiralTool::VSpiralOptionsWidget::fade() const
+{
+ return m_fade->value();
+}
+
+bool
+VSpiralTool::VSpiralOptionsWidget::clockwise() const
+{
+ return m_clockwise->currentItem() == 0;
+}
+
+uint
+VSpiralTool::VSpiralOptionsWidget::type() const
+{
+ return m_type->currentItem();
+}
+
+void
+VSpiralTool::VSpiralOptionsWidget::setRadius( double value )
+{
+ m_radius->changeValue( value );
+}
+
+void
+VSpiralTool::VSpiralOptionsWidget::setSegments( uint value )
+{
+ m_segments->setValue( value );
+}
+
+void
+VSpiralTool::VSpiralOptionsWidget::setFade( double value )
+{
+ m_fade->setValue( value );
+}
+
+void
+VSpiralTool::VSpiralOptionsWidget::setClockwise( bool value )
+{
+ m_clockwise->setCurrentItem( value ? 0 : 1 );
+}
+
+void
+VSpiralTool::VSpiralOptionsWidget::refreshUnit()
+{
+ m_radius->setUnit( m_part->unit() );
+}
+
+VSpiralTool::VSpiralTool( KarbonView *view )
+ : VShapeTool( view, "tool_spiral", true )
+{
+ // create config dialog:
+ m_optionsWidget = new VSpiralOptionsWidget( view->part() );
+ m_optionsWidget->setSegments( 8 );
+ m_optionsWidget->setFade( 0.8 );
+ m_optionsWidget->setClockwise( true );
+ registerTool( this );
+}
+
+void
+VSpiralTool::arrowKeyReleased( Qt::Key key )
+{
+ int change = 0;
+ if( key == Qt::Key_Up )
+ change = 1;
+ else if( key == Qt::Key_Down )
+ change = -1;
+
+ if( change != 0 )
+ {
+ draw();
+
+ m_optionsWidget->setSegments( m_optionsWidget->segments() + change );
+
+ draw();
+ }
+}
+
+VSpiralTool::~VSpiralTool()
+{
+ delete( m_optionsWidget );
+}
+
+void
+VSpiralTool::refreshUnit()
+{
+ m_optionsWidget->refreshUnit();
+}
+
+VPath*
+VSpiralTool::shape( bool interactive ) const
+{
+ if( interactive )
+ {
+ return
+ new VSpiral(
+ 0L,
+ m_p,
+ m_optionsWidget->radius(),
+ m_optionsWidget->segments(),
+ m_optionsWidget->fade(),
+ m_optionsWidget->clockwise(),
+ m_d2, (VSpiral::VSpiralType)m_optionsWidget->type() );
+ }
+ else
+ return
+ new VSpiral(
+ 0L,
+ m_p,
+ m_d1,
+ m_optionsWidget->segments(),
+ m_optionsWidget->fade(),
+ m_optionsWidget->clockwise(),
+ m_d2, (VSpiral::VSpiralType)m_optionsWidget->type() );
+}
+
+bool
+VSpiralTool::showDialog() const
+{
+ return m_optionsWidget->exec() == QDialog::Accepted;
+}
+
+void
+VSpiralTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ m_action = new KRadioAction( i18n( "Spiral Tool" ), "14_spiral", Qt::SHIFT+Qt::Key_H, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Spiral" ) );
+ m_action->setExclusiveGroup( "shapes" );
+ //m_ownAction = true;
+ }
+}
+
diff --git a/karbon/tools/vspiraltool.h b/karbon/tools/vspiraltool.h
new file mode 100644
index 00000000..2976deda
--- /dev/null
+++ b/karbon/tools/vspiraltool.h
@@ -0,0 +1,81 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VSPIRALTOOL_H__
+#define __VSPIRALTOOL_H__
+
+#include <kdialogbase.h>
+#include <klocale.h>
+
+#include "vshapetool.h"
+
+class KComboBox;
+class KoUnitDoubleSpinBox;
+class KDoubleNumInput;
+class KIntSpinBox;
+class KarbonView;
+
+class VSpiralTool : public VShapeTool
+{
+public:
+ VSpiralTool( KarbonView *view );
+ virtual ~VSpiralTool();
+
+ virtual void setup(KActionCollection *collection);
+ virtual bool showDialog() const;
+ virtual QString uiname() { return i18n( "Spiral Tool" ); }
+
+ virtual VPath* shape( bool interactive = false ) const;
+
+ void refreshUnit();
+
+ virtual void arrowKeyReleased( Qt::Key );
+
+private:
+ class VSpiralOptionsWidget : public KDialogBase
+ {
+ public:
+ VSpiralOptionsWidget( KarbonPart *part, QWidget *parent = 0L, const char* name = 0L );
+
+ double radius() const;
+ uint segments() const;
+ double fade() const;
+ uint type() const;
+ bool clockwise() const;
+ void setRadius( double value );
+ void setSegments( uint value );
+ void setFade( double value );
+ void setClockwise( bool value );
+
+ void refreshUnit();
+
+ private:
+ KoUnitDoubleSpinBox *m_radius;
+ KIntSpinBox *m_segments;
+ KDoubleNumInput *m_fade;
+ KComboBox *m_type;
+ KComboBox *m_clockwise;
+ KarbonPart *m_part;
+ };
+
+ VSpiralOptionsWidget *m_optionsWidget;
+};
+
+#endif
+
diff --git a/karbon/tools/vstartool.cc b/karbon/tools/vstartool.cc
new file mode 100644
index 00000000..612a0bce
--- /dev/null
+++ b/karbon/tools/vstartool.cc
@@ -0,0 +1,249 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <qlabel.h>
+#include <qgroupbox.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+#include <kcombobox.h>
+
+#include <karbon_view.h>
+#include <karbon_part.h>
+#include <shapes/vstar.h>
+#include "vstartool.h"
+#include "KoUnitWidgets.h"
+
+
+VStarOptionsWidget::VStarOptionsWidget( KarbonPart *part, QWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, i18n( "Insert Star" ), Ok | Cancel ), m_part( part )
+{
+ QGroupBox *group = new QGroupBox( 2, Qt::Horizontal, i18n( "Properties" ), this );
+ new QLabel( i18n( "Type:" ), group );
+ m_type = new KComboBox( false, group );
+ m_type->insertItem( i18n( "Star Outline" ), VStar::star_outline );
+ m_type->insertItem( i18n( "Spoke" ), VStar::spoke );
+ m_type->insertItem( i18n( "Wheel" ), VStar::wheel );
+ m_type->insertItem( i18n( "Polygon" ), VStar::polygon );
+ m_type->insertItem( i18n( "Framed Star" ), VStar::framed_star);
+ m_type->insertItem( i18n( "Star" ), VStar::star );
+ m_type->insertItem( i18n( "Gear" ), VStar::gear );
+ connect( m_type, SIGNAL( activated( int ) ), this, SLOT( typeChanged( int ) ) );
+
+ // add width/height-input:
+ m_outerRLabel = new QLabel( i18n( "Outer radius:" ), group );
+ m_outerR = new KoUnitDoubleSpinBox( group, 0.0, 1000.0, 0.5, 50.0, KoUnit::U_MM );
+ connect( m_outerR, SIGNAL( valueChanged( double ) ), this, SLOT( setOuterRadius( double ) ) );
+
+ m_innerRLabel = new QLabel( i18n( "Inner radius:" ), group );
+ m_innerR = new KoUnitDoubleSpinBox( group, 0.0, 1000.0, 0.5, 25.0, KoUnit::U_MM );
+
+ refreshUnit();
+
+ new QLabel( i18n( "Edges:" ), group );
+ m_edges = new KIntSpinBox( group );
+ m_edges->setMinValue( 3 );
+ connect( m_edges, SIGNAL( valueChanged( int ) ), this, SLOT( setEdges( int ) ) );
+
+ new QLabel( i18n( "Inner angle:" ), group );
+ m_innerAngle = new KIntSpinBox( group );
+ m_innerAngle->setMinValue( 0 );
+ m_innerAngle->setMaxValue( 360 );
+
+ new QLabel( i18n( "Roundness:" ), group );
+ m_roundness = new KDoubleNumInput( group );
+ m_roundness->setRange( 0.0, 1.0, 0.05 );
+
+ typeChanged( VStar::star_outline );
+
+ group->setInsideMargin( 4 );
+ group->setInsideSpacing( 2 );
+
+ setMainWidget( group );
+ setFixedSize( baseSize() );
+}
+
+void
+VStarOptionsWidget::refreshUnit()
+{
+ m_outerR->setUnit( m_part->unit() );
+ m_innerR->setUnit( m_part->unit() );
+}
+
+void
+VStarOptionsWidget::setEdges( int v )
+{
+ m_edges->setValue( v );
+
+ // set optimal inner radius
+ if( type() == VStar::star )
+ m_innerR->setValue( VStar::getOptimalInnerRadius( edges(), outerRadius(), innerAngle() ) );
+}
+
+void
+VStarOptionsWidget::setInnerRadius( double v )
+{
+ m_innerR->changeValue( v );
+}
+
+void
+VStarOptionsWidget::setOuterRadius( double v )
+{
+ m_outerR->setValue( v );
+
+ // set optimal inner radius
+ if( type() == VStar::star )
+ m_innerR->setValue( VStar::getOptimalInnerRadius( edges(), outerRadius(), innerAngle() ) );
+}
+
+double
+VStarOptionsWidget::roundness() const
+{
+ return m_roundness->value();
+}
+
+int
+VStarOptionsWidget::edges() const
+{
+ return m_edges->value();
+}
+
+double
+VStarOptionsWidget::innerRadius() const
+{
+ return m_innerR->value();
+}
+
+double
+VStarOptionsWidget::outerRadius() const
+{
+ return m_outerR->value();
+}
+
+uint
+VStarOptionsWidget::type() const
+{
+ return m_type->currentItem();
+}
+
+uint
+VStarOptionsWidget::innerAngle() const
+{
+ return m_innerAngle->value();
+}
+
+void
+VStarOptionsWidget::typeChanged( int type )
+{
+ m_innerR->setEnabled( type == VStar::star || type == VStar::star_outline || type == VStar::framed_star || type == VStar::gear );
+ m_innerAngle->setEnabled( type == VStar::star || type == VStar::star_outline || type == VStar::framed_star || type == VStar::gear );
+
+ // set optimal inner radius
+ if( type == VStar::star )
+ m_innerR->changeValue( VStar::getOptimalInnerRadius( edges(), outerRadius(), innerAngle() ) );
+}
+
+VStarTool::VStarTool( KarbonView *view )
+ : VShapeTool( view, "tool_star", true )
+{
+ // create config dialog:
+ m_optionsWidget = new VStarOptionsWidget( view->part() );
+ m_optionsWidget->setEdges( 5 );
+ registerTool( this );
+}
+
+void VStarTool::refreshUnit()
+{
+ m_optionsWidget->refreshUnit();
+}
+
+VStarTool::~VStarTool()
+{
+ delete( m_optionsWidget );
+}
+
+void
+VStarTool::arrowKeyReleased( Qt::Key key )
+{
+ int change = 0;
+ if( key == Qt::Key_Up )
+ change = 1;
+ else if( key == Qt::Key_Down )
+ change = -1;
+
+ if( change != 0 )
+ {
+ draw();
+
+ m_optionsWidget->setEdges( m_optionsWidget->edges() + change );
+
+ draw();
+ }
+}
+
+VPath*
+VStarTool::shape( bool interactive ) const
+{
+ if( interactive )
+ {
+ return
+ new VStar(
+ 0L,
+ m_p,
+ m_optionsWidget->outerRadius(),
+ m_optionsWidget->innerRadius(),
+ m_optionsWidget->edges(), 0.0, m_optionsWidget->innerAngle(),
+ m_optionsWidget->roundness(), (VStar::VStarType)m_optionsWidget->type() );
+ }
+ else
+ return
+ new VStar(
+ 0L,
+ m_p,
+ m_d1,
+ m_optionsWidget->innerRadius() * m_d1 /
+ m_optionsWidget->outerRadius(),
+ m_optionsWidget->edges(),
+ m_d2, m_optionsWidget->innerAngle(),
+ m_optionsWidget->roundness(), (VStar::VStarType)m_optionsWidget->type() );
+}
+
+bool
+VStarTool::showDialog() const
+{
+ return m_optionsWidget->exec() == QDialog::Accepted;
+}
+
+void
+VStarTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ KShortcut shortcut( Qt::Key_Plus );
+ shortcut.append(KShortcut( Qt::Key_F9 ) );
+ m_action = new KRadioAction( i18n( "Star Tool" ), "14_star", shortcut, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Draw a star" ) );
+ m_action->setExclusiveGroup( "shapes" );
+ //m_ownAction = true;
+ }
+}
+
+#include "vstartool.moc"
diff --git a/karbon/tools/vstartool.h b/karbon/tools/vstartool.h
new file mode 100644
index 00000000..f9ec716b
--- /dev/null
+++ b/karbon/tools/vstartool.h
@@ -0,0 +1,87 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VSTARTOOL_H__
+#define __VSTARTOOL_H__
+
+#include <klocale.h>
+#include <kdialogbase.h>
+
+#include "vshapetool.h"
+
+
+class KoUnitDoubleSpinBox;
+class KIntSpinBox;
+class KComboBox;
+class KarbonView;
+
+class VStarOptionsWidget : public KDialogBase
+{
+Q_OBJECT
+public:
+ VStarOptionsWidget( KarbonPart *part, QWidget* parent = 0L, const char* name = 0L );
+
+ void refreshUnit();
+
+ int edges() const;
+ double innerRadius() const;
+ double outerRadius() const;
+ double roundness() const;
+ uint type() const;
+ uint innerAngle() const;
+ void setInnerRadius( double );
+
+public slots:
+ void typeChanged( int );
+ void setEdges( int );
+ void setOuterRadius( double );
+
+private:
+ KoUnitDoubleSpinBox *m_innerR;
+ KoUnitDoubleSpinBox *m_outerR;
+ KDoubleNumInput *m_roundness;
+ KIntSpinBox *m_edges;
+ KIntSpinBox *m_innerAngle;
+ KComboBox *m_type;
+ KarbonPart *m_part;
+ QLabel *m_innerRLabel;
+ QLabel *m_outerRLabel;
+};
+
+class VStarTool : public VShapeTool
+{
+public:
+ VStarTool( KarbonView *view );
+ virtual ~VStarTool();
+
+ virtual bool showDialog() const;
+ virtual void setup(KActionCollection *collection);
+ virtual QString uiname() { return i18n( "Star Tool" ); }
+ virtual VPath* shape( bool interactive = false ) const;
+
+ void refreshUnit();
+
+ virtual void arrowKeyReleased( Qt::Key );
+
+private:
+ VStarOptionsWidget* m_optionsWidget;
+};
+
+#endif
+
diff --git a/karbon/tools/vtexttool.cc b/karbon/tools/vtexttool.cc
new file mode 100644
index 00000000..1d59ebda
--- /dev/null
+++ b/karbon/tools/vtexttool.cc
@@ -0,0 +1,1159 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <math.h>
+
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qcursor.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qpushbutton.h>
+#include <qtabwidget.h>
+
+#include <kdebug.h>
+#include <kfontcombo.h>
+#include <kfontdialog.h>
+#include <kiconloader.h>
+#include <knuminput.h>
+#include <kglobalsettings.h>
+
+#include <karbon_view.h>
+#include <karbon_part.h>
+#include <core/vdocument.h>
+#include <core/vglobal.h>
+#include <core/vselection.h>
+#include <core/vfill.h>
+#include <core/vgroup.h>
+#include <core/vstroke.h>
+#include <core/vcursor.h>
+#include <render/vpainterfactory.h>
+#include <render/vkopainter.h>
+#include "vtexttool.h"
+
+
+static void
+traceShape( VKoPainter* p, int x, int y, int w, int h )
+{
+ p->newPath();
+ p->moveTo( KoPoint( x + w , y + h ) );
+ p->lineTo( KoPoint( x + w / 3, y + h ) );
+ p->lineTo( KoPoint( x + w / 3, y + h / 3 ) );
+ p->lineTo( KoPoint( x + w , y + h / 3 ) );
+ p->lineTo( KoPoint( x + w , y + h ) );
+
+ p->moveTo( KoPoint( x , y ) );
+ p->lineTo( KoPoint( x + ( w / 3 ) * 2, y ) );
+ p->lineTo( KoPoint( x + ( w / 3 ) * 2, y + ( h / 3 ) * 2 ) );
+ p->lineTo( KoPoint( x , y + ( h / 3 ) * 2 ) );
+ p->lineTo( KoPoint( x , y ) );
+}
+
+ShadowPreview::ShadowPreview( ShadowWidget* parent )
+ : QWidget( parent ), m_parent( parent )
+{
+ setBackgroundMode( Qt::NoBackground );
+ setMinimumSize( 60, 60 );
+
+ connect( this, SIGNAL( changed( int, int, bool ) ), m_parent, SLOT( setShadowValues( int, int, bool ) ) );
+}
+
+ShadowPreview::~ShadowPreview()
+{
+}
+
+void
+ShadowPreview::mouseReleaseEvent( QMouseEvent* e )
+{
+ int dx = e->x() - width() / 2;
+ int dy = e->y() - height() / 2;
+
+ float fd = sqrt( double( dx * dx + dy * dy ) );
+ int a;
+
+ if( fd == 0 )
+ a = 0;
+ else if( dy == 0 && dx < 0 )
+ a = 180;
+ else
+ {
+ float r = acos( dx / fd );
+ a = int( ( dy <= 0 ? r : VGlobal::twopi - r ) / VGlobal::twopi * 360. );
+ }
+
+ emit changed( a, ( int ) fd, m_parent->isTranslucent() );
+}
+
+void
+ShadowPreview::paintEvent( QPaintEvent* )
+{
+ int w = width() - 4;
+ int h = height() - 4;
+ int d = m_parent->shadowDistance();
+ int a = 360 - m_parent->shadowAngle();
+
+ QPixmap pm( w, h );
+ VKoPainter p( &pm, w, h );
+ VColor color( VColor::rgb );
+
+ VFill fill;
+ KIconLoader il;
+ fill.pattern() = VPattern( il.iconPath( "karbon.png", KIcon::Small ) );
+ fill.setType( VFill::patt );
+
+ p.newPath();
+ p.moveTo( KoPoint( 0, 0 ) );
+ p.lineTo( KoPoint( 0, h ) );
+ p.lineTo( KoPoint( w, h ) );
+ p.lineTo( KoPoint( w, 0 ) );
+ p.lineTo( KoPoint( 0, 0 ) );
+ p.setBrush( fill );
+ p.fillPath();
+
+ color.set( 1., 1., 1. );
+ color.setOpacity( .5 );
+ p.setBrush( VFill( color ) );
+ p.fillPath();
+
+ if( m_parent->isTranslucent() )
+ {
+ color.set( 0., 0., 0. );
+ color.setOpacity( .3 );
+ }
+ else
+ {
+ color.set( .3, .3, .3 );
+ color.setOpacity( 1. );
+ }
+
+ p.setPen( VStroke( color ) );
+ p.setBrush( VFill( color ) );
+
+ traceShape(
+ &p,
+ int( w / 4 + d * cos( a / 360. * VGlobal::twopi ) ),
+ int( h / 4 + d * sin( a / 360. * VGlobal::twopi ) ), int( w / 2 ), int( h / 2 ) );
+
+ p.strokePath();
+ p.fillPath();
+
+ color.set( 0., 0., 1. );
+ color.setOpacity( 1. );
+ p.setBrush( VFill( color ) );
+ color.set( 0., 0., .5 );
+ p.setPen( VStroke( color ) );
+ traceShape( &p, w / 4, h / 4, w / 2, h / 2 );
+ p.strokePath();
+ p.fillPath();
+
+ if( !m_parent->useShadow() )
+ {
+ p.newPath();
+ p.moveTo( KoPoint( 0, 0 ) );
+ p.lineTo( KoPoint( 0, h ) );
+ p.lineTo( KoPoint( w, h ) );
+ p.lineTo( KoPoint( w, 0 ) );
+ p.lineTo( KoPoint( 0, 0 ) );
+ VColor c( colorGroup().background() );
+ c.setOpacity( .8 );
+ p.setBrush( VFill( c ) );
+ p.fillPath();
+ }
+
+ p.end();
+
+ QPainter painter( this );
+ painter.drawPixmap( 2, 2, pm );
+ painter.setPen( colorGroup().light() );
+ painter.moveTo( 1, height() - 1 );
+ painter.lineTo( 1, 1 );
+ painter.lineTo( width() - 1, 1 );
+ painter.lineTo( width() - 1, height() - 1 );
+ painter.lineTo( 1, height() - 1 );
+ painter.setPen( colorGroup().dark() );
+ painter.moveTo( 0, height() - 1 );
+ painter.lineTo( 0, 0 );
+ painter.lineTo( width() - 1, 0 );
+ painter.moveTo( width() - 2, 2 );
+ painter.lineTo( width() - 2, height() - 2 );
+ painter.lineTo( 2, height() - 2 );
+ painter.setPen( Qt::black );
+ painter.drawLine( width() / 2 - 2, height() / 2, width() / 2 + 2, height() / 2 );
+ painter.drawLine( width() / 2, height() / 2 - 2, width() / 2, height() / 2 + 2 );
+}
+
+ShadowWidget::ShadowWidget( QWidget* parent, const char* name, int angle, int distance, bool translucent )
+ : QGroupBox( parent, name )
+{
+ setTitle( i18n( "Shadow" ) );
+ setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ) );
+
+ QGridLayout* layout = new QGridLayout( this );
+ layout->addRowSpacing( 0, 12 );
+ layout->setMargin( 3 );
+ layout->setSpacing( 2 );
+ layout->setColStretch( 0, 1 );
+ layout->setColStretch( 1, 0 );
+ layout->setColStretch( 2, 2 );
+ layout->addMultiCellWidget( m_preview = new ShadowPreview( this ), 1, 3, 0, 0 );
+ layout->addWidget( new QLabel( i18n( "Angle:" ), this ), 1, 1 );
+ layout->addWidget( m_angle = new KIntNumInput( this ), 1, 2 );
+ layout->addWidget( new QLabel( i18n( "Distance:" ), this ), 2, 1 );
+ layout->addWidget( m_distance = new KIntNumInput( this ), 2, 2 );
+ layout->addWidget( m_useShadow = new QCheckBox( i18n( "Shadow" ), this ), 3, 1 );
+ layout->addWidget( m_translucent = new QCheckBox( i18n( "Draw translucent shadow" ), this ), 3, 2 );
+ m_distance->setRange( 1, 37, 1, true );
+ m_angle->setRange( 0, 360, 10, true );
+ m_angle->setValue( angle );
+ m_distance->setValue( distance );
+ m_translucent->setChecked( translucent );
+
+ connect( m_angle, SIGNAL( valueChanged( int ) ), this, SLOT( updatePreview( int ) ) );
+ connect( m_distance, SIGNAL( valueChanged( int ) ), this, SLOT( updatePreview( int ) ) );
+ connect( m_useShadow, SIGNAL( clicked() ), this, SLOT( updatePreview() ) );
+ connect( m_translucent, SIGNAL( clicked() ), this, SLOT( updatePreview() ) );
+
+ updatePreview();
+}
+
+ShadowWidget::~ShadowWidget()
+{
+}
+
+void
+ShadowWidget::setUseShadow( bool use )
+{
+ m_useShadow->setChecked( use );
+ updatePreview();
+}
+
+bool ShadowWidget::useShadow()
+{
+ return m_useShadow->isChecked();
+}
+
+void
+ShadowWidget::setShadowAngle( int angle )
+{
+ m_angle->setValue( angle );
+ m_preview->repaint();
+}
+
+int
+ShadowWidget::shadowAngle()
+{
+ return m_angle->value();
+}
+
+void
+ShadowWidget::setShadowDistance( int distance )
+{
+ m_distance->setValue( distance );
+ m_preview->repaint();
+}
+
+int
+ShadowWidget::shadowDistance()
+{
+ return m_distance->value();
+}
+
+void
+ShadowWidget::setTranslucent( bool translucent )
+{
+ m_translucent->setChecked( translucent );
+ m_preview->repaint();
+}
+
+bool ShadowWidget::isTranslucent()
+{
+ return m_translucent->isChecked();
+}
+
+void
+ShadowWidget::setShadowValues( int angle, int distance, bool translucent )
+{
+ m_angle->setValue( angle );
+ m_distance->setValue( distance );
+ m_translucent->setChecked( translucent );
+ updatePreview();
+}
+
+void
+ShadowWidget::updatePreview( int )
+{
+ m_preview->repaint();
+}
+
+void
+ShadowWidget::updatePreview()
+{
+ m_preview->repaint();
+ bool ok = m_useShadow->isChecked();
+ m_angle->setEnabled( ok );
+ m_distance->setEnabled( ok );
+ m_translucent->setEnabled( ok );
+}
+
+VTextOptionsWidget::VTextOptionsWidget( VTextTool* tool, QWidget *parent )
+ : KDialogBase( parent, "", true, i18n( "Text" ), Ok | Cancel ), m_tool( tool )
+{
+ //setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ) );
+ //setFrameStyle( Box | Sunken );
+ QWidget *base = new QWidget( this );
+ QVBoxLayout* mainLayout = new QVBoxLayout( base );
+ mainLayout->setMargin( 3 );
+
+ mainLayout->add( m_tabWidget = new QTabWidget( base ) );
+
+ m_tabWidget->setFont( QFont( KGlobalSettings::generalFont().family() , 8 ) );
+
+ QWidget* textWidget = new QWidget( m_tabWidget );
+
+ QGridLayout* textLayout = new QGridLayout( textWidget );
+
+ QStringList list;
+ KFontChooser::getFontList( list, KFontChooser::SmoothScalableFonts );
+
+ textLayout->setMargin( 3 );
+ textLayout->setSpacing( 2 );
+ textLayout->addMultiCellWidget( m_fontCombo = new KFontCombo( list, textWidget ), 0, 0, 0, 2 );
+ textLayout->addWidget( m_fontSize = new KIntNumInput( textWidget ), 1, 0 );
+ textLayout->addWidget( m_boldCheck = new QCheckBox( i18n( "Bold" ), textWidget ), 1, 1 );
+ textLayout->addWidget( m_italicCheck = new QCheckBox( i18n( "Italic" ), textWidget ), 1, 2 );
+ textLayout->addMultiCellWidget( m_textEditor = new QLineEdit( textWidget ), 2, 2, 0, 2 );
+
+ m_tabWidget->addTab( textWidget, i18n( "Text" ) );
+
+ QWidget* posWidget = new QWidget( m_tabWidget );
+
+ QGridLayout* posLayout = new QGridLayout( posWidget );
+ textLayout->setMargin( 3 );
+ posLayout->setSpacing( 2 );
+ posLayout->addWidget( new QLabel( i18n( "Alignment:" ), posWidget ), 0, 0 );
+ posLayout->addWidget( m_textAlignment = new QComboBox( posWidget ), 0, 1 );
+ posLayout->addWidget( new QLabel( i18n( "Position:" ), posWidget ), 1, 0 );
+ posLayout->addWidget( m_textPosition = new QComboBox( posWidget ), 1, 1 );
+ posLayout->addWidget( new QLabel( i18n( "Offset:" ), posWidget ), 2, 0 );
+ posLayout->addWidget( m_textOffset = new KDoubleNumInput( posWidget ), 2, 1 );
+ posLayout->setColStretch( 0, 0 );
+ posLayout->setColStretch( 1, 1 );
+
+ m_tabWidget->addTab( posWidget, i18n( "Position" ) );
+
+ QWidget* fxWidget = new QWidget( m_tabWidget );
+
+ QVBoxLayout* fxLayout = new QVBoxLayout( fxWidget );
+
+ fxLayout->setMargin( 3 );
+ fxLayout->setSpacing( 2 );
+ fxLayout->add( m_shadow = new ShadowWidget( fxWidget, 0L, 315, 4, true ) );
+
+ QHBoxLayout* fxLayout2 = new QHBoxLayout( fxLayout );
+
+ fxLayout2->setSpacing( 2 );
+ fxLayout2->addWidget( m_editBasePath = new QPushButton( i18n( "Edit Base Path" ), fxWidget ) );
+ fxLayout2->addWidget( m_convertToShapes = new QPushButton( i18n( "Convert to Shapes" ), fxWidget ) );
+
+ m_tabWidget->addTab( fxWidget, i18n( "Effects" ) );
+
+ m_fontCombo->setCurrentText( KGlobalSettings::generalFont().family() );
+
+ m_fontSize->setValue( 12 );
+ m_fontSize->setSuffix( " pt" );
+
+ m_textEditor->setMinimumHeight( 100 );
+ m_textEditor->setText( i18n( "New text") );
+ m_textEditor->selectAll();
+
+ m_convertToShapes->setEnabled( true );
+
+ m_textAlignment->insertItem( i18n( "Horizontal alignment", "Left") );
+ m_textAlignment->insertItem( i18n( "Horizontal alignment", "Center") );
+ m_textAlignment->insertItem( i18n( "Horizontal alignment", "Right") );
+
+ m_textPosition->insertItem( i18n( "Vertical alignment", "Above") );
+ m_textPosition->insertItem( i18n( "Vertical alignment", "On") );
+ m_textPosition->insertItem( i18n( "Vertical alignment", "Under") );
+
+ m_textOffset->setRange( 0.0, 100.0, 1.0, true );
+
+ connect( m_fontCombo, SIGNAL( activated( int ) ), this, SLOT( valueChanged( int ) ) );
+ connect( m_boldCheck, SIGNAL( stateChanged( int ) ), this, SLOT( valueChanged( int ) ) );
+ connect( m_italicCheck, SIGNAL( stateChanged( int ) ), this, SLOT( valueChanged( int ) ) );
+ connect( m_fontSize, SIGNAL( valueChanged( int ) ), this, SLOT( valueChanged( int ) ) );
+ connect( m_textPosition, SIGNAL( activated( int ) ), this, SLOT( valueChanged( int ) ) );
+ connect( m_textAlignment, SIGNAL( activated( int ) ), this, SLOT( valueChanged( int ) ) );
+ connect( m_textOffset, SIGNAL( valueChanged( double ) ), this, SLOT( valueChanged( double ) ) );
+ connect( m_textEditor, SIGNAL( returnPressed() ), this, SLOT( accept() ) );
+ connect( m_textEditor, SIGNAL( textChanged( const QString& ) ), this, SLOT( textChanged( const QString& ) ) );
+ connect( m_editBasePath, SIGNAL( clicked() ), this, SLOT( editBasePath() ) );
+ connect( m_convertToShapes, SIGNAL( clicked() ), this, SLOT( convertToShapes() ) );
+ connect( this, SIGNAL( cancelClicked() ), this, SLOT( cancel() ) );
+
+ setMainWidget( base );
+ setFixedSize( baseSize() );
+}
+
+VTextOptionsWidget::~VTextOptionsWidget()
+{
+}
+
+void
+VTextOptionsWidget::valueChanged( int )
+{
+ m_fontCombo->setBold( m_boldCheck->isChecked() );
+ m_fontCombo->setItalic( m_italicCheck->isChecked() );
+
+ m_textEditor->setFont( QFont( m_fontCombo->currentText(), m_fontSize->value(), ( m_boldCheck->isChecked() ? 75 : 50 ), m_italicCheck->isChecked() ) );
+
+ if( m_tool && isVisible() )
+ m_tool->textChanged();
+}
+
+void
+VTextOptionsWidget::valueChanged( double )
+{
+ if( m_tool && isVisible() )
+ m_tool->textChanged();
+}
+
+void
+VTextOptionsWidget::accept()
+{
+ if( m_tool )
+ m_tool->accept();
+ hide();
+}
+
+void
+VTextOptionsWidget::cancel()
+{
+ if( m_tool )
+ m_tool->cancel();
+}
+
+void
+VTextOptionsWidget::textChanged( const QString& )
+{
+ if( m_tool && isVisible() )
+ m_tool->textChanged();
+}
+
+void
+VTextOptionsWidget::editBasePath()
+{
+ if( m_tool )
+ m_tool->editBasePath();
+}
+
+void
+VTextOptionsWidget::convertToShapes()
+{
+ if( m_tool )
+ m_tool->convertToShapes();
+}
+
+void
+VTextOptionsWidget::setFont( const QFont& font )
+{
+ m_fontCombo->setCurrentText( font.family() );
+
+ m_boldCheck->setChecked( font.bold() );
+
+ m_italicCheck->setChecked( font.italic() );
+
+ m_fontSize->setValue( font.pointSize() );
+
+ m_fontCombo->setBold( m_boldCheck->isChecked() );
+ m_fontCombo->setItalic( m_italicCheck->isChecked() );
+
+ m_textEditor->setFont( QFont( m_fontCombo->currentText(), m_fontSize->value(), ( m_boldCheck->isChecked() ? 75 : 50 ), m_italicCheck->isChecked() ) );
+}
+
+QFont VTextOptionsWidget::font()
+{
+ return QFont( m_fontCombo->currentText(), m_fontSize->value(), ( m_boldCheck->isChecked() ? 75 : 50 ), m_italicCheck->isChecked() );
+}
+
+void
+VTextOptionsWidget::setText( const QString& text )
+{
+ m_textEditor->setText( text );
+}
+
+QString VTextOptionsWidget::text()
+{
+ return m_textEditor->text();
+}
+
+void
+VTextOptionsWidget::setPosition( VText::Position position )
+{
+ m_textPosition->setCurrentItem( position );
+}
+
+VText::Position VTextOptionsWidget::position()
+{
+ return ( VText::Position ) m_textPosition->currentItem();
+}
+
+void
+VTextOptionsWidget::setAlignment( VText::Alignment alignment )
+{
+ m_textAlignment->setCurrentItem( alignment );
+}
+
+VText::Alignment VTextOptionsWidget::alignment()
+{
+ return ( VText::Alignment ) m_textAlignment->currentItem();
+}
+
+void
+VTextOptionsWidget::setOffset( double offset )
+{
+ if( offset < 0.0 ) offset = 0.0;
+ if( offset > 100.0 ) offset = 100.0;
+
+ m_textOffset->setValue( offset );
+}
+double
+VTextOptionsWidget::offset()
+{
+ return m_textOffset->value();
+}
+
+void
+VTextOptionsWidget::setUseShadow( bool state )
+{
+ m_shadow->setUseShadow( state );
+}
+
+bool VTextOptionsWidget::useShadow()
+{
+ return m_shadow->useShadow();
+}
+
+void
+VTextOptionsWidget::setShadow( int angle, int distance, bool translucent )
+{
+ m_shadow->setShadowValues( angle, distance, translucent );
+}
+
+bool VTextOptionsWidget::translucentShadow()
+{
+ return m_shadow->isTranslucent();
+}
+
+int
+VTextOptionsWidget::shadowAngle()
+{
+ return m_shadow->shadowAngle();
+}
+
+int
+VTextOptionsWidget::shadowDistance()
+{
+ return m_shadow->shadowDistance();
+}
+
+void
+VTextOptionsWidget::initialize( VObject &text )
+{
+ if( m_tool )
+ m_tool->visit( text );
+}
+
+VTextTool::VTextTool( KarbonView *view )
+ : VTool( view, "tool_text" )
+{
+ m_optionsWidget = new VTextOptionsWidget( this, 0L );
+ m_text = 0L;
+ m_editedText = 0L;
+ registerTool( this );
+ m_cursor = new QCursor( VCursor::createCursor( VCursor::CrossHair ) );
+}
+
+VTextTool::~VTextTool()
+{
+ delete m_optionsWidget;
+ delete m_editedText;
+ delete m_cursor;
+}
+
+QString VTextTool::contextHelp()
+{
+ QString s = i18n( "<qt><b>Text Tool</b><br>" );
+ s += i18n("<i>Click</i> on document to place horizontal text.<br>" );
+ s += i18n("<i>Click and drag</i> in document to place directional text.<br>" );
+ s += i18n("<i>Click</i> on a selected path object to place text along its outline.<br>" );
+ s += i18n("<i>Click</i> on a selected text object to change it.<br></qt>" );
+
+ return s;
+}
+
+void
+VTextTool::activate()
+{
+ VTool::activate();
+ view()->statusMessage()->setText( i18n( "Text Tool" ) );
+ view()->setCursor( *m_cursor );
+
+ m_creating = true;
+ m_text = 0L;
+ delete m_editedText;
+ m_editedText = 0L;
+}
+
+void
+VTextTool::deactivate()
+{
+}
+
+void
+VTextTool::draw( VPainter* painter )
+{
+ if( m_editedText )
+ m_editedText->draw( painter, &m_editedText->boundingBox() );
+}
+
+void
+VTextTool::drawPathCreation()
+{
+ VPainter * painter = view()->painterFactory()->editpainter();
+
+ painter->setZoomFactor( view()->zoom() );
+
+ painter->setRasterOp( Qt::NotROP );
+ painter->newPath();
+ painter->setPen( Qt::DotLine );
+ painter->setBrush( Qt::NoBrush );
+
+ painter->moveTo( first() );
+ painter->lineTo( m_last );
+ painter->strokePath();
+}
+
+void
+VTextTool::drawEditedText()
+{
+ if( m_editedText )
+ view()->repaintAll( m_editedText->boundingBox() );
+}
+
+void
+VTextTool::mouseButtonPress()
+{
+ m_last = first();
+ drawPathCreation();
+ m_stepwise = false;
+}
+
+void
+VTextTool::mouseButtonRelease()
+{
+ if( ! view() )
+ return;
+
+ VSelection* selection = view()->part()->document().selection();
+ VObject* selObj = selection->objects().getFirst();
+
+ // initialize dialog with single selected object
+ if( selection->objects().count() == 1 && selObj->boundingBox().contains( last() ) )
+ m_optionsWidget->initialize( *selObj );
+ else
+ {
+ // use a default horizontal path when just clicking
+ VSubpath path( 0L );
+ path.moveTo( first() );
+ path.lineTo( KoPoint( first().x()+10, first().y() ) );
+
+ if( ! createText( path ) )
+ return;
+ }
+
+ if( dynamic_cast<VText*>( selObj ) && selObj->boundingBox().contains( last() ) )
+ m_optionsWidget->setCaption( i18n( "Change Text") );
+ else
+ m_optionsWidget->setCaption( i18n( "Insert Text") );
+
+ m_optionsWidget->show();
+}
+
+void
+VTextTool::mouseDrag()
+{
+ drawPathCreation();
+
+ if( m_stepwise && shiftPressed() )
+ {
+ KoPoint act = last();
+ KoPoint dst = act - first();
+
+ double angle = atan2( dst.y(), dst.x() );
+ if( angle < 0 )
+ angle += VGlobal::twopi;
+
+ // calculate previuos and next modulo 45 degree step
+ double prevStep = angle - fmod( angle, VGlobal::pi_2 / 2.0f );
+ double nextStep = prevStep + VGlobal::pi_2 / 2.0f;
+ // calculate distance between first and last point
+ double length = sqrt( dst.x()*dst.x() + dst.y()*dst.y() );
+
+ // use nearest step
+ if( angle - prevStep < nextStep - angle )
+ {
+ m_last.setX( first().x() + length * cos( prevStep ) );
+ m_last.setY( first().y() + length * sin( prevStep ) );
+ }
+ else
+ {
+ m_last.setX( first().x() + length * cos( nextStep ) );
+ m_last.setY( first().y() + length * sin( nextStep ) );
+ }
+ }
+ else
+ m_last = last();
+
+ drawPathCreation();
+}
+
+void
+VTextTool::mouseDragRelease()
+{
+ drawPathCreation();
+
+ if( m_creating && m_editedText )
+ {
+ drawEditedText();
+ delete m_editedText;
+ m_editedText = 0L;
+ }
+
+ // use dragged path to create text along
+ VSubpath path( 0L );
+ path.moveTo( first() );
+ path.lineTo( m_last );
+
+ if( createText( path ) )
+ {
+ m_optionsWidget->setCaption( i18n( "Insert Text") );
+ m_optionsWidget->show();
+ }
+}
+
+bool
+VTextTool::createText( VSubpath &path )
+{
+ // no original text is used
+ m_text = 0L;
+ delete m_editedText;
+
+ m_editedText = new VText( m_optionsWidget->font(), path, m_optionsWidget->position(), m_optionsWidget->alignment(), m_optionsWidget->text() );
+
+ if( ! m_editedText )
+ return false;
+
+ m_editedText->setState( VObject::edit );
+
+#ifdef HAVE_KARBONTEXT
+ m_editedText->traceText();
+#endif
+
+ // yes, we are creating a new text object
+ m_creating = true;
+
+ return true;
+}
+
+void
+VTextTool::textChanged()
+{
+ if( !m_editedText )
+ return;
+
+ if( !m_creating && m_text && m_text->state() != VObject::hidden )
+ {
+ // hide the original text if we are changing it
+ m_text->setState( VObject::hidden );
+ view()->repaintAll( m_text->boundingBox() );
+ }
+ else
+ view()->repaintAll( m_editedText->boundingBox() );
+
+ m_editedText->setText( m_optionsWidget->text() );
+ m_editedText->setFont( m_optionsWidget->font() );
+ m_editedText->setPosition( m_optionsWidget->position() );
+ m_editedText->setAlignment( m_optionsWidget->alignment() );
+ m_editedText->setOffset( 0.01 * m_optionsWidget->offset() );
+#ifdef HAVE_KARBONTEXT
+ m_editedText->traceText();
+#endif
+
+ drawEditedText();
+}
+
+void
+VTextTool::accept()
+{
+ if( !m_editedText )
+ return;
+
+ VTextCmd* cmd;
+
+ if( !m_creating )
+ {
+ cmd = new VTextCmd(
+ &view()->part()->document(),
+ i18n( "Change Text" ),
+ m_text,
+ m_editedText->font(),
+ m_editedText->basePath(),
+ m_editedText->position(),
+ m_editedText->alignment(),
+ m_editedText->offset(),
+ m_editedText->text(),
+ m_optionsWidget->useShadow(),
+ m_optionsWidget->shadowAngle(),
+ m_optionsWidget->shadowDistance(),
+ m_optionsWidget->translucentShadow() );
+ }
+ else
+ {
+ VText *newText = m_editedText->clone();
+ newText->setUseShadow( m_optionsWidget->useShadow() );
+ newText->setShadow( m_optionsWidget->shadowAngle(), m_optionsWidget->shadowDistance(), m_optionsWidget->translucentShadow() );
+
+ cmd = new VTextCmd(
+ &view()->part()->document(),
+ i18n( "Insert Text" ),
+ newText );
+
+ delete m_editedText;
+ m_editedText = 0L;
+ }
+
+ view()->part()->addCommand( cmd, true );
+ view()->part()->repaintAllViews();
+ m_creating = false;
+}
+
+void
+VTextTool::cancel()
+{
+ if( m_text )
+ {
+ // show original text if we canceled changing it
+ m_text->setState( VObject::selected );
+ view()->repaintAll( m_text->boundingBox() );
+ }
+ else
+ drawPathCreation();
+
+ delete m_editedText;
+ m_editedText = 0L;
+}
+
+void
+VTextTool::editBasePath()
+{
+ if( !m_editedText )
+ return;
+
+ view()->part()->document().selection()->clear();
+ view()->part()->document().selection()->append( &m_editedText->basePath() );
+ view()->part()->repaintAllViews();
+}
+
+void
+VTextTool::convertToShapes()
+{
+ if( !m_text )
+ return;
+
+ VTextToCompositeCmd* cmd = new VTextToCompositeCmd(
+ &view()->part()->document(),
+ i18n( "Text Conversion" ),
+ m_text );
+
+ view()->part()->addCommand( cmd, true );
+
+ m_creating = false;
+
+ delete m_editedText;
+
+ m_text = 0L;
+ m_editedText = 0L;
+}
+
+void
+VTextTool::visitVPath( VPath& composite )
+{
+ if( composite.paths().count() == 0 )
+ return;
+
+ if( createText( *composite.paths().getFirst() ) )
+ drawEditedText();
+}
+
+void
+VTextTool::visitVSubpath( VSubpath& path )
+{
+ if( createText( path ) )
+ drawEditedText();
+}
+
+void
+VTextTool::visitVText( VText& text )
+{
+ m_text = &text;
+ delete m_editedText;
+ m_editedText = text.clone();
+
+ m_optionsWidget->setFont( text.font() );
+ m_optionsWidget->setText( text.text() );
+ m_optionsWidget->setPosition( text.position() );
+ m_optionsWidget->setAlignment( text.alignment() );
+ m_optionsWidget->setOffset( text.offset() * 100.0 );
+ m_optionsWidget->setUseShadow( text.useShadow() );
+ m_optionsWidget->setShadow( text.shadowAngle(), text.shadowDistance(), text.translucentShadow() );
+ m_creating = false;
+ m_text->setState( VObject::hidden );
+ m_editedText->setState( VObject::edit );
+}
+
+VTextTool::VTextCmd::VTextCmd( VDocument* doc, const QString& name, VText* text )
+ : VCommand( doc, name, "14_text" ), m_text( text )
+{
+ m_textModifications = 0L;
+
+ m_executed = false;
+}
+
+VTextTool::VTextCmd::VTextCmd( VDocument* doc, const QString& name, VText* text,
+ const QFont &newFont, const VSubpath& newBasePath, VText::Position newPosition, VText::Alignment newAlignment, double newOffset, const QString& newText,
+ bool newUseShadow, int newShadowAngle, int newShadowDistance, bool newTranslucentShadow )
+ : VCommand( doc, name, "14_text" ), m_text( text )
+{
+ m_textModifications = new VTextModifPrivate();
+ m_textModifications->newFont = newFont;
+ m_textModifications->oldFont = text->font();
+ m_textModifications->newBasePath = newBasePath;
+ m_textModifications->oldBasePath = text->basePath();
+ m_textModifications->newPosition = newPosition;
+ m_textModifications->oldPosition = text->position();
+ m_textModifications->newAlignment = newAlignment;
+ m_textModifications->oldAlignment = text->alignment();
+ m_textModifications->newOffset = newOffset;
+ m_textModifications->oldOffset = text->offset();
+ m_textModifications->newText = newText;
+ m_textModifications->oldText = text->text();
+ m_textModifications->newUseShadow = newUseShadow;
+ m_textModifications->oldUseShadow = text->useShadow();
+ m_textModifications->newShadowAngle = newShadowAngle;
+ m_textModifications->oldShadowAngle = text->shadowAngle();
+ m_textModifications->newShadowDistance = newShadowDistance;
+ m_textModifications->oldShadowDistance = text->shadowDistance();
+ m_textModifications->newTranslucentShadow = newTranslucentShadow;
+ m_textModifications->oldTranslucentShadow = text->translucentShadow();
+
+ m_executed = false;
+}
+
+VTextTool::VTextCmd::~VTextCmd()
+{
+ delete m_textModifications;
+}
+
+void
+VTextTool::VTextCmd::execute()
+{
+ if( !m_text )
+ return;
+
+ if( !m_textModifications )
+ {
+ if( m_text->state() == VObject::deleted )
+ m_text->setState( VObject::normal );
+ else
+ {
+ m_text->setState( VObject::normal );
+ document()->append( m_text );
+ document()->selection()->clear();
+ document()->selection()->append( m_text );
+ }
+ }
+ else
+ {
+ m_text->setFont( m_textModifications->newFont );
+ m_text->setBasePath( m_textModifications->newBasePath );
+ m_text->setPosition( m_textModifications->newPosition );
+ m_text->setAlignment( m_textModifications->newAlignment );
+ m_text->setOffset( m_textModifications->newOffset );
+ m_text->setText( m_textModifications->newText );
+ m_text->setUseShadow( m_textModifications->newUseShadow );
+ m_text->setShadow( m_textModifications->newShadowAngle, m_textModifications->newShadowDistance, m_textModifications->newTranslucentShadow );
+
+#ifdef HAVE_KARBONTEXT
+ m_text->traceText();
+#endif
+
+ m_text->setState( VObject::normal );
+ }
+
+ m_executed = true;
+
+ setSuccess( true );
+}
+
+void
+VTextTool::VTextCmd::unexecute()
+{
+ if( !m_text )
+ return;
+
+ if( !m_textModifications )
+ {
+ document()->selection()->take( *m_text );
+ m_text->setState( VObject::deleted );
+ }
+ else
+ {
+ m_text->setFont( m_textModifications->oldFont );
+ m_text->setBasePath( m_textModifications->oldBasePath );
+ m_text->setPosition( m_textModifications->oldPosition );
+ m_text->setAlignment( m_textModifications->oldAlignment );
+ m_text->setOffset( m_textModifications->oldOffset );
+ m_text->setText( m_textModifications->oldText );
+ m_text->setUseShadow( m_textModifications->oldUseShadow );
+ m_text->setShadow( m_textModifications->oldShadowAngle, m_textModifications->oldShadowDistance, m_textModifications->oldTranslucentShadow );
+
+#ifdef HAVE_KARBONTEXT
+ m_text->traceText();
+#endif
+
+ m_text->setState( VObject::normal );
+ }
+
+ m_executed = false;
+
+ setSuccess( false );
+}
+
+VTextTool::VTextToCompositeCmd::VTextToCompositeCmd( VDocument* doc, const QString& name, VText* text )
+ : VCommand( doc, name, "14_text" ), m_text( text ), m_group( 0L ), m_executed( false )
+{
+}
+
+VTextTool::VTextToCompositeCmd::~VTextToCompositeCmd()
+{
+}
+
+void
+VTextTool::VTextToCompositeCmd::execute()
+{
+ if( !m_text )
+ return;
+
+ if( !m_group )
+ {
+ m_group = m_text->toVGroup();
+ document()->append( m_group );
+ }
+
+ m_text->setState( VObject::deleted );
+ m_group->setState( VObject::normal );
+ document()->selection()->clear();
+ document()->selection()->append( m_group );
+
+ m_executed = true;
+
+ setSuccess( true );
+}
+
+void
+VTextTool::VTextToCompositeCmd::unexecute()
+{
+ if( !m_text )
+ return;
+
+ m_text->setState( VObject::normal );
+
+ document()->selection()->take( *m_group );
+
+ m_group->setState( VObject::deleted );
+
+ m_executed = false;
+
+ setSuccess( false );
+}
+
+bool
+VTextTool::showDialog() const
+{
+ VSelection* selection = view()->part()->document().selection();
+
+ // initialize dialog with single selected object
+ if( selection->objects().count() == 1 )
+ m_optionsWidget->initialize( *selection->objects().getFirst());
+ else
+ return false;
+
+ if( dynamic_cast<VText*>( selection->objects().getFirst() ) )
+ m_optionsWidget->setCaption(i18n( "Change Text") );
+ else
+ m_optionsWidget->setCaption(i18n( "Insert Text") );
+
+ m_optionsWidget->show();
+ return true;
+}
+
+void
+VTextTool::mouseDragShiftPressed()
+{
+ m_stepwise = true;
+ mouseDrag();
+}
+
+void
+VTextTool::mouseDragShiftReleased()
+{
+ m_stepwise = false;
+ mouseDrag();
+}
+
+void
+VTextTool::setup( KActionCollection *collection )
+{
+ m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
+
+ if( m_action == 0 )
+ {
+ m_action = new KRadioAction( i18n( "Text Tool" ), "14_text", Qt::SHIFT+Qt::Key_T, this, SLOT( activate() ), collection, name() );
+ m_action->setToolTip( i18n( "Text Tool" ) );
+ m_action->setExclusiveGroup( "misc" );
+ //m_ownAction = true;
+ }
+}
+
+#include "vtexttool.moc"
+
diff --git a/karbon/tools/vtexttool.h b/karbon/tools/vtexttool.h
new file mode 100644
index 00000000..add0dd35
--- /dev/null
+++ b/karbon/tools/vtexttool.h
@@ -0,0 +1,287 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VTEXTTOOL_H__
+#define __VTEXTTOOL_H__
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kdialogbase.h>
+
+#include "qframe.h"
+#include "qgroupbox.h"
+#include "qcombobox.h"
+
+#include "vcommand.h"
+#include "vtext.h"
+#include "vtool.h"
+
+class KFontCombo;
+class KIntNumInput;
+class QCheckBox;
+class QLineEdit;
+class QPushButton;
+class QTabWidget;
+class ShadowWidget;
+class VTextTool;
+class QCursor;
+
+class ShadowPreview : public QWidget
+{
+ Q_OBJECT
+
+public:
+ ShadowPreview( ShadowWidget* parent );
+ ~ShadowPreview();
+
+signals:
+ void changed( int angle, int distance, bool );
+
+protected:
+ virtual void mouseReleaseEvent( QMouseEvent* );
+ virtual void paintEvent( QPaintEvent* );
+
+private:
+ ShadowWidget* m_parent;
+};
+
+
+class ShadowWidget : public QGroupBox
+{
+ Q_OBJECT
+
+public:
+ ShadowWidget( QWidget* parent, const char* name, int angle, int distance, bool translucent );
+ ~ShadowWidget();
+
+ void setUseShadow( bool use );
+ bool useShadow();
+ void setShadowAngle( int angle );
+ int shadowAngle();
+ void setShadowDistance( int distance );
+ int shadowDistance();
+ void setTranslucent( bool translucent );
+ bool isTranslucent();
+
+public slots:
+ void setShadowValues( int angle, int distance, bool translucent );
+ void updatePreview( int );
+ void updatePreview();
+
+protected:
+ QCheckBox* m_useShadow;
+ KIntNumInput* m_angle;
+ KIntNumInput* m_distance;
+ QCheckBox* m_translucent;
+ ShadowPreview* m_preview;
+};
+
+
+class VTextOptionsWidget : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ VTextOptionsWidget( VTextTool* tool, QWidget *parent );
+ ~VTextOptionsWidget();
+
+ void setFont( const QFont& font );
+ QFont font();
+ void setText( const QString& text );
+ QString text();
+ void setPosition( VText::Position position );
+ VText::Position position();
+ void setAlignment( VText::Alignment alignment );
+ VText::Alignment alignment();
+ void setOffset( double offset );
+ double offset();
+ void setUseShadow( bool state );
+ bool useShadow();
+ void setShadow( int angle, int distance, bool translucent );
+ bool translucentShadow();
+ int shadowAngle();
+ int shadowDistance();
+
+public slots:
+ void valueChanged( int );
+ void valueChanged( double );
+ void accept();
+ void cancel();
+ void textChanged( const QString& );
+ void editBasePath();
+ void convertToShapes();
+ void initialize( VObject &text );
+
+protected:
+ QTabWidget* m_tabWidget;
+ KFontCombo* m_fontCombo;
+ QCheckBox* m_boldCheck;
+ QCheckBox* m_italicCheck;
+ KIntNumInput* m_fontSize;
+ QLineEdit* m_textEditor;
+ ShadowWidget* m_shadow;
+ QComboBox* m_textAlignment;
+ QComboBox* m_textPosition;
+ QPushButton* m_editBasePath;
+ QPushButton* m_convertToShapes;
+ KDoubleNumInput* m_textOffset;
+ VTextTool* m_tool;
+};
+
+
+class VTextTool : public VTool, public VVisitor
+{
+public:
+ VTextTool( KarbonView *view );
+ ~VTextTool();
+
+ virtual void setup (KActionCollection *collection );
+ virtual QString uiname() { return i18n( "Text Tool" ); }
+
+ virtual QString contextHelp();
+ virtual bool showDialog() const;
+
+ virtual void activate();
+ virtual void deactivate();
+
+ virtual void mouseButtonPress();
+ virtual void mouseButtonRelease();
+ virtual void mouseDrag();
+ virtual void mouseDragRelease();
+ virtual void textChanged();
+ virtual void accept();
+ virtual void cancel();
+ virtual void editBasePath();
+ virtual void convertToShapes();
+
+ virtual void visitVPath( VPath& composite );
+ virtual void visitVDocument( VDocument& )
+ {}
+
+ virtual void visitVGroup( VGroup& )
+ {}
+
+ virtual void visitVLayer( VLayer& )
+ {}
+
+ virtual void visitVSubpath( VSubpath& path );
+ virtual void visitVText( VText& text );
+
+ virtual void draw( VPainter* painter );
+
+protected:
+ virtual void mouseDragShiftPressed();
+ virtual void mouseDragShiftReleased();
+
+private:
+ class VTextCmd : public VCommand
+ {
+ public:
+ VTextCmd( VDocument* doc, const QString& name, VText* text );
+ VTextCmd( VDocument* doc, const QString& name, VText* text,
+ const QFont &newFont, const VSubpath& newBasePath, VText::Position newPosition, VText::Alignment newAlignment, double newOffset, const QString& newText,
+ bool newUseShadow, int newShadowAngle, int newShadowDistance, bool newTranslucentShadow );
+ virtual ~VTextCmd();
+
+ virtual void execute();
+ virtual void unexecute();
+ virtual bool isExecuted()
+ {
+ return m_executed;
+ }
+ virtual bool changesSelection() const { return true; }
+
+ private:
+ class VTextModifPrivate
+ {
+ public:
+ VTextModifPrivate() : oldBasePath( 0L ), newBasePath( 0L )
+ {}
+
+ QFont oldFont;
+ QFont newFont;
+ VSubpath oldBasePath;
+ VSubpath newBasePath;
+ VText::Position oldPosition;
+ VText::Position newPosition;
+ VText::Alignment oldAlignment;
+ VText::Alignment newAlignment;
+ double oldOffset;
+ double newOffset;
+ QString oldText;
+ QString newText;
+ bool oldUseShadow;
+ bool newUseShadow;
+ int oldShadowAngle;
+ int newShadowAngle;
+ int oldShadowDistance;
+ int newShadowDistance;
+ bool oldTranslucentShadow;
+ bool newTranslucentShadow;
+ };
+
+ VText* m_text;
+ bool m_executed;
+ VTextModifPrivate* m_textModifications;
+ };
+
+ class VTextToCompositeCmd : public VCommand
+ {
+ public:
+ VTextToCompositeCmd( VDocument* doc, const QString& name, VText* text );
+ virtual ~VTextToCompositeCmd();
+
+ virtual void execute();
+ virtual void unexecute();
+ virtual bool isExecuted()
+ {
+ return m_executed;
+ }
+
+ private:
+ VText* m_text;
+ VGroup* m_group;
+ bool m_executed;
+ };
+
+ void drawPathCreation();
+ void drawEditedText();
+
+ /**
+ * Creates new temporary text object along given path for displaying.
+ *
+ * @param path the path to create the text along
+ */
+ bool createText( VSubpath &path );
+
+ VTextOptionsWidget* m_optionsWidget;
+ KoPoint m_last;
+ VText* m_text;
+ VText* m_editedText;
+ bool m_creating;
+ // are we dragging in 45 degree steps?
+ bool m_stepwise;
+ QCursor* m_cursor;
+};
+
+#endif
+