dpline.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2005 by David Saxton                                    *
00003  *   david@bluehaze.org                                                    *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  ***************************************************************************/
00010 
00011 #include "dpline.h"
00012 #include "libraryitem.h"
00013 #include "resizeoverlay.h"
00014 #include "variant.h"
00015 
00016 #include <cmath>
00017 #include <kiconloader.h>
00018 #include <klocale.h>
00019 #include <qpainter.h>
00020 
00021 
00022 //BEGIN class DPLine
00023 Item* DPLine::construct( ItemDocument *itemDocument, bool newItem, const char *id )
00024 {
00025         return new DPLine( itemDocument, newItem, id );
00026 }
00027 
00028 LibraryItem* DPLine::libraryItem()
00029 {
00030         return new LibraryItem(
00031                 QString("dp/line"),
00032                 i18n("Line"),
00033                 i18n("Other"),
00034                 KGlobal::iconLoader()->loadIcon( "text", KIcon::Small ),
00035                 LibraryItem::lit_drawpart,
00036                 DPLine::construct );
00037 }
00038 
00039 DPLine::DPLine( ItemDocument *itemDocument, bool newItem, const char *id )
00040         : DrawPart( itemDocument, newItem, id ? id : "line" )
00041 {
00042         m_pLineOverlay = new LineOverlay(this);
00043         m_name = i18n("Line");
00044         m_desc = i18n("Select the line to position the end points");
00045         
00046         createProperty( "line-color", Variant::Type::Color );
00047         property("line-color")->setCaption( i18n("Line Color") );
00048         property("line-color")->setValue(Qt::black);
00049         
00050         createProperty( "line-width", Variant::Type::Int );
00051         property("line-width")->setCaption( i18n("Line Width") );
00052         property("line-width")->setMinValue(1);
00053         property("line-width")->setMaxValue(1000);
00054         property("line-width")->setValue(1);
00055         
00056         createProperty( "line-style", Variant::Type::PenStyle );
00057         property("line-style")->setCaption( i18n("Line Style") );
00058         property("line-style")->setAdvanced(true);
00059         setDataPenStyle( "line-style", Qt::SolidLine );
00060         
00061         createProperty( "cap-style", Variant::Type::PenCapStyle );
00062         property("cap-style")->setCaption( i18n("Cap Style") );
00063         property("cap-style")->setAdvanced(true);
00064         setDataPenCapStyle( "cap-style", Qt::FlatCap );
00065 }
00066 
00067 DPLine::~DPLine()
00068 {
00069 }
00070 
00071 void DPLine::setSelected( bool yes )
00072 {
00073         if ( yes == isSelected() )
00074                 return;
00075         
00076         DrawPart::setSelected(yes);
00077         m_pLineOverlay->showResizeHandles(yes);
00078 }
00079 
00080 
00081 void DPLine::dataChanged()
00082 {
00083         setPen( QPen( dataColor("line-color"),
00084                         unsigned( dataInt("line-width") ),
00085                         getDataPenStyle("line-style"),
00086                         getDataPenCapStyle("cap-style"),
00087                         Qt::MiterJoin ) );
00088         
00089         postResize(); // in case the pen width has changed
00090         update();
00091 }
00092 
00093 
00094 void DPLine::postResize()
00095 {
00096         int x1 = offsetX();
00097         int y1 = offsetY();
00098         int x2 = x1+width();
00099         int y2 = y1+height();
00100         
00101         QPointArray p(4);
00102         int pw = pen().width();
00103         int dx = QABS(x1-x2);
00104         int dy = QABS(y1-y2);
00105         pw = pw*4/3+2; // approx pw*sqrt(2)
00106         int px = x1<x2 ? -pw : pw ;
00107         int py = y1<y2 ? -pw : pw ;
00108         if ( dx && dy && (dx > dy ? (dx*2/dy <= 2) : (dy*2/dx <= 2)) ) {
00109         // steep
00110                 if ( px == py ) {
00111                         p[0] = QPoint(x1   ,y1+py);
00112                         p[1] = QPoint(x2-px,y2   );
00113                         p[2] = QPoint(x2   ,y2-py);
00114                         p[3] = QPoint(x1+px,y1   );
00115                 } else {
00116                         p[0] = QPoint(x1+px,y1   );
00117                         p[1] = QPoint(x2   ,y2-py);
00118                         p[2] = QPoint(x2-px,y2   );
00119                         p[3] = QPoint(x1   ,y1+py);
00120                 }
00121         } else if ( dx > dy ) {
00122         // horizontal
00123                 p[0] = QPoint(x1+px,y1+py);
00124                 p[1] = QPoint(x2-px,y2+py);
00125                 p[2] = QPoint(x2-px,y2-py);
00126                 p[3] = QPoint(x1+px,y1-py);
00127         } else {
00128         // vertical
00129                 p[0] = QPoint(x1+px,y1+py);
00130                 p[1] = QPoint(x2+px,y2-py);
00131                 p[2] = QPoint(x2-px,y2-py);
00132                 p[3] = QPoint(x1-px,y1+py);
00133         }
00134         setItemPoints( p, false );
00135 }
00136 
00137 
00138 void DPLine::drawShape( QPainter & p )
00139 {
00140         int x1 = int(x()+offsetX());
00141         int y1 = int(y()+offsetY());
00142         int x2 = x1+width();
00143         int y2 = y1+height();
00144         
00145         p.drawLine( x1, y1, x2, y2 );
00146 }
00147 //END class DPLine
00148 
00149 
00150 //BEGIN class DPArrow
00151 Item* DPArrow::construct( ItemDocument *itemDocument, bool newItem, const char *id )
00152 {
00153         return new DPArrow( itemDocument, newItem, id );
00154 }
00155 
00156 LibraryItem* DPArrow::libraryItem()
00157 {
00158         return new LibraryItem(
00159                 QString("dp/arrow"),
00160                 i18n("Arrow"),
00161                 i18n("Other"),
00162                 KGlobal::iconLoader()->loadIcon( "text", KIcon::Small ),
00163                 LibraryItem::lit_drawpart,
00164                 DPArrow::construct );
00165 }
00166 
00167 DPArrow::DPArrow( ItemDocument *itemDocument, bool newItem, const char *id )
00168         : DPLine( itemDocument, newItem, id ? id : "arrow" )
00169 {
00170         m_name = i18n("Arrow");
00171         
00172         // We don't want to use the square cap style as it screws up drawing our arrow head
00173         QStringList allowed = property("cap-style")->allowed();
00174         allowed.remove( DrawPart::penCapStyleToName( Qt::SquareCap ) );
00175         property("cap-style")->setAllowed(allowed);
00176 }
00177 
00178 DPArrow::~DPArrow()
00179 {
00180 }
00181 
00182 
00183 void DPArrow::drawShape( QPainter & p )
00184 {
00185         int x1 = int(x()+offsetX());
00186         int y1 = int(y()+offsetY());
00187         int x2 = x1+width();
00188         int y2 = y1+height();
00189         
00190         p.drawLine( x1, y1, x2, y2 );
00191         
00192         double dx = x2-x1;
00193         double dy = y2-y1;
00194         
00195         if ( dx == 0. && dy == 0. ) return;
00196         
00197         double arrow_angle = ( dx == 0 ? (dy>0?(M_PI/2.):(-M_PI/2.)) : std::atan(dy/dx) );
00198         if ( dx < 0 ) arrow_angle += M_PI;
00199         
00200         double head_angle = 0.6; // Angle of arrowhead
00201         double head_length = 10.;
00202         
00203         // Position of arrowhead
00204         int x3 = int( x2 + head_length*std::cos( M_PI + arrow_angle - head_angle ) );
00205         int y3 = int( y2 + head_length*std::sin( M_PI + arrow_angle - head_angle ) );
00206         int x4 = int( x2 + head_length*std::cos( M_PI + arrow_angle + head_angle ) );
00207         int y4 = int( y2 + head_length*std::sin( M_PI + arrow_angle + head_angle ) );
00208         
00209         // Draw arrowhead
00210         QPen pen = p.pen();
00211         pen.setCapStyle( Qt::RoundCap );
00212         p.setPen(pen);
00213         p.setBrush(pen.color());
00214         QPointArray pa(3);
00215         pa[0] = QPoint( x2, y2 );
00216         pa[1] = QPoint( x3, y3 );
00217         pa[2] = QPoint( x4, y4 );
00218         p.drawPolygon(pa);
00219         p.drawPolyline(pa);
00220 //      p.drawLine( x2, y2, x3, y3 );
00221 //      p.drawLine( x2, y2, x4, y4 );
00222 }
00223 //END class DPLine
00224 

Generated on Tue May 8 17:05:29 2007 for KTechLab by  doxygen 1.5.1