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 <tools/debug.hxx>
21 #include <vcl/builderfactory.hxx>
22 #include <vcl/decoview.hxx>
23 #include <vcl/svapp.hxx>
24 #include <vcl/scrbar.hxx>
25 #include <vcl/help.hxx>
26 #include <vcl/settings.hxx>
28 #include <com/sun/star/accessibility/AccessibleEventObject.hpp>
29 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
30 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
31 #include <com/sun/star/lang/XComponent.hpp>
32 #include <rtl/ustring.hxx>
33 #include "valueimp.hxx"
35 #include <svtools/valueset.hxx>
37 using namespace css::uno
;
38 using namespace css::lang
;
39 using namespace css::accessibility
;
47 ITEM_OFFSET_DOUBLE
= 6,
58 void ValueSet::ImplInit()
60 mpNoneItem
.reset(NULL
);
61 mxScrollBar
.reset(NULL
);
78 mnFrameStyle
= DrawFrameStyle::NONE
;
83 mbDrawSelection
= true;
88 mbEdgeBlending
= false;
89 mbHasVisibleItems
= false;
91 // #106446#, #106601# force mirroring of virtual device
92 maVirDev
->EnableRTL( GetParent()->IsRTLEnabled() );
94 ImplInitSettings( true, true, true );
97 ValueSet::ValueSet( vcl::Window
* pParent
, WinBits nWinStyle
, bool bDisableTransientChildren
) :
98 Control( pParent
, nWinStyle
),
99 maVirDev( VclPtr
<VirtualDevice
>::Create(*this) ),
100 maColor( COL_TRANSPARENT
)
103 mbIsTransientChildrenDisabled
= bDisableTransientChildren
;
106 VCL_BUILDER_DECL_FACTORY(ValueSet
)
108 WinBits nWinBits
= WB_TABSTOP
;
110 OString sBorder
= VclBuilder::extractCustomProperty(rMap
);
111 if (!sBorder
.isEmpty())
112 nWinBits
|= WB_BORDER
;
114 rRet
= VclPtr
<ValueSet
>::Create(pParent
, nWinBits
);
117 ValueSet::ValueSet( vcl::Window
* pParent
, const ResId
& rResId
, bool bDisableTransientChildren
) :
118 Control( pParent
, rResId
),
119 maVirDev( VclPtr
<VirtualDevice
>::Create(*this) ),
120 maColor( COL_TRANSPARENT
)
123 mbIsTransientChildrenDisabled
= bDisableTransientChildren
;
126 ValueSet::~ValueSet()
131 void ValueSet::dispose()
133 Reference
<XComponent
> xComponent(GetAccessible(false), UNO_QUERY
);
135 xComponent
->dispose();
138 mxScrollBar
.disposeAndClear();
142 void ValueSet::ImplDeleteItems()
144 const size_t n
= mItemList
.size();
146 for ( size_t i
= 0; i
< n
; ++i
)
148 ValueSetItem
* pItem
= mItemList
[i
];
149 if ( pItem
->mbVisible
&& ImplHasAccessibleListeners() )
154 aOldAny
<<= pItem
->GetAccessible( mbIsTransientChildrenDisabled
);
155 ImplFireAccessibleEvent(AccessibleEventId::CHILD
, aOldAny
, aNewAny
);
164 void ValueSet::ApplySettings(vcl::RenderContext
& rRenderContext
)
166 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
168 ApplyControlFont(rRenderContext
, rStyleSettings
.GetAppFont());
169 ApplyControlForeground(rRenderContext
, rStyleSettings
.GetButtonTextColor());
172 if (GetStyle() & WB_MENUSTYLEVALUESET
)
173 aColor
= rStyleSettings
.GetMenuColor();
174 else if (IsEnabled() && (GetStyle() & WB_FLATVALUESET
))
175 aColor
= rStyleSettings
.GetWindowColor();
177 aColor
= rStyleSettings
.GetFaceColor();
178 ApplyControlBackground(rRenderContext
, aColor
);
181 void ValueSet::ImplInitSettings(bool bFont
, bool bForeground
, bool bBackground
)
183 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
187 ApplyControlFont(*this, rStyleSettings
.GetAppFont());
190 if (bForeground
|| bFont
)
192 ApplyControlForeground(*this, rStyleSettings
.GetButtonTextColor());
199 if (GetStyle() & WB_MENUSTYLEVALUESET
)
200 aColor
= rStyleSettings
.GetMenuColor();
201 else if (IsEnabled() && (GetStyle() & WB_FLATVALUESET
))
202 aColor
= rStyleSettings
.GetWindowColor();
204 aColor
= rStyleSettings
.GetFaceColor();
205 ApplyControlBackground(*this, aColor
);
209 void ValueSet::ImplInitScrollBar()
211 if (GetStyle() & WB_VSCROLL
)
213 if (!mxScrollBar
.get())
215 mxScrollBar
.reset(VclPtr
<ScrollBar
>::Create(this, WB_VSCROLL
| WB_DRAG
));
216 mxScrollBar
->SetScrollHdl(LINK(this, ValueSet
, ImplScrollHdl
));
220 // adapt the width because of the changed settings
221 long nScrBarWidth
= Application::GetSettings().GetStyleSettings().GetScrollBarSize();
222 mxScrollBar
->setPosSizePixel(0, 0, nScrBarWidth
, 0, PosSizeFlags::Width
);
227 void ValueSet::ImplFormatItem(vcl::RenderContext
& rRenderContext
, ValueSetItem
* pItem
, Rectangle aRect
)
229 WinBits nStyle
= GetStyle();
230 if (nStyle
& WB_ITEMBORDER
)
237 if (nStyle
& WB_FLATVALUESET
)
239 sal_Int32 nBorder
= (nStyle
& WB_DOUBLEBORDER
) ? 2 : 1;
241 aRect
.Left() += nBorder
;
242 aRect
.Top() += nBorder
;
243 aRect
.Right() -= nBorder
;
244 aRect
.Bottom() -= nBorder
;
248 DecorationView
aView(maVirDev
.get());
249 aRect
= aView
.DrawFrame(aRect
, mnFrameStyle
);
253 if (pItem
== mpNoneItem
.get())
254 pItem
->maText
= GetText();
256 if ((aRect
.GetHeight() > 0) && (aRect
.GetWidth() > 0))
258 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
260 if (pItem
== mpNoneItem
.get())
262 maVirDev
->SetFont(rRenderContext
.GetFont());
263 maVirDev
->SetTextColor((nStyle
& WB_MENUSTYLEVALUESET
) ? rStyleSettings
.GetMenuTextColor() : rStyleSettings
.GetWindowTextColor());
264 maVirDev
->SetTextFillColor();
265 maVirDev
->SetFillColor((nStyle
& WB_MENUSTYLEVALUESET
) ? rStyleSettings
.GetMenuColor() : rStyleSettings
.GetWindowColor());
266 maVirDev
->DrawRect(aRect
);
267 Point
aTxtPos(aRect
.Left() + 2, aRect
.Top());
268 long nTxtWidth
= rRenderContext
.GetTextWidth(pItem
->maText
);
269 if (nStyle
& WB_RADIOSEL
)
274 if ((aTxtPos
.X() + nTxtWidth
) > aRect
.Right())
276 maVirDev
->SetClipRegion(vcl::Region(aRect
));
277 maVirDev
->DrawText(aTxtPos
, pItem
->maText
);
278 maVirDev
->SetClipRegion();
281 maVirDev
->DrawText(aTxtPos
, pItem
->maText
);
283 else if (pItem
->meType
== VALUESETITEM_COLOR
)
285 maVirDev
->SetFillColor(pItem
->maColor
);
286 maVirDev
->DrawRect(aRect
);
291 maVirDev
->SetFillColor(maColor
);
292 else if (nStyle
& WB_MENUSTYLEVALUESET
)
293 maVirDev
->SetFillColor(rStyleSettings
.GetMenuColor());
294 else if (IsEnabled())
295 maVirDev
->SetFillColor(rStyleSettings
.GetWindowColor());
297 maVirDev
->SetFillColor(rStyleSettings
.GetFaceColor());
298 maVirDev
->DrawRect(aRect
);
300 if (pItem
->meType
== VALUESETITEM_USERDRAW
)
302 UserDrawEvent
aUDEvt(this, maVirDev
.get(), aRect
, pItem
->mnId
);
307 Size aImageSize
= pItem
->maImage
.GetSizePixel();
308 Size aRectSize
= aRect
.GetSize();
309 Point
aPos(aRect
.Left(), aRect
.Top());
310 aPos
.X() += (aRectSize
.Width() - aImageSize
.Width()) / 2;
311 aPos
.Y() += (aRectSize
.Height() - aImageSize
.Height()) / 2;
313 DrawImageFlags nImageStyle
= DrawImageFlags::NONE
;
315 nImageStyle
|= DrawImageFlags::Disable
;
317 if (aImageSize
.Width() > aRectSize
.Width() ||
318 aImageSize
.Height() > aRectSize
.Height())
320 maVirDev
->SetClipRegion(vcl::Region(aRect
));
321 maVirDev
->DrawImage(aPos
, pItem
->maImage
, nImageStyle
);
322 maVirDev
->SetClipRegion();
325 maVirDev
->DrawImage(aPos
, pItem
->maImage
, nImageStyle
);
329 const sal_uInt16
nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings
.GetEdgeBlending() : 0);
331 if (nEdgeBlendingPercent
)
333 const Color
& rTopLeft(rStyleSettings
.GetEdgeBlendingTopLeftColor());
334 const Color
& rBottomRight(rStyleSettings
.GetEdgeBlendingBottomRightColor());
335 const sal_uInt8
nAlpha((nEdgeBlendingPercent
* 255) / 100);
336 const BitmapEx
aBlendFrame(createBlendFrame(aRect
.GetSize(), nAlpha
, rTopLeft
, rBottomRight
));
338 if (!aBlendFrame
.IsEmpty())
340 maVirDev
->DrawBitmapEx(aRect
.TopLeft(), aBlendFrame
);
346 Reference
<XAccessible
> ValueSet::CreateAccessible()
348 return new ValueSetAcc( this, mbIsTransientChildrenDisabled
);
351 void ValueSet::Format(vcl::RenderContext
& rRenderContext
)
353 Size
aWinSize(GetOutputSizePixel());
354 size_t nItemCount
= mItemList
.size();
355 WinBits nStyle
= GetStyle();
356 long nTxtHeight
= rRenderContext
.GetTextHeight();
360 VclPtr
<ScrollBar
> xDeletedScrollBar
;
362 // consider the scrolling
363 if (nStyle
& WB_VSCROLL
)
367 xDeletedScrollBar
= mxScrollBar
;
371 // calculate item offset
372 if (nStyle
& WB_ITEMBORDER
)
374 if (nStyle
& WB_DOUBLEBORDER
)
375 nOff
= ITEM_OFFSET_DOUBLE
;
382 // consider size, if NameField does exist
383 if (nStyle
& WB_NAMEFIELD
)
385 mnTextOffset
= aWinSize
.Height() - nTxtHeight
- NAME_OFFSET
;
386 aWinSize
.Height() -= nTxtHeight
+ NAME_OFFSET
;
388 if (!(nStyle
& WB_FLATVALUESET
))
390 mnTextOffset
-= NAME_LINE_HEIGHT
+ NAME_LINE_OFF_Y
;
391 aWinSize
.Height() -= NAME_LINE_HEIGHT
+ NAME_LINE_OFF_Y
;
397 // consider offset and size, if NoneField does exist
398 if (nStyle
& WB_NONEFIELD
)
400 nNoneHeight
= nTxtHeight
+ nOff
;
401 nNoneSpace
= mnSpacing
;
402 if (nStyle
& WB_RADIOSEL
)
410 if (mpNoneItem
.get())
411 mpNoneItem
.reset(NULL
);
414 // calculate ScrollBar width
415 long nScrBarWidth
= 0;
416 if (mxScrollBar
.get())
417 nScrBarWidth
= mxScrollBar
->GetSizePixel().Width() + SCRBAR_OFFSET
;
419 // calculate number of columns
424 mnCols
= static_cast<sal_uInt16
>((aWinSize
.Width() - nScrBarWidth
+ mnSpacing
) / (mnUserItemWidth
+ mnSpacing
));
438 // calculate number of rows
441 // Floor( (M+N-1)/N )==Ceiling( M/N )
442 mnLines
= (static_cast<long>(nItemCount
) + mnCols
- 1) / mnCols
;
446 long nCalcHeight
= aWinSize
.Height() - nNoneHeight
;
449 mnVisLines
= mnUserVisLines
;
451 else if (mnUserItemHeight
)
453 mnVisLines
= (nCalcHeight
- nNoneSpace
+ mnSpacing
) / (mnUserItemHeight
+ mnSpacing
);
459 mnVisLines
= mnLines
;
462 if (mnLines
> mnVisLines
)
465 if (mnLines
<= mnVisLines
)
471 if (mnFirstLine
> static_cast<sal_uInt16
>(mnLines
- mnVisLines
))
472 mnFirstLine
= static_cast<sal_uInt16
>(mnLines
- mnVisLines
);
475 // calculate item size
476 const long nColSpace
= (mnCols
- 1) * static_cast<long>(mnSpacing
);
477 const long nLineSpace
= ((mnVisLines
- 1) * mnSpacing
) + nNoneSpace
;
478 if (mnUserItemWidth
&& !mnUserCols
)
480 mnItemWidth
= mnUserItemWidth
;
481 if (mnItemWidth
> aWinSize
.Width() - nScrBarWidth
- nColSpace
)
482 mnItemWidth
= aWinSize
.Width() - nScrBarWidth
- nColSpace
;
485 mnItemWidth
= (aWinSize
.Width() - nScrBarWidth
-nColSpace
) / mnCols
;
486 if (mnUserItemHeight
&& !mnUserVisLines
)
488 mnItemHeight
= mnUserItemHeight
;
489 if (mnItemHeight
> nCalcHeight
- nNoneSpace
)
490 mnItemHeight
= nCalcHeight
- nNoneSpace
;
494 nCalcHeight
-= nLineSpace
;
495 mnItemHeight
= nCalcHeight
/ mnVisLines
;
499 maVirDev
->SetSettings(rRenderContext
.GetSettings());
500 maVirDev
->SetBackground(rRenderContext
.GetBackground());
501 maVirDev
->SetOutputSizePixel(aWinSize
, true);
503 // nothing is changed in case of too small items
504 if ((mnItemWidth
<= 0) ||
505 (mnItemHeight
<= ((nStyle
& WB_ITEMBORDER
) ? 4 : 2)) ||
508 mbHasVisibleItems
= false;
510 if (nStyle
& WB_NONEFIELD
)
512 if (mpNoneItem
.get())
514 mpNoneItem
->mbVisible
= false;
515 mpNoneItem
->maText
= GetText();
519 for (size_t i
= 0; i
< nItemCount
; i
++)
521 mItemList
[i
]->mbVisible
= false;
524 if (mxScrollBar
.get())
529 mbHasVisibleItems
= true;
531 // determine Frame-Style
532 if (nStyle
& WB_DOUBLEBORDER
)
533 mnFrameStyle
= DrawFrameStyle::DoubleIn
;
535 mnFrameStyle
= DrawFrameStyle::In
;
537 // determine selected color and width
538 // if necessary change the colors, to make the selection
540 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
541 Color
aHighColor(rStyleSettings
.GetHighlightColor());
542 if (((aHighColor
.GetRed() > 0x80) || (aHighColor
.GetGreen() > 0x80) ||
543 (aHighColor
.GetBlue() > 0x80)) ||
544 ((aHighColor
.GetRed() == 0x80) && (aHighColor
.GetGreen() == 0x80) &&
545 (aHighColor
.GetBlue() == 0x80)))
553 // draw the selection with double width if the items are bigger
554 if ((nStyle
& WB_DOUBLEBORDER
) &&
555 ((mnItemWidth
>= 25) && (mnItemHeight
>= 20)))
569 long nAllItemWidth
= (mnItemWidth
* mnCols
) + nColSpace
;
570 long nAllItemHeight
= (mnItemHeight
* mnVisLines
) + nNoneHeight
+ nLineSpace
;
571 nStartX
= (aWinSize
.Width() - nScrBarWidth
- nAllItemWidth
) / 2;
572 nStartY
= (aWinSize
.Height() - nAllItemHeight
) / 2;
580 // calculate and draw items
581 maVirDev
->SetLineColor();
585 // create NoSelection field and show it
586 if (nStyle
& WB_NONEFIELD
)
588 if (mpNoneItem
.get() == NULL
)
589 mpNoneItem
.reset(new ValueSetItem(*this));
591 mpNoneItem
->mnId
= 0;
592 mpNoneItem
->meType
= VALUESETITEM_NONE
;
593 mpNoneItem
->mbVisible
= true;
594 maNoneItemRect
.Left() = x
;
595 maNoneItemRect
.Top() = y
;
596 maNoneItemRect
.Right() = maNoneItemRect
.Left() + aWinSize
.Width() - x
- 1;
597 maNoneItemRect
.Bottom() = y
+ nNoneHeight
- 1;
599 ImplFormatItem(rRenderContext
, mpNoneItem
.get(), maNoneItemRect
);
601 y
+= nNoneHeight
+ nNoneSpace
;
605 sal_uLong nFirstItem
= static_cast<sal_uLong
>(mnFirstLine
) * mnCols
;
606 sal_uLong nLastItem
= nFirstItem
+ (mnVisLines
* mnCols
);
608 maItemListRect
.Left() = x
;
609 maItemListRect
.Top() = y
;
610 maItemListRect
.Right() = x
+ mnCols
* (mnItemWidth
+ mnSpacing
) - mnSpacing
- 1;
611 maItemListRect
.Bottom() = y
+ mnVisLines
* (mnItemHeight
+ mnSpacing
) - mnSpacing
- 1;
615 // If want also draw parts of items in the last line,
616 // then we add one more line if parts of these line are
618 if (y
+ (mnVisLines
* (mnItemHeight
+ mnSpacing
)) < aWinSize
.Height())
620 maItemListRect
.Bottom() = aWinSize
.Height() - y
;
622 for (size_t i
= 0; i
< nItemCount
; i
++)
624 ValueSetItem
* pItem
= mItemList
[i
];
626 if (i
>= nFirstItem
&& i
< nLastItem
)
628 if (!pItem
->mbVisible
&& ImplHasAccessibleListeners())
633 aNewAny
<<= pItem
->GetAccessible(mbIsTransientChildrenDisabled
);
634 ImplFireAccessibleEvent(AccessibleEventId::CHILD
, aOldAny
, aNewAny
);
637 pItem
->mbVisible
= true;
638 ImplFormatItem(rRenderContext
, pItem
, Rectangle(Point(x
, y
), Size(mnItemWidth
, mnItemHeight
)));
640 if (!((i
+ 1) % mnCols
))
643 y
+= mnItemHeight
+ mnSpacing
;
646 x
+= mnItemWidth
+ mnSpacing
;
650 if (pItem
->mbVisible
&& ImplHasAccessibleListeners())
655 aOldAny
<<= pItem
->GetAccessible(mbIsTransientChildrenDisabled
);
656 ImplFireAccessibleEvent(AccessibleEventId::CHILD
, aOldAny
, aNewAny
);
659 pItem
->mbVisible
= false;
663 // arrange ScrollBar, set values and show it
664 if (mxScrollBar
.get())
666 Point
aPos(aWinSize
.Width() - nScrBarWidth
+ SCRBAR_OFFSET
, 0);
667 Size
aSize(nScrBarWidth
- SCRBAR_OFFSET
, aWinSize
.Height());
668 // If a none field is visible, then we center the scrollbar
669 if (nStyle
& WB_NONEFIELD
)
671 aPos
.Y() = nStartY
+ nNoneHeight
+ 1;
672 aSize
.Height() = ((mnItemHeight
+ mnSpacing
) * mnVisLines
) - 2 - mnSpacing
;
674 mxScrollBar
->SetPosSizePixel(aPos
, aSize
);
675 mxScrollBar
->SetRangeMax(mnLines
);
676 mxScrollBar
->SetVisibleSize(mnVisLines
);
677 mxScrollBar
->SetThumbPos((long)mnFirstLine
);
678 long nPageSize
= mnVisLines
;
681 mxScrollBar
->SetPageSize(nPageSize
);
686 // waiting for the next since the formatting is finished
689 xDeletedScrollBar
.disposeAndClear();
692 void ValueSet::ImplDrawItemText(vcl::RenderContext
& rRenderContext
, const OUString
& rText
)
694 if (!(GetStyle() & WB_NAMEFIELD
))
697 Size
aWinSize(GetOutputSizePixel());
698 long nTxtWidth
= rRenderContext
.GetTextWidth(rText
);
699 long nTxtOffset
= mnTextOffset
;
701 // delete rectangle and show text
702 if (GetStyle() & WB_FLATVALUESET
)
704 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
705 rRenderContext
.SetLineColor();
706 rRenderContext
.SetFillColor(rStyleSettings
.GetFaceColor());
707 rRenderContext
.DrawRect(Rectangle(Point(0, nTxtOffset
), Point(aWinSize
.Width(), aWinSize
.Height())));
708 rRenderContext
.SetTextColor(rStyleSettings
.GetButtonTextColor());
712 nTxtOffset
+= NAME_LINE_HEIGHT
+NAME_LINE_OFF_Y
;
713 rRenderContext
.Erase(Rectangle(Point(0, nTxtOffset
), Point(aWinSize
.Width(), aWinSize
.Height())));
715 rRenderContext
.DrawText(Point((aWinSize
.Width() - nTxtWidth
) / 2, nTxtOffset
+ (NAME_OFFSET
/ 2)), rText
);
718 void ValueSet::ImplDrawSelect(vcl::RenderContext
& rRenderContext
)
720 if (!IsReallyVisible())
723 const bool bFocus
= HasFocus();
724 const bool bDrawSel
= !((mbNoSelection
&& !mbHighlight
) || (!mbDrawSelection
&& mbHighlight
));
726 if (!bFocus
&& !bDrawSel
)
728 ImplDrawItemText(rRenderContext
, OUString());
732 ImplDrawSelect(rRenderContext
, mnSelItemId
, bFocus
, bDrawSel
);
735 ImplDrawSelect(rRenderContext
, mnHighItemId
, bFocus
, bDrawSel
);
739 void ValueSet::ImplDrawSelect(vcl::RenderContext
& rRenderContext
, sal_uInt16 nItemId
, const bool bFocus
, const bool bDrawSel
)
745 const size_t nPos
= GetItemPos( nItemId
);
746 pItem
= mItemList
[ nPos
];
747 aRect
= ImplGetItemRect( nPos
);
749 else if (mpNoneItem
.get())
751 pItem
= mpNoneItem
.get();
752 aRect
= maNoneItemRect
;
754 else if (bFocus
&& (pItem
= ImplGetFirstItem()))
756 aRect
= ImplGetItemRect(0);
763 if (pItem
->mbVisible
)
766 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
767 rRenderContext
.SetFillColor();
769 Color
aDoubleColor(rStyleSettings
.GetHighlightColor());
770 Color
aSingleColor(rStyleSettings
.GetHighlightTextColor());
774 * #99777# contrast enhancement for thin mode
776 const Wallpaper
& rWall
= GetDisplayBackground();
777 if (!rWall
.IsBitmap() && ! rWall
.IsGradient())
779 const Color
& rBack
= rWall
.GetColor();
780 if (rBack
.IsDark() && ! aDoubleColor
.IsBright())
782 aDoubleColor
= Color(COL_WHITE
);
783 aSingleColor
= Color(COL_BLACK
);
785 else if (rBack
.IsBright() && ! aDoubleColor
.IsDark())
787 aDoubleColor
= Color(COL_BLACK
);
788 aSingleColor
= Color(COL_WHITE
);
793 // specify selection output
794 WinBits nStyle
= GetStyle();
795 if (nStyle
& WB_MENUSTYLEVALUESET
)
802 rRenderContext
.SetLineColor(mbBlackSel
? Color(COL_BLACK
) : aDoubleColor
);
803 rRenderContext
.DrawRect(aRect
);
806 else if (nStyle
& WB_RADIOSEL
)
812 if (nStyle
& WB_DOUBLEBORDER
)
830 rRenderContext
.SetLineColor(aDoubleColor
);
835 rRenderContext
.DrawRect(aRect
);
840 rRenderContext
.DrawRect(aRect
);
847 rRenderContext
.SetLineColor(mbBlackSel
? Color(COL_BLACK
) : aDoubleColor
);
848 rRenderContext
.DrawRect(aRect
);
857 rRenderContext
.DrawRect(aRect
);
863 Rectangle aRect2
= aRect
;
869 rRenderContext
.DrawRect(aRect
);
877 rRenderContext
.DrawRect(aRect
);
882 rRenderContext
.SetLineColor(mbBlackSel
? Color(COL_WHITE
) : aSingleColor
);
886 rRenderContext
.SetLineColor(Color(COL_LIGHTGRAY
));
888 rRenderContext
.DrawRect(aRect2
);
894 ImplDrawItemText(rRenderContext
, pItem
->maText
);
898 void ValueSet::ImplHideSelect( sal_uInt16 nItemId
)
902 const size_t nItemPos
= GetItemPos( nItemId
);
903 if ( nItemPos
!= VALUESET_ITEM_NOTFOUND
)
905 if ( !mItemList
[nItemPos
]->mbVisible
)
909 aRect
= ImplGetItemRect(nItemPos
);
913 if (mpNoneItem
.get() == NULL
)
917 aRect
= maNoneItemRect
;
921 const Point aPos
= aRect
.TopLeft();
922 const Size aSize
= aRect
.GetSize();
923 DrawOutDev( aPos
, aSize
, aPos
, aSize
, *maVirDev
.get() );
926 void ValueSet::ImplHighlightItem( sal_uInt16 nItemId
, bool bIsSelection
)
928 if ( mnHighItemId
!= nItemId
)
930 // remember the old item to delete the previous selection
931 sal_uInt16 nOldItem
= mnHighItemId
;
932 mnHighItemId
= nItemId
;
934 // don't draw the selection if nothing is selected
935 if ( !bIsSelection
&& mbNoSelection
)
936 mbDrawSelection
= false;
938 // remove the old selection and draw the new one
939 ImplHideSelect( nOldItem
);
941 mbDrawSelection
= true;
945 void ValueSet::ImplDraw(vcl::RenderContext
& rRenderContext
)
948 Format(rRenderContext
);
953 Size aSize
= maVirDev
->GetOutputSizePixel();
955 if (mxScrollBar
.get() && mxScrollBar
->IsVisible())
957 Point aScrPos
= mxScrollBar
->GetPosPixel();
958 Size aScrSize
= mxScrollBar
->GetSizePixel();
959 Point
aTempPos(0, aScrPos
.Y());
960 Size
aTempSize(aSize
.Width(), aScrPos
.Y());
962 rRenderContext
.DrawOutDev(aDefPos
, aTempSize
, aDefPos
, aTempSize
, *maVirDev
.get());
963 aTempSize
.Width() = aScrPos
.X() - 1;
964 aTempSize
.Height() = aScrSize
.Height();
965 rRenderContext
.DrawOutDev(aTempPos
, aTempSize
, aTempPos
, aTempSize
, *maVirDev
.get());
966 aTempPos
.Y() = aScrPos
.Y() + aScrSize
.Height();
967 aTempSize
.Width() = aSize
.Width();
968 aTempSize
.Height() = aSize
.Height() - aTempPos
.Y();
969 rRenderContext
.DrawOutDev(aTempPos
, aTempSize
, aTempPos
, aTempSize
, *maVirDev
.get());
972 rRenderContext
.DrawOutDev(aDefPos
, aSize
, aDefPos
, aSize
, *maVirDev
.get());
974 // draw parting line to the Namefield
975 if (GetStyle() & WB_NAMEFIELD
)
977 if (!(GetStyle() & WB_FLATVALUESET
))
979 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
980 Size
aWinSize(GetOutputSizePixel());
981 Point
aPos1(NAME_LINE_OFF_X
, mnTextOffset
+ NAME_LINE_OFF_Y
);
982 Point
aPos2(aWinSize
.Width() - (NAME_LINE_OFF_X
* 2), mnTextOffset
+ NAME_LINE_OFF_Y
);
983 if (!(rStyleSettings
.GetOptions() & StyleSettingsOptions::Mono
))
985 rRenderContext
.SetLineColor(rStyleSettings
.GetShadowColor());
986 rRenderContext
.DrawLine(aPos1
, aPos2
);
989 rRenderContext
.SetLineColor(rStyleSettings
.GetLightColor());
992 rRenderContext
.SetLineColor(rStyleSettings
.GetWindowTextColor());
993 rRenderContext
.DrawLine(aPos1
, aPos2
);
997 ImplDrawSelect(rRenderContext
);
1000 bool ValueSet::ImplScroll(const Point
& rPos
)
1002 if (!mbScroll
|| !maItemListRect
.IsInside(rPos
))
1005 const long nScrollOffset
= (mnItemHeight
<= 16) ? SCROLL_OFFSET
/ 2 : SCROLL_OFFSET
;
1006 bool bScroll
= false;
1008 if (rPos
.Y() <= maItemListRect
.Top() + nScrollOffset
)
1010 if (mnFirstLine
> 0)
1016 else if (rPos
.Y() >= maItemListRect
.Bottom() - nScrollOffset
)
1018 if (mnFirstLine
< static_cast<sal_uInt16
>(mnLines
- mnVisLines
))
1033 size_t ValueSet::ImplGetItem( const Point
& rPos
, bool bMove
) const
1035 if (!mbHasVisibleItems
)
1037 return VALUESET_ITEM_NOTFOUND
;
1040 if (mpNoneItem
.get() && maNoneItemRect
.IsInside(rPos
))
1042 return VALUESET_ITEM_NONEITEM
;
1045 if (maItemListRect
.IsInside(rPos
))
1047 const int xc
= rPos
.X() - maItemListRect
.Left();
1048 const int yc
= rPos
.Y() - maItemListRect
.Top();
1049 // The point is inside the area of item list,
1050 // let's find the containing item.
1051 const int col
= xc
/ (mnItemWidth
+ mnSpacing
);
1052 const int x
= xc
% (mnItemWidth
+ mnSpacing
);
1053 const int row
= yc
/ (mnItemHeight
+ mnSpacing
);
1054 const int y
= yc
% (mnItemHeight
+ mnSpacing
);
1056 if (x
< mnItemWidth
&& y
< mnItemHeight
)
1058 // the point is inside item rect and not inside spacing
1059 const size_t item
= (mnFirstLine
+ row
) * static_cast<size_t>(mnCols
) + col
;
1060 if (item
< mItemList
.size())
1066 // return the previously selected item if spacing is set and
1067 // the mouse hasn't left the window yet
1068 if (bMove
&& mnSpacing
&& mnHighItemId
)
1070 return GetItemPos( mnHighItemId
);
1074 return VALUESET_ITEM_NOTFOUND
;
1077 ValueSetItem
* ValueSet::ImplGetItem( size_t nPos
)
1079 if (nPos
== VALUESET_ITEM_NONEITEM
)
1080 return mpNoneItem
.get();
1082 return (nPos
< mItemList
.size()) ? mItemList
[nPos
] : NULL
;
1085 ValueSetItem
* ValueSet::ImplGetFirstItem()
1087 return mItemList
.size() ? mItemList
[0] : NULL
;
1090 sal_uInt16
ValueSet::ImplGetVisibleItemCount() const
1092 sal_uInt16 nRet
= 0;
1093 const size_t nItemCount
= mItemList
.size();
1095 for ( size_t n
= 0; n
< nItemCount
; ++n
)
1097 if ( mItemList
[n
]->mbVisible
)
1104 void ValueSet::ImplFireAccessibleEvent( short nEventId
, const Any
& rOldValue
, const Any
& rNewValue
)
1106 ValueSetAcc
* pAcc
= ValueSetAcc::getImplementation( GetAccessible( false ) );
1109 pAcc
->FireAccessibleEvent( nEventId
, rOldValue
, rNewValue
);
1112 bool ValueSet::ImplHasAccessibleListeners()
1114 ValueSetAcc
* pAcc
= ValueSetAcc::getImplementation( GetAccessible( false ) );
1115 return( pAcc
&& pAcc
->HasAccessibleListeners() );
1118 IMPL_LINK( ValueSet
,ImplScrollHdl
, ScrollBar
*, pScrollBar
)
1120 sal_uInt16 nNewFirstLine
= (sal_uInt16
)pScrollBar
->GetThumbPos();
1121 if ( nNewFirstLine
!= mnFirstLine
)
1123 mnFirstLine
= nNewFirstLine
;
1130 IMPL_LINK_NOARG_TYPED(ValueSet
, ImplTimerHdl
, Timer
*, void)
1132 ImplTracking( GetPointerPosPixel(), true );
1135 void ValueSet::ImplTracking( const Point
& rPos
, bool bRepeat
)
1137 if ( bRepeat
|| mbSelection
)
1139 if ( ImplScroll( rPos
) )
1143 maTimer
.SetTimeoutHdl( LINK( this, ValueSet
, ImplTimerHdl
) );
1144 maTimer
.SetTimeout( GetSettings().GetMouseSettings().GetScrollRepeat() );
1150 ValueSetItem
* pItem
= ImplGetItem( ImplGetItem( rPos
) );
1153 if( GetStyle() & WB_MENUSTYLEVALUESET
)
1156 ImplHighlightItem( pItem
->mnId
);
1160 if( GetStyle() & WB_MENUSTYLEVALUESET
)
1163 ImplHighlightItem( mnSelItemId
, false );
1167 void ValueSet::ImplEndTracking( const Point
& rPos
, bool bCancel
)
1169 ValueSetItem
* pItem
;
1171 // restore the old status in case of termination
1175 pItem
= ImplGetItem( ImplGetItem( rPos
) );
1179 SelectItem( pItem
->mnId
);
1180 if ( !mbSelection
&& !(GetStyle() & WB_NOPOINTERFOCUS
) )
1182 mbHighlight
= false;
1183 mbSelection
= false;
1188 ImplHighlightItem( mnSelItemId
, false );
1189 mbHighlight
= false;
1190 mbSelection
= false;
1194 void ValueSet::MouseButtonDown( const MouseEvent
& rMouseEvent
)
1196 if ( rMouseEvent
.IsLeft() )
1198 ValueSetItem
* pItem
= ImplGetItem( ImplGetItem( rMouseEvent
.GetPosPixel() ) );
1204 mnHighItemId
= mnSelItemId
;
1205 ImplHighlightItem( pItem
->mnId
);
1212 if ( pItem
&& !rMouseEvent
.IsMod2() )
1214 if ( rMouseEvent
.GetClicks() == 1 )
1217 mnHighItemId
= mnSelItemId
;
1218 ImplHighlightItem( pItem
->mnId
);
1219 StartTracking( STARTTRACK_SCROLLREPEAT
);
1221 else if ( rMouseEvent
.GetClicks() == 2 )
1229 Control::MouseButtonDown( rMouseEvent
);
1232 void ValueSet::MouseButtonUp( const MouseEvent
& rMouseEvent
)
1234 // because of SelectionMode
1235 if ( rMouseEvent
.IsLeft() && mbSelection
)
1236 ImplEndTracking( rMouseEvent
.GetPosPixel(), false );
1238 Control::MouseButtonUp( rMouseEvent
);
1241 void ValueSet::MouseMove( const MouseEvent
& rMouseEvent
)
1243 // because of SelectionMode
1244 if ( mbSelection
|| (GetStyle() & WB_MENUSTYLEVALUESET
) )
1245 ImplTracking( rMouseEvent
.GetPosPixel(), false );
1246 Control::MouseMove( rMouseEvent
);
1249 void ValueSet::Tracking( const TrackingEvent
& rTrackingEvent
)
1251 Point aMousePos
= rTrackingEvent
.GetMouseEvent().GetPosPixel();
1253 if ( rTrackingEvent
.IsTrackingEnded() )
1254 ImplEndTracking( aMousePos
, rTrackingEvent
.IsTrackingCanceled() );
1256 ImplTracking( aMousePos
, rTrackingEvent
.IsTrackingRepeat() );
1259 void ValueSet::KeyInput( const KeyEvent
& rKeyEvent
)
1261 size_t nLastItem
= mItemList
.size();
1263 if ( !nLastItem
|| !ImplGetFirstItem() )
1265 Control::KeyInput( rKeyEvent
);
1274 const size_t nCurPos
= mnSelItemId
? GetItemPos(mnSelItemId
)
1275 : (mpNoneItem
.get() ? VALUESET_ITEM_NONEITEM
: 0);
1276 size_t nItemPos
= VALUESET_ITEM_NOTFOUND
;
1277 size_t nVStep
= mnCols
;
1279 switch (rKeyEvent
.GetKeyCode().GetCode())
1282 nItemPos
= mpNoneItem
.get() ? VALUESET_ITEM_NONEITEM
: 0;
1286 nItemPos
= nLastItem
;
1290 if (nCurPos
!= VALUESET_ITEM_NONEITEM
)
1294 nItemPos
= nCurPos
-1;
1296 else if (mpNoneItem
.get())
1298 nItemPos
= VALUESET_ITEM_NONEITEM
;
1304 if (nCurPos
< nLastItem
)
1306 if (nCurPos
== VALUESET_ITEM_NONEITEM
)
1312 nItemPos
= nCurPos
+1;
1318 if (rKeyEvent
.GetKeyCode().IsShift() || rKeyEvent
.GetKeyCode().IsMod1() || rKeyEvent
.GetKeyCode().IsMod2())
1320 Control::KeyInput( rKeyEvent
);
1323 nVStep
*= mnVisLines
;
1324 // intentional fall-through
1326 if (nCurPos
!= VALUESET_ITEM_NONEITEM
)
1328 if (nCurPos
== nLastItem
)
1330 const size_t nCol
= mnCols
? nLastItem
% mnCols
: 0;
1331 if (nCol
< mnCurCol
)
1333 // Move to previous row/page, keeping the old column
1334 nVStep
-= mnCurCol
- nCol
;
1337 if (nCurPos
>= nVStep
)
1339 // Go up of a whole page
1340 nItemPos
= nCurPos
-nVStep
;
1342 else if (mpNoneItem
.get())
1344 nItemPos
= VALUESET_ITEM_NONEITEM
;
1346 else if (nCurPos
> mnCols
)
1348 // Go to same column in first row
1349 nItemPos
= nCurPos
% mnCols
;
1355 if (rKeyEvent
.GetKeyCode().IsShift() || rKeyEvent
.GetKeyCode().IsMod1() || rKeyEvent
.GetKeyCode().IsMod2())
1357 Control::KeyInput( rKeyEvent
);
1360 nVStep
*= mnVisLines
;
1361 // intentional fall-through
1363 if (nCurPos
!= nLastItem
)
1365 if (nCurPos
== VALUESET_ITEM_NONEITEM
)
1367 nItemPos
= nVStep
-mnCols
+mnCurCol
;
1371 nItemPos
= nCurPos
+nVStep
;
1373 if (nItemPos
> nLastItem
)
1375 nItemPos
= nLastItem
;
1381 if (GetStyle() & WB_NO_DIRECTSELECT
)
1386 // intentional fall-through
1388 Control::KeyInput( rKeyEvent
);
1392 // This point is reached only if key travelling was used,
1393 // in which case selection mode should be switched off
1396 if ( nItemPos
!= VALUESET_ITEM_NOTFOUND
)
1398 if ( nItemPos
!=VALUESET_ITEM_NONEITEM
&& nItemPos
<nLastItem
)
1400 // update current column only in case of a new position
1401 // which is also not a "specially" handled one.
1402 mnCurCol
= mnCols
? nItemPos
% mnCols
: 0;
1404 const sal_uInt16 nItemId
= (nItemPos
!= VALUESET_ITEM_NONEITEM
) ? GetItemId( nItemPos
) : 0;
1405 if ( nItemId
!= mnSelItemId
)
1407 SelectItem( nItemId
);
1408 if (!(GetStyle() & WB_NO_DIRECTSELECT
))
1410 // select only if WB_NO_DIRECTSELECT is not set
1417 void ValueSet::Command( const CommandEvent
& rCommandEvent
)
1419 if ( rCommandEvent
.GetCommand() == CommandEventId::Wheel
||
1420 rCommandEvent
.GetCommand() == CommandEventId::StartAutoScroll
||
1421 rCommandEvent
.GetCommand() == CommandEventId::AutoScroll
)
1423 if ( HandleScrollCommand( rCommandEvent
, NULL
, mxScrollBar
.get() ) )
1427 Control::Command( rCommandEvent
);
1430 void ValueSet::Paint(vcl::RenderContext
& rRenderContext
, const Rectangle
&)
1432 if (GetStyle() & WB_FLATVALUESET
)
1434 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
1435 rRenderContext
.SetLineColor();
1436 rRenderContext
.SetFillColor(rStyleSettings
.GetFaceColor());
1437 long nOffY
= maVirDev
->GetOutputSizePixel().Height();
1438 Size
aWinSize(GetOutputSizePixel());
1439 rRenderContext
.DrawRect(Rectangle(Point(0, nOffY
), Point( aWinSize
.Width(), aWinSize
.Height())));
1442 ImplDraw(rRenderContext
);
1445 void ValueSet::GetFocus()
1447 OSL_TRACE ("value set getting focus");
1449 Control::GetFocus();
1451 // Tell the accessible object that we got the focus.
1452 ValueSetAcc
* pAcc
= ValueSetAcc::getImplementation(GetAccessible(false));
1457 void ValueSet::LoseFocus()
1459 OSL_TRACE ("value set losing focus");
1460 if ( mbNoSelection
&& mnSelItemId
)
1461 ImplHideSelect( mnSelItemId
);
1464 Control::LoseFocus();
1466 // Tell the accessible object that we lost the focus.
1467 ValueSetAcc
* pAcc
= ValueSetAcc::getImplementation( GetAccessible( false ) );
1472 void ValueSet::Resize()
1475 if ( IsReallyVisible() && IsUpdateMode() )
1480 void ValueSet::RequestHelp( const HelpEvent
& rHelpEvent
)
1482 if ( (rHelpEvent
.GetMode() & (HelpEventMode::QUICK
| HelpEventMode::BALLOON
)) == HelpEventMode::QUICK
)
1484 Point aPos
= ScreenToOutputPixel( rHelpEvent
.GetMousePosPixel() );
1485 size_t nItemPos
= ImplGetItem( aPos
);
1486 if ( nItemPos
!= VALUESET_ITEM_NOTFOUND
)
1488 Rectangle aItemRect
= ImplGetItemRect( nItemPos
);
1489 Point aPt
= OutputToScreenPixel( aItemRect
.TopLeft() );
1490 aItemRect
.Left() = aPt
.X();
1491 aItemRect
.Top() = aPt
.Y();
1492 aPt
= OutputToScreenPixel( aItemRect
.BottomRight() );
1493 aItemRect
.Right() = aPt
.X();
1494 aItemRect
.Bottom() = aPt
.Y();
1495 Help::ShowQuickHelp( this, aItemRect
, GetItemText( ImplGetItem( nItemPos
)->mnId
) );
1500 Control::RequestHelp( rHelpEvent
);
1503 void ValueSet::StateChanged(StateChangedType nType
)
1505 Control::StateChanged(nType
);
1507 if (nType
== StateChangedType::InitShow
)
1512 else if (nType
== StateChangedType::UpdateMode
)
1514 if (IsReallyVisible() && IsUpdateMode())
1517 else if (nType
== StateChangedType::Text
)
1519 if (mpNoneItem
.get() && !mbFormat
&& IsReallyVisible() && IsUpdateMode())
1521 Invalidate(maNoneItemRect
);
1524 else if ((nType
== StateChangedType::Zoom
) ||
1525 (nType
== StateChangedType::ControlFont
))
1527 ImplInitSettings(true, false, false);
1530 else if (nType
== StateChangedType::ControlForeground
)
1532 ImplInitSettings(false, true, false);
1535 else if (nType
== StateChangedType::ControlBackground
)
1537 ImplInitSettings(false, false, true);
1540 else if ((nType
== StateChangedType::Style
) || (nType
== StateChangedType::Enable
))
1543 ImplInitSettings(false, false, true);
1548 void ValueSet::DataChanged( const DataChangedEvent
& rDataChangedEvent
)
1550 Control::DataChanged( rDataChangedEvent
);
1552 if ( rDataChangedEvent
.GetType() == DataChangedEventType::FONTS
||
1553 rDataChangedEvent
.GetType() == DataChangedEventType::DISPLAY
||
1554 rDataChangedEvent
.GetType() == DataChangedEventType::FONTSUBSTITUTION
||
1555 (rDataChangedEvent
.GetType() == DataChangedEventType::SETTINGS
&&
1556 rDataChangedEvent
.GetFlags() & AllSettingsFlags::STYLE
) )
1559 ImplInitSettings( true, true, true );
1564 void ValueSet::Select()
1566 maSelectHdl
.Call( this );
1569 void ValueSet::DoubleClick()
1571 maDoubleClickHdl
.Call( this );
1574 void ValueSet::UserDraw( const UserDrawEvent
& )
1578 void ValueSet::InsertItem( sal_uInt16 nItemId
, const Image
& rImage
, size_t nPos
)
1580 ValueSetItem
* pItem
= new ValueSetItem( *this );
1581 pItem
->mnId
= nItemId
;
1582 pItem
->meType
= VALUESETITEM_IMAGE
;
1583 pItem
->maImage
= rImage
;
1584 ImplInsertItem( pItem
, nPos
);
1587 void ValueSet::InsertItem( sal_uInt16 nItemId
, const Image
& rImage
,
1588 const OUString
& rText
, size_t nPos
)
1590 ValueSetItem
* pItem
= new ValueSetItem( *this );
1591 pItem
->mnId
= nItemId
;
1592 pItem
->meType
= VALUESETITEM_IMAGE
;
1593 pItem
->maImage
= rImage
;
1594 pItem
->maText
= rText
;
1595 ImplInsertItem( pItem
, nPos
);
1598 void ValueSet::InsertItem( sal_uInt16 nItemId
, const Color
& rColor
,
1599 const OUString
& rText
, size_t nPos
)
1601 ValueSetItem
* pItem
= new ValueSetItem( *this );
1602 pItem
->mnId
= nItemId
;
1603 pItem
->meType
= VALUESETITEM_COLOR
;
1604 pItem
->maColor
= rColor
;
1605 pItem
->maText
= rText
;
1606 ImplInsertItem( pItem
, nPos
);
1609 void ValueSet::InsertItem( sal_uInt16 nItemId
, size_t nPos
)
1611 ValueSetItem
* pItem
= new ValueSetItem( *this );
1612 pItem
->mnId
= nItemId
;
1613 pItem
->meType
= VALUESETITEM_USERDRAW
;
1614 ImplInsertItem( pItem
, nPos
);
1617 void ValueSet::ImplInsertItem( ValueSetItem
*const pItem
, const size_t nPos
)
1619 DBG_ASSERT( pItem
->mnId
, "ValueSet::InsertItem(): ItemId == 0" );
1620 DBG_ASSERT( GetItemPos( pItem
->mnId
) == VALUESET_ITEM_NOTFOUND
,
1621 "ValueSet::InsertItem(): ItemId already exists" );
1623 if ( nPos
< mItemList
.size() ) {
1624 ValueItemList::iterator it
= mItemList
.begin();
1625 ::std::advance( it
, nPos
);
1626 mItemList
.insert( it
, pItem
);
1628 mItemList
.push_back( pItem
);
1634 if ( IsReallyVisible() && IsUpdateMode() )
1638 Rectangle
ValueSet::ImplGetItemRect( size_t nPos
) const
1640 const size_t nVisibleBegin
= static_cast<size_t>(mnFirstLine
)*mnCols
;
1641 const size_t nVisibleEnd
= nVisibleBegin
+ static_cast<size_t>(mnVisLines
)*mnCols
;
1643 // Check if the item is inside the range of the displayed ones,
1644 // taking into account that last row could be incomplete
1645 if ( nPos
<nVisibleBegin
|| nPos
>=nVisibleEnd
|| nPos
>=mItemList
.size() )
1648 nPos
-= nVisibleBegin
;
1650 const size_t row
= mnCols
? nPos
/mnCols
: 0;
1651 const size_t col
= mnCols
? nPos
%mnCols
: 0;
1652 const long x
= maItemListRect
.Left()+col
*(mnItemWidth
+mnSpacing
);
1653 const long y
= maItemListRect
.Top()+row
*(mnItemHeight
+mnSpacing
);
1655 return Rectangle( Point(x
, y
), Size(mnItemWidth
, mnItemHeight
) );
1658 void ValueSet::RemoveItem( sal_uInt16 nItemId
)
1660 size_t nPos
= GetItemPos( nItemId
);
1662 if ( nPos
== VALUESET_ITEM_NOTFOUND
)
1665 if ( nPos
< mItemList
.size() ) {
1666 ValueItemList::iterator it
= mItemList
.begin();
1667 ::std::advance( it
, nPos
);
1669 mItemList
.erase( it
);
1673 if ( (mnHighItemId
== nItemId
) || (mnSelItemId
== nItemId
) )
1678 mbNoSelection
= true;
1684 if ( IsReallyVisible() && IsUpdateMode() )
1688 void ValueSet::Clear()
1697 mbNoSelection
= true;
1700 if ( IsReallyVisible() && IsUpdateMode() )
1704 size_t ValueSet::GetItemCount() const
1706 return mItemList
.size();
1709 size_t ValueSet::GetItemPos( sal_uInt16 nItemId
) const
1711 for ( size_t i
= 0, n
= mItemList
.size(); i
< n
; ++i
) {
1712 if ( mItemList
[i
]->mnId
== nItemId
) {
1716 return VALUESET_ITEM_NOTFOUND
;
1719 sal_uInt16
ValueSet::GetItemId( size_t nPos
) const
1721 return ( nPos
< mItemList
.size() ) ? mItemList
[nPos
]->mnId
: 0 ;
1724 sal_uInt16
ValueSet::GetItemId( const Point
& rPos
) const
1726 size_t nItemPos
= ImplGetItem( rPos
);
1727 if ( nItemPos
!= VALUESET_ITEM_NOTFOUND
)
1728 return GetItemId( nItemPos
);
1733 Rectangle
ValueSet::GetItemRect( sal_uInt16 nItemId
) const
1735 const size_t nPos
= GetItemPos( nItemId
);
1737 if ( nPos
!=VALUESET_ITEM_NOTFOUND
&& mItemList
[nPos
]->mbVisible
)
1738 return ImplGetItemRect( nPos
);
1743 void ValueSet::EnableFullItemMode( bool bFullMode
)
1745 mbFullMode
= bFullMode
;
1748 void ValueSet::SetColCount( sal_uInt16 nNewCols
)
1750 if ( mnUserCols
!= nNewCols
)
1752 mnUserCols
= nNewCols
;
1755 if ( IsReallyVisible() && IsUpdateMode() )
1760 void ValueSet::SetLineCount( sal_uInt16 nNewLines
)
1762 if ( mnUserVisLines
!= nNewLines
)
1764 mnUserVisLines
= nNewLines
;
1767 if ( IsReallyVisible() && IsUpdateMode() )
1772 void ValueSet::SetItemWidth( long nNewItemWidth
)
1774 if ( mnUserItemWidth
!= nNewItemWidth
)
1776 mnUserItemWidth
= nNewItemWidth
;
1779 if ( IsReallyVisible() && IsUpdateMode() )
1784 //method to set accessible when the style is user draw.
1785 void ValueSet::InsertItem( sal_uInt16 nItemId
, const OUString
& rText
, size_t nPos
)
1787 DBG_ASSERT( nItemId
, "ValueSet::InsertItem(): ItemId == 0" );
1788 DBG_ASSERT( GetItemPos( nItemId
) == VALUESET_ITEM_NOTFOUND
,
1789 "ValueSet::InsertItem(): ItemId already exists" );
1790 ValueSetItem
* pItem
= new ValueSetItem( *this );
1791 pItem
->mnId
= nItemId
;
1792 pItem
->meType
= VALUESETITEM_USERDRAW
;
1793 pItem
->maText
= rText
;
1794 ImplInsertItem( pItem
, nPos
);
1797 void ValueSet::SetItemHeight( long nNewItemHeight
)
1799 if ( mnUserItemHeight
!= nNewItemHeight
)
1801 mnUserItemHeight
= nNewItemHeight
;
1804 if ( IsReallyVisible() && IsUpdateMode() )
1809 void ValueSet::SelectItem( sal_uInt16 nItemId
)
1811 size_t nItemPos
= 0;
1815 nItemPos
= GetItemPos( nItemId
);
1816 if ( nItemPos
== VALUESET_ITEM_NOTFOUND
)
1820 if ( (mnSelItemId
!= nItemId
) || mbNoSelection
)
1822 sal_uInt16 nOldItem
= mnSelItemId
? mnSelItemId
: 1;
1823 mnSelItemId
= nItemId
;
1824 mbNoSelection
= false;
1826 bool bNewOut
= !mbFormat
&& IsReallyVisible() && IsUpdateMode();
1827 bool bNewLine
= false;
1829 // if necessary scroll to the visible area
1830 if (mbScroll
&& nItemId
&& mnCols
)
1832 sal_uInt16 nNewLine
= (sal_uInt16
)(nItemPos
/ mnCols
);
1833 if ( nNewLine
< mnFirstLine
)
1835 mnFirstLine
= nNewLine
;
1838 else if ( nNewLine
> (sal_uInt16
)(mnFirstLine
+mnVisLines
-1) )
1840 mnFirstLine
= (sal_uInt16
)(nNewLine
-mnVisLines
+1);
1849 // redraw everything if the visible area has changed
1855 // remove old selection and draw the new one
1856 ImplHideSelect( nOldItem
);
1861 if( ImplHasAccessibleListeners() )
1863 // focus event (deselect)
1866 const size_t nPos
= GetItemPos( nItemId
);
1868 if( nPos
!= VALUESET_ITEM_NOTFOUND
)
1870 ValueItemAcc
* pItemAcc
= ValueItemAcc::getImplementation(
1871 mItemList
[nPos
]->GetAccessible( mbIsTransientChildrenDisabled
) );
1877 if( !mbIsTransientChildrenDisabled
)
1879 aOldAny
<<= Reference
<XInterface
>(static_cast<cppu::OWeakObject
*>(pItemAcc
));
1880 ImplFireAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
, aOldAny
, aNewAny
);
1884 aOldAny
<<= AccessibleStateType::FOCUSED
;
1885 pItemAcc
->FireAccessibleEvent(AccessibleEventId::STATE_CHANGED
, aOldAny
, aNewAny
);
1891 // focus event (select)
1892 const size_t nPos
= GetItemPos( mnSelItemId
);
1894 ValueSetItem
* pItem
;
1895 if( nPos
!= VALUESET_ITEM_NOTFOUND
)
1896 pItem
= mItemList
[nPos
];
1898 pItem
= mpNoneItem
.get();
1900 ValueItemAcc
* pItemAcc
= NULL
;
1902 pItemAcc
= ValueItemAcc::getImplementation( pItem
->GetAccessible( mbIsTransientChildrenDisabled
) );
1908 if( !mbIsTransientChildrenDisabled
)
1910 aNewAny
<<= Reference
<XInterface
>(static_cast<cppu::OWeakObject
*>(pItemAcc
));
1911 ImplFireAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
, aOldAny
, aNewAny
);
1915 aNewAny
<<= AccessibleStateType::FOCUSED
;
1916 pItemAcc
->FireAccessibleEvent(AccessibleEventId::STATE_CHANGED
, aOldAny
, aNewAny
);
1923 ImplFireAccessibleEvent(AccessibleEventId::SELECTION_CHANGED
, aOldAny
, aNewAny
);
1925 maHighlightHdl
.Call(this);
1929 void ValueSet::SetNoSelection()
1931 mbNoSelection
= true;
1932 mbHighlight
= false;
1933 mbSelection
= false;
1935 if (IsReallyVisible() && IsUpdateMode())
1939 void ValueSet::SetItemImage( sal_uInt16 nItemId
, const Image
& rImage
)
1941 size_t nPos
= GetItemPos( nItemId
);
1943 if ( nPos
== VALUESET_ITEM_NOTFOUND
)
1946 ValueSetItem
* pItem
= mItemList
[nPos
];
1947 pItem
->meType
= VALUESETITEM_IMAGE
;
1948 pItem
->maImage
= rImage
;
1950 if ( !mbFormat
&& IsReallyVisible() && IsUpdateMode() )
1952 const Rectangle aRect
= ImplGetItemRect(nPos
);
1959 Image
ValueSet::GetItemImage( sal_uInt16 nItemId
) const
1961 size_t nPos
= GetItemPos( nItemId
);
1963 if ( nPos
!= VALUESET_ITEM_NOTFOUND
)
1964 return mItemList
[nPos
]->maImage
;
1969 void ValueSet::SetItemColor( sal_uInt16 nItemId
, const Color
& rColor
)
1971 size_t nPos
= GetItemPos( nItemId
);
1973 if ( nPos
== VALUESET_ITEM_NOTFOUND
)
1976 ValueSetItem
* pItem
= mItemList
[nPos
];
1977 pItem
->meType
= VALUESETITEM_COLOR
;
1978 pItem
->maColor
= rColor
;
1980 if ( !mbFormat
&& IsReallyVisible() && IsUpdateMode() )
1982 const Rectangle aRect
= ImplGetItemRect(nPos
);
1983 Invalidate( aRect
);
1989 Color
ValueSet::GetItemColor( sal_uInt16 nItemId
) const
1991 size_t nPos
= GetItemPos( nItemId
);
1993 if ( nPos
!= VALUESET_ITEM_NOTFOUND
)
1994 return mItemList
[nPos
]->maColor
;
1999 void ValueSet::SetItemData( sal_uInt16 nItemId
, void* pData
)
2001 size_t nPos
= GetItemPos( nItemId
);
2003 if ( nPos
== VALUESET_ITEM_NOTFOUND
)
2006 ValueSetItem
* pItem
= mItemList
[nPos
];
2007 pItem
->mpData
= pData
;
2009 if ( pItem
->meType
== VALUESETITEM_USERDRAW
)
2011 if ( !mbFormat
&& IsReallyVisible() && IsUpdateMode() )
2013 const Rectangle aRect
= ImplGetItemRect(nPos
);
2021 void* ValueSet::GetItemData( sal_uInt16 nItemId
) const
2023 size_t nPos
= GetItemPos( nItemId
);
2025 if ( nPos
!= VALUESET_ITEM_NOTFOUND
)
2026 return mItemList
[nPos
]->mpData
;
2031 void ValueSet::SetItemText(sal_uInt16 nItemId
, const OUString
& rText
)
2033 size_t nPos
= GetItemPos( nItemId
);
2035 if ( nPos
== VALUESET_ITEM_NOTFOUND
)
2039 ValueSetItem
* pItem
= mItemList
[nPos
];
2041 // Remember old and new name for accessibility event.
2044 OUString
sString (pItem
->maText
);
2045 aOldName
<<= sString
;
2047 aNewName
<<= sString
;
2049 pItem
->maText
= rText
;
2051 if (!mbFormat
&& IsReallyVisible() && IsUpdateMode())
2053 sal_uInt16 nTempId
= mnSelItemId
;
2056 nTempId
= mnHighItemId
;
2058 if (nTempId
== nItemId
)
2062 if (ImplHasAccessibleListeners())
2064 Reference
<XAccessible
> xAccessible(pItem
->GetAccessible( mbIsTransientChildrenDisabled
));
2065 ValueItemAcc
* pValueItemAcc
= static_cast<ValueItemAcc
*>(xAccessible
.get());
2066 pValueItemAcc
->FireAccessibleEvent(AccessibleEventId::NAME_CHANGED
, aOldName
, aNewName
);
2070 OUString
ValueSet::GetItemText( sal_uInt16 nItemId
) const
2072 size_t nPos
= GetItemPos( nItemId
);
2074 if ( nPos
!= VALUESET_ITEM_NOTFOUND
)
2075 return mItemList
[nPos
]->maText
;
2080 void ValueSet::SetColor( const Color
& rColor
)
2084 if (IsReallyVisible() && IsUpdateMode())
2088 void ValueSet::SetExtraSpacing( sal_uInt16 nNewSpacing
)
2090 if ( GetStyle() & WB_ITEMBORDER
)
2092 mnSpacing
= nNewSpacing
;
2096 if ( IsReallyVisible() && IsUpdateMode() )
2101 void ValueSet::StartSelection()
2105 mnHighItemId
= mnSelItemId
;
2108 void ValueSet::EndSelection()
2113 EndTracking( TrackingEventFlags::Cancel
);
2115 ImplHighlightItem( mnSelItemId
);
2116 mbHighlight
= false;
2118 mbSelection
= false;
2121 void ValueSet::SetFormat(bool bFormat
)
2126 bool ValueSet::StartDrag( const CommandEvent
& rEvent
, vcl::Region
& rRegion
)
2128 if ( rEvent
.GetCommand() != CommandEventId::StartDrag
)
2131 // if necessary abort an existing action
2134 // Check out if the clicked on page is selected. If this is not the
2135 // case set it as the current item. We only check mouse actions since
2136 // drag-and-drop can also be triggered by the keyboard
2138 if ( rEvent
.IsMouseEvent() )
2139 nSelId
= GetItemId( rEvent
.GetMousePosPixel() );
2141 nSelId
= mnSelItemId
;
2143 // don't activate dragging if no item was clicked on
2147 // Check out if the page was selected. If not set as current page and
2149 if ( nSelId
!= mnSelItemId
)
2151 SelectItem( nSelId
);
2156 vcl::Region aRegion
;
2164 Size
ValueSet::CalcWindowSizePixel( const Size
& rItemSize
, sal_uInt16 nDesireCols
,
2165 sal_uInt16 nDesireLines
) const
2167 size_t nCalcCols
= nDesireCols
;
2168 size_t nCalcLines
= nDesireLines
;
2173 nCalcCols
= mnUserCols
;
2180 nCalcLines
= mnVisLines
;
2184 if ( mnUserVisLines
)
2185 nCalcLines
= mnUserVisLines
;
2188 // Floor( (M+N-1)/N )==Ceiling( M/N )
2189 nCalcLines
= (mItemList
.size()+nCalcCols
-1) / nCalcCols
;
2196 Size
aSize( rItemSize
.Width() * nCalcCols
, rItemSize
.Height() * nCalcLines
);
2197 WinBits nStyle
= GetStyle();
2198 long nTxtHeight
= GetTextHeight();
2201 if ( nStyle
& WB_ITEMBORDER
)
2203 if ( nStyle
& WB_DOUBLEBORDER
)
2204 n
= ITEM_OFFSET_DOUBLE
;
2208 aSize
.Width() += n
* nCalcCols
;
2209 aSize
.Height() += n
* nCalcLines
;
2216 aSize
.Width() += mnSpacing
* (nCalcCols
- 1);
2217 aSize
.Height() += mnSpacing
* (nCalcLines
- 1);
2220 if ( nStyle
& WB_NAMEFIELD
)
2222 aSize
.Height() += nTxtHeight
+ NAME_OFFSET
;
2223 if ( !(nStyle
& WB_FLATVALUESET
) )
2224 aSize
.Height() += NAME_LINE_HEIGHT
+ NAME_LINE_OFF_Y
;
2227 if ( nStyle
& WB_NONEFIELD
)
2229 aSize
.Height() += nTxtHeight
+ n
+ mnSpacing
;
2230 if ( nStyle
& WB_RADIOSEL
)
2231 aSize
.Height() += 8;
2234 // sum possible ScrollBar width
2235 aSize
.Width() += GetScrollWidth();
2240 Size
ValueSet::CalcItemSizePixel( const Size
& rItemSize
, bool bOut
) const
2242 Size aSize
= rItemSize
;
2244 WinBits nStyle
= GetStyle();
2245 if ( nStyle
& WB_ITEMBORDER
)
2249 if ( nStyle
& WB_DOUBLEBORDER
)
2250 n
= ITEM_OFFSET_DOUBLE
;
2257 aSize
.Height() += n
;
2262 aSize
.Height() -= n
;
2269 long ValueSet::GetScrollWidth() const
2271 if (GetStyle() & WB_VSCROLL
)
2273 ValueSet
* pValueSet
= const_cast<ValueSet
*>(this);
2276 pValueSet
->ImplInitScrollBar();
2278 pValueSet
->Invalidate();
2279 return mxScrollBar
->GetSizePixel().Width() + SCRBAR_OFFSET
;
2285 void ValueSet::SetHighlightHdl( const Link
<>& rLink
)
2287 maHighlightHdl
= rLink
;
2290 Size
ValueSet::GetOptimalSize() const
2292 Size aLargestItemSize
;
2294 for (size_t i
= 0, n
= mItemList
.size(); i
< n
; ++i
)
2296 const ValueSetItem
* pItem
= mItemList
[i
];
2297 if (!pItem
->mbVisible
)
2300 if (pItem
->meType
!= VALUESETITEM_IMAGE
)
2302 //handle determining an optimal size for this case
2306 Size aImageSize
= pItem
->maImage
.GetSizePixel();
2307 aLargestItemSize
.Width() = std::max(aLargestItemSize
.Width(), aImageSize
.Width());
2308 aLargestItemSize
.Height() = std::max(aLargestItemSize
.Height(), aImageSize
.Height());
2311 return CalcWindowSizePixel(aLargestItemSize
);
2314 void ValueSet::SetEdgeBlending(bool bNew
)
2316 if(mbEdgeBlending
!= bNew
)
2318 mbEdgeBlending
= bNew
;
2321 if(IsReallyVisible() && IsUpdateMode())
2328 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */