Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * Copyright 2012 LibreOffice contributors.
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 "thumbnailviewacc.hxx"
14 :
15 : #include <basegfx/color/bcolortools.hxx>
16 : #include <basegfx/matrix/b2dhommatrixtools.hxx>
17 : #include <basegfx/range/b2drectangle.hxx>
18 : #include <basegfx/polygon/b2dpolygon.hxx>
19 : #include <basegfx/vector/b2dsize.hxx>
20 : #include <basegfx/vector/b2dvector.hxx>
21 : #include <drawinglayer/attribute/fillbitmapattribute.hxx>
22 : #include <drawinglayer/attribute/fontattribute.hxx>
23 : #include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx>
24 : #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
25 : #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
26 : #include <drawinglayer/primitive2d/textprimitive2d.hxx>
27 : #include <drawinglayer/processor2d/baseprocessor2d.hxx>
28 : #include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
29 : #include <rtl/ustring.hxx>
30 : #include <vcl/decoview.hxx>
31 : #include <vcl/svapp.hxx>
32 : #include <vcl/scrbar.hxx>
33 : #include <vcl/help.hxx>
34 :
35 : #include <com/sun/star/accessibility/AccessibleEventId.hpp>
36 : #include <com/sun/star/accessibility/AccessibleStateType.hpp>
37 :
38 : using namespace basegfx;
39 : using namespace basegfx::tools;
40 : using namespace drawinglayer::attribute;
41 : using namespace drawinglayer::primitive2d;
42 :
43 : enum
44 : {
45 : ITEM_OFFSET = 4,
46 : ITEM_OFFSET_DOUBLE = 6,
47 : NAME_LINE_OFF_X = 2,
48 : NAME_LINE_OFF_Y = 2,
49 : NAME_LINE_HEIGHT = 2,
50 : NAME_OFFSET = 2,
51 : SCROLL_OFFSET = 4
52 : };
53 :
54 0 : ThumbnailView::ThumbnailView (Window *pParent, WinBits nWinStyle, bool bDisableTransientChildren)
55 0 : : Control( pParent, nWinStyle )
56 : {
57 0 : ImplInit();
58 0 : mbIsTransientChildrenDisabled = bDisableTransientChildren;
59 0 : }
60 :
61 0 : ThumbnailView::ThumbnailView (Window *pParent, const ResId &rResId, bool bDisableTransientChildren)
62 0 : : Control( pParent, rResId )
63 : {
64 0 : ImplInit();
65 0 : mbIsTransientChildrenDisabled = bDisableTransientChildren;
66 0 : }
67 :
68 0 : ThumbnailView::~ThumbnailView()
69 : {
70 : com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent>
71 : xComponent(GetAccessible(sal_False),
72 0 : com::sun::star::uno::UNO_QUERY);
73 :
74 0 : if (xComponent.is())
75 0 : xComponent->dispose ();
76 :
77 0 : delete mpScrBar;
78 0 : delete mpItemAttrs;
79 0 : delete mpProcessor;
80 :
81 0 : ImplDeleteItems();
82 0 : }
83 :
84 0 : void ThumbnailView::ImplInit()
85 : {
86 0 : mpScrBar = NULL;
87 0 : mnHeaderHeight = 0;
88 0 : mnItemWidth = 0;
89 0 : mnItemHeight = 0;
90 0 : mnItemPadding = 0;
91 0 : mnVisLines = 0;
92 0 : mnLines = 0;
93 0 : mnFirstLine = 0;
94 0 : mnScrBarOffset = 1;
95 0 : mnSelItemId = 0;
96 0 : mnHighItemId = 0;
97 0 : mnCols = 0;
98 0 : mnSpacing = 0;
99 0 : mbScroll = false;
100 0 : mbHasVisibleItems = false;
101 0 : maFilterFunc = ViewFilterAll();
102 0 : maColor = GetSettings().GetStyleSettings().GetFieldColor();
103 :
104 : // Create the processor and process the primitives
105 0 : const drawinglayer::geometry::ViewInformation2D aNewViewInfos;
106 0 : mpProcessor = drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(*this, aNewViewInfos );
107 :
108 0 : ImplInitSettings( true, true, true );
109 0 : }
110 :
111 0 : void ThumbnailView::ImplDeleteItems()
112 : {
113 0 : const size_t n = mItemList.size();
114 :
115 0 : for ( size_t i = 0; i < n; ++i )
116 : {
117 0 : ThumbnailViewItem *const pItem = mItemList[i];
118 0 : if ( pItem->isVisible() && ImplHasAccessibleListeners() )
119 : {
120 0 : ::com::sun::star::uno::Any aOldAny, aNewAny;
121 :
122 0 : aOldAny <<= pItem->GetAccessible( mbIsTransientChildrenDisabled );
123 0 : ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny );
124 : }
125 :
126 0 : delete pItem;
127 : }
128 :
129 0 : mItemList.clear();
130 0 : }
131 :
132 0 : void ThumbnailView::ImplInitSettings( bool bFont, bool bForeground, bool bBackground )
133 : {
134 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
135 :
136 0 : if ( bFont )
137 : {
138 0 : Font aFont;
139 0 : aFont = rStyleSettings.GetAppFont();
140 0 : if ( IsControlFont() )
141 0 : aFont.Merge( GetControlFont() );
142 0 : SetZoomedPointFont( aFont );
143 : }
144 :
145 0 : if ( bForeground || bFont )
146 : {
147 0 : Color aColor;
148 0 : if ( IsControlForeground() )
149 0 : aColor = GetControlForeground();
150 : else
151 0 : aColor = rStyleSettings.GetButtonTextColor();
152 0 : SetTextColor( aColor );
153 0 : SetTextFillColor();
154 : }
155 :
156 0 : if ( bBackground )
157 : {
158 0 : Color aColor = rStyleSettings.GetFieldColor();
159 0 : SetBackground( aColor );
160 : }
161 :
162 :
163 0 : mpItemAttrs = new ThumbnailItemAttributes;
164 0 : mpItemAttrs->aFillColor = maColor.getBColor();
165 0 : mpItemAttrs->aHighlightColor = rStyleSettings.GetHighlightColor().getBColor();
166 0 : mpItemAttrs->aFontAttr = getFontAttributeFromVclFont(mpItemAttrs->aFontSize,GetFont(),false,true);
167 0 : mpItemAttrs->nMaxTextLenght = -1;
168 0 : }
169 :
170 0 : void ThumbnailView::ImplInitScrollBar()
171 : {
172 0 : if ( GetStyle() & WB_VSCROLL )
173 : {
174 0 : if ( !mpScrBar )
175 : {
176 0 : mpScrBar = new ScrollBar( this, WB_VSCROLL | WB_DRAG );
177 0 : mpScrBar->SetScrollHdl( LINK( this, ThumbnailView, ImplScrollHdl ) );
178 : }
179 : else
180 : {
181 : // adapt the width because of the changed settings
182 0 : long nScrBarWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
183 0 : mpScrBar->setPosSizePixel( 0, 0, nScrBarWidth, 0, WINDOW_POSSIZE_WIDTH );
184 : }
185 : }
186 0 : }
187 :
188 0 : void ThumbnailView::DrawItem (ThumbnailViewItem *pItem)
189 : {
190 0 : if (pItem->isVisible())
191 : {
192 0 : Rectangle aRect = pItem->getDrawArea();
193 :
194 0 : if ( (aRect.GetHeight() > 0) && (aRect.GetWidth() > 0) )
195 0 : pItem->Paint(mpProcessor,mpItemAttrs);
196 : }
197 0 : }
198 :
199 0 : void ThumbnailView::OnItemDblClicked (ThumbnailViewItem*)
200 : {
201 0 : }
202 :
203 0 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > ThumbnailView::CreateAccessible()
204 : {
205 0 : return new ThumbnailViewAcc( this, mbIsTransientChildrenDisabled );
206 : }
207 :
208 0 : void ThumbnailView::CalculateItemPositions ()
209 : {
210 0 : if (!mnItemHeight || !mnItemWidth)
211 0 : return;
212 :
213 0 : Size aWinSize = GetOutputSizePixel();
214 0 : size_t nItemCount = mItemList.size();
215 0 : WinBits nStyle = GetStyle();
216 0 : ScrollBar* pDelScrBar = NULL;
217 :
218 : // consider the scrolling
219 0 : if ( nStyle & WB_VSCROLL )
220 0 : ImplInitScrollBar();
221 : else
222 : {
223 0 : if ( mpScrBar )
224 : {
225 : // delete ScrollBar not until later, to prevent recursive calls
226 0 : pDelScrBar = mpScrBar;
227 0 : mpScrBar = NULL;
228 : }
229 : }
230 :
231 : // calculate ScrollBar width
232 0 : long nScrBarWidth = 0;
233 0 : if ( mpScrBar )
234 0 : nScrBarWidth = mpScrBar->GetSizePixel().Width()+mnScrBarOffset;
235 :
236 : // calculate maximum number of visible columns
237 0 : mnCols = (sal_uInt16)((aWinSize.Width()-nScrBarWidth) / (mnItemWidth));
238 :
239 0 : if (!mnCols)
240 0 : mnCols = 1;
241 :
242 : // calculate maximum number of visible rows
243 0 : mnVisLines = (sal_uInt16)((aWinSize.Height()-mnHeaderHeight) / (mnItemHeight));
244 :
245 : // calculate empty space
246 0 : long nHSpace = aWinSize.Width()-nScrBarWidth - mnCols*mnItemWidth;
247 0 : long nVSpace = aWinSize.Height()-mnHeaderHeight - mnVisLines*mnItemHeight;
248 0 : long nHItemSpace = nHSpace / (mnCols+1);
249 0 : long nVItemSpace = nVSpace / (mnVisLines+1);
250 :
251 : // calculate maximum number of rows
252 : // Floor( (M+N-1)/N )==Ceiling( M/N )
253 0 : mnLines = (static_cast<long>(nItemCount)+mnCols-1) / mnCols;
254 :
255 0 : if ( !mnLines )
256 0 : mnLines = 1;
257 :
258 : // check if scroll is needed
259 0 : mbScroll = mnLines > mnVisLines;
260 :
261 0 : if ( mnLines <= mnVisLines )
262 0 : mnFirstLine = 0;
263 : else
264 : {
265 0 : if ( mnFirstLine > (sal_uInt16)(mnLines-mnVisLines) )
266 0 : mnFirstLine = (sal_uInt16)(mnLines-mnVisLines);
267 : }
268 :
269 0 : mbHasVisibleItems = true;
270 :
271 : // calculate offsets
272 0 : long nStartX = nHItemSpace;
273 0 : long nStartY = nVItemSpace + mnHeaderHeight;
274 :
275 : // calculate and draw items
276 0 : long x = nStartX;
277 0 : long y = nStartY;
278 :
279 : // draw items
280 0 : size_t nFirstItem = mnFirstLine * mnCols;
281 0 : size_t nLastItem = nFirstItem + (mnVisLines * mnCols);
282 0 : size_t nTotalItems = mnFirstLine*mnCols + mnVisLines*mnCols;
283 :
284 0 : maItemListRect.Left() = x;
285 0 : maItemListRect.Top() = y;
286 0 : maItemListRect.Right() = x + mnCols*(mnItemWidth+nHItemSpace) - nHItemSpace - 1;
287 0 : maItemListRect.Bottom() = y + mnVisLines*(mnItemHeight+nVItemSpace) - nVItemSpace - 1;
288 :
289 : // If want also draw parts of items in the last line,
290 : // then we add one more line if parts of these line are
291 : // visible
292 0 : if ( y+(mnVisLines*(mnItemHeight+nVItemSpace)) < aWinSize.Height() )
293 0 : nTotalItems += mnCols;
294 :
295 0 : size_t nCurCount = 0;
296 0 : for ( size_t i = 0; i < nItemCount; i++ )
297 : {
298 0 : ThumbnailViewItem *const pItem = mItemList[i];
299 :
300 0 : if (maFilterFunc(pItem))
301 : {
302 0 : if ((nCurCount >= nFirstItem) && (nCurCount < nLastItem))
303 : {
304 0 : if( !pItem->isVisible())
305 : {
306 0 : if ( ImplHasAccessibleListeners() )
307 : {
308 0 : ::com::sun::star::uno::Any aOldAny, aNewAny;
309 :
310 0 : aNewAny <<= pItem->GetAccessible( mbIsTransientChildrenDisabled );
311 0 : ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny );
312 : }
313 :
314 0 : pItem->show(true);
315 :
316 0 : maItemStateHdl.Call(pItem);
317 : }
318 :
319 0 : pItem->setDrawArea(Rectangle( Point(x,y), Size(mnItemWidth, mnItemHeight) ));
320 0 : pItem->calculateItemsPosition(mnThumbnailHeight,mnDisplayHeight,mnItemPadding,mpItemAttrs->nMaxTextLenght,mpItemAttrs);
321 :
322 0 : if ( !((nCurCount+1) % mnCols) )
323 : {
324 0 : x = nStartX;
325 0 : y += mnItemHeight+nVItemSpace;
326 : }
327 : else
328 0 : x += mnItemWidth+nHItemSpace;
329 : }
330 : else
331 : {
332 0 : if( pItem->isVisible())
333 : {
334 0 : if ( ImplHasAccessibleListeners() )
335 : {
336 0 : ::com::sun::star::uno::Any aOldAny, aNewAny;
337 :
338 0 : aOldAny <<= pItem->GetAccessible( mbIsTransientChildrenDisabled );
339 0 : ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny );
340 : }
341 :
342 0 : pItem->show(false);
343 :
344 0 : maItemStateHdl.Call(pItem);
345 : }
346 :
347 : }
348 :
349 0 : ++nCurCount;
350 : }
351 : else
352 : {
353 0 : if( pItem->isVisible())
354 : {
355 0 : if ( ImplHasAccessibleListeners() )
356 : {
357 0 : ::com::sun::star::uno::Any aOldAny, aNewAny;
358 :
359 0 : aOldAny <<= pItem->GetAccessible( mbIsTransientChildrenDisabled );
360 0 : ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny );
361 : }
362 :
363 0 : pItem->show(false);
364 :
365 0 : maItemStateHdl.Call(pItem);
366 : }
367 : }
368 : }
369 :
370 : // arrange ScrollBar, set values and show it
371 0 : if ( mpScrBar )
372 : {
373 0 : long nLines = (nCurCount+mnCols-1)/mnCols;
374 :
375 0 : Point aPos( aWinSize.Width() - nScrBarWidth - mnScrBarOffset, mnHeaderHeight );
376 0 : Size aSize( nScrBarWidth - mnScrBarOffset, aWinSize.Height() - mnHeaderHeight );
377 :
378 0 : mpScrBar->SetPosSizePixel( aPos, aSize );
379 0 : mpScrBar->SetRangeMax( (nCurCount+mnCols-1)/mnCols);
380 0 : mpScrBar->SetVisibleSize( mnVisLines );
381 0 : mpScrBar->SetThumbPos( (long)mnFirstLine );
382 0 : long nPageSize = mnVisLines;
383 0 : if ( nPageSize < 1 )
384 0 : nPageSize = 1;
385 0 : mpScrBar->SetPageSize( nPageSize );
386 0 : mpScrBar->Show( nLines > mnVisLines );
387 : }
388 :
389 : // delete ScrollBar
390 0 : delete pDelScrBar;
391 : }
392 :
393 0 : size_t ThumbnailView::ImplGetItem( const Point& rPos, bool bMove ) const
394 : {
395 0 : if ( !mbHasVisibleItems )
396 : {
397 0 : return THUMBNAILVIEW_ITEM_NOTFOUND;
398 : }
399 :
400 0 : if ( maItemListRect.IsInside( rPos ) )
401 : {
402 0 : for (size_t i = 0; i < mItemList.size(); ++i)
403 : {
404 0 : if (mItemList[i]->isVisible() && mItemList[i]->getDrawArea().IsInside(rPos))
405 0 : return i;
406 : }
407 :
408 : // return the previously selected item if spacing is set and
409 : // the mouse hasn't left the window yet
410 0 : if ( bMove && mnSpacing && mnHighItemId )
411 : {
412 0 : return GetItemPos( mnHighItemId );
413 : }
414 : }
415 :
416 0 : return THUMBNAILVIEW_ITEM_NOTFOUND;
417 : }
418 :
419 0 : ThumbnailViewItem* ThumbnailView::ImplGetItem( size_t nPos )
420 : {
421 0 : return ( nPos < mItemList.size() ) ? mItemList[nPos] : NULL;
422 : }
423 :
424 0 : sal_uInt16 ThumbnailView::ImplGetVisibleItemCount() const
425 : {
426 0 : sal_uInt16 nRet = 0;
427 0 : const size_t nItemCount = mItemList.size();
428 :
429 0 : for ( size_t n = 0; n < nItemCount; ++n )
430 : {
431 0 : if ( mItemList[n]->isVisible() )
432 0 : ++nRet;
433 : }
434 :
435 0 : return nRet;
436 : }
437 :
438 0 : ThumbnailViewItem* ThumbnailView::ImplGetVisibleItem( sal_uInt16 nVisiblePos )
439 : {
440 0 : const size_t nItemCount = mItemList.size();
441 :
442 0 : for ( size_t n = 0; n < nItemCount; ++n )
443 : {
444 0 : ThumbnailViewItem *const pItem = mItemList[n];
445 :
446 0 : if ( pItem->isVisible() && !nVisiblePos-- )
447 0 : return pItem;
448 : }
449 :
450 0 : return NULL;
451 : }
452 :
453 0 : void ThumbnailView::ImplFireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue )
454 : {
455 0 : ThumbnailViewAcc* pAcc = ThumbnailViewAcc::getImplementation( GetAccessible( sal_False ) );
456 :
457 0 : if( pAcc )
458 0 : pAcc->FireAccessibleEvent( nEventId, rOldValue, rNewValue );
459 0 : }
460 :
461 0 : bool ThumbnailView::ImplHasAccessibleListeners()
462 : {
463 0 : ThumbnailViewAcc* pAcc = ThumbnailViewAcc::getImplementation( GetAccessible( sal_False ) );
464 0 : return( pAcc && pAcc->HasAccessibleListeners() );
465 : }
466 :
467 0 : IMPL_LINK( ThumbnailView,ImplScrollHdl, ScrollBar*, pScrollBar )
468 : {
469 0 : sal_uInt16 nNewFirstLine = mnFirstLine;
470 :
471 0 : if (pScrollBar->GetDelta() > 0)
472 0 : nNewFirstLine += 1;
473 : else
474 0 : nNewFirstLine -= 1;
475 :
476 0 : if ( nNewFirstLine != mnFirstLine )
477 : {
478 0 : mnFirstLine = nNewFirstLine;
479 :
480 0 : CalculateItemPositions();
481 :
482 0 : if ( IsReallyVisible() && IsUpdateMode() )
483 0 : Invalidate();
484 : }
485 0 : return 0;
486 : }
487 :
488 0 : IMPL_LINK (ThumbnailView, OnItemSelected, ThumbnailViewItem*, pItem)
489 : {
490 0 : maItemStateHdl.Call(pItem);
491 0 : return 0;
492 : }
493 :
494 0 : void ThumbnailView::MouseButtonDown( const MouseEvent& rMEvt )
495 : {
496 0 : if ( rMEvt.IsLeft() )
497 : {
498 0 : ThumbnailViewItem* pItem = ImplGetItem( ImplGetItem( rMEvt.GetPosPixel() ) );
499 :
500 0 : if (pItem && pItem->isVisible())
501 : {
502 0 : if ( rMEvt.GetClicks() == 1 )
503 : {
504 0 : if (!pItem->isSelected() && !rMEvt.IsMod1())
505 0 : deselectItems( );
506 0 : pItem->setSelection(!pItem->isSelected());
507 :
508 0 : if (!pItem->isHighlighted())
509 0 : DrawItem(pItem);
510 :
511 0 : maItemStateHdl.Call(pItem);
512 : }
513 0 : else if ( rMEvt.GetClicks() == 2 )
514 : {
515 : // The mouse button down event 1 click right before is pointless
516 0 : pItem->setSelection(!pItem->isSelected());
517 0 : maItemStateHdl.Call(pItem);
518 :
519 0 : Rectangle aRect(pItem->getDrawArea());
520 0 : aRect.SetSize(Size(mnItemWidth,mnThumbnailHeight));
521 :
522 0 : if (aRect.IsInside(rMEvt.GetPosPixel()))
523 0 : OnItemDblClicked(pItem);
524 : }
525 :
526 0 : return;
527 : }
528 : }
529 :
530 0 : Control::MouseButtonDown( rMEvt );
531 : }
532 :
533 0 : void ThumbnailView::MouseButtonUp( const MouseEvent& rMEvt )
534 : {
535 0 : Control::MouseButtonUp( rMEvt );
536 0 : }
537 :
538 0 : void ThumbnailView::Command( const CommandEvent& rCEvt )
539 : {
540 0 : if ( (rCEvt.GetCommand() == COMMAND_WHEEL) ||
541 0 : (rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL) ||
542 0 : (rCEvt.GetCommand() == COMMAND_AUTOSCROLL) )
543 : {
544 0 : if ( HandleScrollCommand( rCEvt, NULL, mpScrBar ) )
545 0 : return;
546 : }
547 :
548 0 : Control::Command( rCEvt );
549 : }
550 :
551 0 : void ThumbnailView::Paint( const Rectangle &aRect)
552 : {
553 0 : size_t nItemCount = mItemList.size();
554 :
555 : // Draw background
556 0 : Primitive2DSequence aSeq(1);
557 0 : aSeq[0] = Primitive2DReference( new PolyPolygonColorPrimitive2D(
558 : B2DPolyPolygon(Polygon(aRect,5,5).getB2DPolygon()),
559 0 : maColor.getBColor()));
560 :
561 0 : mpProcessor->process(aSeq);
562 :
563 : // draw items
564 0 : for ( size_t i = 0; i < nItemCount; i++ )
565 : {
566 0 : ThumbnailViewItem *const pItem = mItemList[i];
567 :
568 0 : if ( pItem->isVisible() )
569 0 : DrawItem(pItem);
570 : }
571 :
572 0 : if ( mpScrBar && mpScrBar->IsVisible() )
573 0 : mpScrBar->Paint(aRect);
574 0 : }
575 :
576 0 : void ThumbnailView::GetFocus()
577 : {
578 0 : Control::GetFocus();
579 :
580 : // Tell the accessible object that we got the focus.
581 0 : ThumbnailViewAcc* pAcc = ThumbnailViewAcc::getImplementation( GetAccessible( sal_False ) );
582 0 : if( pAcc )
583 0 : pAcc->GetFocus();
584 0 : }
585 :
586 0 : void ThumbnailView::LoseFocus()
587 : {
588 0 : if (mnHighItemId)
589 : {
590 0 : size_t nPos = GetItemPos(mnHighItemId);
591 :
592 0 : if (nPos != THUMBNAILVIEW_ITEM_NOTFOUND)
593 : {
594 0 : ThumbnailViewItem *pOld = mItemList[nPos];
595 :
596 0 : pOld->setHighlight(false);
597 :
598 0 : if (!pOld->isSelected())
599 0 : DrawItem(pOld);
600 : }
601 :
602 0 : mnHighItemId = 0;
603 : }
604 :
605 0 : Control::LoseFocus();
606 :
607 : // Tell the accessible object that we lost the focus.
608 0 : ThumbnailViewAcc* pAcc = ThumbnailViewAcc::getImplementation( GetAccessible( sal_False ) );
609 0 : if( pAcc )
610 0 : pAcc->LoseFocus();
611 0 : }
612 :
613 0 : void ThumbnailView::Resize()
614 : {
615 0 : CalculateItemPositions();
616 :
617 0 : if ( IsReallyVisible() && IsUpdateMode() )
618 0 : Invalidate();
619 0 : Control::Resize();
620 0 : }
621 :
622 0 : void ThumbnailView::StateChanged( StateChangedType nType )
623 : {
624 0 : Control::StateChanged( nType );
625 :
626 0 : if ( nType == STATE_CHANGE_INITSHOW )
627 : {
628 0 : if ( IsReallyVisible() && IsUpdateMode() )
629 0 : Invalidate();
630 : }
631 0 : else if ( nType == STATE_CHANGE_UPDATEMODE )
632 : {
633 0 : if ( IsReallyVisible() && IsUpdateMode() )
634 0 : Invalidate();
635 : }
636 0 : else if ( nType == STATE_CHANGE_TEXT )
637 : {
638 : }
639 0 : else if ( (nType == STATE_CHANGE_ZOOM) ||
640 : (nType == STATE_CHANGE_CONTROLFONT) )
641 : {
642 0 : ImplInitSettings( true, false, false );
643 0 : Invalidate();
644 : }
645 0 : else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
646 : {
647 0 : ImplInitSettings( false, true, false );
648 0 : Invalidate();
649 : }
650 0 : else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
651 : {
652 0 : ImplInitSettings( false, false, true );
653 0 : Invalidate();
654 : }
655 0 : else if ( (nType == STATE_CHANGE_STYLE) || (nType == STATE_CHANGE_ENABLE) )
656 : {
657 0 : ImplInitSettings( false, false, true );
658 0 : Invalidate();
659 : }
660 0 : }
661 :
662 0 : void ThumbnailView::DataChanged( const DataChangedEvent& rDCEvt )
663 : {
664 0 : Control::DataChanged( rDCEvt );
665 :
666 0 : if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
667 0 : (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
668 0 : (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
669 0 : ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
670 0 : (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
671 : {
672 0 : ImplInitSettings( true, true, true );
673 0 : Invalidate();
674 : }
675 0 : }
676 :
677 0 : void ThumbnailView::RemoveItem( sal_uInt16 nItemId )
678 : {
679 0 : size_t nPos = GetItemPos( nItemId );
680 :
681 0 : if ( nPos == THUMBNAILVIEW_ITEM_NOTFOUND )
682 0 : return;
683 :
684 0 : if ( nPos < mItemList.size() ) {
685 0 : ValueItemList::iterator it = mItemList.begin();
686 0 : ::std::advance( it, nPos );
687 0 : delete *it;
688 0 : mItemList.erase( it );
689 : }
690 :
691 : // reset variables
692 0 : if ( (mnHighItemId == nItemId) || (mnSelItemId == nItemId) )
693 : {
694 0 : mnHighItemId = 0;
695 0 : mnSelItemId = 0;
696 : }
697 :
698 0 : CalculateItemPositions();
699 :
700 0 : if ( IsReallyVisible() && IsUpdateMode() )
701 0 : Invalidate();
702 : }
703 :
704 0 : void ThumbnailView::Clear()
705 : {
706 0 : ImplDeleteItems();
707 :
708 : // reset variables
709 0 : mnFirstLine = 0;
710 0 : mnHighItemId = 0;
711 0 : mnSelItemId = 0;
712 :
713 0 : CalculateItemPositions();
714 :
715 0 : if ( IsReallyVisible() && IsUpdateMode() )
716 0 : Invalidate();
717 0 : }
718 :
719 0 : size_t ThumbnailView::GetItemPos( sal_uInt16 nItemId ) const
720 : {
721 0 : for ( size_t i = 0, n = mItemList.size(); i < n; ++i ) {
722 0 : if ( mItemList[i]->mnId == nItemId ) {
723 0 : return i;
724 : }
725 : }
726 0 : return THUMBNAILVIEW_ITEM_NOTFOUND;
727 : }
728 :
729 0 : sal_uInt16 ThumbnailView::GetItemId( size_t nPos ) const
730 : {
731 0 : return ( nPos < mItemList.size() ) ? mItemList[nPos]->mnId : 0 ;
732 : }
733 :
734 0 : sal_uInt16 ThumbnailView::GetItemId( const Point& rPos ) const
735 : {
736 0 : size_t nItemPos = ImplGetItem( rPos );
737 0 : if ( nItemPos != THUMBNAILVIEW_ITEM_NOTFOUND )
738 0 : return GetItemId( nItemPos );
739 :
740 0 : return 0;
741 : }
742 :
743 0 : void ThumbnailView::setItemMaxTextLength(sal_uInt32 nLength)
744 : {
745 0 : mpItemAttrs->nMaxTextLenght = nLength;
746 0 : }
747 :
748 0 : void ThumbnailView::setItemDimensions(long itemWidth, long thumbnailHeight, long displayHeight, int itemPadding)
749 : {
750 0 : mnItemWidth = itemWidth + 2*itemPadding;
751 0 : mnThumbnailHeight = thumbnailHeight;
752 0 : mnDisplayHeight = displayHeight;
753 0 : mnItemPadding = itemPadding;
754 0 : mnItemHeight = mnDisplayHeight + mnThumbnailHeight + 2*itemPadding;
755 0 : }
756 :
757 0 : void ThumbnailView::SelectItem( sal_uInt16 nItemId )
758 : {
759 0 : size_t nItemPos = 0;
760 :
761 0 : if ( nItemId )
762 : {
763 0 : nItemPos = GetItemPos( nItemId );
764 0 : if ( nItemPos == THUMBNAILVIEW_ITEM_NOTFOUND )
765 0 : return;
766 : }
767 :
768 0 : if ( mnSelItemId != nItemId)
769 : {
770 0 : sal_uInt16 nOldItem = mnSelItemId ? mnSelItemId : 1;
771 0 : mnSelItemId = nItemId;
772 :
773 0 : bool bNewOut = IsReallyVisible() && IsUpdateMode();
774 :
775 : // if necessary scroll to the visible area
776 0 : if ( mbScroll && nItemId )
777 : {
778 0 : sal_uInt16 nNewLine = (sal_uInt16)(nItemPos / mnCols);
779 0 : if ( nNewLine < mnFirstLine )
780 : {
781 0 : mnFirstLine = nNewLine;
782 : }
783 0 : else if ( nNewLine > (sal_uInt16)(mnFirstLine+mnVisLines-1) )
784 : {
785 0 : mnFirstLine = (sal_uInt16)(nNewLine-mnVisLines+1);
786 : }
787 : }
788 :
789 0 : if ( bNewOut )
790 : {
791 0 : if ( IsReallyVisible() && IsUpdateMode() )
792 0 : Invalidate();
793 : }
794 :
795 0 : if( ImplHasAccessibleListeners() )
796 : {
797 : // focus event (deselect)
798 0 : if( nOldItem )
799 : {
800 0 : const size_t nPos = GetItemPos( nItemId );
801 :
802 0 : if( nPos != THUMBNAILVIEW_ITEM_NOTFOUND )
803 : {
804 : ThumbnailViewAcc* pItemAcc = ThumbnailViewAcc::getImplementation(
805 0 : mItemList[nPos]->GetAccessible( mbIsTransientChildrenDisabled ) );
806 :
807 0 : if( pItemAcc )
808 : {
809 0 : ::com::sun::star::uno::Any aOldAny, aNewAny;
810 0 : if( !mbIsTransientChildrenDisabled )
811 : {
812 : aOldAny <<= ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >(
813 0 : static_cast< ::cppu::OWeakObject* >( pItemAcc ));
814 0 : ImplFireAccessibleEvent (::com::sun::star::accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny );
815 : }
816 : else
817 : {
818 0 : aOldAny <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED;
819 0 : pItemAcc->FireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny );
820 0 : }
821 : }
822 : }
823 : }
824 :
825 : // focus event (select)
826 0 : const size_t nPos = GetItemPos( mnSelItemId );
827 :
828 0 : ThumbnailViewItem* pItem = NULL;
829 0 : if( nPos != THUMBNAILVIEW_ITEM_NOTFOUND )
830 0 : pItem = mItemList[nPos];
831 :
832 0 : ThumbnailViewAcc* pItemAcc = NULL;
833 0 : if (pItem != NULL)
834 0 : pItemAcc = ThumbnailViewAcc::getImplementation( pItem->GetAccessible( mbIsTransientChildrenDisabled ) );
835 :
836 0 : if( pItemAcc )
837 : {
838 0 : ::com::sun::star::uno::Any aOldAny, aNewAny;
839 0 : if( !mbIsTransientChildrenDisabled )
840 : {
841 : aNewAny <<= ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >(
842 0 : static_cast< ::cppu::OWeakObject* >( pItemAcc ));
843 0 : ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny );
844 : }
845 : else
846 : {
847 0 : aNewAny <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED;
848 0 : pItemAcc->FireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny );
849 0 : }
850 : }
851 :
852 : // selection event
853 0 : ::com::sun::star::uno::Any aOldAny, aNewAny;
854 0 : ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::SELECTION_CHANGED, aOldAny, aNewAny );
855 : }
856 : }
857 : }
858 :
859 0 : void ThumbnailView::deselectItem(const sal_uInt16 nItemId)
860 : {
861 0 : for (size_t i = 0, n = mItemList.size(); i < n; ++i)
862 : {
863 0 : if (mItemList[i]->mnId == nItemId)
864 : {
865 0 : mItemList[i]->setSelection(false);
866 :
867 0 : maItemStateHdl.Call(mItemList[i]);
868 :
869 0 : if (IsReallyVisible() && IsUpdateMode())
870 0 : mItemList[i]->Paint(mpProcessor,mpItemAttrs);
871 :
872 0 : break;
873 : }
874 : }
875 0 : }
876 :
877 0 : void ThumbnailView::deselectItems()
878 : {
879 0 : for (size_t i = 0, n = mItemList.size(); i < n; ++i)
880 : {
881 0 : if (mItemList[i]->isSelected())
882 : {
883 0 : mItemList[i]->setSelection(false);
884 :
885 0 : maItemStateHdl.Call(mItemList[i]);
886 : }
887 : }
888 :
889 0 : if (IsReallyVisible() && IsUpdateMode())
890 0 : Invalidate();
891 0 : }
892 :
893 0 : OUString ThumbnailView::GetItemText( sal_uInt16 nItemId ) const
894 : {
895 0 : size_t nPos = GetItemPos( nItemId );
896 :
897 0 : if ( nPos != THUMBNAILVIEW_ITEM_NOTFOUND )
898 0 : return mItemList[nPos]->maTitle;
899 :
900 0 : return OUString();
901 : }
902 :
903 0 : void ThumbnailView::SetColor( const Color& rColor )
904 : {
905 0 : maColor = rColor;
906 0 : mpItemAttrs->aFillColor = rColor.getBColor();
907 :
908 0 : if ( IsReallyVisible() && IsUpdateMode() )
909 0 : Invalidate();
910 0 : }
911 :
912 0 : bool ThumbnailView::StartDrag( const CommandEvent& rCEvt, Region& rRegion )
913 : {
914 0 : if ( rCEvt.GetCommand() != COMMAND_STARTDRAG )
915 0 : return false;
916 :
917 : // if necessary abort an existing action
918 :
919 : // Check out if the the clicked on page is selected. If this is not the
920 : // case set it as the current item. We only check mouse actions since
921 : // drag-and-drop can also be triggered by the keyboard
922 : sal_uInt16 nSelId;
923 0 : if ( rCEvt.IsMouseEvent() )
924 0 : nSelId = GetItemId( rCEvt.GetMousePosPixel() );
925 : else
926 0 : nSelId = mnSelItemId;
927 :
928 : // don't activate dragging if no item was clicked on
929 0 : if ( !nSelId )
930 0 : return false;
931 :
932 : // Check out if the page was selected. If not set as current page and
933 : // call select.
934 0 : if ( nSelId != mnSelItemId )
935 : {
936 0 : SelectItem( nSelId );
937 0 : Update();
938 : }
939 :
940 0 : Region aRegion;
941 :
942 : // assign region
943 0 : rRegion = aRegion;
944 :
945 0 : return true;
946 : }
947 :
948 0 : void ThumbnailView::filterItems (const boost::function<bool (const ThumbnailViewItem*) > &func)
949 : {
950 0 : mnFirstLine = 0; // start at the top of the list instead of the current position
951 0 : maFilterFunc = func;
952 :
953 0 : CalculateItemPositions();
954 :
955 0 : Invalidate();
956 0 : }
957 :
958 0 : void ThumbnailView::sortItems (const boost::function<bool (const ThumbnailViewItem*, const ThumbnailViewItem*) > &func)
959 : {
960 0 : std::sort(mItemList.begin(),mItemList.end(),func);
961 :
962 0 : CalculateItemPositions();
963 :
964 0 : Invalidate();
965 0 : }
966 :
967 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
968 :
969 :
|