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