karbon

vgradientwidget.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2001, The Karbon Developers
3 Copyright (C) 2002, The Karbon Developers
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include <tqlabel.h>
22#include <tqframe.h>
23#include <tqbitmap.h>
24
25#include <kcolorbutton.h>
26#include <kcombobox.h>
27#include <tdelocale.h>
28#include <tqpainter.h>
29#include <kiconloader.h>
30
31#include "vgradientwidget.h"
32#include "vcolordlg.h"
33#include "vfill.h"
34#include "vkopainter.h"
35#include "vcursor.h"
36
37#define midPoint_width 7
38#define midPoint_height 10
39static unsigned char midPoint_bits[] = {
40 0x08, 0x08, 0x1c, 0x1c, 0x2a, 0x2a, 0x08, 0x08, 0x08, 0x08
41};
42
43#define colorStopBorder_width 11
44#define colorStopBorder_height 11
45static unsigned char colorStopBorder_bits[] = {
46 0x20, 0x00, 0x50, 0x00, 0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x04, 0x01,
47 0x04, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x04, 0xff, 0x07
48};
49
50#define colorStop_width 9
51#define colorStop_height 10
52static unsigned char colorStop_bits[] = {
53 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x38, 0x00, 0x38, 0x00, 0x7c, 0x00,
54 0x7c, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xff, 0x01
55};
56
57VGradientWidget::VGradientWidget( VGradient& gradient, TQWidget* parent, const char* name )
58 : TQWidget( parent, name ), m_gradient( &gradient )
59{
60 setBackgroundMode( TQt::NoBackground );
61 setMinimumSize( 105, 35 );
62} // VGradientWidget::VGradientWidget
63
64VGradientWidget::~VGradientWidget()
65{
66} // VGradientWidget::~VGradientWidget
67
68void VGradientWidget::paintColorStop( TQPainter& p, int x, VColor& color )
69{
70 TQBitmap bitmap;
71
72 bitmap = TQBitmap( colorStop_width, colorStop_height, colorStop_bits, true );
73 bitmap.setMask( bitmap );
74 p.setPen( color );
75 p.drawPixmap( x - 4, 1, bitmap );
76
77 bitmap = TQBitmap( colorStopBorder_width, colorStopBorder_height, colorStopBorder_bits, true );
78 bitmap.setMask( bitmap );
79 p.setPen( TQt::black );
80 p.drawPixmap( x - 5, 1, bitmap );
81} // VGradientWidget::paintColorStop
82
83void VGradientWidget::paintMidPoint( TQPainter& p, int x )
84{
85 TQBitmap bitmap( midPoint_width, midPoint_height, midPoint_bits, true );
86 bitmap.setMask( bitmap );
87 p.setPen( TQt::black );
88 p.drawPixmap( x - 3, 1, bitmap );
89} // VGradientWidget::paintMidPoint
90
91void VGradientWidget::paintEvent( TQPaintEvent* )
92{
93 int w = width() - 4; // available width for gradient and points
94 int h = height() - 7; // available height for gradient and points
95 int ph = colorStopBorder_height + 2; // point marker height
96 int gh = h - ph; // gradient area height
97
98 TQPixmap pixmap( width(), height() );
99 VKoPainter gp( &pixmap, width(), height() );
100 gp.setRasterOp( TQt::XorROP );
101 VGradient gradient( *m_gradient );
102 gradient.setType( VGradient::linear );
103 gradient.setOrigin( KoPoint( 2, 2 ) );
104 gradient.setFocalPoint( KoPoint( 2, 2 ) );
105 gradient.setVector( KoPoint( 2 + w, 2 ) );
106 VFill fill;
107 TDEIconLoader il;
108 fill.pattern() = VPattern( il.iconPath( "karbon.png", TDEIcon::Small ) );
109 fill.setType( VFill::patt );
110 gp.setBrush( fill );
111 gp.drawRect( KoRect( 2, 2, w, gh ) );
112 fill.gradient() = gradient;
113 fill.setType( VFill::grad );
114 gp.setBrush( fill );
115 gp.drawRect( KoRect( 2, 2, w, gh ) );
116 gp.end();
117
118 TQPainter p( &pixmap );
119
120 p.setPen( colorGroup().light() );
121 // light frame around widget
122 p.moveTo( 1, height() - 1 );
123 p.lineTo( 1, 1 );
124 p.lineTo( width() - 1, 1 );
125 p.lineTo( width() - 1, height() - 1 );
126 p.lineTo( 1, height() - 1 );
127
128 // light line between gradient and point area
129 p.moveTo( 1, 3 + gh );
130 p.lineTo( width() - 1, 3 + gh );
131
132 p.setPen( colorGroup().dark() );
133 // left-top frame around widget
134 p.moveTo( 0, height() - 1 );
135 p.lineTo( 0, 0 );
136 p.lineTo( width() - 1, 0 );
137
138 // right-bottom from around gradient
139 p.moveTo( width() - 2, 2 );
140 p.lineTo( width() - 2, 2 + gh );
141 p.lineTo( 2, 2 + gh );
142
143 // upper line around point area
144 p.moveTo( 1, height() - 3 - ph );
145 p.lineTo( width() - 1, height() - 3 - ph );
146
147 // right-bottom line around point area
148 p.moveTo( width() - 2, height() - ph - 1 );
149 p.lineTo( width() - 2, height() - 2 );
150 p.lineTo( 2, height() - 2 );
151
152 m_pntArea.setRect( 2, height() - ph - 2, w, ph );
153 // clear point area
154 p.fillRect( m_pntArea.x(), m_pntArea.y(), m_pntArea.width(), m_pntArea.height(), colorGroup().background() );
155
156 p.setClipRect( m_pntArea.x(), m_pntArea.y(), m_pntArea.width(), m_pntArea.height() );
157 p.translate( m_pntArea.x(), m_pntArea.y() );
158
159 TQPtrList<VColorStop>& colorStops = m_gradient->m_colorStops;
160 if( colorStops.count() > 1 )
161 {
162 VColorStop* stop, *nextstop;
163 for( stop = colorStops.first(), nextstop = colorStops.next();
164 nextstop; stop = nextstop, nextstop = colorStops.next() )
165 {
166 paintColorStop( p, (int)( stop->rampPoint * m_pntArea.width() ), stop->color );
167 paintMidPoint( p, (int)(( stop->rampPoint + ( nextstop->rampPoint - stop->rampPoint ) * stop->midPoint ) * m_pntArea.width() ) );
168 }
169 paintColorStop( p, int( stop->rampPoint * w ), stop->color );
170 }
171 p.end();
172 bitBlt( this, 0, 0, &pixmap, 0, 0, width(), height() );
173} // VGradientWidget::paintEvent
174
175void VGradientWidget::mousePressEvent( TQMouseEvent* e )
176{
177 if( ! m_pntArea.contains( e->x(), e->y() ) )
178 return;
179
180 TQPtrList<VColorStop>& colorStops = m_gradient->m_colorStops;
181
182 currentPoint = 0;
183
184 int x = e->x() - m_pntArea.left();
185
186 int i = colorStops.count() - 1;
187 VColorStop *stop, *nextstop = 0;
188 for( stop = colorStops.last(); i >= 0; i--, stop = colorStops.prev() )
189 {
190 int r = int( stop->rampPoint * m_pntArea.width() );
191 if( nextstop )
192 {
193 int m = int( ( stop->rampPoint + ( nextstop->rampPoint - stop->rampPoint ) * stop->midPoint ) * m_pntArea.width() );
194 if( ( x > m - 5 ) && ( x < m + 5 ) )
195 {
196 // found mid point at position
197 currentPoint = 2 * i + 2;
198 if( e->button() == TQt::LeftButton )
199 setCursor( VCursor::horzMove() );
200 return;
201 }
202 }
203 if( ( x > r - 5 ) && ( x < r + 5 ) )
204 {
205 // found ramp point at position
206 currentPoint = 2 * i + 1;
207 if( e->button() == TQt::LeftButton )
208 setCursor( VCursor::horzMove() );
209 return;
210 }
211
212 nextstop = stop;
213 }
214} // VGradientWidget::mousePressEvent
215
216void VGradientWidget::mouseReleaseEvent( TQMouseEvent* e )
217{
218 if( e->button() == TQt::RightButton && currentPoint )
219 {
220 if( m_pntArea.contains( e->x(), e->y() ) && ( currentPoint % 2 == 1 ) )
221 {
222 int x = e->x() - m_pntArea.left();
223 // check if we are still above the actual ramp point
224 int r = int( m_gradient->m_colorStops.at( int(0.5 * currentPoint) )->rampPoint * m_pntArea.width() );
225 if( ( x > r - 5 ) && ( x < r + 5 ) )
226 {
227 m_gradient->m_colorStops.remove( int(0.5 * currentPoint) );
228 update();
229 emit changed();
230 }
231 }
232 }
233 setCursor( TQCursor( TQt::ArrowCursor ) );
234} // VGradientWidget::mouseReleaseEvent
235
236void VGradientWidget::mouseDoubleClickEvent( TQMouseEvent* e )
237{
238 if( ! m_pntArea.contains( e->x(), e->y() ) )
239 return;
240
241 if( e->button() != TQt::LeftButton )
242 return;
243
244 if( currentPoint % 2 == 1 )
245 {
246 // ramp point hit -> change color
247 VColorDlg* d = new VColorDlg( m_gradient->m_colorStops.at( currentPoint / 2 )->color, this->topLevelWidget() );
248 if( d->exec() == TQDialog::Accepted )
249 {
250 m_gradient->m_colorStops.at( currentPoint / 2 )->color = d->Color();
251 update();
252 emit changed();
253 }
254 delete d;
255 }
256 else if( currentPoint == 0 )
257 {
258 // now point hit -> create new color stop
259 VColorDlg* d = new VColorDlg( m_gradient->m_colorStops.at( 0 )->color, this->topLevelWidget() );
260 if( d->exec() == TQDialog::Accepted )
261 {
262 m_gradient->addStop( d->Color(), (float)( e->x() - 2 ) / ( m_pntArea.width() ), 0.5 );
263 update();
264 emit changed();
265 }
266 delete d;
267 }
268} // VGradientWidget::mouseDoubleClickEvent
269
270void VGradientWidget::mouseMoveEvent( TQMouseEvent* e )
271{
272 if( e->state() & TQt::RightButton )
273 return;
274
275 TQPtrList<VColorStop>& colorStops = m_gradient->m_colorStops;
276
277 if( currentPoint >= colorStops.count() * 2 )
278 return;
279
280 int x = e->x() - m_pntArea.left();
281
282 if( currentPoint % 2 == 1 )
283 {
284 // move ramp point
285 int actRP = int( 0.5 * ( currentPoint - 1 ) );
286 int prevRP = actRP - 1;
287 int nextRP = int( 0.5 * ( currentPoint + 1 ) );
288 // Clip the color stop between to others.
289 x = kMin( x, ( actRP < int( colorStops.count() - 1 ) ) ? int( colorStops.at( nextRP )->rampPoint * m_pntArea.width() ) : m_pntArea.width() );
290 x = kMax( x, ( actRP > 0 ) ? int( colorStops.at( prevRP )->rampPoint * m_pntArea.width() ) : 0 );
291 colorStops.at( actRP )->rampPoint = (float)( x ) / m_pntArea.width();
292 update();
293 emit changed();
294 }
295 else if( currentPoint > 0 )
296 {
297 // move mid point
298 int prevRP = int( 0.5 * ( currentPoint - 1 ) );
299 int nextRP = int( 0.5 * ( currentPoint + 1 ) );
300 // Clip the mid point between to ramp points.
301 x = kMin( x, int( colorStops.at( nextRP )->rampPoint * m_pntArea.width() ) );
302 x = kMax( x, int( colorStops.at( prevRP )->rampPoint * m_pntArea.width() ) );
303 colorStops.at( prevRP )->midPoint = ( (float)( x ) / m_pntArea.width() - ( colorStops.at( prevRP )->rampPoint ) ) / ( colorStops.at( nextRP )->rampPoint - colorStops.at( prevRP )->rampPoint );
304 update();
305 emit changed();
306 }
307} // VGradientWidget::mouseMoveEvent
308
309#include "vgradientwidget.moc"
This class keeps track of color properties.
Definition vcolor.h:41
@ grad
solid fill
Definition vfill.h:51
@ patt
gradient fill
Definition vfill.h:52