2 * This file is part of RawTherapee.
4 * Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
6 * RawTherapee is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * RawTherapee is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
19 #include <thumbbrowserentrybase.h>
20 #include <thumbbrowserbase.h>
24 ThumbBrowserEntryBase::ThumbBrowserEntryBase (const Glib::ustring
& fname
)
25 : filename(fname
), selected(false), drawable(false),framed(false), processing(false),
26 italicstyle(false), preview(NULL
), exifline(""), datetimeline(""),
27 buttonSet(NULL
), updatepriority(false), redrawRequests(0),
28 parent(NULL
), exp_width(0), exp_height(0) {
30 shortname
= Glib::path_get_basename (fname
);
42 ThumbBrowserEntryBase::~ThumbBrowserEntryBase () {
48 void ThumbBrowserEntryBase::addButtonSet (LWButtonSet
* bs
) {
53 void ThumbBrowserEntryBase::updateBackBuffer () {
58 Gtk::Widget
* w
= parent
->getDrawingArea ();
60 backBuffer
= Gdk::Pixmap::create (w
->get_window(), exp_width
, exp_height
);
62 bbSelected
= selected
;
66 Glib::RefPtr
<Gdk::GC
> gc_
= Gdk::GC::create (backBuffer
);
68 Gdk::Color textn
= w
->get_style()->get_text(Gtk::STATE_NORMAL
);
69 Gdk::Color texts
= w
->get_style()->get_text(Gtk::STATE_SELECTED
);
70 Gdk::Color bgn
= w
->get_style()->get_bg(Gtk::STATE_NORMAL
);
71 Gdk::Color bgs
= w
->get_style()->get_bg(Gtk::STATE_SELECTED
);
73 // clear area, draw frames and background
74 gc_
->set_foreground (bgn
);
75 gc_
->set_background (bgn
);
76 backBuffer
->draw_rectangle (gc_
, true, 0, 0, exp_width
, exp_height
);
77 Cairo::RefPtr
<Cairo::Context
> cr
= backBuffer
->create_cairo_context();
78 drawFrame (cr
, bgs
, bgn
);
80 // calculate height of button set
84 buttonSet
->getAllocatedDimensions (tmp
, bsHeight
);
88 backBuffer
->draw_rectangle (gc_
, false, (exp_width
-prew
)/2, upperMargin
+bsHeight
, prew
+1, preh
+1);
89 // draw thumbnail image
91 prex
= borderWidth
+ (exp_width
-prew
)/2;
92 prey
= upperMargin
+bsHeight
+borderWidth
;
93 backBuffer
->draw_rgb_image (gc_
, prex
, prey
, prew
, preh
, Gdk::RGB_DITHER_NONE
, preview
, prew
*3);
96 customBackBufferUpdate (cr
);
98 // draw icons onto the thumbnail area
99 bbIcons
= getIconsOnImageArea ();
102 getTextSizes (infow
, infoh
);
104 int iofs_x
= 4, iofs_y
= 4;
109 if (options
.overlayedFileNames
) {
110 cr
->begin_new_path ();
111 cr
->rectangle (istartx
, istarty
, prew
, fnlabh
+dtlabh
+exlabh
+2*iofs_y
);
112 if ((texts
.get_red_p()+texts
.get_green_p()+texts
.get_blue_p())/3 > 0.5)
113 cr
->set_source_rgba (0, 0, 0, 0.5);
115 cr
->set_source_rgba (1, 1, 1, 0.5);
122 if (bbIcons
.size()>0) {
125 for (int i
=0; i
<bbIcons
.size(); i
++) {
126 iwidth
+= bbIcons
[i
]->get_width() + igap
;
127 if (bbIcons
[i
]->get_height() > iheight
)
128 iheight
= bbIcons
[i
]->get_height();
131 if (!options
.overlayedFileNames
) {
132 cr
->begin_new_path ();
133 cr
->rectangle (istartx
-igap
, istarty
-igap
, iwidth
, iheight
);
134 cr
->set_source_rgba (0, 0, 0, 0.75);
137 for (int i
=0; i
<bbIcons
.size(); i
++) {
138 backBuffer
->draw_pixbuf (gc_
, bbIcons
[i
], 0, 0, istartx
, istarty
, bbIcons
[i
]->get_width(), bbIcons
[i
]->get_height(), Gdk::RGB_DITHER_NONE
, 0, 0);
139 istartx
+= bbIcons
[i
]->get_width() + igap
;
143 int textposx_fn
, textposx_ex
, textposx_dt
, textposy
, textw
;
144 if (!options
.overlayedFileNames
) {
145 textposx_fn
= exp_width
/2 - fnlabw
/2;
146 if (textposx_fn
<0) textposx_fn
= 0;
147 textposx_ex
= exp_width
/2 - exlabw
/2;
148 if (textposx_ex
<0) textposx_ex
= 0;
149 textposx_dt
= exp_width
/2 - dtlabw
/2;
150 if (textposx_dt
<0) textposx_dt
= 0;
151 textposy
= upperMargin
+ bsHeight
+ 2*borderWidth
+ preh
+ borderWidth
+ textGap
;
152 textw
= exp_width
- 2*textGap
;
153 gc_
->set_foreground (selected
? texts
: textn
);
156 textposx_fn
= istartx
;
157 textposx_ex
= istartx
;
158 textposx_dt
= istartx
;
160 textw
= prew
- (istartx
- prex
);
161 gc_
->set_foreground (texts
);
165 Glib::RefPtr
<Pango::Context
> context
= w
->get_pango_context () ;
166 Pango::FontDescription fontd
= context
->get_font_description ();
167 fontd
.set_weight (Pango::WEIGHT_BOLD
);
169 fontd
.set_style (Pango::STYLE_ITALIC
);
171 fontd
.set_style (Pango::STYLE_NORMAL
);
173 context
->set_font_description (fontd
);
174 Glib::RefPtr
<Pango::Layout
> fn
= w
->create_pango_layout (dispname
);
175 fn
->set_width (textw
*Pango::SCALE
);
176 fn
->set_ellipsize (Pango::ELLIPSIZE_MIDDLE
);
177 backBuffer
->draw_layout(gc_
, textposx_fn
, textposy
, fn
);
179 fontd
.set_weight (Pango::WEIGHT_NORMAL
);
180 fontd
.set_style (Pango::STYLE_NORMAL
);
181 context
->set_font_description (fontd
);
183 // draw date/time label
185 if (options
.fbShowDateTime
&& datetimeline
!="") {
186 fn
= w
->create_pango_layout (datetimeline
);
187 fn
->set_width (textw
*Pango::SCALE
);
188 fn
->set_ellipsize (Pango::ELLIPSIZE_MIDDLE
);
189 backBuffer
->draw_layout(gc_
, textposx_dt
, textposy
+ tpos
, fn
);
192 // draw basic exif info
193 if (options
.fbShowBasicExif
&& exifline
!="") {
194 fn
= w
->create_pango_layout (exifline
);
195 fn
->set_width (textw
*Pango::SCALE
);
196 fn
->set_ellipsize (Pango::ELLIPSIZE_MIDDLE
);
197 backBuffer
->draw_layout (gc_
, textposx_ex
, textposy
+ tpos
, fn
);
202 void ThumbBrowserEntryBase::getTextSizes (int& infow
, int& infoh
) {
207 Gtk::Widget
* w
= parent
->getDrawingArea ();
209 // calculate dimensions of the text based fields
210 dispname
= shortname
;
212 Glib::RefPtr
<Pango::Context
> context
= w
->get_pango_context () ;
213 context
->set_font_description (w
->get_style()->get_font());
216 Pango::FontDescription fontd
= context
->get_font_description ();
217 fontd
.set_weight (Pango::WEIGHT_BOLD
);
218 context
->set_font_description (fontd
);
219 Glib::RefPtr
<Pango::Layout
> fn
= w
->create_pango_layout(shortname
);
220 fn
->get_pixel_size (fnlabw
, fnlabh
);
223 fontd
.set_weight (Pango::WEIGHT_NORMAL
);
224 context
->set_font_description (fontd
);
225 fn
= w
->create_pango_layout (datetimeline
);
226 fn
->get_pixel_size (dtlabw
, dtlabh
);
229 fn
= w
->create_pango_layout (exifline
);
230 fn
->get_pixel_size (exlabw
, exlabh
);
232 // calculate cummulated height of all info fields
235 // add date/tile size:
236 if (options
.fbShowDateTime
) {
238 if (dtlabw
+ 2*sideMargin
> infow
)
239 infow
= dtlabw
+ 2*sideMargin
;
241 if (options
.fbShowBasicExif
) {
243 if (exlabw
+ 2*sideMargin
> infow
)
244 infow
= exlabw
+ 2*sideMargin
;
248 void ThumbBrowserEntryBase::resize (int h
) {
254 // dimensions of the button set
257 buttonSet
->getMinimalDimensions (bsw
, bsh
);
259 // calculate the height remaining for the thumbnail image
260 preh
= height
- upperMargin
- 2*borderWidth
- lowerMargin
- bsh
;
262 if (!options
.overlayedFileNames
) {
263 // dimensions of the info text
264 getTextSizes (infow
, infoh
);
265 preh
-= infoh
+ textGap
;
268 calcThumbnailSize ();
269 width
= prew
+ 2*sideMargin
+ 2*borderWidth
;
270 if (!options
.overlayedFileNames
) {
271 width
= prew
+ 2*sideMargin
+ 2*borderWidth
;
272 if (width
<infow
+ 2*sideMargin
+ 2*borderWidth
)
273 width
= infow
+ 2*sideMargin
+ 2*borderWidth
;
274 if (width
< bsw
+ 2*sideMargin
+ 2*borderWidth
)
275 width
= bsw
+ 2*sideMargin
+ 2*borderWidth
;
277 // updateBackBuffer ();
279 refreshThumbnailImage ();
283 void ThumbBrowserEntryBase::drawFrame (Cairo::RefPtr
<Cairo::Context
> cr
, const Gdk::Color
& bg
, const Gdk::Color
& fg
) {
286 if (selected
|| framed
) {
287 cr
->set_antialias (Cairo::ANTIALIAS_SUBPIXEL
);
288 cr
->move_to (radius
, 0);
289 cr
->arc (exp_width
-1-radius
, radius
, radius
, -M_PI
/2, 0);
290 cr
->arc (exp_width
-1-radius
, exp_height
-1-radius
, radius
, 0, M_PI
/2);
291 cr
->arc (radius
, exp_height
-1-radius
, radius
, M_PI
/2, M_PI
);
292 cr
->arc (radius
, radius
, radius
, M_PI
, -M_PI
/2);
295 cr
->set_source_rgb (bg
.get_red_p(), bg
.get_green_p(), bg
.get_blue_p());
296 cr
->fill_preserve ();
298 cr
->set_source_rgb (bg
.get_red_p()*2/3, bg
.get_green_p()*2/3, bg
.get_blue_p()*2/3);
299 cr
->set_line_width (1.0);
305 cr
->set_antialias (Cairo::ANTIALIAS_SUBPIXEL
);
306 cr
->move_to (+2+0.5+radius
, +2+0.5);
307 cr
->arc (-2+0.5+exp_width
-1-radius
, +2+0.5+radius
, radius
, -M_PI
/2, 0);
308 cr
->arc (-2+0.5+exp_width
-1-radius
, -2+0.5+exp_height
-1-radius
, radius
, 0, M_PI
/2);
309 cr
->arc (+2+0.5+radius
, -2+exp_height
-1-radius
, radius
, M_PI
/2, M_PI
);
310 cr
->arc (+2+0.5+radius
, +2+radius
, radius
, M_PI
, -M_PI
/2);
312 cr
->set_source_rgb (fg
.get_red_p(), fg
.get_green_p(), fg
.get_blue_p());
313 cr
->set_line_width (2.0);
318 void ThumbBrowserEntryBase::draw () {
323 int bbWidth
, bbHeight
;
325 backBuffer
->get_size (bbWidth
, bbHeight
);
328 if (!backBuffer
|| selected
!=bbSelected
|| framed
!=bbFramed
|| preview
!=bbPreview
329 || exp_width
!=bbWidth
|| exp_height
!=bbHeight
|| getIconsOnImageArea ()!=bbIcons
)
335 Gtk::Widget
* w
= parent
->getDrawingArea ();
337 Glib::RefPtr
<Gdk::GC
> gc_
= Gdk::GC::create (w
->get_window());
339 Gdk::Color textn
= w
->get_style()->get_text(Gtk::STATE_NORMAL
);
340 Gdk::Color texts
= w
->get_style()->get_text(Gtk::STATE_SELECTED
);
341 Gdk::Color bgn
= w
->get_style()->get_bg(Gtk::STATE_NORMAL
);
342 Gdk::Color bgs
= w
->get_style()->get_bg(Gtk::STATE_SELECTED
);
344 w
->get_window()->draw_drawable (gc_
, backBuffer
, 0, 0, startx
+ ofsX
, starty
+ ofsY
);
346 // check icon set changes!!!
348 // drawProgressBar (window, gc_, selected ? texts : textn, selected ? bgs : bgn, ofsX+startx, exp_width, ofsY+starty + upperMargin+bsHeight+borderWidth+preh+borderWidth+textGap+tpos, fnlabh);
350 // redraw button set above the thumbnail
352 buttonSet
->setColors (selected
? bgs
: bgn
, selected
? bgn
: bgs
);
353 buttonSet
->redraw (w
->get_window()->create_cairo_context());
357 void ThumbBrowserEntryBase::setPosition (int x
, int y
, int w
, int h
) {
365 buttonSet
->arrangeButtons (ofsX
+x
+sideMargin
, ofsY
+y
+upperMargin
, w
-2*sideMargin
, -1);
368 void ThumbBrowserEntryBase::setOffset (int x
, int y
) {
374 buttonSet
->move (ofsX
+startx
+sideMargin
, ofsY
+starty
+upperMargin
);
377 bool ThumbBrowserEntryBase::inside (int x
, int y
) {
379 return x
>ofsX
+startx
&& x
<ofsX
+startx
+exp_width
&& y
>ofsY
+starty
&& y
<ofsY
+starty
+exp_height
;
382 bool ThumbBrowserEntryBase::insideWindow (int x
, int y
, int w
, int h
) {
384 return !(ofsX
+startx
>x
+w
|| ofsX
+startx
+exp_width
<x
|| ofsY
+starty
>y
+h
|| ofsY
+starty
+exp_height
<y
);
387 bool ThumbBrowserEntryBase::motionNotify (int x
, int y
) {
389 return buttonSet
? buttonSet
->motionNotify (x
, y
) : false;
392 bool ThumbBrowserEntryBase::pressNotify (int button
, int type
, int bstate
, int x
, int y
) {
394 return buttonSet
? buttonSet
->pressNotify (x
, y
) : false;
397 bool ThumbBrowserEntryBase::releaseNotify (int button
, int type
, int bstate
, int x
, int y
) {
399 return buttonSet
? buttonSet
->releaseNotify (x
, y
) : false;
401 Glib::ustring
ThumbBrowserEntryBase::getToolTip (int x
, int y
) {
403 return buttonSet
? buttonSet
->getToolTip (x
, y
) : "";