Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include <sfx2/thumbnailview.hxx>
11 : #include <sfx2/thumbnailviewitem.hxx>
12 :
13 : #include <utility>
14 :
15 : #include "thumbnailviewacc.hxx"
16 :
17 : #include <basegfx/color/bcolortools.hxx>
18 : #include <basegfx/matrix/b2dhommatrixtools.hxx>
19 : #include <basegfx/range/b2drectangle.hxx>
20 : #include <basegfx/polygon/b2dpolygon.hxx>
21 : #include <basegfx/vector/b2dsize.hxx>
22 : #include <basegfx/vector/b2dvector.hxx>
23 : #include <drawinglayer/attribute/fillgraphicattribute.hxx>
24 : #include <drawinglayer/attribute/fontattribute.hxx>
25 : #include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
26 : #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
27 : #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
28 : #include <drawinglayer/primitive2d/textprimitive2d.hxx>
29 : #include <drawinglayer/processor2d/baseprocessor2d.hxx>
30 : #include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
31 : #include <rtl/ustring.hxx>
32 : #include <vcl/decoview.hxx>
33 : #include <vcl/svapp.hxx>
34 : #include <vcl/scrbar.hxx>
35 : #include <vcl/help.hxx>
36 : #include <vcl/settings.hxx>
37 :
38 : #include <com/sun/star/accessibility/AccessibleEventId.hpp>
39 : #include <com/sun/star/accessibility/AccessibleStateType.hpp>
40 :
41 : #include <boost/scoped_ptr.hpp>
42 :
43 : using namespace basegfx;
44 : using namespace basegfx::tools;
45 : using namespace drawinglayer::attribute;
46 : using namespace drawinglayer::primitive2d;
47 :
48 : enum
49 : {
50 : ITEM_OFFSET = 4,
51 : ITEM_OFFSET_DOUBLE = 6,
52 : NAME_LINE_OFF_X = 2,
53 : NAME_LINE_OFF_Y = 2,
54 : NAME_LINE_HEIGHT = 2,
55 : NAME_OFFSET = 2,
56 : SCROLL_OFFSET = 4
57 : };
58 :
59 2 : ThumbnailView::ThumbnailView (vcl::Window *pParent, WinBits nWinStyle, bool bDisableTransientChildren)
60 2 : : Control( pParent, nWinStyle )
61 : {
62 2 : mpItemAttrs = NULL;
63 2 : ImplInit();
64 2 : mbIsTransientChildrenDisabled = bDisableTransientChildren;
65 2 : }
66 :
67 2 : ThumbnailView::~ThumbnailView()
68 : {
69 1 : disposeOnce();
70 1 : }
71 :
72 2 : void ThumbnailView::dispose()
73 : {
74 : com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent>
75 : xComponent(GetAccessible(false),
76 2 : com::sun::star::uno::UNO_QUERY);
77 :
78 2 : if (xComponent.is())
79 0 : xComponent->dispose ();
80 :
81 2 : mpScrBar.disposeAndClear();
82 2 : delete mpItemAttrs;
83 :
84 2 : ImplDeleteItems();
85 2 : Control::dispose();
86 2 : }
87 :
88 0 : void ThumbnailView::MouseMove(const MouseEvent& rMEvt)
89 : {
90 0 : size_t nItemCount = mFilteredItemList.size();
91 0 : Point aPoint = rMEvt.GetPosPixel();
92 0 : OUString aHelp;
93 :
94 0 : for (size_t i = 0; i < nItemCount; i++)
95 : {
96 0 : ThumbnailViewItem *pItem = mFilteredItemList[i];
97 :
98 0 : if (pItem->mbVisible && !rMEvt.IsLeaveWindow() && pItem->getDrawArea().IsInside(aPoint))
99 : {
100 0 : aHelp = pItem->getHelpText();
101 : }
102 :
103 0 : Rectangle aToInvalidate(pItem->updateHighlight(pItem->mbVisible && !rMEvt.IsLeaveWindow(), aPoint));
104 :
105 0 : if (!aToInvalidate.IsEmpty() && IsReallyVisible() && IsUpdateMode())
106 0 : Invalidate(aToInvalidate);
107 : }
108 :
109 0 : if (mbShowTooltips)
110 0 : SetQuickHelpText(aHelp);
111 0 : }
112 :
113 0 : void ThumbnailView::AppendItem(ThumbnailViewItem *pItem)
114 : {
115 0 : if (maFilterFunc(pItem))
116 : {
117 : // Save current start,end range, iterator might get invalidated
118 0 : size_t nSelStartPos = 0;
119 0 : ThumbnailViewItem *pSelStartItem = NULL;
120 :
121 0 : if (mpStartSelRange != mFilteredItemList.end())
122 : {
123 0 : pSelStartItem = *mpStartSelRange;
124 0 : nSelStartPos = mpStartSelRange - mFilteredItemList.begin();
125 : }
126 :
127 0 : mFilteredItemList.push_back(pItem);
128 0 : mpStartSelRange = pSelStartItem != NULL ? mFilteredItemList.begin() + nSelStartPos : mFilteredItemList.end();
129 : }
130 :
131 0 : mItemList.push_back(pItem);
132 0 : }
133 :
134 2 : void ThumbnailView::ImplInit()
135 : {
136 2 : mpScrBar = NULL;
137 2 : mnHeaderHeight = 0;
138 2 : mnItemWidth = 0;
139 2 : mnItemHeight = 0;
140 2 : mnItemPadding = 0;
141 2 : mnVisLines = 0;
142 2 : mnLines = 0;
143 2 : mnFineness = 5;
144 2 : mnFirstLine = 0;
145 2 : mnCols = 0;
146 2 : mbScroll = false;
147 2 : mbHasVisibleItems = false;
148 2 : mbShowTooltips = false;
149 2 : maFilterFunc = ViewFilterAll();
150 2 : maColor = GetSettings().GetStyleSettings().GetFieldColor();
151 2 : mpStartSelRange = mFilteredItemList.end();
152 :
153 2 : ImplInitSettings(true, true, true);
154 2 : }
155 :
156 3 : void ThumbnailView::ImplDeleteItems()
157 : {
158 3 : const size_t n = mItemList.size();
159 :
160 3 : for ( size_t i = 0; i < n; ++i )
161 : {
162 0 : ThumbnailViewItem *const pItem = mItemList[i];
163 :
164 : // deselect all current selected items and fire events
165 0 : if (pItem->isSelected())
166 : {
167 0 : pItem->setSelection(false);
168 0 : maItemStateHdl.Call(pItem);
169 :
170 : // fire accessible event???
171 : }
172 :
173 0 : if ( pItem->isVisible() && ImplHasAccessibleListeners() )
174 : {
175 0 : ::com::sun::star::uno::Any aOldAny, aNewAny;
176 :
177 0 : aOldAny <<= pItem->GetAccessible( mbIsTransientChildrenDisabled );
178 0 : ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny );
179 : }
180 :
181 0 : delete pItem;
182 : }
183 :
184 3 : mItemList.clear();
185 3 : mFilteredItemList.clear();
186 :
187 3 : mpStartSelRange = mFilteredItemList.end();
188 3 : }
189 :
190 3 : void ThumbnailView::ApplySettings(vcl::RenderContext& rRenderContext)
191 : {
192 3 : const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
193 :
194 3 : ApplyControlFont(*this, rStyleSettings.GetAppFont());
195 3 : ApplyControlForeground(*this, rStyleSettings.GetButtonTextColor());
196 3 : rRenderContext.SetTextFillColor();
197 3 : Color aColor = rStyleSettings.GetFieldColor();
198 3 : rRenderContext.SetBackground(aColor);
199 3 : }
200 :
201 4 : void ThumbnailView::ImplInitSettings( bool bFont, bool bForeground, bool bBackground )
202 : {
203 4 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
204 :
205 4 : if (bFont)
206 : {
207 2 : ApplyControlFont(*this, rStyleSettings.GetAppFont());
208 : }
209 :
210 4 : if (bForeground || bFont)
211 : {
212 2 : ApplyControlForeground(*this, rStyleSettings.GetButtonTextColor());
213 2 : SetTextFillColor();
214 : }
215 :
216 4 : if (bBackground)
217 : {
218 4 : Color aColor = rStyleSettings.GetFieldColor();
219 4 : SetBackground(aColor);
220 : }
221 :
222 4 : delete mpItemAttrs;
223 4 : mpItemAttrs = new ThumbnailItemAttributes;
224 4 : mpItemAttrs->aFillColor = maColor.getBColor();
225 4 : mpItemAttrs->aHighlightColor = rStyleSettings.GetHighlightColor().getBColor();
226 4 : mpItemAttrs->aFontAttr = getFontAttributeFromVclFont(mpItemAttrs->aFontSize,GetFont(),false,true);
227 4 : mpItemAttrs->nMaxTextLength = 0;
228 4 : }
229 :
230 7 : void ThumbnailView::ImplInitScrollBar()
231 : {
232 7 : if ( GetStyle() & WB_VSCROLL )
233 : {
234 7 : if ( !mpScrBar )
235 : {
236 1 : mpScrBar = VclPtr<ScrollBar>::Create( this, WB_VSCROLL | WB_DRAG );
237 1 : mpScrBar->SetScrollHdl( LINK( this, ThumbnailView, ImplScrollHdl ) );
238 : }
239 : else
240 : {
241 : // adapt the width because of the changed settings
242 6 : long nScrBarWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
243 6 : mpScrBar->setPosSizePixel( 0, 0, nScrBarWidth, 0, PosSizeFlags::Width );
244 : }
245 : }
246 7 : }
247 :
248 0 : void ThumbnailView::DrawItem(ThumbnailViewItem *pItem)
249 : {
250 0 : if (pItem->isVisible())
251 : {
252 0 : Rectangle aRect = pItem->getDrawArea();
253 :
254 0 : if ((aRect.GetHeight() > 0) && (aRect.GetWidth() > 0))
255 0 : pItem->Paint(mpProcessor.get(), mpItemAttrs);
256 : }
257 0 : }
258 :
259 0 : void ThumbnailView::OnItemDblClicked (ThumbnailViewItem*)
260 : {
261 0 : }
262 :
263 0 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > ThumbnailView::CreateAccessible()
264 : {
265 0 : return new ThumbnailViewAcc( this, mbIsTransientChildrenDisabled );
266 : }
267 :
268 11 : void ThumbnailView::CalculateItemPositions (bool bScrollBarUsed)
269 : {
270 11 : if (!mnItemHeight || !mnItemWidth)
271 11 : return;
272 :
273 11 : Size aWinSize = GetOutputSizePixel();
274 11 : size_t nItemCount = mFilteredItemList.size();
275 11 : WinBits nStyle = GetStyle();
276 11 : VclPtr<ScrollBar> pDelScrBar;
277 :
278 : // consider the scrolling
279 11 : if ( nStyle & WB_VSCROLL )
280 7 : ImplInitScrollBar();
281 : else
282 : {
283 4 : if ( mpScrBar )
284 : {
285 : // delete ScrollBar not until later, to prevent recursive calls
286 0 : pDelScrBar = mpScrBar;
287 0 : mpScrBar = NULL;
288 : }
289 : }
290 :
291 : // calculate window scroll ratio
292 : float nScrollRatio;
293 11 : if( bScrollBarUsed && mpScrBar )
294 0 : nScrollRatio = static_cast<float>(mpScrBar->GetThumbPos()) /
295 0 : static_cast<float>(mpScrBar->GetRangeMax()-2);
296 : else
297 11 : nScrollRatio = 0;
298 :
299 : // calculate ScrollBar width
300 11 : long nScrBarWidth = 0;
301 11 : if ( mpScrBar )
302 7 : nScrBarWidth = mpScrBar->GetSizePixel().Width();
303 :
304 : // calculate maximum number of visible columns
305 11 : mnCols = (sal_uInt16)((aWinSize.Width()-nScrBarWidth) / (mnItemWidth));
306 :
307 11 : if (!mnCols)
308 4 : mnCols = 1;
309 :
310 : // calculate maximum number of visible rows
311 11 : mnVisLines = (sal_uInt16)((aWinSize.Height()-mnHeaderHeight) / (mnItemHeight));
312 :
313 : // calculate empty space
314 11 : long nHSpace = aWinSize.Width()-nScrBarWidth - mnCols*mnItemWidth;
315 11 : long nVSpace = aWinSize.Height()-mnHeaderHeight - mnVisLines*mnItemHeight;
316 11 : long nHItemSpace = nHSpace / (mnCols+1);
317 11 : long nVItemSpace = nVSpace / (mnVisLines+1);
318 :
319 : // calculate maximum number of rows
320 : // Floor( (M+N-1)/N )==Ceiling( M/N )
321 11 : mnLines = (static_cast<long>(nItemCount)+mnCols-1) / mnCols;
322 :
323 11 : if ( !mnLines )
324 11 : mnLines = 1;
325 :
326 11 : if ( mnLines <= mnVisLines )
327 7 : mnFirstLine = 0;
328 4 : else if ( mnFirstLine > (sal_uInt16)(mnLines-mnVisLines) )
329 0 : mnFirstLine = (sal_uInt16)(mnLines-mnVisLines);
330 :
331 11 : mbHasVisibleItems = true;
332 :
333 11 : long nItemHeightOffset = mnItemHeight + nVItemSpace;
334 : long nHiddenLines = (static_cast<long>(
335 11 : ( mnLines - 1 ) * nItemHeightOffset * nScrollRatio ) -
336 11 : nVItemSpace - mnHeaderHeight) /
337 11 : nItemHeightOffset;
338 :
339 : // calculate offsets
340 11 : long nStartX = nHItemSpace;
341 11 : long nStartY = nVItemSpace + mnHeaderHeight;
342 :
343 : // calculate and draw items
344 11 : long x = nStartX;
345 22 : long y = nStartY - ( mnLines - 1 ) * nItemHeightOffset * nScrollRatio +
346 22 : nHiddenLines * nItemHeightOffset;
347 :
348 : // draw items
349 : // Unless we are scrolling (via scrollbar) we just use the precalculated
350 : // mnFirstLine -- our nHiddenLines calculation takes into account only
351 : // what the user has done with the scrollbar but not any changes of selection
352 : // using the keyboard, meaning we could accidentally hide the selected item
353 : // if we believe the scrollbar (fdo#72287).
354 11 : size_t nFirstItem = (bScrollBarUsed ? nHiddenLines : mnFirstLine) * mnCols;
355 11 : size_t nLastItem = nFirstItem + (mnVisLines + 1) * mnCols;
356 :
357 : // If want also draw parts of items in the last line,
358 : // then we add one more line if parts of these line are
359 : // visible
360 :
361 11 : size_t nCurCount = 0;
362 11 : for ( size_t i = 0; i < nItemCount; i++ )
363 : {
364 0 : ThumbnailViewItem *const pItem = mFilteredItemList[i];
365 :
366 0 : if ((nCurCount >= nFirstItem) && (nCurCount < nLastItem))
367 : {
368 0 : if( !pItem->isVisible())
369 : {
370 0 : if ( ImplHasAccessibleListeners() )
371 : {
372 0 : ::com::sun::star::uno::Any aOldAny, aNewAny;
373 :
374 0 : aNewAny <<= pItem->GetAccessible( mbIsTransientChildrenDisabled );
375 0 : ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny );
376 : }
377 :
378 0 : pItem->show(true);
379 :
380 0 : maItemStateHdl.Call(pItem);
381 : }
382 :
383 0 : pItem->setDrawArea(Rectangle( Point(x,y), Size(mnItemWidth, mnItemHeight) ));
384 0 : pItem->calculateItemsPosition(mnThumbnailHeight,mnDisplayHeight,mnItemPadding,mpItemAttrs->nMaxTextLength,mpItemAttrs);
385 :
386 0 : if ( !((nCurCount+1) % mnCols) )
387 : {
388 0 : x = nStartX;
389 0 : y += mnItemHeight+nVItemSpace;
390 : }
391 : else
392 0 : x += mnItemWidth+nHItemSpace;
393 : }
394 : else
395 : {
396 0 : if( pItem->isVisible())
397 : {
398 0 : if ( ImplHasAccessibleListeners() )
399 : {
400 0 : ::com::sun::star::uno::Any aOldAny, aNewAny;
401 :
402 0 : aOldAny <<= pItem->GetAccessible( mbIsTransientChildrenDisabled );
403 0 : ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny );
404 : }
405 :
406 0 : pItem->show(false);
407 :
408 0 : maItemStateHdl.Call(pItem);
409 : }
410 :
411 : }
412 :
413 0 : ++nCurCount;
414 : }
415 :
416 : // arrange ScrollBar, set values and show it
417 11 : if ( mpScrBar )
418 : {
419 7 : mnLines = (nCurCount+mnCols-1)/mnCols;
420 :
421 : // check if scroll is needed
422 7 : mbScroll = mnLines > mnVisLines;
423 :
424 :
425 7 : Point aPos( aWinSize.Width() - nScrBarWidth, mnHeaderHeight );
426 7 : Size aSize( nScrBarWidth, aWinSize.Height() - mnHeaderHeight );
427 :
428 7 : mpScrBar->SetPosSizePixel( aPos, aSize );
429 7 : mpScrBar->SetRangeMax( (nCurCount+mnCols-1)*mnFineness/mnCols);
430 7 : mpScrBar->SetVisibleSize( mnVisLines );
431 7 : if (!bScrollBarUsed)
432 7 : mpScrBar->SetThumbPos( (long)mnFirstLine*mnFineness );
433 7 : long nPageSize = mnVisLines;
434 7 : if ( nPageSize < 1 )
435 2 : nPageSize = 1;
436 7 : mpScrBar->SetPageSize( nPageSize );
437 7 : mpScrBar->Show( mbScroll );
438 : }
439 :
440 : // delete ScrollBar
441 11 : pDelScrBar.disposeAndClear();
442 : }
443 :
444 0 : size_t ThumbnailView::ImplGetItem( const Point& rPos ) const
445 : {
446 0 : if ( !mbHasVisibleItems )
447 : {
448 0 : return THUMBNAILVIEW_ITEM_NOTFOUND;
449 : }
450 :
451 0 : for (size_t i = 0; i < mFilteredItemList.size(); ++i)
452 : {
453 0 : if (mFilteredItemList[i]->isVisible() && mFilteredItemList[i]->getDrawArea().IsInside(rPos))
454 0 : return i;
455 : }
456 :
457 0 : return THUMBNAILVIEW_ITEM_NOTFOUND;
458 : }
459 :
460 0 : ThumbnailViewItem* ThumbnailView::ImplGetItem( size_t nPos )
461 : {
462 0 : return ( nPos < mFilteredItemList.size() ) ? mFilteredItemList[nPos] : NULL;
463 : }
464 :
465 0 : sal_uInt16 ThumbnailView::ImplGetVisibleItemCount() const
466 : {
467 0 : sal_uInt16 nRet = 0;
468 0 : const size_t nItemCount = mItemList.size();
469 :
470 0 : for ( size_t n = 0; n < nItemCount; ++n )
471 : {
472 0 : if ( mItemList[n]->isVisible() )
473 0 : ++nRet;
474 : }
475 :
476 0 : return nRet;
477 : }
478 :
479 0 : ThumbnailViewItem* ThumbnailView::ImplGetVisibleItem( sal_uInt16 nVisiblePos )
480 : {
481 0 : const size_t nItemCount = mItemList.size();
482 :
483 0 : for ( size_t n = 0; n < nItemCount; ++n )
484 : {
485 0 : ThumbnailViewItem *const pItem = mItemList[n];
486 :
487 0 : if ( pItem->isVisible() && !nVisiblePos-- )
488 0 : return pItem;
489 : }
490 :
491 0 : return NULL;
492 : }
493 :
494 0 : void ThumbnailView::ImplFireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue )
495 : {
496 0 : ThumbnailViewAcc* pAcc = ThumbnailViewAcc::getImplementation( GetAccessible( false ) );
497 :
498 0 : if( pAcc )
499 0 : pAcc->FireAccessibleEvent( nEventId, rOldValue, rNewValue );
500 0 : }
501 :
502 0 : bool ThumbnailView::ImplHasAccessibleListeners()
503 : {
504 0 : ThumbnailViewAcc* pAcc = ThumbnailViewAcc::getImplementation( GetAccessible( false ) );
505 0 : return( pAcc && pAcc->HasAccessibleListeners() );
506 : }
507 :
508 0 : IMPL_LINK( ThumbnailView,ImplScrollHdl, ScrollBar*, pScrollBar )
509 : {
510 0 : if ( pScrollBar->GetDelta() )
511 : {
512 0 : CalculateItemPositions(true);
513 :
514 0 : if ( IsReallyVisible() && IsUpdateMode() )
515 0 : Invalidate();
516 : }
517 0 : return 0;
518 : }
519 :
520 0 : IMPL_LINK (ThumbnailView, OnItemSelected, ThumbnailViewItem*, pItem)
521 : {
522 0 : maItemStateHdl.Call(pItem);
523 0 : return 0;
524 : }
525 :
526 0 : void ThumbnailView::KeyInput( const KeyEvent& rKEvt )
527 : {
528 : // Get the last selected item in the list
529 0 : size_t nLastPos = 0;
530 0 : bool bFoundLast = false;
531 0 : for ( long i = mFilteredItemList.size() - 1; !bFoundLast && i >= 0; --i )
532 : {
533 0 : ThumbnailViewItem* pItem = mFilteredItemList[i];
534 0 : if ( pItem->isSelected() )
535 : {
536 0 : nLastPos = i;
537 0 : bFoundLast = true;
538 : }
539 : }
540 :
541 0 : bool bValidRange = false;
542 0 : bool bHasSelRange = mpStartSelRange != mFilteredItemList.end();
543 0 : size_t nNextPos = nLastPos;
544 0 : vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
545 0 : ThumbnailViewItem* pNext = NULL;
546 :
547 0 : if (aKeyCode.IsShift() && bHasSelRange)
548 : {
549 : //If the last elemented selected is the start range position
550 : //search for the first selected item
551 0 : size_t nSelPos = mpStartSelRange - mFilteredItemList.begin();
552 :
553 0 : if (nLastPos == nSelPos)
554 : {
555 0 : while (nLastPos && mFilteredItemList[nLastPos-1]->isSelected())
556 0 : --nLastPos;
557 : }
558 : }
559 :
560 0 : switch ( aKeyCode.GetCode() )
561 : {
562 : case KEY_RIGHT:
563 0 : if (!mFilteredItemList.empty())
564 : {
565 0 : if ( bFoundLast && nLastPos + 1 < mFilteredItemList.size() )
566 : {
567 0 : bValidRange = true;
568 0 : nNextPos = nLastPos + 1;
569 : }
570 :
571 0 : pNext = mFilteredItemList[nNextPos];
572 : }
573 0 : break;
574 : case KEY_LEFT:
575 0 : if (!mFilteredItemList.empty())
576 : {
577 0 : if ( nLastPos > 0 )
578 : {
579 0 : bValidRange = true;
580 0 : nNextPos = nLastPos - 1;
581 : }
582 :
583 0 : pNext = mFilteredItemList[nNextPos];
584 : }
585 0 : break;
586 : case KEY_DOWN:
587 0 : if (!mFilteredItemList.empty())
588 : {
589 0 : if ( bFoundLast )
590 : {
591 : //If we are in the second last row just go the one in
592 : //the row below, if theres not row below just go to the
593 : //last item but for the last row dont do anything.
594 0 : if ( nLastPos + mnCols < mFilteredItemList.size( ) )
595 : {
596 0 : bValidRange = true;
597 0 : nNextPos = nLastPos + mnCols;
598 : }
599 : else
600 : {
601 0 : int curRow = nLastPos/mnCols;
602 :
603 0 : if (curRow < mnLines-1)
604 0 : nNextPos = mFilteredItemList.size()-1;
605 : }
606 : }
607 :
608 0 : pNext = mFilteredItemList[nNextPos];
609 : }
610 0 : break;
611 : case KEY_UP:
612 0 : if (!mFilteredItemList.empty())
613 : {
614 0 : if ( nLastPos >= mnCols )
615 : {
616 0 : bValidRange = true;
617 0 : nNextPos = nLastPos - mnCols;
618 : }
619 :
620 0 : pNext = mFilteredItemList[nNextPos];
621 : }
622 0 : break;
623 : case KEY_RETURN:
624 : {
625 0 : if ( bFoundLast )
626 0 : OnItemDblClicked( mFilteredItemList[nLastPos] );
627 : }
628 : //fall-through
629 : default:
630 0 : Control::KeyInput( rKEvt );
631 : }
632 :
633 0 : if ( pNext )
634 : {
635 0 : if (aKeyCode.IsShift() && bValidRange)
636 : {
637 0 : std::pair<size_t,size_t> aRange;
638 0 : size_t nSelPos = mpStartSelRange - mFilteredItemList.begin();
639 :
640 0 : if (nLastPos < nSelPos)
641 : {
642 0 : if (nNextPos > nLastPos)
643 : {
644 0 : if ( nNextPos > nSelPos)
645 0 : aRange = std::make_pair(nLastPos,nNextPos);
646 : else
647 0 : aRange = std::make_pair(nLastPos,nNextPos-1);
648 : }
649 : else
650 0 : aRange = std::make_pair(nNextPos,nLastPos-1);
651 : }
652 0 : else if (nLastPos == nSelPos)
653 : {
654 0 : if (nNextPos > nLastPos)
655 0 : aRange = std::make_pair(nLastPos+1,nNextPos);
656 : else
657 0 : aRange = std::make_pair(nNextPos,nLastPos-1);
658 : }
659 : else
660 : {
661 0 : if (nNextPos > nLastPos)
662 0 : aRange = std::make_pair(nLastPos+1,nNextPos);
663 : else
664 : {
665 0 : if ( nNextPos < nSelPos)
666 0 : aRange = std::make_pair(nNextPos,nLastPos);
667 : else
668 0 : aRange = std::make_pair(nNextPos+1,nLastPos);
669 : }
670 : }
671 :
672 0 : for (size_t i = aRange.first; i <= aRange.second; ++i)
673 : {
674 0 : if (i != nSelPos)
675 : {
676 0 : ThumbnailViewItem *pCurItem = mFilteredItemList[i];
677 :
678 0 : pCurItem->setSelection(!pCurItem->isSelected());
679 :
680 0 : if (pCurItem->isVisible())
681 0 : DrawItem(pCurItem);
682 :
683 0 : maItemStateHdl.Call(pCurItem);
684 : }
685 : }
686 : }
687 0 : else if (!aKeyCode.IsShift())
688 : {
689 0 : deselectItems();
690 0 : SelectItem(pNext->mnId);
691 :
692 : //Mark it as the selection range start position
693 0 : mpStartSelRange = mFilteredItemList.begin() + nNextPos;
694 : }
695 :
696 0 : MakeItemVisible(pNext->mnId);
697 : }
698 0 : }
699 :
700 0 : void ThumbnailView::MakeItemVisible( sal_uInt16 nItemId )
701 : {
702 : // Get the item row
703 0 : size_t nPos = 0;
704 0 : bool bFound = false;
705 0 : for ( size_t i = 0; !bFound && i < mFilteredItemList.size(); ++i )
706 : {
707 0 : ThumbnailViewItem* pItem = mFilteredItemList[i];
708 0 : if ( pItem->mnId == nItemId )
709 : {
710 0 : nPos = i;
711 0 : bFound = true;
712 : }
713 : }
714 0 : sal_uInt16 nRow = mnCols ? nPos / mnCols : 0;
715 :
716 : // Move the visible rows as little as possible to include that one
717 0 : if ( nRow < mnFirstLine )
718 0 : mnFirstLine = nRow;
719 0 : else if ( nRow > mnFirstLine + mnVisLines )
720 0 : mnFirstLine = nRow - mnVisLines;
721 :
722 0 : CalculateItemPositions();
723 0 : Invalidate();
724 0 : }
725 :
726 0 : void ThumbnailView::MouseButtonDown( const MouseEvent& rMEvt )
727 : {
728 0 : if ( !rMEvt.IsLeft() )
729 : {
730 0 : Control::MouseButtonDown( rMEvt );
731 0 : return;
732 : }
733 :
734 0 : size_t nPos = ImplGetItem(rMEvt.GetPosPixel());
735 0 : ThumbnailViewItem* pItem = ImplGetItem(nPos);
736 :
737 0 : if ( !pItem )
738 : {
739 0 : deselectItems();
740 0 : Control::MouseButtonDown( rMEvt );
741 0 : return;
742 : }
743 :
744 0 : if ( rMEvt.GetClicks() == 2 )
745 : {
746 0 : OnItemDblClicked(pItem);
747 0 : return;
748 : }
749 :
750 0 : if ( rMEvt.GetClicks() == 1 )
751 : {
752 0 : if (rMEvt.IsMod1())
753 : {
754 : //Keep selected item group state and just invert current desired one state
755 0 : pItem->setSelection(!pItem->isSelected());
756 :
757 : //This one becomes the selection range start position if it changes its state to selected otherwise resets it
758 0 : mpStartSelRange = pItem->isSelected() ? mFilteredItemList.begin() + nPos : mFilteredItemList.end();
759 : }
760 0 : else if (rMEvt.IsShift() && mpStartSelRange != mFilteredItemList.end())
761 : {
762 0 : std::pair<size_t,size_t> aNewRange;
763 0 : aNewRange.first = mpStartSelRange - mFilteredItemList.begin();
764 0 : aNewRange.second = nPos;
765 :
766 0 : if (aNewRange.first > aNewRange.second)
767 0 : std::swap(aNewRange.first,aNewRange.second);
768 :
769 : //Deselect the ones outside of it
770 0 : for (size_t i = 0, n = mFilteredItemList.size(); i < n; ++i)
771 : {
772 0 : ThumbnailViewItem *pCurItem = mFilteredItemList[i];
773 :
774 0 : if (pCurItem->isSelected() && (i < aNewRange.first || i > aNewRange.second))
775 : {
776 0 : pCurItem->setSelection(false);
777 :
778 0 : if (pCurItem->isVisible())
779 0 : DrawItem(pCurItem);
780 :
781 0 : maItemStateHdl.Call(pCurItem);
782 : }
783 : }
784 :
785 0 : size_t nSelPos = mpStartSelRange - mFilteredItemList.begin();
786 :
787 : //Select the items between start range and the selected item
788 0 : if (nSelPos != nPos)
789 : {
790 0 : int dir = nSelPos < nPos ? 1 : -1;
791 0 : size_t nCurPos = nSelPos + dir;
792 :
793 0 : while (nCurPos != nPos)
794 : {
795 0 : ThumbnailViewItem *pCurItem = mFilteredItemList[nCurPos];
796 :
797 0 : if (!pCurItem->isSelected())
798 : {
799 0 : pCurItem->setSelection(true);
800 :
801 0 : if (pCurItem->isVisible())
802 0 : DrawItem(pCurItem);
803 :
804 0 : maItemStateHdl.Call(pCurItem);
805 : }
806 :
807 0 : nCurPos += dir;
808 : }
809 : }
810 :
811 0 : pItem->setSelection(true);
812 : }
813 : else
814 : {
815 : //If we got a group of selected items deselect the rest and only keep the desired one
816 : //mark items as not selected to not fire unnecessary change state events.
817 0 : pItem->setSelection(false);
818 0 : deselectItems();
819 0 : pItem->setSelection(true);
820 :
821 : //Mark as initial selection range position and reset end one
822 0 : mpStartSelRange = mFilteredItemList.begin() + nPos;
823 : }
824 :
825 0 : if (pItem->isSelected())
826 : {
827 0 : bool bClickOnTitle = pItem->getTextArea().IsInside(rMEvt.GetPosPixel());
828 0 : pItem->setEditTitle(bClickOnTitle);
829 : }
830 :
831 0 : if (!pItem->isHighlighted())
832 0 : DrawItem(pItem);
833 :
834 0 : maItemStateHdl.Call(pItem);
835 :
836 : //fire accessible event??
837 : }
838 : }
839 :
840 0 : void ThumbnailView::MouseButtonUp( const MouseEvent& rMEvt )
841 : {
842 0 : Control::MouseButtonUp( rMEvt );
843 0 : }
844 :
845 0 : void ThumbnailView::Command( const CommandEvent& rCEvt )
846 : {
847 0 : if ( (rCEvt.GetCommand() == CommandEventId::Wheel) ||
848 0 : (rCEvt.GetCommand() == CommandEventId::StartAutoScroll) ||
849 0 : (rCEvt.GetCommand() == CommandEventId::AutoScroll) )
850 : {
851 0 : if ( HandleScrollCommand( rCEvt, NULL, mpScrBar ) )
852 0 : return;
853 : }
854 :
855 0 : Control::Command( rCEvt );
856 : }
857 :
858 0 : void ThumbnailView::Paint(vcl::RenderContext& /*rRenderContext*/, const Rectangle& rRect)
859 : {
860 0 : size_t nItemCount = mItemList.size();
861 :
862 : // Draw background
863 0 : drawinglayer::primitive2d::Primitive2DSequence aSeq(1);
864 0 : aSeq[0] = drawinglayer::primitive2d::Primitive2DReference(new PolyPolygonColorPrimitive2D(
865 : B2DPolyPolygon(Polygon(rRect, 5, 5).getB2DPolygon()),
866 0 : maColor.getBColor()));
867 :
868 0 : mpProcessor->process(aSeq);
869 :
870 : // draw items
871 0 : for (size_t i = 0; i < nItemCount; i++)
872 : {
873 0 : ThumbnailViewItem *const pItem = mItemList[i];
874 :
875 0 : if (pItem->isVisible())
876 : {
877 0 : DrawItem(pItem);
878 : }
879 : }
880 :
881 0 : if (mpScrBar && mpScrBar->IsVisible())
882 0 : mpScrBar->Invalidate(rRect);
883 0 : }
884 :
885 4 : void ThumbnailView::PrePaint(vcl::RenderContext& rRenderContext)
886 : {
887 : // Create the processor and process the primitives
888 4 : const drawinglayer::geometry::ViewInformation2D aNewViewInfos;
889 4 : mpProcessor.reset(drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(rRenderContext, aNewViewInfos));
890 4 : }
891 :
892 4 : void ThumbnailView::PostPaint(vcl::RenderContext& /*rRenderContext*/)
893 : {
894 4 : mpProcessor.reset();
895 4 : }
896 :
897 0 : void ThumbnailView::GetFocus()
898 : {
899 : // Select the first item if nothing selected
900 0 : int nSelected = -1;
901 0 : for (size_t i = 0, n = mItemList.size(); i < n && nSelected == -1; ++i)
902 : {
903 0 : if (mItemList[i]->isSelected())
904 0 : nSelected = i;
905 : }
906 :
907 0 : if (nSelected == -1 && mItemList.size() > 0)
908 : {
909 0 : SelectItem(1);
910 : }
911 :
912 : // Tell the accessible object that we got the focus.
913 0 : ThumbnailViewAcc* pAcc = ThumbnailViewAcc::getImplementation( GetAccessible( false ) );
914 0 : if( pAcc )
915 0 : pAcc->GetFocus();
916 :
917 0 : Control::GetFocus();
918 0 : }
919 :
920 0 : void ThumbnailView::LoseFocus()
921 : {
922 0 : Control::LoseFocus();
923 :
924 : // Tell the accessible object that we lost the focus.
925 0 : ThumbnailViewAcc* pAcc = ThumbnailViewAcc::getImplementation( GetAccessible( false ) );
926 0 : if( pAcc )
927 0 : pAcc->LoseFocus();
928 0 : }
929 :
930 9 : void ThumbnailView::Resize()
931 : {
932 9 : Control::Resize();
933 9 : CalculateItemPositions();
934 :
935 9 : if ( IsReallyVisible() && IsUpdateMode() )
936 5 : Invalidate();
937 9 : }
938 :
939 7 : void ThumbnailView::StateChanged( StateChangedType nType )
940 : {
941 7 : Control::StateChanged( nType );
942 :
943 7 : if ( nType == StateChangedType::InitShow )
944 : {
945 2 : if ( IsReallyVisible() && IsUpdateMode() )
946 0 : Invalidate();
947 : }
948 5 : else if ( nType == StateChangedType::UpdateMode )
949 : {
950 0 : if ( IsReallyVisible() && IsUpdateMode() )
951 0 : Invalidate();
952 : }
953 5 : else if ( nType == StateChangedType::Text )
954 : {
955 : }
956 5 : else if ( (nType == StateChangedType::Zoom) ||
957 : (nType == StateChangedType::ControlFont) )
958 : {
959 0 : ImplInitSettings( true, false, false );
960 0 : Invalidate();
961 : }
962 5 : else if ( nType == StateChangedType::ControlForeground )
963 : {
964 0 : ImplInitSettings( false, true, false );
965 0 : Invalidate();
966 : }
967 5 : else if ( nType == StateChangedType::ControlBackground )
968 : {
969 0 : ImplInitSettings( false, false, true );
970 0 : Invalidate();
971 : }
972 5 : else if ( (nType == StateChangedType::Style) || (nType == StateChangedType::Enable) )
973 : {
974 2 : ImplInitSettings( false, false, true );
975 2 : Invalidate();
976 : }
977 7 : }
978 :
979 0 : void ThumbnailView::DataChanged( const DataChangedEvent& rDCEvt )
980 : {
981 0 : Control::DataChanged( rDCEvt );
982 :
983 0 : if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
984 0 : (rDCEvt.GetType() == DataChangedEventType::DISPLAY) ||
985 0 : (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
986 0 : ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
987 0 : (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
988 : {
989 0 : ImplInitSettings( true, true, true );
990 0 : Invalidate();
991 : }
992 0 : }
993 :
994 0 : void ThumbnailView::RemoveItem( sal_uInt16 nItemId )
995 : {
996 0 : size_t nPos = GetItemPos( nItemId );
997 :
998 0 : if ( nPos == THUMBNAILVIEW_ITEM_NOTFOUND )
999 0 : return;
1000 :
1001 0 : if ( nPos < mFilteredItemList.size() ) {
1002 :
1003 : // delete item from the thumbnail list
1004 0 : for (size_t i = 0, n = mItemList.size(); i < n; ++i)
1005 : {
1006 0 : if (mItemList[i]->mnId == nItemId)
1007 : {
1008 0 : mItemList.erase(mItemList.begin()+i);
1009 0 : break;
1010 : }
1011 : }
1012 :
1013 : // delete item from the filter item list
1014 0 : ThumbnailValueItemList::iterator it = mFilteredItemList.begin();
1015 0 : ::std::advance( it, nPos );
1016 :
1017 0 : if ((*it)->isSelected())
1018 : {
1019 0 : (*it)->setSelection(false);
1020 0 : maItemStateHdl.Call(*it);
1021 : }
1022 :
1023 0 : delete *it;
1024 0 : mFilteredItemList.erase( it );
1025 0 : mpStartSelRange = mFilteredItemList.end();
1026 : }
1027 :
1028 0 : CalculateItemPositions();
1029 :
1030 0 : if ( IsReallyVisible() && IsUpdateMode() )
1031 0 : Invalidate();
1032 : }
1033 :
1034 1 : void ThumbnailView::Clear()
1035 : {
1036 1 : ImplDeleteItems();
1037 :
1038 : // reset variables
1039 1 : mnFirstLine = 0;
1040 :
1041 1 : CalculateItemPositions();
1042 :
1043 1 : if ( IsReallyVisible() && IsUpdateMode() )
1044 1 : Invalidate();
1045 1 : }
1046 :
1047 0 : void ThumbnailView::updateItems (const std::vector<ThumbnailViewItem*> &items)
1048 : {
1049 0 : ImplDeleteItems();
1050 :
1051 : // reset variables
1052 0 : mnFirstLine = 0;
1053 :
1054 0 : mItemList = items;
1055 :
1056 0 : filterItems(maFilterFunc);
1057 0 : }
1058 :
1059 0 : size_t ThumbnailView::GetItemPos( sal_uInt16 nItemId ) const
1060 : {
1061 0 : for ( size_t i = 0, n = mFilteredItemList.size(); i < n; ++i ) {
1062 0 : if ( mFilteredItemList[i]->mnId == nItemId ) {
1063 0 : return i;
1064 : }
1065 : }
1066 0 : return THUMBNAILVIEW_ITEM_NOTFOUND;
1067 : }
1068 :
1069 0 : sal_uInt16 ThumbnailView::GetItemId( size_t nPos ) const
1070 : {
1071 0 : return ( nPos < mFilteredItemList.size() ) ? mFilteredItemList[nPos]->mnId : 0 ;
1072 : }
1073 :
1074 0 : sal_uInt16 ThumbnailView::GetItemId( const Point& rPos ) const
1075 : {
1076 0 : size_t nItemPos = ImplGetItem( rPos );
1077 0 : if ( nItemPos != THUMBNAILVIEW_ITEM_NOTFOUND )
1078 0 : return GetItemId( nItemPos );
1079 :
1080 0 : return 0;
1081 : }
1082 :
1083 0 : sal_uInt16 ThumbnailView::getNextItemId() const
1084 : {
1085 0 : return mItemList.empty() ? 1 : mItemList.back()->mnId + 1;
1086 : }
1087 :
1088 1 : void ThumbnailView::setItemMaxTextLength(sal_uInt32 nLength)
1089 : {
1090 1 : mpItemAttrs->nMaxTextLength = nLength;
1091 1 : }
1092 :
1093 2 : void ThumbnailView::setItemDimensions(long itemWidth, long thumbnailHeight, long displayHeight, int itemPadding)
1094 : {
1095 2 : mnItemWidth = itemWidth + 2*itemPadding;
1096 2 : mnThumbnailHeight = thumbnailHeight;
1097 2 : mnDisplayHeight = displayHeight;
1098 2 : mnItemPadding = itemPadding;
1099 2 : mnItemHeight = mnDisplayHeight + mnThumbnailHeight + 2*itemPadding;
1100 2 : }
1101 :
1102 0 : void ThumbnailView::SelectItem( sal_uInt16 nItemId )
1103 : {
1104 0 : size_t nItemPos = GetItemPos( nItemId );
1105 0 : if ( nItemPos == THUMBNAILVIEW_ITEM_NOTFOUND )
1106 0 : return;
1107 :
1108 0 : ThumbnailViewItem* pItem = mFilteredItemList[nItemPos];
1109 0 : if (!pItem->isSelected())
1110 : {
1111 0 : pItem->setSelection(true);
1112 0 : maItemStateHdl.Call(pItem);
1113 :
1114 0 : if (IsReallyVisible() && IsUpdateMode())
1115 0 : Invalidate();
1116 :
1117 0 : bool bNewOut = IsReallyVisible() && IsUpdateMode();
1118 :
1119 : // if necessary scroll to the visible area
1120 0 : if ( mbScroll && nItemId )
1121 : {
1122 0 : sal_uInt16 nNewLine = (sal_uInt16)(nItemPos / mnCols);
1123 0 : if ( nNewLine < mnFirstLine )
1124 : {
1125 0 : mnFirstLine = nNewLine;
1126 : }
1127 0 : else if ( nNewLine > (sal_uInt16)(mnFirstLine+mnVisLines-1) )
1128 : {
1129 0 : mnFirstLine = (sal_uInt16)(nNewLine-mnVisLines+1);
1130 : }
1131 : }
1132 :
1133 0 : if ( bNewOut )
1134 : {
1135 0 : if ( IsReallyVisible() && IsUpdateMode() )
1136 0 : Invalidate();
1137 : }
1138 :
1139 0 : if( ImplHasAccessibleListeners() )
1140 : {
1141 : // focus event (select)
1142 0 : ThumbnailViewItemAcc* pItemAcc = ThumbnailViewItemAcc::getImplementation( pItem->GetAccessible( mbIsTransientChildrenDisabled ) );
1143 :
1144 0 : if( pItemAcc )
1145 : {
1146 0 : ::com::sun::star::uno::Any aOldAny, aNewAny;
1147 0 : if( !mbIsTransientChildrenDisabled )
1148 : {
1149 0 : aNewAny <<= ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >(
1150 0 : static_cast< ::cppu::OWeakObject* >( pItemAcc ));
1151 0 : ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny );
1152 : }
1153 : else
1154 : {
1155 0 : aNewAny <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED;
1156 0 : pItemAcc->FireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny );
1157 0 : }
1158 : }
1159 :
1160 : // selection event
1161 0 : ::com::sun::star::uno::Any aOldAny, aNewAny;
1162 0 : ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::SELECTION_CHANGED, aOldAny, aNewAny );
1163 : }
1164 : }
1165 : }
1166 :
1167 0 : bool ThumbnailView::IsItemSelected( sal_uInt16 nItemId ) const
1168 : {
1169 0 : size_t nItemPos = GetItemPos( nItemId );
1170 0 : if ( nItemPos == THUMBNAILVIEW_ITEM_NOTFOUND )
1171 0 : return false;
1172 :
1173 0 : ThumbnailViewItem* pItem = mFilteredItemList[nItemPos];
1174 0 : return pItem->isSelected();
1175 : }
1176 :
1177 0 : void ThumbnailView::deselectItems()
1178 : {
1179 0 : for (size_t i = 0, n = mItemList.size(); i < n; ++i)
1180 : {
1181 0 : if (mItemList[i]->isSelected())
1182 : {
1183 0 : mItemList[i]->setEditTitle(false);
1184 0 : mItemList[i]->setSelection(false);
1185 :
1186 0 : maItemStateHdl.Call(mItemList[i]);
1187 : }
1188 : }
1189 :
1190 0 : if (IsReallyVisible() && IsUpdateMode())
1191 0 : Invalidate();
1192 0 : }
1193 :
1194 1 : void ThumbnailView::ShowTooltips( bool bShowTooltips )
1195 : {
1196 1 : mbShowTooltips = bShowTooltips;
1197 1 : }
1198 :
1199 0 : void ThumbnailView::filterItems (const boost::function<bool (const ThumbnailViewItem*) > &func)
1200 : {
1201 0 : mnFirstLine = 0; // start at the top of the list instead of the current position
1202 0 : maFilterFunc = func;
1203 :
1204 0 : size_t nSelPos = 0;
1205 0 : bool bHasSelRange = false;
1206 0 : ThumbnailViewItem *curSel = mpStartSelRange != mFilteredItemList.end() ? *mpStartSelRange : NULL;
1207 :
1208 0 : mFilteredItemList.clear();
1209 :
1210 0 : for (size_t i = 0, n = mItemList.size(); i < n; ++i)
1211 : {
1212 0 : ThumbnailViewItem *const pItem = mItemList[i];
1213 :
1214 0 : if (maFilterFunc(pItem))
1215 : {
1216 0 : if (curSel == pItem)
1217 : {
1218 0 : nSelPos = i;
1219 0 : bHasSelRange = true;
1220 : }
1221 :
1222 0 : mFilteredItemList.push_back(pItem);
1223 : }
1224 : else
1225 : {
1226 0 : if( pItem->isVisible())
1227 : {
1228 0 : if ( ImplHasAccessibleListeners() )
1229 : {
1230 0 : ::com::sun::star::uno::Any aOldAny, aNewAny;
1231 :
1232 0 : aOldAny <<= pItem->GetAccessible( mbIsTransientChildrenDisabled );
1233 0 : ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny );
1234 : }
1235 :
1236 0 : pItem->show(false);
1237 0 : pItem->setSelection(false);
1238 :
1239 0 : maItemStateHdl.Call(pItem);
1240 : }
1241 : }
1242 : }
1243 :
1244 0 : mpStartSelRange = bHasSelRange ? mFilteredItemList.begin() + nSelPos : mFilteredItemList.end();
1245 0 : CalculateItemPositions();
1246 :
1247 0 : Invalidate();
1248 0 : }
1249 :
1250 0 : void ThumbnailView::sortItems (const boost::function<bool (const ThumbnailViewItem*, const ThumbnailViewItem*) > &func)
1251 : {
1252 0 : std::sort(mItemList.begin(),mItemList.end(),func);
1253 :
1254 0 : CalculateItemPositions();
1255 :
1256 0 : Invalidate();
1257 0 : }
1258 :
1259 0 : bool ThumbnailView::renameItem(ThumbnailViewItem*, const OUString&)
1260 : {
1261 : // Do nothing by default
1262 0 : return false;
1263 : }
1264 :
1265 0 : BitmapEx ThumbnailView::readThumbnail(const OUString &msURL)
1266 : {
1267 : using namespace ::com::sun::star;
1268 : using namespace ::com::sun::star::uno;
1269 :
1270 : // Load the thumbnail from a template document.
1271 0 : uno::Reference<io::XInputStream> xIStream;
1272 :
1273 0 : uno::Reference< uno::XComponentContext > xContext(::comphelper::getProcessComponentContext());
1274 : try
1275 : {
1276 0 : uno::Reference<lang::XSingleServiceFactory> xStorageFactory = embed::StorageFactory::create(xContext);
1277 :
1278 0 : uno::Sequence<uno::Any> aArgs (2);
1279 0 : aArgs[0] <<= msURL;
1280 0 : aArgs[1] <<= embed::ElementModes::READ;
1281 : uno::Reference<embed::XStorage> xDocStorage (
1282 0 : xStorageFactory->createInstanceWithArguments(aArgs),
1283 0 : uno::UNO_QUERY);
1284 :
1285 : try
1286 : {
1287 0 : if (xDocStorage.is())
1288 : {
1289 : uno::Reference<embed::XStorage> xStorage (
1290 0 : xDocStorage->openStorageElement(
1291 : "Thumbnails",
1292 0 : embed::ElementModes::READ));
1293 0 : if (xStorage.is())
1294 : {
1295 : uno::Reference<io::XStream> xThumbnailCopy (
1296 0 : xStorage->cloneStreamElement("thumbnail.png"));
1297 0 : if (xThumbnailCopy.is())
1298 0 : xIStream = xThumbnailCopy->getInputStream();
1299 0 : }
1300 : }
1301 : }
1302 0 : catch (const uno::Exception& rException)
1303 : {
1304 : OSL_TRACE (
1305 : "caught exception while trying to access Thumbnail/thumbnail.png of %s: %s",
1306 : OUStringToOString(msURL,
1307 : RTL_TEXTENCODING_UTF8).getStr(),
1308 : OUStringToOString(rException.Message,
1309 : RTL_TEXTENCODING_UTF8).getStr());
1310 : }
1311 :
1312 : try
1313 : {
1314 : // An (older) implementation had a bug - The storage
1315 : // name was "Thumbnail" instead of "Thumbnails". The
1316 : // old name is still used as fallback but this code can
1317 : // be removed soon.
1318 0 : if ( ! xIStream.is())
1319 : {
1320 : uno::Reference<embed::XStorage> xStorage (
1321 0 : xDocStorage->openStorageElement( "Thumbnail",
1322 0 : embed::ElementModes::READ));
1323 0 : if (xStorage.is())
1324 : {
1325 : uno::Reference<io::XStream> xThumbnailCopy (
1326 0 : xStorage->cloneStreamElement("thumbnail.png"));
1327 0 : if (xThumbnailCopy.is())
1328 0 : xIStream = xThumbnailCopy->getInputStream();
1329 0 : }
1330 : }
1331 : }
1332 0 : catch (const uno::Exception& rException)
1333 : {
1334 : OSL_TRACE (
1335 : "caught exception while trying to access Thumbnails/thumbnail.png of %s: %s",
1336 : OUStringToOString(msURL,
1337 : RTL_TEXTENCODING_UTF8).getStr(),
1338 : OUStringToOString(rException.Message,
1339 : RTL_TEXTENCODING_UTF8).getStr());
1340 0 : }
1341 : }
1342 0 : catch (const uno::Exception& rException)
1343 : {
1344 : OSL_TRACE (
1345 : "caught exception while trying to access tuhmbnail of %s: %s",
1346 : OUStringToOString(msURL,
1347 : RTL_TEXTENCODING_UTF8).getStr(),
1348 : OUStringToOString(rException.Message,
1349 : RTL_TEXTENCODING_UTF8).getStr());
1350 : }
1351 :
1352 : // Extract the image from the stream.
1353 0 : BitmapEx aThumbnail;
1354 0 : if (xIStream.is())
1355 : {
1356 : boost::scoped_ptr<SvStream> pStream (
1357 0 : ::utl::UcbStreamHelper::CreateStream (xIStream));
1358 0 : vcl::PNGReader aReader (*pStream);
1359 0 : aThumbnail = aReader.Read ();
1360 : }
1361 :
1362 : // Note that the preview is returned without scaling it to the desired
1363 : // width. This gives the caller the chance to take advantage of a
1364 : // possibly larger resolution then was asked for.
1365 0 : return aThumbnail;
1366 648 : }
1367 :
1368 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|