chalk

kis_birdeye_box.cpp
1/*
2 * Copyright (c) 2004 Kivio Team
3 * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program 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
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20#include "tqlayout.h"
21#include "tqlabel.h"
22#include "tqpixmap.h"
23#include "tqpainter.h"
24#include "tqimage.h"
25#include "config.h"
26#include LCMS_HEADER
27#include "tdelocale.h"
28#include "tqtooltip.h"
29
30#include "kis_view.h"
31#include "kis_doc.h"
32#include "kis_canvas_controller.h"
33#include "kis_birdeye_box.h"
34#include "kis_double_widget.h"
35#include "kis_canvas.h"
36#include "kis_image.h"
37#include "kis_rect.h"
38#include "kis_iterators_pixel.h"
39
40#include "kobirdeyepanel.h"
41
42namespace {
43
44 class CanvasAdapter : public KoCanvasAdapter {
45
46 public:
47 CanvasAdapter(KisCanvasSubject * canvasSubject) : KoCanvasAdapter(), m_canvasSubject(canvasSubject) {}
48 virtual ~CanvasAdapter() {}
49
50 public:
51
52 virtual KoRect visibleArea()
53 {
54 if (!m_canvasSubject->currentImg()) return KoRect(0,0,0,0);
55
56 KisCanvasController * c = m_canvasSubject->canvasController();
57
58 if (c && c->kiscanvas())
59 return c->viewToWindow(KisRect(0, 0, c->kiscanvas()->width(), c->kiscanvas()->height()));
60 else
61 return KoRect(0,0,0,0);
62 }
63
64 virtual double zoomFactor()
65 {
66 return m_canvasSubject->zoomFactor();
67 }
68
69 virtual TQRect size()
70 {
71 if (!m_canvasSubject->currentImg()) return TQRect(0,0,0,0);
72
73 return TQRect(0, 0, m_canvasSubject->currentImg()->width(), m_canvasSubject->currentImg()->height());
74 }
75
76 virtual void setViewCenterPoint(double x, double y)
77 {
78 m_canvasSubject->canvasController()->zoomAroundPoint(x, y, m_canvasSubject->zoomFactor());
79 }
80
81 private:
82
83 KisCanvasSubject * m_canvasSubject;
84
85 };
86
87 class ZoomListener : public KoZoomAdapter {
88
89 public:
90
91 ZoomListener(KisCanvasController * canvasController)
93 , m_canvasController(canvasController) {}
94 virtual ~ZoomListener() {}
95
96 public:
97
98 void zoomTo( double x, double y, double factor ) { m_canvasController->zoomAroundPoint(x, y, factor); }
99 void zoomIn() { m_canvasController->zoomIn(); }
100 void zoomOut() { m_canvasController->zoomOut(); }
101 double getMinZoom() { return (1.0 / 500); }
102 double getMaxZoom() { return 16.0; }
103
104 private:
105
106 KisCanvasController * m_canvasController;
107
108 };
109
110 class ThumbnailProvider : public KoThumbnailAdapter {
111
112 public:
113 ThumbnailProvider(KisImageSP image, KisCanvasSubject* canvasSubject)
114 : KoThumbnailAdapter()
115 , m_image(image)
116 , m_canvasSubject(canvasSubject) {}
117
118 virtual ~ThumbnailProvider() {}
119
120 public:
121
122 virtual TQSize pixelSize()
123 {
124 if (!m_image) return TQSize(0, 0);
125 return TQSize(m_image->width(), m_image->height());
126 }
127
128 virtual TQImage image(TQRect r, TQSize thumbnailSize)
129 {
130 if (!m_image || r.isEmpty() || thumbnailSize.width() == 0 || thumbnailSize.height() == 0) {
131 return TQImage();
132 }
133
134 KisPaintDevice thumbnailRect(m_image->colorSpace(), "thumbnailRect");
135 KisPaintDeviceSP mergedImage = m_image->projection();
136
137 TQ_INT32 imageWidth = m_image->width();
138 TQ_INT32 imageHeight = m_image->height();
139 TQ_UINT32 pixelSize = m_image->colorSpace()->pixelSize();
140
141 for (TQ_INT32 y = 0; y < r.height(); ++y) {
142
143 KisHLineIteratorPixel it = thumbnailRect.createHLineIterator(0, y, r.width(), true);
144 TQ_INT32 thumbnailY = r.y() + y;
145 TQ_INT32 thumbnailX = r.x();
146 TQ_INT32 imageY = (thumbnailY * imageHeight) / thumbnailSize.height();
147 KisHLineIteratorPixel srcIt = mergedImage -> createHLineIterator(0, imageY, imageWidth, false);
148
149 while (!it.isDone()) {
150
151 TQ_INT32 imageX = (thumbnailX * imageWidth) / thumbnailSize.width();
152 TQ_INT32 dx = imageX - srcIt.x();
153 srcIt += dx;
154
155 //KisColor pixelColor = mergedImage->colorAt(imageX, imageY);
156 memcpy(it.rawData(), srcIt.rawData(), pixelSize);
157
158 ++it;
159 ++thumbnailX;
160 }
161 }
162
163 return thumbnailRect.convertToTQImage(m_canvasSubject->monitorProfile(), 0, 0, r.width(), r.height(),
164 m_canvasSubject->HDRExposure());
165 }
166
167 void setImage(KisImageSP image)
168 {
169 m_image = image;
170 }
171 private:
172
173 KisImageSP m_image;
174 KisCanvasSubject * m_canvasSubject;
175
176 };
177
178}
179
180KisBirdEyeBox::KisBirdEyeBox(KisView * view, TQWidget* parent, const char* name)
181 : TQWidget(parent, name)
182 , m_view(view)
183 , m_subject(view->canvasSubject())
184{
185 TQVBoxLayout * l = new TQVBoxLayout(this);
186
187 m_image = m_subject->currentImg();
188
189 m_zoomAdapter = new ZoomListener(m_subject->canvasController()); // The birdeye panel deletes
190 KoThumbnailAdapter * ktp = new ThumbnailProvider(m_image, m_subject); // The birdeye panel deletes
191 KoCanvasAdapter * kpc = new CanvasAdapter(m_subject); // The birdeye panel deletes
192
193 m_birdEyePanel = new KoBirdEyePanel(m_zoomAdapter, ktp, kpc, this);
194
195 connect(view, TQ_SIGNAL(cursorPosition( TQ_INT32, TQ_INT32 )), m_birdEyePanel, TQ_SLOT(cursorPosChanged( TQ_INT32, TQ_INT32 )));
196 connect(view, TQ_SIGNAL(viewTransformationsChanged()), m_birdEyePanel, TQ_SLOT(slotViewTransformationChanged()));
197
198 l->addWidget(m_birdEyePanel);
199
200 TQHBoxLayout * hl = new TQHBoxLayout(l);
201
202 m_exposureLabel = new TQLabel(i18n("Exposure:"), this);
203 hl->addWidget(m_exposureLabel);
204
205 m_exposureDoubleWidget = new KisDoubleWidget(-10, 10, this);
206 m_exposureDoubleWidget->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed);
207 hl->addWidget(m_exposureDoubleWidget);
208 TQToolTip::add(m_exposureDoubleWidget, i18n("Select the exposure (stops) for HDR images"));
209 l->addItem(new TQSpacerItem(0, 1, TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding));
210
211 m_exposureDoubleWidget->setPrecision(1);
212 m_exposureDoubleWidget->setValue(0);
213 m_exposureDoubleWidget->setLineStep(0.1);
214 m_exposureDoubleWidget->setPageStep(1);
215
216 connect(m_exposureDoubleWidget, TQ_SIGNAL(valueChanged(double)), TQ_SLOT(exposureValueChanged(double)));
217 connect(m_exposureDoubleWidget, TQ_SIGNAL(sliderPressed()), TQ_SLOT(exposureSliderPressed()));
218 connect(m_exposureDoubleWidget, TQ_SIGNAL(sliderReleased()), TQ_SLOT(exposureSliderReleased()));
219
220 m_draggingExposureSlider = false;
221
222 Q_ASSERT(m_subject->document() != 0);
223 connect(m_subject->document(), TQ_SIGNAL(sigCommandExecuted()), TQ_SLOT(slotDocCommandExecuted()));
224
225 if (m_image) {
226 connect(m_image, TQ_SIGNAL(sigImageUpdated(TQRect)), TQ_SLOT(slotImageUpdated(TQRect)));
227 }
228}
229
230KisBirdEyeBox::~KisBirdEyeBox()
231{
232 // Huh? Why does this cause a crash?
233 // delete m_zoomAdapter;
234}
235
236void KisBirdEyeBox::setImage(KisImageSP image)
237{
238 if (m_image) {
239 m_image->disconnect(this);
240 }
241
242 m_image = image;
243
244 KoThumbnailAdapter * ktp = new ThumbnailProvider(m_image, m_subject);
245 m_birdEyePanel->setThumbnailProvider(ktp);
246
247 if (m_image) {
248 connect(m_image, TQ_SIGNAL(sigImageUpdated(TQRect)), TQ_SLOT(slotImageUpdated(TQRect)));
249 connect(m_image, TQ_SIGNAL(sigSizeChanged(TQ_INT32, TQ_INT32)), TQ_SLOT(slotImageSizeChanged(TQ_INT32, TQ_INT32)));
250 connect(m_image, TQ_SIGNAL(sigColorSpaceChanged(KisColorSpace *)), TQ_SLOT(slotImageColorSpaceChanged(KisColorSpace *)));
251 m_birdEyePanel->slotUpdate(m_image->bounds());
252 slotImageColorSpaceChanged(m_image->colorSpace());
253 }
254}
255
256void KisBirdEyeBox::slotDocCommandExecuted()
257{
258 if (m_image) {
259 if (!m_dirtyRect.isEmpty()) {
260 m_birdEyePanel->slotUpdate(m_dirtyRect);
261 }
262 m_dirtyRect = TQRect();
263 }
264}
265
266void KisBirdEyeBox::slotImageUpdated(TQRect r)
267{
268 m_dirtyRect |= r;
269}
270
271void KisBirdEyeBox::slotImageSizeChanged(TQ_INT32 /*w*/, TQ_INT32 /*h*/)
272{
273 if (m_image) {
274 m_birdEyePanel->slotUpdate(m_image->bounds());
275 }
276}
277
278void KisBirdEyeBox::slotImageColorSpaceChanged(KisColorSpace *cs)
279{
280 if (cs->hasHighDynamicRange()) {
281 m_exposureDoubleWidget->show();
282 m_exposureLabel->show();
283 } else {
284 m_exposureDoubleWidget->hide();
285 m_exposureLabel->hide();
286 }
287}
288
289void KisBirdEyeBox::exposureValueChanged(double exposure)
290{
291 if (!m_draggingExposureSlider) {
292 m_subject->setHDRExposure(exposure);
293
294 if (m_image && m_image->colorSpace()->hasHighDynamicRange()) {
295 m_birdEyePanel->slotUpdate(m_image->bounds());
296 }
297 }
298}
299
300void KisBirdEyeBox::exposureSliderPressed()
301{
302 m_draggingExposureSlider = true;
303}
304
305void KisBirdEyeBox::exposureSliderReleased()
306{
307 m_draggingExposureSlider = false;
308 exposureValueChanged(m_exposureDoubleWidget->value());
309}
310
311#include "kis_birdeye_box.moc"
Interface for classes that implement a canvas; i.e., a widget where KisImages are painted onto.
virtual TQPoint viewToWindow(const TQPoint &pt)=0
Conversion functions from view coordinates to image coordinates.
virtual KisCanvas * kiscanvas() const =0
KisCanvasSubject is part of the Observer pattern.
A colorspace is the definition of a certain color model in Chalk.
virtual bool hasHighDynamicRange() const =0
Returns true if the colorspace supports channel values outside the (normalised) range 0 to 1.
The pixel iterators are high level iterarators.
A paint device contains the actual pixel data and offers methods to read and write pixels.
A double-based rect class that can return a TQRect that encloses the KisRect.
Definition kis_rect.h:29
A complex widget that provides an overview of a document with a red panning rectangle to and a zoom s...
The zoom listener interface defines methods that the bird eye panel will call whenever the zoomlevel ...
virtual double getMaxZoom()=0
Get the maximum zoom factor that this listener supports.
virtual void zoomOut()=0
Zoom one step out.
virtual double getMinZoom()=0
Get the minimum zoom factor that this listener supports.
virtual void zoomIn()=0
Zoom one step in.
virtual void zoomTo(double x, double y, double factor)=0
Zoom to the specified factor around the point x and y.