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 <thumbbrowserbase.h>
21 #include <multilangmgr.h>
24 ThumbBrowserBase::ThumbBrowserBase ()
25 : previewHeight(options
.thumbSize
), lastClicked(NULL
) {
27 signal_style_changed().connect( sigc::mem_fun(*this, &ThumbBrowserBase::styleChanged
) );
30 void ThumbBrowserBase::arrangeFiles () {
34 for (int i
=0; i
<N
; i
++)
35 fd
[i
]->filtered
= !checkFilter (fd
[i
]);
38 // compute size of the items
39 for (int i
=0; i
<N
; i
++)
40 if (!fd
[i
]->filtered
&& fd
[i
]->getMinimalHeight() > rowHeight
)
41 rowHeight
= fd
[i
]->getMinimalHeight ();
43 if (arrangement
==TB_Horizontal
) {
46 if (get_parent () && rowHeight
>0) {
47 Gtk::Allocation alloc
= get_parent ()->get_allocation ();
48 numOfRows
= (alloc
.get_height()+rowHeight
/2)/rowHeight
;
54 int currx
= 0; int curry
= 0;
56 // find widest item in the column
58 for (int i
=0; ct
+i
<N
&& i
<numOfRows
; i
++)
59 if (fd
[ct
+i
]->getMinimalWidth() > maxw
)
60 maxw
= fd
[ct
+i
]->getMinimalWidth ();
62 // arrange items in the column
64 for (int i
=0; ct
<N
&& i
<numOfRows
; i
++, ct
++) {
65 while (ct
<N
&& fd
[ct
]->filtered
)
66 fd
[ct
++]->drawable
= false;
68 fd
[ct
]->setPosition (currx
, curry
, maxw
, rowHeight
);
69 fd
[ct
]->drawable
= true;
75 set_size_request (currx
, numOfRows
*rowHeight
);
80 Gtk::Allocation alloc
= get_parent ()->get_allocation ();
81 availWidth
= alloc
.get_width();
84 // initial number of columns
88 for (int i
=0; i
<N
; i
++)
89 if (!fd
[i
]->filtered
&& colsWidth
+ fd
[i
]->getMinimalWidth() <= availWidth
) {
90 colsWidth
+= fd
[numOfCols
]->getMinimalWidth ();
95 std::vector
<int> colWidths
;
96 for (; numOfCols
>0; numOfCols
--) {
97 // compute column widths
98 colWidths
.resize (numOfCols
);
99 for (int i
=0; i
<numOfCols
; i
++)
101 for (int i
=0, j
=0; i
<N
; i
++) {
102 if (!fd
[i
]->filtered
&& fd
[i
]->getMinimalWidth() > colWidths
[j
%numOfCols
])
103 colWidths
[j
%numOfCols
] = fd
[i
]->getMinimalWidth ();
104 if (!fd
[i
]->filtered
)
107 // if not wider than the space available, arrange it and we are ready
109 for (int i
=0; i
<numOfCols
; i
++)
110 colsWidth
+= colWidths
[i
];
111 if (numOfCols
==1 || colsWidth
< availWidth
)
116 int currx
= 0; int curry
= 0;
118 // arrange items in the row
120 for (int i
=0; ct
<N
&& i
<numOfCols
; i
++, ct
++) {
121 while (ct
<N
&& fd
[ct
]->filtered
)
122 fd
[ct
++]->drawable
= false;
124 fd
[ct
]->setPosition (currx
, curry
, colWidths
[i
%numOfCols
], rowHeight
);
125 fd
[ct
]->drawable
= true;
126 currx
+= colWidths
[i
%numOfCols
];
131 set_size_request (colsWidth
, curry
);
136 void ThumbBrowserBase::on_realize()
138 Cairo::FontOptions cfo
;
139 cfo
.set_antialias (Cairo::ANTIALIAS_SUBPIXEL
);
140 get_pango_context()->set_cairo_font_options (cfo
);
142 add_events(Gdk::LEAVE_NOTIFY_MASK
);
143 Gtk::DrawingArea::on_realize();
144 Glib::RefPtr
<Gdk::Window
> window
= get_window();
145 add_events(Gdk::EXPOSURE_MASK
| Gdk::BUTTON_PRESS_MASK
| Gdk::BUTTON_RELEASE_MASK
| Gdk::POINTER_MOTION_MASK
);
147 gc_
= Gdk::GC::create(window
);
150 void ThumbBrowserBase::styleChanged (const Glib::RefPtr
<Gtk::Style
>& style
) {
155 bool ThumbBrowserBase::on_expose_event(GdkEventExpose
* event
) {
157 Gtk::Viewport
* vp
= (Gtk::Viewport
*) get_parent ();
158 Gtk::ScrolledWindow
* sw
= (Gtk::ScrolledWindow
*) vp
->get_parent ();
160 int px
= (int)(sw
->get_hscrollbar()->get_value ());
161 int py
= (int)(sw
->get_vscrollbar()->get_value ());
162 int pw
= vp
->get_width ();
163 int ph
= vp
->get_height ();
164 Glib::RefPtr
<Gdk::Window
> window
= get_window();
168 Glib::RefPtr
<Pango::Context
> context
= get_pango_context ();
169 context
->set_font_description (get_style()->get_font());
170 for (int i
=0; i
<fd
.size(); i
++) {
171 if (!fd
[i
]->drawable
|| !fd
[i
]->insideWindow (px
, py
, pw
, ph
))
178 bool ThumbBrowserBase::on_button_press_event (GdkEventButton
* event
) {
180 Gtk::Viewport
* vp
= (Gtk::Viewport
*) get_parent ();
181 Gtk::ScrolledWindow
* sw
= (Gtk::ScrolledWindow
*) vp
->get_parent ();
183 int px
= (int)(sw
->get_hscrollbar()->get_value ());
184 int py
= (int)(sw
->get_vscrollbar()->get_value ());
185 int pw
= vp
->get_width ();
186 int ph
= vp
->get_height ();
188 ThumbBrowserEntryBase
* fileDescr
= NULL
;
189 bool handled
= false;
190 for (int i
=0; i
<fd
.size(); i
++)
191 if (fd
[i
]->drawable
&& fd
[i
]->insideWindow (px
, py
, pw
, ph
)) {
192 if (fd
[i
]->inside ((int)event
->x
, (int)event
->y
))
194 bool b
= fd
[i
]->pressNotify (this, (int)event
->x
, (int)event
->y
);
195 handled
= handled
|| b
;
197 if (handled
|| (fileDescr
&& fileDescr
->processing
))
200 if (selected
.size()==1 && event
->type
==GDK_2BUTTON_PRESS
&& event
->button
==1)
201 doubleClicked (selected
[0]);
202 else if (event
->button
==1 && event
->type
==GDK_BUTTON_PRESS
) {
203 if (fileDescr
&& event
->state
& GDK_SHIFT_MASK
) {
204 if (selected
.size()==0) {
205 selected
.push_back (fileDescr
);
206 fileDescr
->selected
= true;
207 lastClicked
= fileDescr
;
210 // find the start and the end of the selection interval
211 int startx
= fd
.size()-1;
213 for (; startx
>=0; startx
--)
214 if (fd
[startx
]==lastClicked
)
218 for (; startx
>=0; startx
--)
219 if (fd
[startx
]==selected
[0])
223 for (; endx
<fd
.size(); endx
++)
224 if (fd
[endx
]==fileDescr
)
231 // clear current selection
232 for (int i
=0; i
<selected
.size(); i
++)
233 selected
[i
]->selected
= false;
235 // select thumbnails in the interval
236 for (int i
=startx
; i
<=endx
; i
++) {
237 fd
[i
]->selected
= true;
238 selected
.push_back (fd
[i
]);
242 else if (fileDescr
&& event
->state
& GDK_CONTROL_MASK
) {
243 std::vector
<ThumbBrowserEntryBase
*>::iterator i
= std::find (selected
.begin(), selected
.end(), fileDescr
);
244 if (i
!=selected
.end()) {
245 (*i
)->selected
= false;
249 selected
.push_back (fileDescr
);
250 fileDescr
->selected
= true;
252 lastClicked
= fileDescr
;
255 for (int i
=0; i
<selected
.size(); i
++)
256 selected
[i
]->selected
= false;
259 selected
.push_back (fileDescr
);
260 fileDescr
->selected
= true;
262 lastClicked
= fileDescr
;
265 else if (fileDescr
&& event
->button
==3 && event
->type
==GDK_BUTTON_PRESS
) {
266 if (!fileDescr
->selected
) {
267 for (int i
=0; i
<selected
.size(); i
++)
268 selected
[i
]->selected
= false;
270 fileDescr
->selected
= true;
271 selected
.push_back (fileDescr
);
272 lastClicked
= fileDescr
;
274 rightClicked (fileDescr
);
276 Glib::RefPtr
<Gdk::Window
> window
= get_window();
281 window
->get_size (rect
.width
, rect
.height
);
283 gdk_window_invalidate_rect (window
->gobj(), &rect
, true);
284 gdk_window_process_updates (window
->gobj(), true);
289 bool ThumbBrowserBase::on_button_release_event (GdkEventButton
* event
) {
291 Gtk::Viewport
* vp
= (Gtk::Viewport
*) get_parent ();
292 Gtk::ScrolledWindow
* sw
= (Gtk::ScrolledWindow
*) vp
->get_parent ();
294 int px
= (int)(sw
->get_hscrollbar()->get_value ());
295 int py
= (int)(sw
->get_vscrollbar()->get_value ());
296 int pw
= vp
->get_width ();
297 int ph
= vp
->get_height ();
299 for (int i
=0; i
<fd
.size(); i
++)
300 if (fd
[i
]->drawable
&& fd
[i
]->insideWindow (px
, py
, pw
, ph
))
301 fd
[i
]->releaseNotify (this, (int)event
->x
, (int)event
->y
);
305 bool ThumbBrowserBase::on_motion_notify_event (GdkEventMotion
* event
) {
307 Gtk::Viewport
* vp
= (Gtk::Viewport
*) get_parent ();
308 Gtk::ScrolledWindow
* sw
= (Gtk::ScrolledWindow
*) vp
->get_parent ();
310 int px
= (int)(sw
->get_hscrollbar()->get_value ());
311 int py
= (int)(sw
->get_vscrollbar()->get_value ());
312 int pw
= vp
->get_width ();
313 int ph
= vp
->get_height ();
315 for (int i
=0; i
<fd
.size(); i
++)
316 if (fd
[i
]->drawable
&& fd
[i
]->insideWindow (px
, py
, pw
, ph
))
317 fd
[i
]->motionNotify (this, (int)event
->x
, (int)event
->y
);
321 void ThumbBrowserBase::resized (Gtk::Allocation
& req
) {
325 void ThumbBrowserBase::redraw () {
331 void ThumbBrowserBase::setPreviewHeight (int h
) {
334 for (int i
=0; i
<fd
.size(); i
++)
335 fd
[i
]->initSizes (this, previewHeight
);
339 void ThumbBrowserBase::refreshAll () {
341 for (int i
=0; i
<fd
.size(); i
++) {
342 fd
[i
]->forceHeight (options
.thumbSize
);
344 fd
[i
]->initSizes (this, options
.thumbSize
);
349 void ThumbBrowserBase::setOpenedFileName (const Glib::ustring
& fname
) {
351 fileInEditor
= fname
;
352 for (int i
=0; i
<fd
.size(); i
++)
353 fd
[i
]->framed
= fd
[i
]->filename
==fileInEditor
;
356 void ThumbBrowserBase::setArrangement (Arrangement a
) {