lib Library API Documentation

koborder.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2000, 2001 Thomas Zander <zander@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #include "koborder.h"
00021 #include <qdom.h>
00022 #include <kdebug.h>
00023 #include "kozoomhandler.h"
00024 #include "kotextformat.h"
00025 #include "korichtext.h" // for KoTextFormat
00026 #include <float.h>
00027 
00028 static const struct BorderStyle {
00029     QPen::PenStyle penStyle;
00030     QCString oasisName;
00031     QCString uiStringStyle;
00032 } s_borderStyles[] = {
00033     { QPen::SolidLine, "solid", "_________" }, // SOLID
00034     { QPen::DashLine, "dashed", "___ ___ __" }, // DASH
00035     { QPen::DotLine, "dotted", "_ _ _ _ _ _" }, // DOT
00036     { QPen::DashDotLine, "dot-dash", "___ _ ___ _" }, // DASH_DOT
00037     { QPen::DashDotDotLine, "dot-dot-dash", "___ _ _ ___" }, // DASH_DOT_DOT
00038     { QPen::SolidLine, "double", "===========" } // DOUBLE_LINE
00039 };
00040 
00041 KoBorder::KoBorder()
00042     : color(), m_style( SOLID )
00043 {
00044     setPenWidth( 1 );
00045 }
00046 
00047 KoBorder::KoBorder( const QColor & c, BorderStyle s, double width )
00048     : color( c ), m_style( s )
00049 {
00050     setPenWidth( width );
00051 }
00052 
00053 bool KoBorder::operator==( const KoBorder _brd ) const {
00054     return ( m_style == _brd.m_style && color == _brd.color && ptPenWidth == _brd.ptPenWidth );
00055 }
00056 
00057 bool KoBorder::operator!=( const KoBorder _brd ) const {
00058     return ( m_style != _brd.m_style || color != _brd.color || ptPenWidth != _brd.ptPenWidth );
00059 }
00060 
00061 void KoBorder::setStyle(BorderStyle _style)
00062 {
00063     m_style = _style;
00064     setPenWidth( ptPenWidth );
00065 }
00066 
00067 void KoBorder::setPenWidth(double _w)
00068 {
00069     ptPenWidth = _w;
00070     if ( m_style == KoBorder::DOUBLE_LINE )
00071         ptWidth = 2 * ptPenWidth + 1;
00072     else
00073         ptWidth = _w;
00074 }
00075 
00076 QPen KoBorder::borderPen( const KoBorder & _brd, int width, QColor defaultColor )
00077 {
00078     QPen pen( _brd.color, width );
00079     if ( !_brd.color.isValid() )
00080         pen.setColor( defaultColor );
00081 
00082     pen.setStyle( s_borderStyles[ _brd.m_style ].penStyle );
00083 
00084     return pen;
00085 }
00086 
00087 // KOffice-1.3 file format (deprecated)
00088 KoBorder KoBorder::loadBorder( const QDomElement & elem )
00089 {
00090     KoBorder bd;
00091     if ( elem.hasAttribute("red") )
00092     {
00093         int r = elem.attribute("red").toInt();
00094         int g = elem.attribute("green").toInt();
00095         int b = elem.attribute("blue").toInt();
00096         bd.color.setRgb( r, g, b );
00097     }
00098     bd.m_style = static_cast<BorderStyle>( elem.attribute("style").toInt() );
00099     bd.setPenWidth( elem.attribute("width").toDouble() );
00100     return bd;
00101 }
00102 
00103 void KoBorder::loadFoBorder( const QString& border )
00104 {
00105     //string like "0.088cm solid #800000"
00106 
00107     if (border.isEmpty() || border=="none" || border=="hidden") // in fact no border
00108         return;
00109 
00110     // ## isn't it faster to use QStringList::split than parse it 3 times?
00111     QString _width = border.section(' ', 0, 0);
00112     QCString _style = border.section(' ', 1, 1).latin1();
00113     QString _color = border.section(' ', 2, 2);
00114 
00115     double const width = KoUnit::parseValue( _width, 1.0 );
00116     //TODO: let the user choose a more precise border width with KUIntSpinBox (or something like that)
00117     if ( width < 1 )
00118          setPenWidth( 1 );
00119     else
00120         setPenWidth( width );
00121 
00122     m_style = SOLID;
00123     for ( uint i = 0; i < sizeof( s_borderStyles ) / sizeof *s_borderStyles; ++i ) {
00124         if ( _style == s_borderStyles[i].oasisName )
00125             m_style = static_cast<BorderStyle>( i );
00126     }
00127 
00128     if ( _color.isEmpty() )
00129         color = QColor();
00130     else
00131         color.setNamedColor( _color );
00132 }
00133 
00134 QString KoBorder::saveFoBorder() const
00135 {
00136     if ( QABS( ptPenWidth ) < 1E-10 ) // i.e. ptPenWidth == 0
00137         return "none";
00138     //string like "2pt solid #800000"
00139     QString str = QString::number( ptPenWidth, 'g', DBL_DIG );
00140     str += "pt ";
00141     str += s_borderStyles[ m_style ].oasisName;
00142     if ( color.isValid() ) {
00143         str += ' ';
00144         str += color.name();
00145     }
00146     return str;
00147 }
00148 
00149 // KOffice-1.3 file format (deprecated)
00150 void KoBorder::save( QDomElement & elem ) const
00151 {
00152     if (color.isValid()) {
00153         elem.setAttribute("red", color.red());
00154         elem.setAttribute("green", color.green());
00155         elem.setAttribute("blue", color.blue());
00156     }
00157     elem.setAttribute("style", static_cast<int>( m_style ));
00158     elem.setAttribute("width", ptPenWidth);
00159 }
00160 
00161 KoBorder::BorderStyle KoBorder::getStyle( const QString &style )
00162 {
00163     for ( uint i = 0; i < sizeof( s_borderStyles ) / sizeof *s_borderStyles; ++i ) {
00164         if ( style == s_borderStyles[i].uiStringStyle.data() )
00165             return static_cast<BorderStyle>( i );
00166     }
00167     // default
00168     return KoBorder::SOLID;
00169 }
00170 
00171 QString KoBorder::getStyle( const BorderStyle &style )
00172 {
00173     return s_borderStyles[style].uiStringStyle;
00174 }
00175 
00176 int KoBorder::zoomWidthX( double ptWidth, KoZoomHandler * zoomHandler, int minborder )
00177 {
00178     // If a border was set, then zoom it and apply a minimum of 1, so that it's always visible.
00179     // If no border was set, apply minborder ( 0 for paragraphs, 1 for frames )
00180     return ptWidth > 0 ? QMAX( 1, zoomHandler->zoomItX( ptWidth ) /*applies qRound*/ ) : minborder;
00181 }
00182 
00183 int KoBorder::zoomWidthY( double ptWidth, KoZoomHandler * zoomHandler, int minborder )
00184 {
00185     // If a border was set, then zoom it and apply a minimum of 1, so that it's always visible.
00186     // If no border was set, apply minborder ( 0 for paragraphs, 1 for frames )
00187     return ptWidth > 0 ? QMAX( 1, zoomHandler->zoomItY( ptWidth ) /*applies qRound*/ ) : minborder;
00188 }
00189 
00190 void KoBorder::drawBorders( QPainter& painter, KoZoomHandler * zoomHandler, const QRect& rect, const KoBorder& leftBorder, const KoBorder& rightBorder, const KoBorder& topBorder, const KoBorder& bottomBorder, int minborder, const QPen& defaultPen )
00191 {
00192     int topBorderWidth = zoomWidthY( topBorder.width(), zoomHandler, minborder );
00193     int bottomBorderWidth = zoomWidthY( bottomBorder.width(), zoomHandler, minborder );
00194     int leftBorderWidth = zoomWidthX( leftBorder.width(), zoomHandler, minborder );
00195     int rightBorderWidth = zoomWidthX( rightBorder.width(), zoomHandler, minborder );
00196 
00197     int topBorderPenWidth = zoomWidthY( topBorder.penWidth(), zoomHandler, minborder );
00198     int bottomBorderPenWidth = zoomWidthY( bottomBorder.penWidth(), zoomHandler, minborder );
00199     int leftBorderPenWidth = zoomWidthX( leftBorder.penWidth(), zoomHandler, minborder );
00200     int rightBorderPenWidth = zoomWidthX( rightBorder.penWidth(), zoomHandler, minborder );
00201 
00202     // Wide pen don't draw the last pixel, so add one to the bottom and right coords
00203     int lastPixelAdj = 1;
00204 
00205     //kdDebug(32500) << "KoBorder::drawBorders widths: top=" << topBorderWidth << " bottom=" << bottomBorderWidth
00206     //               << " left=" << leftBorderWidth << " right=" << rightBorderWidth << endl;
00207 
00208     //kdDebug(32500) << "                   penWidths: top=" << topBorderPenWidth << " bottom=" << bottomBorderPenWidth
00209     //               << " left=" << leftBorderPenWidth << " right=" << rightBorderPenWidth << endl;
00210 
00211     QColor defaultColor = KoTextFormat::defaultTextColor( &painter );
00212 
00213     if ( topBorderWidth > 0 )
00214     {
00215         if ( topBorder.penWidth() > 0 )
00216             painter.setPen( KoBorder::borderPen( topBorder, topBorderPenWidth, defaultColor ) );
00217         else
00218             painter.setPen( defaultPen );
00219         int y = rect.top() - topBorderWidth + topBorderPenWidth/2;
00220         if ( topBorder.m_style==KoBorder::DOUBLE_LINE)
00221         {
00222             painter.drawLine( rect.left()-leftBorderWidth, y, rect.right()+2*(rightBorderPenWidth+lastPixelAdj), y );
00223             y += topBorderPenWidth + 1;
00224             painter.drawLine( rect.left()-leftBorderPenWidth, y, rect.right()+rightBorderPenWidth+lastPixelAdj, y );
00225         }
00226         else
00227         {
00228             painter.drawLine( rect.left()-leftBorderWidth, y, rect.right()+rightBorderWidth+lastPixelAdj, y );
00229         }
00230     }
00231     if ( bottomBorderWidth > 0 )
00232     {
00233         if ( bottomBorder.penWidth() > 0 )
00234             painter.setPen( KoBorder::borderPen( bottomBorder, bottomBorderPenWidth, defaultColor ) );
00235         else
00236             painter.setPen( defaultPen );
00237     //kdDebug(32500) << "bottomBorderWidth=" << bottomBorderWidth << " bottomBorderWidth/2=" << (int)bottomBorderWidth/2 << endl;
00238         int y = rect.bottom() + bottomBorderPenWidth/2 + 1;
00239     //kdDebug(32500) << "   -> bottom=" << rect.bottom() << " y=" << y << endl;
00240         if ( bottomBorder.m_style==KoBorder::DOUBLE_LINE)
00241         {
00242             painter.drawLine( rect.left()-leftBorderPenWidth, y, rect.right()+rightBorderPenWidth+lastPixelAdj, y );
00243             y += bottomBorderPenWidth + 1;
00244             painter.drawLine( rect.left()-leftBorderWidth, y, rect.right()+2*(rightBorderPenWidth+lastPixelAdj), y );
00245         }
00246         else
00247         {
00248             painter.drawLine( rect.left()-leftBorderWidth, y, rect.right()+rightBorderWidth+lastPixelAdj, y );
00249         }
00250     }
00251     if ( leftBorderWidth > 0 )
00252     {
00253         if ( leftBorder.penWidth() > 0 )
00254             painter.setPen( KoBorder::borderPen( leftBorder, leftBorderPenWidth, defaultColor ) );
00255         else
00256             painter.setPen( defaultPen );
00257         int x = rect.left() - leftBorderWidth + leftBorderPenWidth/2;
00258         if ( leftBorder.m_style==KoBorder::DOUBLE_LINE)
00259         {
00260             painter.drawLine( x, rect.top()-topBorderWidth, x, rect.bottom()+2*(bottomBorderPenWidth+lastPixelAdj) );
00261             x += leftBorderPenWidth + 1;
00262             painter.drawLine( x, rect.top()-topBorderPenWidth, x, rect.bottom()+bottomBorderPenWidth+lastPixelAdj );
00263         }
00264         else
00265         {
00266             int yTop = rect.top() - topBorderWidth;
00267             int yBottom = rect.bottom() + bottomBorderWidth;
00268             /*kdDebug(32500) << " pen=" << painter.pen() << " rect=" << rect << " topBorderWidth=" << topBorderWidth
00269                            << " painting from " << x << "," << yTop
00270                            << " to " << x << "," << yBottom << endl;*/
00271             painter.drawLine( x, yTop, x, yBottom+lastPixelAdj );
00272         }
00273     }
00274     if ( rightBorderWidth > 0 )
00275     {
00276         if ( rightBorder.penWidth() > 0 )
00277             painter.setPen( KoBorder::borderPen( rightBorder, rightBorderPenWidth, defaultColor ) );
00278         else
00279             painter.setPen( defaultPen );
00280         int x = rect.right() + rightBorderPenWidth/2 + 1;
00281         if ( rightBorder.m_style==KoBorder::DOUBLE_LINE)
00282         {
00283             painter.drawLine( x, rect.top()-topBorderPenWidth, x, rect.bottom()+bottomBorderPenWidth+lastPixelAdj );
00284             x += rightBorderPenWidth + 1;
00285             painter.drawLine( x, rect.top()-topBorderWidth, x, rect.bottom()+2*(bottomBorderPenWidth+lastPixelAdj) );
00286 
00287         }
00288         else
00289         {
00290             int yTop = rect.top()-topBorderWidth;
00291             int yBottom = rect.bottom()+bottomBorderWidth+lastPixelAdj;
00292             /*kdDebug(32500) << " pen=" << painter.pen() << " rect=" << rect << " topBorderWidth=" << topBorderWidth
00293                            << " painting from " << x << "," << yTop
00294                            << " to " << x << "," << yBottom << endl;*/
00295             painter.drawLine( x, yTop, x, yBottom );
00296         }
00297     }
00298 }
KDE Logo
This file is part of the documentation for lib Library Version 1.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Feb 13 09:39:59 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003