diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /karbon/tools | |
download | koffice-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')
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 + |