marginpreview.cpp

00001 /*
00002  *  This file is part of the KDE libraries
00003  *  Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be>
00004  *
00005  *  This library is free software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License version 2 as published by the Free Software Foundation.
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., 51 Franklin Street, Fifth Floor,
00017  *  Boston, MA 02110-1301, USA.
00018  **/
00019 
00020 #include "marginpreview.h"
00021 
00022 #include <klocale.h>
00023 #include <kdebug.h>
00024 #include <qpainter.h>
00025 #include <kcursor.h>
00026 
00027 #define A4_WIDTH    595
00028 #define A4_HEIGHT   842
00029 #define A4_TOP      36
00030 #define A4_BOTTOM   806
00031 #define A4_LEFT     18
00032 #define A4_RIGHT    577
00033 
00034 #define SCALE(d,z)  ((int)(float(d)*z+0.5))
00035 #define UNSCALE(d,z)    ((int)(float(d)/z+0.5))
00036 
00037 static void draw3DPage(QPainter *p, QRect r)
00038 {
00039     // draw white page
00040     p->fillRect(r,Qt::white);
00041     // draw 3D border
00042     p->setPen(Qt::black);
00043     p->moveTo(r.left(),r.bottom());
00044     p->lineTo(r.right(),r.bottom());
00045     p->lineTo(r.right(),r.top());
00046     p->setPen(Qt::darkGray);
00047     p->lineTo(r.left(),r.top());
00048     p->lineTo(r.left(),r.bottom());
00049     p->setPen(Qt::gray);
00050     p->moveTo(r.left()+1,r.bottom()-1);
00051     p->lineTo(r.right()-1,r.bottom()-1);
00052     p->lineTo(r.right()-1,r.top()+1);
00053 }
00054 
00055 MarginPreview::MarginPreview(QWidget *parent, const char *name)
00056     : QWidget(parent,name)
00057 {
00058     width_ = A4_WIDTH;
00059     height_ = A4_HEIGHT;
00060     top_ = A4_TOP;
00061     bottom_ = A4_BOTTOM;
00062     left_ = A4_LEFT;
00063     right_ = A4_RIGHT;
00064     nopreview_ = false;
00065 
00066     box_ = rect();
00067     zoom_ = 1.0;
00068     state_ = Fixed;
00069     oldpos_ = -1;
00070     symetric_ = false;
00071 
00072     setMouseTracking(true);
00073 }
00074 
00075 MarginPreview::~MarginPreview()
00076 {
00077 }
00078 
00079 void MarginPreview::setPageSize(float w, float h)
00080 {
00081     setNoPreview(w <= 0 && h <= 0);
00082     // do not change relative margins when changing page size !!
00083     float   old_b(height_-bottom_), old_r(width_-right_);
00084     width_ = w;
00085     height_ = h;
00086     resizeEvent(NULL);
00087     setMargins(top_,old_b,left_,old_r);
00088     update();
00089 }
00090 
00091 void MarginPreview::setMargins(float t, float b, float l, float r)
00092 {
00093     top_ = t;
00094     left_ = l;
00095     bottom_ = height_-b;
00096     right_ = width_-r;
00097     update();
00098 }
00099 
00100 void MarginPreview::setSymetric(bool on)
00101 {
00102     symetric_ = on;
00103 }
00104 
00105 void MarginPreview::resizeEvent(QResizeEvent *)
00106 {
00107     if (width_/height_ > float(width())/height())
00108     {
00109         zoom_ = float(width()-3)/width_;
00110         box_.setLeft(1);
00111         box_.setRight(width()-3);
00112         int m = (height()-3-SCALE(height_,zoom_))/2;
00113         box_.setTop(m+1);
00114         box_.setBottom(height()-m-3);
00115     }
00116     else
00117     {
00118         zoom_ = float(height()-3)/height_;
00119         box_.setTop(1);
00120         box_.setBottom(height()-3);
00121         int m = (width()-3-SCALE(width_,zoom_))/2;
00122         box_.setLeft(m+1);
00123         box_.setRight(width()-m-3);
00124     }
00125 }
00126 
00127 void MarginPreview::paintEvent(QPaintEvent *)
00128 {
00129     QPainter    p(this);
00130 
00131     QRect   pagebox(QPoint(box_.left()-1,box_.top()-1),QPoint(box_.right()+2,box_.bottom()+2));
00132 
00133     if (nopreview_)
00134     {
00135         p.drawText(pagebox,AlignCenter,i18n("No preview available"));
00136     }
00137     else
00138     {
00139         draw3DPage(&p,pagebox);
00140 
00141         // draw margins
00142         p.setPen(DotLine);
00143         int m = box_.left()+SCALE(left_,zoom_);
00144         margbox_.setLeft(m+1);
00145         p.drawLine(m,box_.top(),m,box_.bottom());
00146         m = box_.left()+SCALE(right_,zoom_);
00147         margbox_.setRight(m-1);
00148         p.drawLine(m,box_.top(),m,box_.bottom());
00149         m = box_.top()+SCALE(top_,zoom_);
00150         margbox_.setTop(m+1);
00151         p.drawLine(box_.left(),m,box_.right(),m);
00152         m = box_.top()+SCALE(bottom_,zoom_);
00153         margbox_.setBottom(m-1);
00154         p.drawLine(box_.left(),m,box_.right(),m);
00155 
00156         // fill useful area
00157         p.fillRect(margbox_,QColor(220,220,220));
00158     }
00159 }
00160 
00161 void MarginPreview::setNoPreview(bool on)
00162 {
00163     nopreview_ = on;
00164     update();
00165 }
00166 
00167 // 0: nothing
00168 // 1: top
00169 // 2: bottom
00170 // 3: left
00171 // 4: right
00172 int MarginPreview::locateMouse(const QPoint& p)
00173 {
00174     int tol = 2;
00175     if (p.x() <= margbox_.left()+tol && p.x() >= margbox_.left()-tol)
00176         return LMoving;
00177     else if (p.x() <= margbox_.right()+tol && p.x() >= margbox_.right()-tol)
00178         return RMoving;
00179     else if (p.y() <= margbox_.top()+tol && p.y() >= margbox_.top()-tol)
00180         return TMoving;
00181     else if (p.y() <= margbox_.bottom()+tol && p.y() >= margbox_.bottom()-tol)
00182         return BMoving;
00183     else
00184         return 0;
00185 }
00186 
00187 void MarginPreview::mouseMoveEvent(QMouseEvent *e)
00188 {
00189     if (nopreview_ || state_ == Fixed)
00190         return;
00191     int pos = locateMouse(e->pos());
00192     if (state_ == None && e->button() == Qt::NoButton)
00193     {
00194         switch (pos)
00195         {
00196             case 1:
00197             case 2:
00198                 setCursor(KCursor::sizeVerCursor());
00199                 break;
00200             case 3:
00201             case 4:
00202                 setCursor(KCursor::sizeHorCursor());
00203                 break;
00204             default:
00205                 setCursor(KCursor::arrowCursor());
00206                 break;
00207         }
00208     }
00209     else if (state_ > None)
00210     {
00211         int newpos = -1;
00212         switch (state_)
00213         {
00214             case TMoving:
00215                 newpos = QMIN(QMAX(e->pos().y(), box_.top()), (symetric_ ? (box_.top()+box_.bottom())/2 : margbox_.bottom()+1));
00216                 break;
00217             case BMoving:
00218                 newpos = QMIN(QMAX(e->pos().y(), (symetric_? (box_.top()+box_.bottom()+1)/2 : margbox_.top()-1)), box_.bottom());
00219                 break;
00220             case LMoving:
00221                 newpos = QMIN(QMAX(e->pos().x(), box_.left()), (symetric_ ? (box_.left()+box_.right())/2 : margbox_.right()+1));
00222                 break;
00223             case RMoving:
00224                 newpos = QMIN(QMAX(e->pos().x(), (symetric_ ? (box_.left()+box_.right()+1)/2 : margbox_.left()-1)), box_.right());
00225                 break;
00226         }
00227         if (newpos != oldpos_)
00228         {
00229             QPainter    p(this);
00230             p.setRasterOp(Qt::XorROP);
00231             p.setPen(gray);
00232             for (int i=0; i<2; i++, oldpos_ = newpos)
00233             {
00234                 if (oldpos_ >= 0)
00235                     drawTempLine(&p);
00236             }
00237         }
00238     }
00239 }
00240 
00241 void MarginPreview::drawTempLine(QPainter *p)
00242 {
00243     if (state_ >= LMoving)
00244     {
00245         p->drawLine(oldpos_, box_.top(), oldpos_, box_.bottom());
00246         if (symetric_)
00247         {
00248             int mirror = box_.left()+box_.right()-oldpos_;
00249             p->drawLine(mirror, box_.top(), mirror, box_.bottom());
00250         }
00251     }
00252     else
00253     {
00254         p->drawLine(box_.left(), oldpos_, box_.right(), oldpos_);
00255         if (symetric_)
00256         {
00257             int mirror = box_.top()+box_.bottom()-oldpos_;
00258             p->drawLine(box_.left(), mirror, box_.right(), mirror);
00259         }
00260     }
00261 }
00262 
00263 void MarginPreview::mousePressEvent(QMouseEvent *e)
00264 {
00265     if (e->button() != Qt::LeftButton || state_ != None)
00266         return;
00267     int mpos = locateMouse(e->pos());
00268     if (mpos)
00269     {
00270         state_ = mpos;
00271     }
00272 }
00273 
00274 void MarginPreview::mouseReleaseEvent(QMouseEvent *e)
00275 {
00276     if (state_ > None)
00277     {
00278         QPainter    p(this);
00279         p.setRasterOp(Qt::XorROP);
00280         p.setPen(gray);
00281         if (oldpos_ >= 0)
00282         {
00283             drawTempLine(&p);
00284             if (e)
00285             {
00286                 float   val = 0;
00287                 int st(state_);
00288                 if (symetric_ && (st == BMoving || st == RMoving))
00289                     st--;
00290                 switch (st)
00291                 {
00292                     case TMoving:
00293                         val = top_ = UNSCALE(oldpos_-box_.top(), zoom_);
00294                         if (symetric_)
00295                             bottom_ = height_-top_;
00296                         break;
00297                     case BMoving:
00298                         bottom_ = UNSCALE(oldpos_-box_.top(), zoom_);
00299                         val = UNSCALE(box_.bottom()-oldpos_, zoom_);
00300                         break;
00301                     case LMoving:
00302                         val = left_ = UNSCALE(oldpos_-box_.left(), zoom_);
00303                         if (symetric_)
00304                             right_ = width_-left_;
00305                         break;
00306                     case RMoving:
00307                         right_ = UNSCALE(oldpos_-box_.left(), zoom_);
00308                         val = UNSCALE(box_.right()-oldpos_, zoom_);
00309                         break;
00310                 }
00311                 update();
00312                 emit marginChanged(st, val);
00313             }
00314         }
00315         state_ = 0;
00316         oldpos_ = -1;
00317     }
00318 }
00319 
00320 void MarginPreview::enableRubberBand(bool on)
00321 {
00322     if (on && state_ == Fixed)
00323         state_ = None;
00324     else if (!on && state_ > Fixed)
00325     {
00326         mouseReleaseEvent(NULL);
00327         state_ = Fixed;
00328     }
00329 }
00330 
00331 #include "marginpreview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys