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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <o3tl/safeint.hxx>
23 #include <tools/debug.hxx>
24 #include <tools/stream.hxx>
25 #include <comphelper/base64.hxx>
26 #include <vcl/decoview.hxx>
27 #include <vcl/event.hxx>
28 #include <vcl/graph.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/cvtgrf.hxx>
31 #include <vcl/help.hxx>
32 #include <vcl/settings.hxx>
33 #include <vcl/commandevent.hxx>
34 #include <vcl/virdev.hxx>
36 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
37 #include <com/sun/star/lang/XComponent.hpp>
38 #include <rtl/ustring.hxx>
39 #include <sal/log.hxx>
40 #include "valueimp.hxx"
42 #include <svtools/valueset.hxx>
43 #include <boost/property_tree/ptree.hpp>
45 #include <uiobject.hxx>
46 #include <vcl/uitest/logger.hxx>
47 #include <vcl/uitest/eventdescription.hxx>
49 using namespace css::uno
;
50 using namespace css::lang
;
51 using namespace css::accessibility
;
55 void collectUIInformation( const OUString
& aID
, const OUString
& aParentID
, const OUString
& aPos
)
57 EventDescription aDescription
;
58 aDescription
.aID
= aID
;
59 aDescription
.aParameters
= {{"POS", aPos
}};
60 aDescription
.aAction
= "SELECT";
61 aDescription
.aKeyWord
= "ValueSet";
62 aDescription
.aParent
= aParentID
;
63 UITestLogger::getInstance().logEvent(aDescription
);
69 ITEM_OFFSET_DOUBLE
= 6,
78 ValueSet::ValueSet(std::unique_ptr
<weld::ScrolledWindow
> pScrolledWindow
)
79 : maVirDev( VclPtr
<VirtualDevice
>::Create())
80 , mxScrolledWindow(std::move(pScrolledWindow
))
82 , maColor(COL_TRANSPARENT
)
87 maVirDev
->SetBackground(Application::GetSettings().GetStyleSettings().GetFaceColor());
104 mnFrameStyle
= DrawFrameStyle::NONE
;
105 mbNoSelection
= true;
106 mbDrawSelection
= true;
111 mbEdgeBlending
= false;
112 mbHasVisibleItems
= false;
114 if (mxScrolledWindow
)
115 mxScrolledWindow
->connect_vadjustment_changed(LINK(this, ValueSet
, ImplScrollHdl
));
118 void ValueSet::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
120 CustomWidgetController::SetDrawingArea(pDrawingArea
);
121 // #106446#, #106601# force mirroring of virtual device
122 maVirDev
->EnableRTL(pDrawingArea
->get_direction());
125 Reference
<XAccessible
> ValueSet::CreateAccessible()
128 mxAccessible
.set(new ValueSetAcc(this));
132 ValueSet::~ValueSet()
134 Reference
<XComponent
> xComponent(mxAccessible
, UNO_QUERY
);
136 xComponent
->dispose();
141 void ValueSet::ImplDeleteItems()
143 const size_t n
= mItemList
.size();
145 for ( size_t i
= 0; i
< n
; ++i
)
147 ValueSetItem
* pItem
= mItemList
[i
].get();
148 if ( pItem
->mbVisible
&& ImplHasAccessibleListeners() )
153 aOldAny
<<= pItem
->GetAccessible( false/*bIsTransientChildrenDisabled*/ );
154 ImplFireAccessibleEvent(AccessibleEventId::CHILD
, aOldAny
, aNewAny
);
157 mItemList
[i
].reset();
163 void ValueSet::Select()
165 collectUIInformation(OStringToOUString(GetDrawingArea()->get_buildable_name(),RTL_TEXTENCODING_UTF8
) , OStringToOUString(GetDrawingArea()->get_help_id(),RTL_TEXTENCODING_UTF8
) , OUString::number(GetSelectedItemId()));
166 maSelectHdl
.Call( this );
169 void ValueSet::UserDraw( const UserDrawEvent
& )
173 size_t ValueSet::ImplGetItem( const Point
& rPos
) const
175 if (!mbHasVisibleItems
)
177 return VALUESET_ITEM_NOTFOUND
;
180 if (mpNoneItem
&& maNoneItemRect
.IsInside(rPos
))
182 return VALUESET_ITEM_NONEITEM
;
185 if (maItemListRect
.IsInside(rPos
))
187 const int xc
= rPos
.X() - maItemListRect
.Left();
188 const int yc
= rPos
.Y() - maItemListRect
.Top();
189 // The point is inside the area of item list,
190 // let's find the containing item.
191 const int col
= xc
/ (mnItemWidth
+ mnSpacing
);
192 const int x
= xc
% (mnItemWidth
+ mnSpacing
);
193 const int row
= yc
/ (mnItemHeight
+ mnSpacing
);
194 const int y
= yc
% (mnItemHeight
+ mnSpacing
);
196 if (x
< mnItemWidth
&& y
< mnItemHeight
)
198 // the point is inside item rect and not inside spacing
199 const size_t item
= (mnFirstLine
+ row
) * static_cast<size_t>(mnCols
) + col
;
200 if (item
< mItemList
.size())
207 return VALUESET_ITEM_NOTFOUND
;
210 ValueSetItem
* ValueSet::ImplGetItem( size_t nPos
)
212 if (nPos
== VALUESET_ITEM_NONEITEM
)
213 return mpNoneItem
.get();
215 return (nPos
< mItemList
.size()) ? mItemList
[nPos
].get() : nullptr;
218 ValueSetItem
* ValueSet::ImplGetFirstItem()
220 return !mItemList
.empty() ? mItemList
[0].get() : nullptr;
223 sal_uInt16
ValueSet::ImplGetVisibleItemCount() const
226 const size_t nItemCount
= mItemList
.size();
228 for ( size_t n
= 0; n
< nItemCount
; ++n
)
230 if ( mItemList
[n
]->mbVisible
)
237 void ValueSet::ImplFireAccessibleEvent( short nEventId
, const Any
& rOldValue
, const Any
& rNewValue
)
239 ValueSetAcc
* pAcc
= ValueSetAcc::getImplementation(mxAccessible
);
242 pAcc
->FireAccessibleEvent( nEventId
, rOldValue
, rNewValue
);
245 bool ValueSet::ImplHasAccessibleListeners()
247 ValueSetAcc
* pAcc
= ValueSetAcc::getImplementation(mxAccessible
);
248 return( pAcc
&& pAcc
->HasAccessibleListeners() );
251 IMPL_LINK(ValueSet
, ImplScrollHdl
, weld::ScrolledWindow
&, rScrollWin
, void)
253 auto nNewFirstLine
= rScrollWin
.vadjustment_get_value();
254 if ( nNewFirstLine
!= mnFirstLine
)
256 mnFirstLine
= nNewFirstLine
;
262 void ValueSet::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
264 if (GetStyle() & WB_FLATVALUESET
)
266 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
267 rRenderContext
.SetLineColor();
268 rRenderContext
.SetFillColor(rStyleSettings
.GetFaceColor());
269 tools::Long nOffY
= maVirDev
->GetOutputSizePixel().Height();
270 Size
aWinSize(GetOutputSizePixel());
271 rRenderContext
.DrawRect(tools::Rectangle(Point(0, nOffY
), Point( aWinSize
.Width(), aWinSize
.Height())));
274 ImplDraw(rRenderContext
);
277 void ValueSet::GetFocus()
279 SAL_INFO("svtools", "value set getting focus");
281 CustomWidgetController::GetFocus();
283 // Tell the accessible object that we got the focus.
284 ValueSetAcc
* pAcc
= ValueSetAcc::getImplementation(mxAccessible
);
289 void ValueSet::LoseFocus()
291 SAL_INFO("svtools", "value set losing focus");
293 CustomWidgetController::LoseFocus();
295 // Tell the accessible object that we lost the focus.
296 ValueSetAcc
* pAcc
= ValueSetAcc::getImplementation(mxAccessible
);
301 void ValueSet::Resize()
304 if ( IsReallyVisible() && IsUpdateMode() )
306 CustomWidgetController::Resize();
309 bool ValueSet::KeyInput( const KeyEvent
& rKeyEvent
)
311 size_t nLastItem
= mItemList
.size();
313 if ( !nLastItem
|| !ImplGetFirstItem() )
314 return CustomWidgetController::KeyInput(rKeyEvent
);
322 = mnSelItemId
? GetItemPos(mnSelItemId
) : (mpNoneItem
? VALUESET_ITEM_NONEITEM
: 0);
323 size_t nItemPos
= VALUESET_ITEM_NOTFOUND
;
324 size_t nVStep
= mnCols
;
326 switch (rKeyEvent
.GetKeyCode().GetCode())
329 nItemPos
= mpNoneItem
? VALUESET_ITEM_NONEITEM
: 0;
333 nItemPos
= nLastItem
;
337 if (nCurPos
!= VALUESET_ITEM_NONEITEM
)
341 nItemPos
= nCurPos
-1;
345 nItemPos
= VALUESET_ITEM_NONEITEM
;
351 if (nCurPos
< nLastItem
)
353 if (nCurPos
== VALUESET_ITEM_NONEITEM
)
359 nItemPos
= nCurPos
+1;
365 if (rKeyEvent
.GetKeyCode().IsShift() || rKeyEvent
.GetKeyCode().IsMod1() || rKeyEvent
.GetKeyCode().IsMod2())
367 return CustomWidgetController::KeyInput(rKeyEvent
);
369 nVStep
*= mnVisLines
;
372 if (nCurPos
!= VALUESET_ITEM_NONEITEM
)
374 if (nCurPos
== nLastItem
)
376 const size_t nCol
= mnCols
? nLastItem
% mnCols
: 0;
379 // Move to previous row/page, keeping the old column
380 nVStep
-= mnCurCol
- nCol
;
383 if (nCurPos
>= nVStep
)
385 // Go up of a whole page
386 nItemPos
= nCurPos
-nVStep
;
390 nItemPos
= VALUESET_ITEM_NONEITEM
;
392 else if (nCurPos
> mnCols
)
394 // Go to same column in first row
395 nItemPos
= nCurPos
% mnCols
;
401 if (rKeyEvent
.GetKeyCode().IsShift() || rKeyEvent
.GetKeyCode().IsMod1() || rKeyEvent
.GetKeyCode().IsMod2())
403 return CustomWidgetController::KeyInput(rKeyEvent
);
405 nVStep
*= mnVisLines
;
408 if (nCurPos
!= nLastItem
)
410 if (nCurPos
== VALUESET_ITEM_NONEITEM
)
412 nItemPos
= nVStep
-mnCols
+mnCurCol
;
416 nItemPos
= nCurPos
+nVStep
;
418 if (nItemPos
> nLastItem
)
420 nItemPos
= nLastItem
;
426 if (GetStyle() & WB_NO_DIRECTSELECT
)
428 // tdf#142479 on return select the entry the cursor is in
429 // before calling Select
430 if (nCurPos
!= VALUESET_ITEM_NONEITEM
)
432 const sal_uInt16 nItemId
= GetItemId(nCurPos
);
433 if (nItemId
!= mnSelItemId
)
441 return CustomWidgetController::KeyInput(rKeyEvent
);
444 if ( nItemPos
== VALUESET_ITEM_NOTFOUND
)
447 if ( nItemPos
!=VALUESET_ITEM_NONEITEM
&& nItemPos
<nLastItem
)
449 // update current column only in case of a new position
450 // which is also not a "specially" handled one.
451 mnCurCol
= mnCols
? nItemPos
% mnCols
: 0;
453 const sal_uInt16 nItemId
= (nItemPos
!= VALUESET_ITEM_NONEITEM
) ? GetItemId( nItemPos
) : 0;
454 if ( nItemId
!= mnSelItemId
)
456 SelectItem( nItemId
);
457 if (!(GetStyle() & WB_NO_DIRECTSELECT
))
459 // select only if WB_NO_DIRECTSELECT is not set
467 void ValueSet::ImplTracking(const Point
& rPos
)
469 ValueSetItem
* pItem
= ImplGetItem( ImplGetItem( rPos
) );
472 if( GetStyle() & WB_MENUSTYLEVALUESET
|| GetStyle() & WB_FLATVALUESET
)
475 ImplHighlightItem( pItem
->mnId
);
479 if( GetStyle() & WB_MENUSTYLEVALUESET
|| GetStyle() & WB_FLATVALUESET
)
482 ImplHighlightItem( mnSelItemId
, false );
486 bool ValueSet::MouseButtonDown( const MouseEvent
& rMouseEvent
)
488 if ( rMouseEvent
.IsLeft() )
490 ValueSetItem
* pItem
= ImplGetItem( ImplGetItem( rMouseEvent
.GetPosPixel() ) );
491 if (pItem
&& !rMouseEvent
.IsMod2())
493 if (rMouseEvent
.GetClicks() == 1)
495 SelectItem( pItem
->mnId
);
496 if (!(GetStyle() & WB_NOPOINTERFOCUS
))
499 else if ( rMouseEvent
.GetClicks() == 2 )
500 maDoubleClickHdl
.Call( this );
506 return CustomWidgetController::MouseButtonDown( rMouseEvent
);
509 bool ValueSet::MouseButtonUp( const MouseEvent
& rMouseEvent
)
511 if (rMouseEvent
.IsLeft() && !rMouseEvent
.IsMod2())
513 // tdf#142150 MouseUp seen without previous MouseDown
519 return CustomWidgetController::MouseButtonUp( rMouseEvent
);
522 bool ValueSet::MouseMove(const MouseEvent
& rMouseEvent
)
524 // because of SelectionMode
525 if ((GetStyle() & WB_MENUSTYLEVALUESET
) || (GetStyle() & WB_FLATVALUESET
))
526 ImplTracking(rMouseEvent
.GetPosPixel());
527 return CustomWidgetController::MouseMove(rMouseEvent
);
530 void ValueSet::QueueReformat()
535 if ( IsReallyVisible() && IsUpdateMode() )
539 void ValueSet::RemoveItem( sal_uInt16 nItemId
)
541 size_t nPos
= GetItemPos( nItemId
);
543 if ( nPos
== VALUESET_ITEM_NOTFOUND
)
546 if ( nPos
< mItemList
.size() ) {
547 mItemList
.erase( mItemList
.begin() + nPos
);
551 if (mnHighItemId
== nItemId
|| mnSelItemId
== nItemId
)
556 mbNoSelection
= true;
562 bool ValueSet::TurnOffScrollBar()
564 if (mxScrolledWindow
->get_vpolicy() == VclPolicyType::NEVER
)
566 mxScrolledWindow
->set_vpolicy(VclPolicyType::NEVER
);
567 weld::DrawingArea
* pDrawingArea
= GetDrawingArea();
568 Size
aPrefSize(pDrawingArea
->get_preferred_size());
569 pDrawingArea
->set_size_request(aPrefSize
.Width() + GetScrollWidth(), aPrefSize
.Height());
573 void ValueSet::TurnOnScrollBar()
575 if (mxScrolledWindow
->get_vpolicy() == VclPolicyType::ALWAYS
)
577 mxScrolledWindow
->set_vpolicy(VclPolicyType::ALWAYS
);
578 weld::DrawingArea
* pDrawingArea
= GetDrawingArea();
579 Size
aPrefSize(pDrawingArea
->get_preferred_size());
580 pDrawingArea
->set_size_request(aPrefSize
.Width() - GetScrollWidth(), aPrefSize
.Height());
583 void ValueSet::RecalcScrollBar()
585 if (!mxScrolledWindow
)
587 const bool bScrollAllowed
= GetStyle() & WB_VSCROLL
;
590 // reset scrolled window state to initial value so it will get configured
591 // to the right adjustment on the next format which we toggle on to happen
592 // if the scrolledwindow wasn't in its initial state already
593 if (TurnOffScrollBar())
597 void ValueSet::Clear()
606 mbNoSelection
= true;
611 if ( IsReallyVisible() && IsUpdateMode() )
615 size_t ValueSet::GetItemCount() const
617 return mItemList
.size();
620 size_t ValueSet::GetItemPos( sal_uInt16 nItemId
) const
622 for ( size_t i
= 0, n
= mItemList
.size(); i
< n
; ++i
) {
623 if ( mItemList
[i
]->mnId
== nItemId
) {
627 return VALUESET_ITEM_NOTFOUND
;
630 sal_uInt16
ValueSet::GetItemId( size_t nPos
) const
632 return ( nPos
< mItemList
.size() ) ? mItemList
[nPos
]->mnId
: 0 ;
635 sal_uInt16
ValueSet::GetItemId( const Point
& rPos
) const
637 size_t nItemPos
= ImplGetItem( rPos
);
638 if ( nItemPos
!= VALUESET_ITEM_NOTFOUND
)
639 return GetItemId( nItemPos
);
644 tools::Rectangle
ValueSet::GetItemRect( sal_uInt16 nItemId
) const
646 const size_t nPos
= GetItemPos( nItemId
);
648 if ( nPos
!=VALUESET_ITEM_NOTFOUND
&& mItemList
[nPos
]->mbVisible
)
649 return ImplGetItemRect( nPos
);
651 return tools::Rectangle();
654 tools::Rectangle
ValueSet::ImplGetItemRect( size_t nPos
) const
656 const size_t nVisibleBegin
= static_cast<size_t>(mnFirstLine
)*mnCols
;
657 const size_t nVisibleEnd
= nVisibleBegin
+ static_cast<size_t>(mnVisLines
)*mnCols
;
659 // Check if the item is inside the range of the displayed ones,
660 // taking into account that last row could be incomplete
661 if ( nPos
<nVisibleBegin
|| nPos
>=nVisibleEnd
|| nPos
>=mItemList
.size() )
662 return tools::Rectangle();
664 nPos
-= nVisibleBegin
;
666 const size_t row
= mnCols
? nPos
/mnCols
: 0;
667 const size_t col
= mnCols
? nPos
%mnCols
: 0;
668 const tools::Long x
= maItemListRect
.Left()+col
*(mnItemWidth
+mnSpacing
);
669 const tools::Long y
= maItemListRect
.Top()+row
*(mnItemHeight
+mnSpacing
);
671 return tools::Rectangle( Point(x
, y
), Size(mnItemWidth
, mnItemHeight
) );
674 void ValueSet::ImplHighlightItem( sal_uInt16 nItemId
, bool bIsSelection
)
676 if ( mnHighItemId
== nItemId
)
679 // remember the old item to delete the previous selection
680 mnHighItemId
= nItemId
;
682 // don't draw the selection if nothing is selected
683 if ( !bIsSelection
&& mbNoSelection
)
684 mbDrawSelection
= false;
686 // remove the old selection and draw the new one
688 mbDrawSelection
= true;
691 void ValueSet::ImplDraw(vcl::RenderContext
& rRenderContext
)
694 Format(rRenderContext
);
697 Size aSize
= maVirDev
->GetOutputSizePixel();
699 rRenderContext
.DrawOutDev(aDefPos
, aSize
, aDefPos
, aSize
, *maVirDev
);
701 // draw parting line to the Namefield
702 if (GetStyle() & WB_NAMEFIELD
)
704 if (!(GetStyle() & WB_FLATVALUESET
))
706 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
707 Size
aWinSize(GetOutputSizePixel());
708 Point
aPos1(NAME_LINE_OFF_X
, mnTextOffset
+ NAME_LINE_OFF_Y
);
709 Point
aPos2(aWinSize
.Width() - (NAME_LINE_OFF_X
* 2), mnTextOffset
+ NAME_LINE_OFF_Y
);
710 if (!(rStyleSettings
.GetOptions() & StyleSettingsOptions::Mono
))
712 rRenderContext
.SetLineColor(rStyleSettings
.GetShadowColor());
713 rRenderContext
.DrawLine(aPos1
, aPos2
);
716 rRenderContext
.SetLineColor(rStyleSettings
.GetLightColor());
719 rRenderContext
.SetLineColor(rStyleSettings
.GetWindowTextColor());
720 rRenderContext
.DrawLine(aPos1
, aPos2
);
724 ImplDrawSelect(rRenderContext
);
728 * An inelegant method; sets the item width & height such that
729 * all of the included items and their labels fit; if we can
732 void ValueSet::RecalculateItemSizes()
734 Size aLargestItem
= GetLargestItemSize();
736 if ( mnUserItemWidth
!= aLargestItem
.Width() ||
737 mnUserItemHeight
!= aLargestItem
.Height() )
739 mnUserItemWidth
= aLargestItem
.Width();
740 mnUserItemHeight
= aLargestItem
.Height();
745 void ValueSet::SetFirstLine(sal_uInt16 nNewFirstLine
)
747 if (nNewFirstLine
!= mnFirstLine
)
749 mnFirstLine
= nNewFirstLine
;
750 if (mxScrolledWindow
)
751 mxScrolledWindow
->vadjustment_set_value(mnFirstLine
);
755 void ValueSet::SelectItem( sal_uInt16 nItemId
)
761 nItemPos
= GetItemPos( nItemId
);
762 if ( nItemPos
== VALUESET_ITEM_NOTFOUND
)
766 if ( !((mnSelItemId
!= nItemId
) || mbNoSelection
) )
769 const sal_uInt16 nOldItem
= mnSelItemId
;
770 mnSelItemId
= nItemId
;
771 mbNoSelection
= false;
773 bool bNewOut
= !mbFormat
&& IsReallyVisible() && IsUpdateMode();
774 bool bNewLine
= false;
776 if (weld::DrawingArea
* pNeedsFormatToScroll
= !mnCols
? GetDrawingArea() : nullptr)
778 Format(pNeedsFormatToScroll
->get_ref_device());
779 // reset scrollbar so its set to the later calculated mnFirstLine on
781 RecalcScrollBar(); // reset scrollbar so its set to the later calculated
784 // if necessary scroll to the visible area
785 if (mbScroll
&& nItemId
&& mnCols
)
787 sal_uInt16 nNewLine
= static_cast<sal_uInt16
>(nItemPos
/ mnCols
);
788 if ( nNewLine
< mnFirstLine
)
790 SetFirstLine(nNewLine
);
793 else if ( nNewLine
> o3tl::make_unsigned(mnFirstLine
+mnVisLines
-1) )
795 SetFirstLine(static_cast<sal_uInt16
>(nNewLine
-mnVisLines
+1));
804 // redraw everything if the visible area has changed
810 if( !ImplHasAccessibleListeners() )
813 // focus event (deselect)
816 const size_t nPos
= GetItemPos( nItemId
);
818 if( nPos
!= VALUESET_ITEM_NOTFOUND
)
820 ValueItemAcc
* pItemAcc
= ValueItemAcc::getImplementation(
821 mItemList
[nPos
]->GetAccessible( false/*bIsTransientChildrenDisabled*/ ) );
827 aOldAny
<<= Reference
<XInterface
>(static_cast<cppu::OWeakObject
*>(pItemAcc
));
828 ImplFireAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
, aOldAny
, aNewAny
);
833 // focus event (select)
834 const size_t nPos
= GetItemPos( mnSelItemId
);
837 if( nPos
!= VALUESET_ITEM_NOTFOUND
)
838 pItem
= mItemList
[nPos
].get();
840 pItem
= mpNoneItem
.get();
842 ValueItemAcc
* pItemAcc
= nullptr;
843 if (pItem
!= nullptr)
844 pItemAcc
= ValueItemAcc::getImplementation( pItem
->GetAccessible( false/*bIsTransientChildrenDisabled*/ ) );
850 aNewAny
<<= Reference
<XInterface
>(static_cast<cppu::OWeakObject
*>(pItemAcc
));
851 ImplFireAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
, aOldAny
, aNewAny
);
857 ImplFireAccessibleEvent(AccessibleEventId::SELECTION_CHANGED
, aOldAny
, aNewAny
);
860 void ValueSet::SetNoSelection()
862 mbNoSelection
= true;
865 if (IsReallyVisible() && IsUpdateMode())
869 void ValueSet::SetStyle(WinBits nStyle
)
871 if (nStyle
!= mnStyle
)
879 void ValueSet::Format(vcl::RenderContext
const & rRenderContext
)
881 Size
aWinSize(GetOutputSizePixel());
882 size_t nItemCount
= mItemList
.size();
883 WinBits nStyle
= GetStyle();
884 tools::Long nTxtHeight
= rRenderContext
.GetTextHeight();
886 tools::Long nNoneHeight
;
887 tools::Long nNoneSpace
;
889 if (mxScrolledWindow
&& !(nStyle
& WB_VSCROLL
) && mxScrolledWindow
->get_vpolicy() != VclPolicyType::NEVER
)
892 // calculate item offset
893 if (nStyle
& WB_ITEMBORDER
)
895 if (nStyle
& WB_DOUBLEBORDER
)
896 nOff
= ITEM_OFFSET_DOUBLE
;
903 // consider size, if NameField does exist
904 if (nStyle
& WB_NAMEFIELD
)
906 mnTextOffset
= aWinSize
.Height() - nTxtHeight
- NAME_OFFSET
;
907 aWinSize
.AdjustHeight( -(nTxtHeight
+ NAME_OFFSET
) );
909 if (!(nStyle
& WB_FLATVALUESET
))
911 mnTextOffset
-= NAME_LINE_HEIGHT
+ NAME_LINE_OFF_Y
;
912 aWinSize
.AdjustHeight( -(NAME_LINE_HEIGHT
+ NAME_LINE_OFF_Y
) );
918 // consider offset and size, if NoneField does exist
919 if (nStyle
& WB_NONEFIELD
)
921 nNoneHeight
= nTxtHeight
+ nOff
;
922 nNoneSpace
= mnSpacing
;
931 // calculate number of columns
936 mnCols
= static_cast<sal_uInt16
>((aWinSize
.Width() - mnSpacing
) / (mnUserItemWidth
+ mnSpacing
));
950 // calculate number of rows
953 auto nOldLines
= mnLines
;
954 // Floor( (M+N-1)/N )==Ceiling( M/N )
955 mnLines
= (static_cast<tools::Long
>(nItemCount
) + mnCols
- 1) / mnCols
;
959 bool bAdjustmentOutOfDate
= nOldLines
!= mnLines
;
961 auto nOldVisLines
= mnVisLines
;
963 tools::Long nCalcHeight
= aWinSize
.Height() - nNoneHeight
;
966 mnVisLines
= mnUserVisLines
;
968 else if (mnUserItemHeight
)
970 mnVisLines
= (nCalcHeight
- nNoneSpace
+ mnSpacing
) / (mnUserItemHeight
+ mnSpacing
);
976 mnVisLines
= mnLines
;
979 bAdjustmentOutOfDate
|= nOldVisLines
!= mnVisLines
;
981 if (mnLines
> mnVisLines
)
984 if (mnLines
<= mnVisLines
)
990 if (mnFirstLine
> o3tl::make_unsigned(mnLines
- mnVisLines
))
991 SetFirstLine(static_cast<sal_uInt16
>(mnLines
- mnVisLines
));
994 // calculate item size
995 const tools::Long nColSpace
= (mnCols
- 1) * static_cast<tools::Long
>(mnSpacing
);
996 const tools::Long nLineSpace
= ((mnVisLines
- 1) * mnSpacing
) + nNoneSpace
;
997 if (mnUserItemWidth
&& !mnUserCols
)
999 mnItemWidth
= mnUserItemWidth
;
1000 if (mnItemWidth
> aWinSize
.Width() - nColSpace
)
1001 mnItemWidth
= aWinSize
.Width() - nColSpace
;
1004 mnItemWidth
= (aWinSize
.Width() - nColSpace
) / mnCols
;
1005 if (mnUserItemHeight
&& !mnUserVisLines
)
1007 mnItemHeight
= mnUserItemHeight
;
1008 if (mnItemHeight
> nCalcHeight
- nNoneSpace
)
1009 mnItemHeight
= nCalcHeight
- nNoneSpace
;
1013 nCalcHeight
-= nLineSpace
;
1014 mnItemHeight
= nCalcHeight
/ mnVisLines
;
1018 maVirDev
->SetSettings(rRenderContext
.GetSettings());
1019 maVirDev
->SetOutputSizePixel(aWinSize
);
1021 // nothing is changed in case of too small items
1022 if ((mnItemWidth
<= 0) ||
1023 (mnItemHeight
<= ((nStyle
& WB_ITEMBORDER
) ? 4 : 2)) ||
1026 mbHasVisibleItems
= false;
1028 if ((nStyle
& WB_NONEFIELD
) && mpNoneItem
)
1030 mpNoneItem
->mbVisible
= false;
1031 mpNoneItem
->maText
= GetText();
1034 for (size_t i
= 0; i
< nItemCount
; i
++)
1036 mItemList
[i
]->mbVisible
= false;
1039 if (mxScrolledWindow
&& mxScrolledWindow
->get_vpolicy() != VclPolicyType::NEVER
)
1044 mbHasVisibleItems
= true;
1046 // determine Frame-Style
1047 if (nStyle
& WB_DOUBLEBORDER
)
1048 mnFrameStyle
= DrawFrameStyle::DoubleIn
;
1050 mnFrameStyle
= DrawFrameStyle::In
;
1052 // determine selected color and width
1053 // if necessary change the colors, to make the selection
1054 // better detectable
1055 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
1056 Color
aHighColor(rStyleSettings
.GetHighlightColor());
1057 if (((aHighColor
.GetRed() > 0x80) || (aHighColor
.GetGreen() > 0x80) ||
1058 (aHighColor
.GetBlue() > 0x80)) ||
1059 ((aHighColor
.GetRed() == 0x80) && (aHighColor
.GetGreen() == 0x80) &&
1060 (aHighColor
.GetBlue() == 0x80)))
1068 // draw the selection with double width if the items are bigger
1069 if ((nStyle
& WB_DOUBLEBORDER
) &&
1070 ((mnItemWidth
>= 25) && (mnItemHeight
>= 20)))
1076 mbDoubleSel
= false;
1079 // calculate offsets
1080 tools::Long nStartX
;
1081 tools::Long nStartY
;
1084 tools::Long nAllItemWidth
= (mnItemWidth
* mnCols
) + nColSpace
;
1085 tools::Long nAllItemHeight
= (mnItemHeight
* mnVisLines
) + nNoneHeight
+ nLineSpace
;
1086 nStartX
= (aWinSize
.Width() - nAllItemWidth
) / 2;
1087 nStartY
= (aWinSize
.Height() - nAllItemHeight
) / 2;
1095 // calculate and draw items
1096 maVirDev
->SetLineColor();
1097 tools::Long x
= nStartX
;
1098 tools::Long y
= nStartY
;
1100 // create NoSelection field and show it
1101 if (nStyle
& WB_NONEFIELD
)
1104 mpNoneItem
.reset(new ValueSetItem(*this));
1106 mpNoneItem
->mnId
= 0;
1107 mpNoneItem
->meType
= VALUESETITEM_NONE
;
1108 mpNoneItem
->mbVisible
= true;
1109 maNoneItemRect
.SetLeft( x
);
1110 maNoneItemRect
.SetTop( y
);
1111 maNoneItemRect
.SetRight( maNoneItemRect
.Left() + aWinSize
.Width() - x
- 1 );
1112 maNoneItemRect
.SetBottom( y
+ nNoneHeight
- 1 );
1114 ImplFormatItem(rRenderContext
, mpNoneItem
.get(), maNoneItemRect
);
1116 y
+= nNoneHeight
+ nNoneSpace
;
1120 sal_uLong nFirstItem
= static_cast<sal_uLong
>(mnFirstLine
) * mnCols
;
1121 sal_uLong nLastItem
= nFirstItem
+ (mnVisLines
* mnCols
);
1123 maItemListRect
.SetLeft( x
);
1124 maItemListRect
.SetTop( y
);
1125 maItemListRect
.SetRight( x
+ mnCols
* (mnItemWidth
+ mnSpacing
) - mnSpacing
- 1 );
1126 maItemListRect
.SetBottom( y
+ mnVisLines
* (mnItemHeight
+ mnSpacing
) - mnSpacing
- 1 );
1130 // If want also draw parts of items in the last line,
1131 // then we add one more line if parts of these line are
1133 if (y
+ (mnVisLines
* (mnItemHeight
+ mnSpacing
)) < aWinSize
.Height())
1134 nLastItem
+= mnCols
;
1135 maItemListRect
.SetBottom( aWinSize
.Height() - y
);
1137 for (size_t i
= 0; i
< nItemCount
; i
++)
1139 ValueSetItem
* pItem
= mItemList
[i
].get();
1141 if (i
>= nFirstItem
&& i
< nLastItem
)
1143 if (!pItem
->mbVisible
&& ImplHasAccessibleListeners())
1148 aNewAny
<<= pItem
->GetAccessible(false/*bIsTransientChildrenDisabled*/);
1149 ImplFireAccessibleEvent(AccessibleEventId::CHILD
, aOldAny
, aNewAny
);
1152 pItem
->mbVisible
= true;
1153 ImplFormatItem(rRenderContext
, pItem
, tools::Rectangle(Point(x
, y
), Size(mnItemWidth
, mnItemHeight
)));
1155 if (!((i
+ 1) % mnCols
))
1158 y
+= mnItemHeight
+ mnSpacing
;
1161 x
+= mnItemWidth
+ mnSpacing
;
1165 if (pItem
->mbVisible
&& ImplHasAccessibleListeners())
1170 aOldAny
<<= pItem
->GetAccessible(false/*bIsTransientChildrenDisabled*/);
1171 ImplFireAccessibleEvent(AccessibleEventId::CHILD
, aOldAny
, aNewAny
);
1174 pItem
->mbVisible
= false;
1178 // arrange ScrollBar, set values and show it
1179 if (mxScrolledWindow
&& (nStyle
& WB_VSCROLL
))
1181 bool bTurnScrollbarOn
= mxScrolledWindow
->get_vpolicy() != VclPolicyType::ALWAYS
;
1182 if (bAdjustmentOutOfDate
|| bTurnScrollbarOn
)
1184 tools::Long nPageSize
= mnVisLines
;
1187 mxScrolledWindow
->vadjustment_configure(mnFirstLine
, 0, mnLines
, 1,
1188 mnVisLines
, nPageSize
);
1191 if (bTurnScrollbarOn
)
1196 // waiting for the next since the formatting is finished
1200 void ValueSet::ImplDrawSelect(vcl::RenderContext
& rRenderContext
)
1202 if (!IsReallyVisible())
1205 const bool bFocus
= HasFocus();
1206 const bool bDrawSel
= !((mbNoSelection
&& !mbHighlight
) || (!mbDrawSelection
&& mbHighlight
));
1208 if (!bFocus
&& !bDrawSel
)
1210 ImplDrawItemText(rRenderContext
, OUString());
1214 ImplDrawSelect(rRenderContext
, mnSelItemId
, bFocus
, bDrawSel
);
1217 ImplDrawSelect(rRenderContext
, mnHighItemId
, bFocus
, bDrawSel
);
1221 void ValueSet::ImplDrawSelect(vcl::RenderContext
& rRenderContext
, sal_uInt16 nItemId
, const bool bFocus
, const bool bDrawSel
)
1223 ValueSetItem
* pItem
;
1224 tools::Rectangle aRect
;
1227 const size_t nPos
= GetItemPos( nItemId
);
1228 pItem
= mItemList
[ nPos
].get();
1229 aRect
= ImplGetItemRect( nPos
);
1231 else if (mpNoneItem
)
1233 pItem
= mpNoneItem
.get();
1234 aRect
= maNoneItemRect
;
1236 else if (bFocus
&& (pItem
= ImplGetFirstItem()))
1238 aRect
= ImplGetItemRect(0);
1245 if (!pItem
->mbVisible
)
1249 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
1250 rRenderContext
.SetFillColor();
1252 Color
aDoubleColor(rStyleSettings
.GetHighlightColor());
1253 Color
aSingleColor(rStyleSettings
.GetHighlightTextColor());
1257 * #99777# contrast enhancement for thin mode
1259 const Wallpaper
& rWall
= maVirDev
->GetBackground();
1260 if (!rWall
.IsBitmap() && ! rWall
.IsGradient())
1262 const Color
& rBack
= rWall
.GetColor();
1263 if (rBack
.IsDark() && ! aDoubleColor
.IsBright())
1265 aDoubleColor
= COL_WHITE
;
1266 aSingleColor
= COL_BLACK
;
1268 else if (rBack
.IsBright() && !aDoubleColor
.IsDark())
1270 aDoubleColor
= COL_BLACK
;
1271 aSingleColor
= COL_WHITE
;
1276 // specify selection output
1277 WinBits nStyle
= GetStyle();
1278 if (nStyle
& WB_MENUSTYLEVALUESET
)
1281 DrawFocusRect(rRenderContext
, aRect
);
1284 rRenderContext
.SetLineColor(mbBlackSel
? COL_BLACK
: aDoubleColor
);
1285 rRenderContext
.DrawRect(aRect
);
1292 rRenderContext
.SetLineColor(mbBlackSel
? COL_BLACK
: aDoubleColor
);
1293 rRenderContext
.DrawRect(aRect
);
1297 aRect
.AdjustLeft( 1 );
1298 aRect
.AdjustTop( 1 );
1299 aRect
.AdjustRight( -1 );
1300 aRect
.AdjustBottom( -1 );
1302 rRenderContext
.DrawRect(aRect
);
1304 aRect
.AdjustLeft( 1 );
1305 aRect
.AdjustTop( 1 );
1306 aRect
.AdjustRight( -1 );
1307 aRect
.AdjustBottom( -1 );
1308 tools::Rectangle aRect2
= aRect
;
1309 aRect
.AdjustLeft( 1 );
1310 aRect
.AdjustTop( 1 );
1311 aRect
.AdjustRight( -1 );
1312 aRect
.AdjustBottom( -1 );
1314 rRenderContext
.DrawRect(aRect
);
1317 aRect
.AdjustLeft( 1 );
1318 aRect
.AdjustTop( 1 );
1319 aRect
.AdjustRight( -1 );
1320 aRect
.AdjustBottom( -1 );
1322 rRenderContext
.DrawRect(aRect
);
1327 rRenderContext
.SetLineColor(mbBlackSel
? COL_WHITE
: aSingleColor
);
1331 rRenderContext
.SetLineColor(COL_LIGHTGRAY
);
1333 rRenderContext
.DrawRect(aRect2
);
1335 DrawFocusRect(rRenderContext
, aRect2
);
1338 ImplDrawItemText(rRenderContext
, pItem
->maText
);
1341 void ValueSet::ImplFormatItem(vcl::RenderContext
const & rRenderContext
, ValueSetItem
* pItem
, tools::Rectangle aRect
)
1343 WinBits nStyle
= GetStyle();
1344 if (nStyle
& WB_ITEMBORDER
)
1346 aRect
.AdjustLeft(1 );
1347 aRect
.AdjustTop(1 );
1348 aRect
.AdjustRight( -1 );
1349 aRect
.AdjustBottom( -1 );
1351 if (nStyle
& WB_FLATVALUESET
)
1353 sal_Int32 nBorder
= (nStyle
& WB_DOUBLEBORDER
) ? 2 : 1;
1355 aRect
.AdjustLeft(nBorder
);
1356 aRect
.AdjustTop(nBorder
);
1357 aRect
.AdjustRight( -nBorder
);
1358 aRect
.AdjustBottom( -nBorder
);
1362 DecorationView
aView(maVirDev
.get());
1363 aRect
= aView
.DrawFrame(aRect
, mnFrameStyle
);
1367 if (pItem
== mpNoneItem
.get())
1368 pItem
->maText
= GetText();
1370 if ((aRect
.GetHeight() <= 0) || (aRect
.GetWidth() <= 0))
1373 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
1375 if (pItem
== mpNoneItem
.get())
1377 maVirDev
->SetFont(rRenderContext
.GetFont());
1378 maVirDev
->SetTextColor((nStyle
& WB_MENUSTYLEVALUESET
) ? rStyleSettings
.GetMenuTextColor() : rStyleSettings
.GetWindowTextColor());
1379 maVirDev
->SetTextFillColor();
1380 maVirDev
->SetFillColor((nStyle
& WB_MENUSTYLEVALUESET
) ? rStyleSettings
.GetMenuColor() : rStyleSettings
.GetWindowColor());
1381 maVirDev
->DrawRect(aRect
);
1382 Point
aTxtPos(aRect
.Left() + 2, aRect
.Top());
1383 tools::Long nTxtWidth
= rRenderContext
.GetTextWidth(pItem
->maText
);
1384 if ((aTxtPos
.X() + nTxtWidth
) > aRect
.Right())
1386 maVirDev
->SetClipRegion(vcl::Region(aRect
));
1387 maVirDev
->DrawText(aTxtPos
, pItem
->maText
);
1388 maVirDev
->SetClipRegion();
1391 maVirDev
->DrawText(aTxtPos
, pItem
->maText
);
1393 else if (pItem
->meType
== VALUESETITEM_COLOR
)
1395 maVirDev
->SetFillColor(pItem
->maColor
);
1396 maVirDev
->DrawRect(aRect
);
1401 maVirDev
->SetFillColor(maColor
);
1402 else if (nStyle
& WB_MENUSTYLEVALUESET
)
1403 maVirDev
->SetFillColor(rStyleSettings
.GetMenuColor());
1404 else if (IsEnabled())
1405 maVirDev
->SetFillColor(rStyleSettings
.GetWindowColor());
1407 maVirDev
->SetFillColor(rStyleSettings
.GetFaceColor());
1408 maVirDev
->DrawRect(aRect
);
1410 if (pItem
->meType
== VALUESETITEM_USERDRAW
)
1412 UserDrawEvent
aUDEvt(nullptr, maVirDev
.get(), aRect
, pItem
->mnId
);
1417 Size aImageSize
= pItem
->maImage
.GetSizePixel();
1418 Size aRectSize
= aRect
.GetSize();
1419 Point
aPos(aRect
.Left(), aRect
.Top());
1420 aPos
.AdjustX((aRectSize
.Width() - aImageSize
.Width()) / 2 );
1422 if (pItem
->meType
!= VALUESETITEM_IMAGE_AND_TEXT
)
1423 aPos
.AdjustY((aRectSize
.Height() - aImageSize
.Height()) / 2 );
1425 DrawImageFlags nImageStyle
= DrawImageFlags::NONE
;
1427 nImageStyle
|= DrawImageFlags::Disable
;
1429 if (aImageSize
.Width() > aRectSize
.Width() ||
1430 aImageSize
.Height() > aRectSize
.Height())
1432 maVirDev
->SetClipRegion(vcl::Region(aRect
));
1433 maVirDev
->DrawImage(aPos
, pItem
->maImage
, nImageStyle
);
1434 maVirDev
->SetClipRegion();
1437 maVirDev
->DrawImage(aPos
, pItem
->maImage
, nImageStyle
);
1439 if (pItem
->meType
== VALUESETITEM_IMAGE_AND_TEXT
)
1441 maVirDev
->SetFont(rRenderContext
.GetFont());
1442 maVirDev
->SetTextColor((nStyle
& WB_MENUSTYLEVALUESET
) ? rStyleSettings
.GetMenuTextColor() : rStyleSettings
.GetWindowTextColor());
1443 maVirDev
->SetTextFillColor();
1445 tools::Long nTxtWidth
= maVirDev
->GetTextWidth(pItem
->maText
);
1447 if (nTxtWidth
> aRect
.GetWidth())
1448 maVirDev
->SetClipRegion(vcl::Region(aRect
));
1450 maVirDev
->DrawText(Point(aRect
.Left() +
1451 (aRect
.GetWidth() - nTxtWidth
) / 2,
1452 aRect
.Bottom() - maVirDev
->GetTextHeight()),
1455 if (nTxtWidth
> aRect
.GetWidth())
1456 maVirDev
->SetClipRegion();
1461 const sal_uInt16
nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings
.GetEdgeBlending() : 0);
1463 if (nEdgeBlendingPercent
)
1465 const Color
& rTopLeft(rStyleSettings
.GetEdgeBlendingTopLeftColor());
1466 const Color
& rBottomRight(rStyleSettings
.GetEdgeBlendingBottomRightColor());
1467 const sal_uInt8
nAlpha((nEdgeBlendingPercent
* 255) / 100);
1468 const BitmapEx
aBlendFrame(createBlendFrame(aRect
.GetSize(), nAlpha
, rTopLeft
, rBottomRight
));
1470 if (!aBlendFrame
.IsEmpty())
1472 maVirDev
->DrawBitmapEx(aRect
.TopLeft(), aBlendFrame
);
1477 void ValueSet::ImplDrawItemText(vcl::RenderContext
& rRenderContext
, const OUString
& rText
)
1479 if (!(GetStyle() & WB_NAMEFIELD
))
1482 Size
aWinSize(GetOutputSizePixel());
1483 tools::Long nTxtWidth
= rRenderContext
.GetTextWidth(rText
);
1484 tools::Long nTxtOffset
= mnTextOffset
;
1486 // delete rectangle and show text
1487 if (GetStyle() & WB_FLATVALUESET
)
1489 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
1490 rRenderContext
.SetLineColor();
1491 rRenderContext
.SetFillColor(rStyleSettings
.GetFaceColor());
1492 rRenderContext
.DrawRect(tools::Rectangle(Point(0, nTxtOffset
), Point(aWinSize
.Width(), aWinSize
.Height())));
1493 rRenderContext
.SetTextColor(rStyleSettings
.GetButtonTextColor());
1497 nTxtOffset
+= NAME_LINE_HEIGHT
+NAME_LINE_OFF_Y
;
1498 rRenderContext
.SetBackground(Application::GetSettings().GetStyleSettings().GetFaceColor());
1499 rRenderContext
.Erase(tools::Rectangle(Point(0, nTxtOffset
), Point(aWinSize
.Width(), aWinSize
.Height())));
1501 rRenderContext
.DrawText(Point((aWinSize
.Width() - nTxtWidth
) / 2, nTxtOffset
+ (NAME_OFFSET
/ 2)), rText
);
1504 void ValueSet::StyleUpdated()
1507 CustomWidgetController::StyleUpdated();
1510 void ValueSet::EnableFullItemMode( bool bFullMode
)
1512 mbFullMode
= bFullMode
;
1515 void ValueSet::SetColCount( sal_uInt16 nNewCols
)
1517 if ( mnUserCols
!= nNewCols
)
1519 mnUserCols
= nNewCols
;
1524 void ValueSet::SetItemImage( sal_uInt16 nItemId
, const Image
& rImage
)
1526 size_t nPos
= GetItemPos( nItemId
);
1528 if ( nPos
== VALUESET_ITEM_NOTFOUND
)
1531 ValueSetItem
* pItem
= mItemList
[nPos
].get();
1532 pItem
->meType
= VALUESETITEM_IMAGE
;
1533 pItem
->maImage
= rImage
;
1535 if ( !mbFormat
&& IsReallyVisible() && IsUpdateMode() )
1537 const tools::Rectangle aRect
= ImplGetItemRect(nPos
);
1544 void ValueSet::SetItemColor( sal_uInt16 nItemId
, const Color
& rColor
)
1546 size_t nPos
= GetItemPos( nItemId
);
1548 if ( nPos
== VALUESET_ITEM_NOTFOUND
)
1551 ValueSetItem
* pItem
= mItemList
[nPos
].get();
1552 pItem
->meType
= VALUESETITEM_COLOR
;
1553 pItem
->maColor
= rColor
;
1555 if ( !mbFormat
&& IsReallyVisible() && IsUpdateMode() )
1557 const tools::Rectangle aRect
= ImplGetItemRect(nPos
);
1558 Invalidate( aRect
);
1564 Color
ValueSet::GetItemColor( sal_uInt16 nItemId
) const
1566 size_t nPos
= GetItemPos( nItemId
);
1568 if ( nPos
!= VALUESET_ITEM_NOTFOUND
)
1569 return mItemList
[nPos
]->maColor
;
1574 Size
ValueSet::CalcWindowSizePixel( const Size
& rItemSize
, sal_uInt16 nDesireCols
,
1575 sal_uInt16 nDesireLines
) const
1577 size_t nCalcCols
= nDesireCols
;
1578 size_t nCalcLines
= nDesireLines
;
1583 nCalcCols
= mnUserCols
;
1590 nCalcLines
= mnVisLines
;
1594 if ( mnUserVisLines
)
1595 nCalcLines
= mnUserVisLines
;
1598 // Floor( (M+N-1)/N )==Ceiling( M/N )
1599 nCalcLines
= (mItemList
.size()+nCalcCols
-1) / nCalcCols
;
1606 Size
aSize( rItemSize
.Width() * nCalcCols
, rItemSize
.Height() * nCalcLines
);
1607 WinBits nStyle
= GetStyle();
1608 tools::Long nTxtHeight
= GetTextHeight();
1611 if ( nStyle
& WB_ITEMBORDER
)
1613 if ( nStyle
& WB_DOUBLEBORDER
)
1614 n
= ITEM_OFFSET_DOUBLE
;
1618 aSize
.AdjustWidth(n
* nCalcCols
);
1619 aSize
.AdjustHeight(n
* nCalcLines
);
1626 aSize
.AdjustWidth(mnSpacing
* (nCalcCols
- 1) );
1627 aSize
.AdjustHeight(mnSpacing
* (nCalcLines
- 1) );
1630 if ( nStyle
& WB_NAMEFIELD
)
1632 aSize
.AdjustHeight(nTxtHeight
+ NAME_OFFSET
);
1633 if ( !(nStyle
& WB_FLATVALUESET
) )
1634 aSize
.AdjustHeight(NAME_LINE_HEIGHT
+ NAME_LINE_OFF_Y
);
1637 if ( nStyle
& WB_NONEFIELD
)
1639 aSize
.AdjustHeight(nTxtHeight
+ n
+ mnSpacing
);
1645 void ValueSet::InsertItem( sal_uInt16 nItemId
, const Image
& rImage
)
1647 std::unique_ptr
<ValueSetItem
> pItem(new ValueSetItem( *this ));
1648 pItem
->mnId
= nItemId
;
1649 pItem
->meType
= VALUESETITEM_IMAGE
;
1650 pItem
->maImage
= rImage
;
1651 ImplInsertItem( std::move(pItem
), VALUESET_APPEND
);
1654 void ValueSet::InsertItem( sal_uInt16 nItemId
, const Image
& rImage
,
1655 const OUString
& rText
, size_t nPos
,
1658 std::unique_ptr
<ValueSetItem
> pItem(new ValueSetItem( *this ));
1659 pItem
->mnId
= nItemId
;
1660 pItem
->meType
= bShowLegend
? VALUESETITEM_IMAGE_AND_TEXT
: VALUESETITEM_IMAGE
;
1661 pItem
->maImage
= rImage
;
1662 pItem
->maText
= rText
;
1663 ImplInsertItem( std::move(pItem
), nPos
);
1666 void ValueSet::InsertItem( sal_uInt16 nItemId
, size_t nPos
)
1668 std::unique_ptr
<ValueSetItem
> pItem(new ValueSetItem( *this ));
1669 pItem
->mnId
= nItemId
;
1670 pItem
->meType
= VALUESETITEM_USERDRAW
;
1671 ImplInsertItem( std::move(pItem
), nPos
);
1674 void ValueSet::InsertItem( sal_uInt16 nItemId
, const Color
& rColor
,
1675 const OUString
& rText
)
1677 std::unique_ptr
<ValueSetItem
> pItem(new ValueSetItem( *this ));
1678 pItem
->mnId
= nItemId
;
1679 pItem
->meType
= VALUESETITEM_COLOR
;
1680 pItem
->maColor
= rColor
;
1681 pItem
->maText
= rText
;
1682 ImplInsertItem( std::move(pItem
), VALUESET_APPEND
);
1685 void ValueSet::ImplInsertItem( std::unique_ptr
<ValueSetItem
> pItem
, const size_t nPos
)
1687 DBG_ASSERT( pItem
->mnId
, "ValueSet::InsertItem(): ItemId == 0" );
1688 DBG_ASSERT( GetItemPos( pItem
->mnId
) == VALUESET_ITEM_NOTFOUND
,
1689 "ValueSet::InsertItem(): ItemId already exists" );
1691 if ( nPos
< mItemList
.size() ) {
1692 mItemList
.insert( mItemList
.begin() + nPos
, std::move(pItem
) );
1694 mItemList
.push_back( std::move(pItem
) );
1700 int ValueSet::GetScrollWidth() const
1702 if (mxScrolledWindow
)
1703 return mxScrolledWindow
->get_vscroll_width();
1707 void ValueSet::SetEdgeBlending(bool bNew
)
1709 if(mbEdgeBlending
!= bNew
)
1711 mbEdgeBlending
= bNew
;
1714 if (GetDrawingArea() && IsReallyVisible() && IsUpdateMode())
1721 Size
ValueSet::CalcItemSizePixel( const Size
& rItemSize
) const
1723 Size aSize
= rItemSize
;
1725 WinBits nStyle
= GetStyle();
1726 if ( nStyle
& WB_ITEMBORDER
)
1730 if ( nStyle
& WB_DOUBLEBORDER
)
1731 n
= ITEM_OFFSET_DOUBLE
;
1735 aSize
.AdjustWidth(n
);
1736 aSize
.AdjustHeight(n
);
1742 void ValueSet::SetLineCount( sal_uInt16 nNewLines
)
1744 if ( mnUserVisLines
!= nNewLines
)
1746 mnUserVisLines
= nNewLines
;
1751 void ValueSet::SetItemWidth( tools::Long nNewItemWidth
)
1753 if ( mnUserItemWidth
!= nNewItemWidth
)
1755 mnUserItemWidth
= nNewItemWidth
;
1760 //method to set accessible when the style is user draw.
1761 void ValueSet::InsertItem( sal_uInt16 nItemId
, const OUString
& rText
, size_t nPos
)
1763 DBG_ASSERT( nItemId
, "ValueSet::InsertItem(): ItemId == 0" );
1764 DBG_ASSERT( GetItemPos( nItemId
) == VALUESET_ITEM_NOTFOUND
,
1765 "ValueSet::InsertItem(): ItemId already exists" );
1766 std::unique_ptr
<ValueSetItem
> pItem(new ValueSetItem( *this ));
1767 pItem
->mnId
= nItemId
;
1768 pItem
->meType
= VALUESETITEM_USERDRAW
;
1769 pItem
->maText
= rText
;
1770 ImplInsertItem( std::move(pItem
), nPos
);
1773 void ValueSet::SetItemHeight( tools::Long nNewItemHeight
)
1775 if ( mnUserItemHeight
!= nNewItemHeight
)
1777 mnUserItemHeight
= nNewItemHeight
;
1782 OUString
ValueSet::RequestHelp(tools::Rectangle
& rHelpRect
)
1784 Point aPos
= rHelpRect
.TopLeft();
1785 const size_t nItemPos
= ImplGetItem( aPos
);
1787 if (nItemPos
!= VALUESET_ITEM_NOTFOUND
)
1789 rHelpRect
= ImplGetItemRect(nItemPos
);
1790 sRet
= GetItemText(ImplGetItem(nItemPos
)->mnId
);
1795 OUString
ValueSet::GetItemText(sal_uInt16 nItemId
) const
1797 const size_t nPos
= GetItemPos(nItemId
);
1799 if ( nPos
!= VALUESET_ITEM_NOTFOUND
)
1800 return mItemList
[nPos
]->maText
;
1805 void ValueSet::SetExtraSpacing( sal_uInt16 nNewSpacing
)
1807 if ( GetStyle() & WB_ITEMBORDER
)
1809 mnSpacing
= nNewSpacing
;
1814 void ValueSet::SetFormat()
1819 void ValueSet::SetItemData( sal_uInt16 nItemId
, void* pData
)
1821 size_t nPos
= GetItemPos( nItemId
);
1823 if ( nPos
== VALUESET_ITEM_NOTFOUND
)
1826 ValueSetItem
* pItem
= mItemList
[nPos
].get();
1827 pItem
->mpData
= pData
;
1829 if ( pItem
->meType
== VALUESETITEM_USERDRAW
)
1831 if ( !mbFormat
&& IsReallyVisible() && IsUpdateMode() )
1833 const tools::Rectangle aRect
= ImplGetItemRect(nPos
);
1841 void* ValueSet::GetItemData( sal_uInt16 nItemId
) const
1843 size_t nPos
= GetItemPos( nItemId
);
1845 if ( nPos
!= VALUESET_ITEM_NOTFOUND
)
1846 return mItemList
[nPos
]->mpData
;
1851 void ValueSet::SetItemText(sal_uInt16 nItemId
, const OUString
& rText
)
1853 size_t nPos
= GetItemPos( nItemId
);
1855 if ( nPos
== VALUESET_ITEM_NOTFOUND
)
1858 ValueSetItem
* pItem
= mItemList
[nPos
].get();
1860 // Remember old and new name for accessibility event.
1863 OUString
sString (pItem
->maText
);
1864 aOldName
<<= sString
;
1866 aNewName
<<= sString
;
1868 pItem
->maText
= rText
;
1870 if (!mbFormat
&& IsReallyVisible() && IsUpdateMode())
1872 sal_uInt16 nTempId
= mnSelItemId
;
1875 nTempId
= mnHighItemId
;
1877 if (nTempId
== nItemId
)
1881 if (ImplHasAccessibleListeners())
1883 Reference
<XAccessible
> xAccessible(pItem
->GetAccessible( false/*bIsTransientChildrenDisabled*/));
1884 ValueItemAcc
* pValueItemAcc
= static_cast<ValueItemAcc
*>(xAccessible
.get());
1885 pValueItemAcc
->FireAccessibleEvent(AccessibleEventId::NAME_CHANGED
, aOldName
, aNewName
);
1889 Size
ValueSet::GetLargestItemSize()
1893 for (const std::unique_ptr
<ValueSetItem
>& pItem
: mItemList
)
1895 if (!pItem
->mbVisible
)
1898 if (pItem
->meType
!= VALUESETITEM_IMAGE
&&
1899 pItem
->meType
!= VALUESETITEM_IMAGE_AND_TEXT
)
1901 // handle determining an optimal size for this case
1905 Size aSize
= pItem
->maImage
.GetSizePixel();
1906 if (pItem
->meType
== VALUESETITEM_IMAGE_AND_TEXT
)
1908 aSize
.AdjustHeight(3 * NAME_LINE_HEIGHT
+
1909 maVirDev
->GetTextHeight() );
1910 aSize
.setWidth( std::max(aSize
.Width(),
1911 maVirDev
->GetTextWidth(pItem
->maText
) + NAME_OFFSET
) );
1914 aLargestItem
.setWidth( std::max(aLargestItem
.Width(), aSize
.Width()) );
1915 aLargestItem
.setHeight( std::max(aLargestItem
.Height(), aSize
.Height()) );
1918 return aLargestItem
;
1921 void ValueSet::SetOptimalSize()
1923 Size
aLargestSize(GetLargestItemSize());
1924 aLargestSize
.setWidth(std::max(aLargestSize
.Width(), mnUserItemWidth
));
1925 aLargestSize
.setHeight(std::max(aLargestSize
.Height(), mnUserItemHeight
));
1926 Size
aPrefSize(CalcWindowSizePixel(aLargestSize
));
1927 GetDrawingArea()->set_size_request(aPrefSize
.Width(), aPrefSize
.Height());
1930 Image
ValueSet::GetItemImage(sal_uInt16 nItemId
) const
1932 size_t nPos
= GetItemPos( nItemId
);
1934 if ( nPos
!= VALUESET_ITEM_NOTFOUND
)
1935 return mItemList
[nPos
]->maImage
;
1940 void ValueSet::SetColor(const Color
& rColor
)
1944 if (IsReallyVisible() && IsUpdateMode())
1948 void ValueSet::Show()
1950 if (mxScrolledWindow
)
1951 mxScrolledWindow
->show();
1952 CustomWidgetController::Show();
1955 void ValueSet::Hide()
1957 CustomWidgetController::Hide();
1958 if (mxScrolledWindow
)
1959 mxScrolledWindow
->hide();
1962 FactoryFunction
ValueSet::GetUITestFactory() const
1964 return ValueSetUIObject::create
;
1967 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */