1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include <sfx2/thumbnailview.hxx>
11 #include <sfx2/thumbnailviewitem.hxx>
15 #include "thumbnailviewacc.hxx"
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/fillbitmapattribute.hxx>
24 #include <drawinglayer/attribute/fontattribute.hxx>
25 #include <drawinglayer/primitive2d/fillbitmapprimitive2d.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>
37 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
38 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
40 using namespace basegfx
;
41 using namespace basegfx::tools
;
42 using namespace drawinglayer::attribute
;
43 using namespace drawinglayer::primitive2d
;
48 ITEM_OFFSET_DOUBLE
= 6,
56 ThumbnailView::ThumbnailView (Window
*pParent
, WinBits nWinStyle
, bool bDisableTransientChildren
)
57 : Control( pParent
, nWinStyle
)
60 mbIsTransientChildrenDisabled
= bDisableTransientChildren
;
63 ThumbnailView::ThumbnailView (Window
*pParent
, const ResId
&rResId
, bool bDisableTransientChildren
)
64 : Control( pParent
, rResId
)
67 mbIsTransientChildrenDisabled
= bDisableTransientChildren
;
70 ThumbnailView::~ThumbnailView()
72 com::sun::star::uno::Reference
< ::com::sun::star::lang::XComponent
>
73 xComponent(GetAccessible(sal_False
),
74 com::sun::star::uno::UNO_QUERY
);
77 xComponent
->dispose ();
86 void ThumbnailView::AppendItem(ThumbnailViewItem
*pItem
)
88 if (maFilterFunc(pItem
))
90 // Save current start,end range, iterator might get invalidated
91 size_t nSelStartPos
= 0;
92 ThumbnailViewItem
*pSelStartItem
= NULL
;
94 if (mpStartSelRange
!= mFilteredItemList
.end())
96 pSelStartItem
= *mpStartSelRange
;
97 nSelStartPos
= mpStartSelRange
- mFilteredItemList
.begin();
100 mFilteredItemList
.push_back(pItem
);
101 mpStartSelRange
= pSelStartItem
!= NULL
? mFilteredItemList
.begin() + nSelStartPos
: mFilteredItemList
.end();
104 mItemList
.push_back(pItem
);
107 void ThumbnailView::ImplInit()
121 mbHasVisibleItems
= false;
122 maFilterFunc
= ViewFilterAll();
123 maColor
= GetSettings().GetStyleSettings().GetFieldColor();
124 mpStartSelRange
= mFilteredItemList
.end();
126 // Create the processor and process the primitives
127 const drawinglayer::geometry::ViewInformation2D aNewViewInfos
;
128 mpProcessor
= drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(*this, aNewViewInfos
);
130 ImplInitSettings( true, true, true );
133 void ThumbnailView::ImplDeleteItems()
135 const size_t n
= mItemList
.size();
137 for ( size_t i
= 0; i
< n
; ++i
)
139 ThumbnailViewItem
*const pItem
= mItemList
[i
];
141 // deselect all current selected items and fire events
142 if (pItem
->isSelected())
144 pItem
->setSelection(false);
145 maItemStateHdl
.Call(pItem
);
147 // fire accessible event???
150 if ( pItem
->isVisible() && ImplHasAccessibleListeners() )
152 ::com::sun::star::uno::Any aOldAny
, aNewAny
;
154 aOldAny
<<= pItem
->GetAccessible( mbIsTransientChildrenDisabled
);
155 ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD
, aOldAny
, aNewAny
);
162 mFilteredItemList
.clear();
164 mpStartSelRange
= mFilteredItemList
.end();
167 void ThumbnailView::ImplInitSettings( bool bFont
, bool bForeground
, bool bBackground
)
169 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
174 aFont
= rStyleSettings
.GetAppFont();
175 if ( IsControlFont() )
176 aFont
.Merge( GetControlFont() );
177 SetZoomedPointFont( aFont
);
180 if ( bForeground
|| bFont
)
183 if ( IsControlForeground() )
184 aColor
= GetControlForeground();
186 aColor
= rStyleSettings
.GetButtonTextColor();
187 SetTextColor( aColor
);
193 Color aColor
= rStyleSettings
.GetFieldColor();
194 SetBackground( aColor
);
198 mpItemAttrs
= new ThumbnailItemAttributes
;
199 mpItemAttrs
->aFillColor
= maColor
.getBColor();
200 mpItemAttrs
->aHighlightColor
= rStyleSettings
.GetHighlightColor().getBColor();
201 mpItemAttrs
->aFontAttr
= getFontAttributeFromVclFont(mpItemAttrs
->aFontSize
,GetFont(),false,true);
202 mpItemAttrs
->nMaxTextLenght
= -1;
205 void ThumbnailView::ImplInitScrollBar()
207 if ( GetStyle() & WB_VSCROLL
)
211 mpScrBar
= new ScrollBar( this, WB_VSCROLL
| WB_DRAG
);
212 mpScrBar
->SetScrollHdl( LINK( this, ThumbnailView
, ImplScrollHdl
) );
216 // adapt the width because of the changed settings
217 long nScrBarWidth
= GetSettings().GetStyleSettings().GetScrollBarSize();
218 mpScrBar
->setPosSizePixel( 0, 0, nScrBarWidth
, 0, WINDOW_POSSIZE_WIDTH
);
223 void ThumbnailView::DrawItem (ThumbnailViewItem
*pItem
)
225 if (pItem
->isVisible())
227 Rectangle aRect
= pItem
->getDrawArea();
229 if ( (aRect
.GetHeight() > 0) && (aRect
.GetWidth() > 0) )
230 pItem
->Paint(mpProcessor
,mpItemAttrs
);
234 void ThumbnailView::OnItemDblClicked (ThumbnailViewItem
*)
238 ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
> ThumbnailView::CreateAccessible()
240 return new ThumbnailViewAcc( this, mbIsTransientChildrenDisabled
);
243 void ThumbnailView::CalculateItemPositions ()
245 if (!mnItemHeight
|| !mnItemWidth
)
248 Size aWinSize
= GetOutputSizePixel();
249 size_t nItemCount
= mFilteredItemList
.size();
250 WinBits nStyle
= GetStyle();
251 ScrollBar
* pDelScrBar
= NULL
;
253 // consider the scrolling
254 if ( nStyle
& WB_VSCROLL
)
260 // delete ScrollBar not until later, to prevent recursive calls
261 pDelScrBar
= mpScrBar
;
266 // calculate ScrollBar width
267 long nScrBarWidth
= 0;
269 nScrBarWidth
= mpScrBar
->GetSizePixel().Width();
271 // calculate maximum number of visible columns
272 mnCols
= (sal_uInt16
)((aWinSize
.Width()-nScrBarWidth
) / (mnItemWidth
));
277 // calculate maximum number of visible rows
278 mnVisLines
= (sal_uInt16
)((aWinSize
.Height()-mnHeaderHeight
) / (mnItemHeight
));
280 // calculate empty space
281 long nHSpace
= aWinSize
.Width()-nScrBarWidth
- mnCols
*mnItemWidth
;
282 long nVSpace
= aWinSize
.Height()-mnHeaderHeight
- mnVisLines
*mnItemHeight
;
283 long nHItemSpace
= nHSpace
/ (mnCols
+1);
284 long nVItemSpace
= nVSpace
/ (mnVisLines
+1);
286 // calculate maximum number of rows
287 // Floor( (M+N-1)/N )==Ceiling( M/N )
288 mnLines
= (static_cast<long>(nItemCount
)+mnCols
-1) / mnCols
;
293 if ( mnLines
<= mnVisLines
)
297 if ( mnFirstLine
> (sal_uInt16
)(mnLines
-mnVisLines
) )
298 mnFirstLine
= (sal_uInt16
)(mnLines
-mnVisLines
);
301 mbHasVisibleItems
= true;
304 long nStartX
= nHItemSpace
;
305 long nStartY
= nVItemSpace
+ mnHeaderHeight
;
307 // calculate and draw items
312 size_t nFirstItem
= mnFirstLine
* mnCols
;
313 size_t nLastItem
= nFirstItem
+ (mnVisLines
* mnCols
);
315 maItemListRect
.Left() = x
;
316 maItemListRect
.Top() = y
;
317 maItemListRect
.Right() = x
+ mnCols
*(mnItemWidth
+nHItemSpace
) - nHItemSpace
- 1;
318 maItemListRect
.Bottom() = y
+ mnVisLines
*(mnItemHeight
+nVItemSpace
) - nVItemSpace
- 1;
320 // If want also draw parts of items in the last line,
321 // then we add one more line if parts of these line are
324 size_t nCurCount
= 0;
325 for ( size_t i
= 0; i
< nItemCount
; i
++ )
327 ThumbnailViewItem
*const pItem
= mFilteredItemList
[i
];
329 if ((nCurCount
>= nFirstItem
) && (nCurCount
< nLastItem
))
331 if( !pItem
->isVisible())
333 if ( ImplHasAccessibleListeners() )
335 ::com::sun::star::uno::Any aOldAny
, aNewAny
;
337 aNewAny
<<= pItem
->GetAccessible( mbIsTransientChildrenDisabled
);
338 ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD
, aOldAny
, aNewAny
);
343 maItemStateHdl
.Call(pItem
);
346 pItem
->setDrawArea(Rectangle( Point(x
,y
), Size(mnItemWidth
, mnItemHeight
) ));
347 pItem
->calculateItemsPosition(mnThumbnailHeight
,mnDisplayHeight
,mnItemPadding
,mpItemAttrs
->nMaxTextLenght
,mpItemAttrs
);
349 if ( !((nCurCount
+1) % mnCols
) )
352 y
+= mnItemHeight
+nVItemSpace
;
355 x
+= mnItemWidth
+nHItemSpace
;
359 if( pItem
->isVisible())
361 if ( ImplHasAccessibleListeners() )
363 ::com::sun::star::uno::Any aOldAny
, aNewAny
;
365 aOldAny
<<= pItem
->GetAccessible( mbIsTransientChildrenDisabled
);
366 ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD
, aOldAny
, aNewAny
);
371 maItemStateHdl
.Call(pItem
);
379 // arrange ScrollBar, set values and show it
382 mnLines
= (nCurCount
+mnCols
-1)/mnCols
;
384 // check if scroll is needed
385 mbScroll
= mnLines
> mnVisLines
;
388 Point
aPos( aWinSize
.Width() - nScrBarWidth
, mnHeaderHeight
);
389 Size
aSize( nScrBarWidth
, aWinSize
.Height() - mnHeaderHeight
);
391 mpScrBar
->SetPosSizePixel( aPos
, aSize
);
392 mpScrBar
->SetRangeMax( (nCurCount
+mnCols
-1)/mnCols
);
393 mpScrBar
->SetVisibleSize( mnVisLines
);
394 mpScrBar
->SetThumbPos( (long)mnFirstLine
);
395 long nPageSize
= mnVisLines
;
398 mpScrBar
->SetPageSize( nPageSize
);
399 mpScrBar
->Show( mbScroll
);
406 size_t ThumbnailView::ImplGetItem( const Point
& rPos
, bool bMove
) const
408 if ( !mbHasVisibleItems
)
410 return THUMBNAILVIEW_ITEM_NOTFOUND
;
413 if ( maItemListRect
.IsInside( rPos
) )
415 for (size_t i
= 0; i
< mFilteredItemList
.size(); ++i
)
417 if (mFilteredItemList
[i
]->isVisible() && mFilteredItemList
[i
]->getDrawArea().IsInside(rPos
))
421 // return the previously selected item if spacing is set and
422 // the mouse hasn't left the window yet
423 if ( bMove
&& mnSpacing
&& mnHighItemId
)
425 return GetItemPos( mnHighItemId
);
429 return THUMBNAILVIEW_ITEM_NOTFOUND
;
432 ThumbnailViewItem
* ThumbnailView::ImplGetItem( size_t nPos
)
434 return ( nPos
< mFilteredItemList
.size() ) ? mFilteredItemList
[nPos
] : NULL
;
437 sal_uInt16
ThumbnailView::ImplGetVisibleItemCount() const
440 const size_t nItemCount
= mItemList
.size();
442 for ( size_t n
= 0; n
< nItemCount
; ++n
)
444 if ( mItemList
[n
]->isVisible() )
451 ThumbnailViewItem
* ThumbnailView::ImplGetVisibleItem( sal_uInt16 nVisiblePos
)
453 const size_t nItemCount
= mItemList
.size();
455 for ( size_t n
= 0; n
< nItemCount
; ++n
)
457 ThumbnailViewItem
*const pItem
= mItemList
[n
];
459 if ( pItem
->isVisible() && !nVisiblePos
-- )
466 void ThumbnailView::ImplFireAccessibleEvent( short nEventId
, const ::com::sun::star::uno::Any
& rOldValue
, const ::com::sun::star::uno::Any
& rNewValue
)
468 ThumbnailViewAcc
* pAcc
= ThumbnailViewAcc::getImplementation( GetAccessible( sal_False
) );
471 pAcc
->FireAccessibleEvent( nEventId
, rOldValue
, rNewValue
);
474 bool ThumbnailView::ImplHasAccessibleListeners()
476 ThumbnailViewAcc
* pAcc
= ThumbnailViewAcc::getImplementation( GetAccessible( sal_False
) );
477 return( pAcc
&& pAcc
->HasAccessibleListeners() );
480 IMPL_LINK( ThumbnailView
,ImplScrollHdl
, ScrollBar
*, pScrollBar
)
482 sal_uInt16 nNewFirstLine
= mnFirstLine
;
484 if (pScrollBar
->GetDelta() > 0)
489 if ( nNewFirstLine
!= mnFirstLine
)
491 mnFirstLine
= nNewFirstLine
;
493 CalculateItemPositions();
495 if ( IsReallyVisible() && IsUpdateMode() )
501 IMPL_LINK (ThumbnailView
, OnItemSelected
, ThumbnailViewItem
*, pItem
)
503 maItemStateHdl
.Call(pItem
);
507 void ThumbnailView::KeyInput( const KeyEvent
& rKEvt
)
509 // Get the last selected item in the list
511 bool bFoundLast
= false;
512 for ( long i
= mFilteredItemList
.size() - 1; !bFoundLast
&& i
>= 0; --i
)
514 ThumbnailViewItem
* pItem
= mFilteredItemList
[i
];
515 if ( pItem
->isSelected() )
522 bool bValidRange
= false;
523 bool bHasSelRange
= mpStartSelRange
!= mFilteredItemList
.end();
524 size_t nNextPos
= nLastPos
;
525 KeyCode aKeyCode
= rKEvt
.GetKeyCode();
526 ThumbnailViewItem
* pNext
= NULL
;
528 if (aKeyCode
.IsShift() && bHasSelRange
)
530 //If the last elemented selected is the start range position
531 //search for the first selected item
532 size_t nSelPos
= mpStartSelRange
- mFilteredItemList
.begin();
534 if (nLastPos
== nSelPos
)
536 while (nLastPos
&& mFilteredItemList
[nLastPos
-1]->isSelected())
541 switch ( aKeyCode
.GetCode() )
545 if ( bFoundLast
&& nLastPos
< mFilteredItemList
.size( ) - 1 )
548 nNextPos
= nLastPos
+ 1;
551 pNext
= mFilteredItemList
[nNextPos
];
559 nNextPos
= nLastPos
- 1;
562 pNext
= mFilteredItemList
[nNextPos
];
569 //If we are in the second last row just go the one in
570 //the row below, if theres not row below just go to the
571 //last item but for the last row dont do anything.
572 if ( nLastPos
< mFilteredItemList
.size( ) - mnCols
)
575 nNextPos
= nLastPos
+ mnCols
;
579 int curRow
= nLastPos
/mnCols
;
581 if (curRow
< mnLines
-1)
582 nNextPos
= mFilteredItemList
.size()-1;
586 pNext
= mFilteredItemList
[nNextPos
];
591 if ( nLastPos
>= mnCols
)
594 nNextPos
= nLastPos
- mnCols
;
597 pNext
= mFilteredItemList
[nNextPos
];
603 OnItemDblClicked( mFilteredItemList
[nLastPos
] );
606 Control::KeyInput( rKEvt
);
611 if (aKeyCode
.IsShift() && bValidRange
)
613 std::pair
<size_t,size_t> aRange
;
614 size_t nSelPos
= mpStartSelRange
- mFilteredItemList
.begin();
616 if (nLastPos
< nSelPos
)
618 if (nNextPos
> nLastPos
)
620 if ( nNextPos
> nSelPos
)
621 aRange
= std::make_pair(nLastPos
,nNextPos
);
623 aRange
= std::make_pair(nLastPos
,nNextPos
-1);
626 aRange
= std::make_pair(nNextPos
,nLastPos
-1);
628 else if (nLastPos
== nSelPos
)
630 if (nNextPos
> nLastPos
)
631 aRange
= std::make_pair(nLastPos
+1,nNextPos
);
633 aRange
= std::make_pair(nNextPos
,nLastPos
-1);
637 if (nNextPos
> nLastPos
)
638 aRange
= std::make_pair(nLastPos
+1,nNextPos
);
641 if ( nNextPos
< nSelPos
)
642 aRange
= std::make_pair(nNextPos
,nLastPos
);
644 aRange
= std::make_pair(nNextPos
+1,nLastPos
);
648 for (size_t i
= aRange
.first
; i
<= aRange
.second
; ++i
)
652 ThumbnailViewItem
*pCurItem
= mFilteredItemList
[i
];
654 pCurItem
->setSelection(!pCurItem
->isSelected());
656 if (pCurItem
->isVisible())
659 maItemStateHdl
.Call(pCurItem
);
663 else if (!aKeyCode
.IsShift())
666 SelectItem(pNext
->mnId
);
668 //Mark it as the selection range start position
669 mpStartSelRange
= mFilteredItemList
.begin() + nNextPos
;
672 MakeItemVisible(pNext
->mnId
);
676 void ThumbnailView::MakeItemVisible( sal_uInt16 nItemId
)
681 for ( size_t i
= 0; !bFound
&& i
< mFilteredItemList
.size(); ++i
)
683 ThumbnailViewItem
* pItem
= mFilteredItemList
[i
];
684 if ( pItem
->mnId
== nItemId
)
690 sal_uInt16 nRow
= nPos
/ mnCols
;
692 // Move the visible rows as little as possible to include that one
693 if ( nRow
< mnFirstLine
)
695 else if ( nRow
> mnFirstLine
+ mnVisLines
)
696 mnFirstLine
= nRow
- mnVisLines
;
698 CalculateItemPositions();
702 void ThumbnailView::MouseButtonDown( const MouseEvent
& rMEvt
)
704 if ( rMEvt
.IsLeft() )
706 size_t nPos
= ImplGetItem(rMEvt
.GetPosPixel());
707 ThumbnailViewItem
* pItem
= ImplGetItem(nPos
);
709 if (pItem
&& pItem
->isVisible())
711 if ( rMEvt
.GetClicks() == 1 )
715 //Keep selected item group state and just invert current desired one state
716 pItem
->setSelection(!pItem
->isSelected());
718 //This one becomes the selection range start position if it changes its state to selected otherwise resets it
719 mpStartSelRange
= pItem
->isSelected() ? mFilteredItemList
.begin() + nPos
: mFilteredItemList
.end();
721 else if (rMEvt
.IsShift() && mpStartSelRange
!= mFilteredItemList
.end())
723 std::pair
<size_t,size_t> aNewRange
;
724 aNewRange
.first
= mpStartSelRange
- mFilteredItemList
.begin();
725 aNewRange
.second
= nPos
;
727 if (aNewRange
.first
> aNewRange
.second
)
728 std::swap(aNewRange
.first
,aNewRange
.second
);
730 //Deselect the ones outside of it
731 for (size_t i
= 0, n
= mFilteredItemList
.size(); i
< n
; ++i
)
733 ThumbnailViewItem
*pCurItem
= mFilteredItemList
[i
];
735 if (pCurItem
->isSelected() && (i
< aNewRange
.first
|| i
> aNewRange
.second
))
737 pCurItem
->setSelection(false);
739 if (pCurItem
->isVisible())
742 maItemStateHdl
.Call(pCurItem
);
746 size_t nSelPos
= mpStartSelRange
- mFilteredItemList
.begin();
748 //Select the items between start range and the selected item
751 int dir
= nSelPos
< nPos
? 1 : -1;
752 size_t nCurPos
= nSelPos
+ dir
;
754 while (nCurPos
!= nPos
)
756 ThumbnailViewItem
*pCurItem
= mFilteredItemList
[nCurPos
];
758 if (!pCurItem
->isSelected())
760 pCurItem
->setSelection(true);
762 if (pCurItem
->isVisible())
765 maItemStateHdl
.Call(pCurItem
);
772 pItem
->setSelection(true);
776 //If we got a group of selected items deselect the rest and only keep the desired one
777 //mark items as not selected to not fire unnecessary change state events.
778 pItem
->setSelection(false);
780 pItem
->setSelection(true);
782 //Mark as initial selection range position and reset end one
783 mpStartSelRange
= mFilteredItemList
.begin() + nPos
;
786 if (pItem
->isSelected())
788 bool bClickOnTitle
= pItem
->getTextArea().IsInside(rMEvt
.GetPosPixel());
789 pItem
->setEditTitle(bClickOnTitle
);
792 if (!pItem
->isHighlighted())
795 maItemStateHdl
.Call(pItem
);
797 //fire accessible event??
799 else if ( rMEvt
.GetClicks() == 2 )
801 Rectangle
aRect(pItem
->getDrawArea());
803 if (aRect
.IsInside(rMEvt
.GetPosPixel()))
804 OnItemDblClicked(pItem
);
813 Control::MouseButtonDown( rMEvt
);
816 void ThumbnailView::MouseButtonUp( const MouseEvent
& rMEvt
)
818 Control::MouseButtonUp( rMEvt
);
821 void ThumbnailView::Command( const CommandEvent
& rCEvt
)
823 if ( (rCEvt
.GetCommand() == COMMAND_WHEEL
) ||
824 (rCEvt
.GetCommand() == COMMAND_STARTAUTOSCROLL
) ||
825 (rCEvt
.GetCommand() == COMMAND_AUTOSCROLL
) )
827 if ( HandleScrollCommand( rCEvt
, NULL
, mpScrBar
) )
831 Control::Command( rCEvt
);
834 void ThumbnailView::Paint( const Rectangle
&aRect
)
836 size_t nItemCount
= mItemList
.size();
839 Primitive2DSequence
aSeq(1);
840 aSeq
[0] = Primitive2DReference( new PolyPolygonColorPrimitive2D(
841 B2DPolyPolygon(Polygon(aRect
,5,5).getB2DPolygon()),
842 maColor
.getBColor()));
844 mpProcessor
->process(aSeq
);
847 for ( size_t i
= 0; i
< nItemCount
; i
++ )
849 ThumbnailViewItem
*const pItem
= mItemList
[i
];
851 if ( pItem
->isVisible() )
855 if ( mpScrBar
&& mpScrBar
->IsVisible() )
856 mpScrBar
->Paint(aRect
);
859 void ThumbnailView::GetFocus()
861 if(GETFOCUS_TAB
& GetGetFocusFlags())
863 // Select the first item if nothing selected
865 for (size_t i
= 0, n
= mItemList
.size(); i
< n
&& nSelected
== -1; ++i
)
867 if (mItemList
[i
]->isSelected())
871 if ( nSelected
== -1 && mItemList
.size( ) > 0 )
877 // Tell the accessible object that we got the focus.
878 ThumbnailViewAcc
* pAcc
= ThumbnailViewAcc::getImplementation( GetAccessible( sal_False
) );
885 void ThumbnailView::LoseFocus()
889 size_t nPos
= GetItemPos(mnHighItemId
);
891 if (nPos
!= THUMBNAILVIEW_ITEM_NOTFOUND
)
893 ThumbnailViewItem
*pOld
= mItemList
[nPos
];
895 pOld
->setHighlight(false);
897 if (!pOld
->isSelected())
904 Control::LoseFocus();
906 // Tell the accessible object that we lost the focus.
907 ThumbnailViewAcc
* pAcc
= ThumbnailViewAcc::getImplementation( GetAccessible( sal_False
) );
912 void ThumbnailView::Resize()
915 CalculateItemPositions();
917 if ( IsReallyVisible() && IsUpdateMode() )
921 void ThumbnailView::StateChanged( StateChangedType nType
)
923 Control::StateChanged( nType
);
925 if ( nType
== STATE_CHANGE_INITSHOW
)
927 if ( IsReallyVisible() && IsUpdateMode() )
930 else if ( nType
== STATE_CHANGE_UPDATEMODE
)
932 if ( IsReallyVisible() && IsUpdateMode() )
935 else if ( nType
== STATE_CHANGE_TEXT
)
938 else if ( (nType
== STATE_CHANGE_ZOOM
) ||
939 (nType
== STATE_CHANGE_CONTROLFONT
) )
941 ImplInitSettings( true, false, false );
944 else if ( nType
== STATE_CHANGE_CONTROLFOREGROUND
)
946 ImplInitSettings( false, true, false );
949 else if ( nType
== STATE_CHANGE_CONTROLBACKGROUND
)
951 ImplInitSettings( false, false, true );
954 else if ( (nType
== STATE_CHANGE_STYLE
) || (nType
== STATE_CHANGE_ENABLE
) )
956 ImplInitSettings( false, false, true );
961 void ThumbnailView::DataChanged( const DataChangedEvent
& rDCEvt
)
963 Control::DataChanged( rDCEvt
);
965 if ( (rDCEvt
.GetType() == DATACHANGED_FONTS
) ||
966 (rDCEvt
.GetType() == DATACHANGED_DISPLAY
) ||
967 (rDCEvt
.GetType() == DATACHANGED_FONTSUBSTITUTION
) ||
968 ((rDCEvt
.GetType() == DATACHANGED_SETTINGS
) &&
969 (rDCEvt
.GetFlags() & SETTINGS_STYLE
)) )
971 ImplInitSettings( true, true, true );
976 void ThumbnailView::RemoveItem( sal_uInt16 nItemId
)
978 size_t nPos
= GetItemPos( nItemId
);
980 if ( nPos
== THUMBNAILVIEW_ITEM_NOTFOUND
)
983 if ( nPos
< mFilteredItemList
.size() ) {
985 // delete item from the thumbnail list
986 for (size_t i
= 0, n
= mItemList
.size(); i
< n
; ++i
)
988 if (mItemList
[i
]->mnId
== nItemId
)
990 mItemList
.erase(mItemList
.begin()+i
);
995 // delete item from the filter item list
996 ValueItemList::iterator it
= mFilteredItemList
.begin();
997 ::std::advance( it
, nPos
);
999 if ((*it
)->isSelected())
1001 (*it
)->setSelection(false);
1002 maItemStateHdl
.Call(*it
);
1006 mFilteredItemList
.erase( it
);
1007 mpStartSelRange
= mFilteredItemList
.end();
1011 if ( mnHighItemId
== nItemId
)
1016 CalculateItemPositions();
1018 if ( IsReallyVisible() && IsUpdateMode() )
1022 void ThumbnailView::Clear()
1030 CalculateItemPositions();
1032 if ( IsReallyVisible() && IsUpdateMode() )
1036 void ThumbnailView::updateItems (const std::vector
<ThumbnailViewItem
*> &items
)
1046 filterItems(maFilterFunc
);
1049 size_t ThumbnailView::GetItemPos( sal_uInt16 nItemId
) const
1051 for ( size_t i
= 0, n
= mFilteredItemList
.size(); i
< n
; ++i
) {
1052 if ( mFilteredItemList
[i
]->mnId
== nItemId
) {
1056 return THUMBNAILVIEW_ITEM_NOTFOUND
;
1059 sal_uInt16
ThumbnailView::GetItemId( size_t nPos
) const
1061 return ( nPos
< mFilteredItemList
.size() ) ? mFilteredItemList
[nPos
]->mnId
: 0 ;
1064 sal_uInt16
ThumbnailView::GetItemId( const Point
& rPos
) const
1066 size_t nItemPos
= ImplGetItem( rPos
);
1067 if ( nItemPos
!= THUMBNAILVIEW_ITEM_NOTFOUND
)
1068 return GetItemId( nItemPos
);
1073 sal_uInt16
ThumbnailView::getNextItemId() const
1075 return mItemList
.empty() ? 1 : mItemList
.back()->mnId
+ 1;
1078 void ThumbnailView::setItemMaxTextLength(sal_uInt32 nLength
)
1080 mpItemAttrs
->nMaxTextLenght
= nLength
;
1083 void ThumbnailView::setItemDimensions(long itemWidth
, long thumbnailHeight
, long displayHeight
, int itemPadding
)
1085 mnItemWidth
= itemWidth
+ 2*itemPadding
;
1086 mnThumbnailHeight
= thumbnailHeight
;
1087 mnDisplayHeight
= displayHeight
;
1088 mnItemPadding
= itemPadding
;
1089 mnItemHeight
= mnDisplayHeight
+ mnThumbnailHeight
+ 2*itemPadding
;
1092 void ThumbnailView::SelectItem( sal_uInt16 nItemId
)
1094 size_t nItemPos
= GetItemPos( nItemId
);
1095 if ( nItemPos
== THUMBNAILVIEW_ITEM_NOTFOUND
)
1098 ThumbnailViewItem
* pItem
= mFilteredItemList
[nItemPos
];
1099 if (!pItem
->isSelected())
1101 pItem
->setSelection(true);
1102 maItemStateHdl
.Call(pItem
);
1104 if (IsReallyVisible() && IsUpdateMode())
1107 bool bNewOut
= IsReallyVisible() && IsUpdateMode();
1109 // if necessary scroll to the visible area
1110 if ( mbScroll
&& nItemId
)
1112 sal_uInt16 nNewLine
= (sal_uInt16
)(nItemPos
/ mnCols
);
1113 if ( nNewLine
< mnFirstLine
)
1115 mnFirstLine
= nNewLine
;
1117 else if ( nNewLine
> (sal_uInt16
)(mnFirstLine
+mnVisLines
-1) )
1119 mnFirstLine
= (sal_uInt16
)(nNewLine
-mnVisLines
+1);
1125 if ( IsReallyVisible() && IsUpdateMode() )
1129 if( ImplHasAccessibleListeners() )
1131 // focus event (select)
1132 ThumbnailViewAcc
* pItemAcc
= ThumbnailViewAcc::getImplementation( pItem
->GetAccessible( mbIsTransientChildrenDisabled
) );
1136 ::com::sun::star::uno::Any aOldAny
, aNewAny
;
1137 if( !mbIsTransientChildrenDisabled
)
1139 aNewAny
<<= ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
>(
1140 static_cast< ::cppu::OWeakObject
* >( pItemAcc
));
1141 ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
, aOldAny
, aNewAny
);
1145 aNewAny
<<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED
;
1146 pItemAcc
->FireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED
, aOldAny
, aNewAny
);
1151 ::com::sun::star::uno::Any aOldAny
, aNewAny
;
1152 ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::SELECTION_CHANGED
, aOldAny
, aNewAny
);
1157 void ThumbnailView::DeselectItem( sal_uInt16 nItemId
)
1159 size_t nItemPos
= GetItemPos( nItemId
);
1160 if ( nItemPos
== THUMBNAILVIEW_ITEM_NOTFOUND
)
1163 ThumbnailViewItem
* pItem
= mFilteredItemList
[nItemPos
];
1164 if (pItem
->isSelected())
1166 pItem
->setSelection(false);
1167 maItemStateHdl
.Call(pItem
);
1169 if (IsReallyVisible() && IsUpdateMode())
1172 // TODO Trigger event in accessible object?
1176 bool ThumbnailView::IsItemSelected( sal_uInt16 nItemId
) const
1178 size_t nItemPos
= GetItemPos( nItemId
);
1179 if ( nItemPos
== THUMBNAILVIEW_ITEM_NOTFOUND
)
1182 ThumbnailViewItem
* pItem
= mFilteredItemList
[nItemPos
];
1183 return pItem
->isSelected();
1186 void ThumbnailView::deselectItems()
1188 for (size_t i
= 0, n
= mItemList
.size(); i
< n
; ++i
)
1190 if (mItemList
[i
]->isSelected())
1192 mItemList
[i
]->setEditTitle(false);
1193 mItemList
[i
]->setSelection(false);
1195 maItemStateHdl
.Call(mItemList
[i
]);
1199 if (IsReallyVisible() && IsUpdateMode())
1203 OUString
ThumbnailView::GetItemText( sal_uInt16 nItemId
) const
1205 size_t nPos
= GetItemPos( nItemId
);
1207 if ( nPos
!= THUMBNAILVIEW_ITEM_NOTFOUND
)
1208 return mFilteredItemList
[nPos
]->maTitle
;
1213 void ThumbnailView::SetColor( const Color
& rColor
)
1216 mpItemAttrs
->aFillColor
= rColor
.getBColor();
1218 if ( IsReallyVisible() && IsUpdateMode() )
1222 void ThumbnailView::filterItems (const boost::function
<bool (const ThumbnailViewItem
*) > &func
)
1224 mnFirstLine
= 0; // start at the top of the list instead of the current position
1225 maFilterFunc
= func
;
1228 bool bHasSelRange
= false;
1229 ThumbnailViewItem
*curSel
= mpStartSelRange
!= mFilteredItemList
.end() ? *mpStartSelRange
: NULL
;
1231 mFilteredItemList
.clear();
1233 for (size_t i
= 0, n
= mItemList
.size(); i
< n
; ++i
)
1235 ThumbnailViewItem
*const pItem
= mItemList
[i
];
1237 if (maFilterFunc(pItem
))
1239 if (curSel
== pItem
)
1242 bHasSelRange
= true;
1245 mFilteredItemList
.push_back(pItem
);
1249 if( pItem
->isVisible())
1251 if ( ImplHasAccessibleListeners() )
1253 ::com::sun::star::uno::Any aOldAny
, aNewAny
;
1255 aOldAny
<<= pItem
->GetAccessible( mbIsTransientChildrenDisabled
);
1256 ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD
, aOldAny
, aNewAny
);
1260 pItem
->setSelection(false);
1262 maItemStateHdl
.Call(pItem
);
1267 mpStartSelRange
= bHasSelRange
? mFilteredItemList
.begin() + nSelPos
: mFilteredItemList
.end();
1268 CalculateItemPositions();
1273 void ThumbnailView::sortItems (const boost::function
<bool (const ThumbnailViewItem
*, const ThumbnailViewItem
*) > &func
)
1275 std::sort(mItemList
.begin(),mItemList
.end(),func
);
1277 CalculateItemPositions();
1282 bool ThumbnailView::renameItem(ThumbnailViewItem
*, OUString
)
1284 // Do nothing by default
1288 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */