1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <sal/config.h>
21
22 #include <o3tl/safeint.hxx>
23 #include <tools/debug.hxx>
24 #include <comphelper/base64.hxx>
25 #include <vcl/decoview.hxx>
26 #include <vcl/event.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/settings.hxx>
29 #include <vcl/virdev.hxx>
30
31 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
32 #include <com/sun/star/lang/XComponent.hpp>
33 #include <rtl/ustring.hxx>
34 #include <sal/log.hxx>
35 #include "valueimp.hxx"
36
37 #include <svtools/valueset.hxx>
38
39 #include <uiobject.hxx>
40 #include <vcl/uitest/logger.hxx>
41 #include <vcl/uitest/eventdescription.hxx>
42
43 using namespace css::uno;
44 using namespace css::lang;
45 using namespace css::accessibility;
46
47 namespace
48 {
collectUIInformation(const OUString & aID,const OUString & aParentID,const OUString & aPos)49 void collectUIInformation( const OUString& aID , const OUString& aParentID , const OUString& aPos )
50 {
51 EventDescription aDescription;
52 aDescription.aID = aID ;
53 aDescription.aParameters = {{"POS", aPos }};
54 aDescription.aAction = "SELECT";
55 aDescription.aKeyWord = "ValueSet";
56 aDescription.aParent = aParentID;
57 UITestLogger::getInstance().logEvent(aDescription);
58 }
59
60 enum
61 {
62 ITEM_OFFSET = 4,
63 ITEM_OFFSET_DOUBLE = 6,
64 NAME_LINE_OFF_X = 2,
65 NAME_LINE_OFF_Y = 2,
66 NAME_LINE_HEIGHT = 2,
67 NAME_OFFSET = 2,
68 };
69
70 }
71
ValueSet(std::unique_ptr<weld::ScrolledWindow> pScrolledWindow)72 ValueSet::ValueSet(std::unique_ptr<weld::ScrolledWindow> pScrolledWindow)
73 : maVirDev( VclPtr<VirtualDevice>::Create())
74 , mxScrolledWindow(std::move(pScrolledWindow))
75 , mnHighItemId(0)
76 , maColor(COL_TRANSPARENT)
77 , mnStyle(0)
78 , mbFormat(true)
79 , mbHighlight(false)
80 {
81 maVirDev->SetBackground(Application::GetSettings().GetStyleSettings().GetFaceColor());
82
83 mnItemWidth = 0;
84 mnItemHeight = 0;
85 mnTextOffset = 0;
86 mnVisLines = 0;
87 mnLines = 0;
88 mnUserItemWidth = 0;
89 mnUserItemHeight = 0;
90 mnFirstLine = 0;
91 mnSelItemId = 0;
92 mnSavedItemId = -1;
93 mnCols = 0;
94 mnCurCol = 0;
95 mnUserCols = 0;
96 mnUserVisLines = 0;
97 mnSpacing = 0;
98 mnFrameStyle = DrawFrameStyle::NONE;
99 mbNoSelection = true;
100 mbDrawSelection = true;
101 mbBlackSel = false;
102 mbDoubleSel = false;
103 mbScroll = false;
104 mbFullMode = true;
105 mbEdgeBlending = false;
106 mbHasVisibleItems = false;
107
108 if (mxScrolledWindow)
109 mxScrolledWindow->connect_vadjustment_changed(LINK(this, ValueSet, ImplScrollHdl));
110 }
111
SetDrawingArea(weld::DrawingArea * pDrawingArea)112 void ValueSet::SetDrawingArea(weld::DrawingArea* pDrawingArea)
113 {
114 CustomWidgetController::SetDrawingArea(pDrawingArea);
115 // #106446#, #106601# force mirroring of virtual device
116 maVirDev->EnableRTL(pDrawingArea->get_direction());
117 }
118
CreateAccessible()119 Reference<XAccessible> ValueSet::CreateAccessible()
120 {
121 if (!mxAccessible)
122 mxAccessible.set(new ValueSetAcc(this));
123 return mxAccessible;
124 }
125
~ValueSet()126 ValueSet::~ValueSet()
127 {
128 Reference<XComponent> xComponent(mxAccessible, UNO_QUERY);
129 if (xComponent.is())
130 xComponent->dispose();
131
132 ImplDeleteItems();
133 }
134
ImplDeleteItems()135 void ValueSet::ImplDeleteItems()
136 {
137 const size_t n = mItemList.size();
138
139 for ( size_t i = 0; i < n; ++i )
140 {
141 ValueSetItem* pItem = mItemList[i].get();
142 if ( pItem->mbVisible && ImplHasAccessibleListeners() )
143 {
144 Any aOldAny;
145 Any aNewAny;
146
147 aOldAny <<= pItem->GetAccessible( false/*bIsTransientChildrenDisabled*/ );
148 ImplFireAccessibleEvent(AccessibleEventId::CHILD, aOldAny, aNewAny);
149 }
150
151 mItemList[i].reset();
152 }
153
154 mItemList.clear();
155 }
156
Select()157 void ValueSet::Select()
158 {
159 collectUIInformation(OStringToOUString(GetDrawingArea()->get_buildable_name(),RTL_TEXTENCODING_UTF8) , OStringToOUString(GetDrawingArea()->get_help_id(),RTL_TEXTENCODING_UTF8) , OUString::number(GetSelectedItemId()));
160 maSelectHdl.Call( this );
161 }
162
UserDraw(const UserDrawEvent &)163 void ValueSet::UserDraw( const UserDrawEvent& )
164 {
165 }
166
ImplGetItem(const Point & rPos) const167 size_t ValueSet::ImplGetItem( const Point& rPos ) const
168 {
169 if (!mbHasVisibleItems)
170 {
171 return VALUESET_ITEM_NOTFOUND;
172 }
173
174 if (mpNoneItem && maNoneItemRect.IsInside(rPos))
175 {
176 return VALUESET_ITEM_NONEITEM;
177 }
178
179 if (maItemListRect.IsInside(rPos))
180 {
181 const int xc = rPos.X() - maItemListRect.Left();
182 const int yc = rPos.Y() - maItemListRect.Top();
183 // The point is inside the area of item list,
184 // let's find the containing item.
185 const int col = xc / (mnItemWidth + mnSpacing);
186 const int x = xc % (mnItemWidth + mnSpacing);
187 const int row = yc / (mnItemHeight + mnSpacing);
188 const int y = yc % (mnItemHeight + mnSpacing);
189
190 if (x < mnItemWidth && y < mnItemHeight)
191 {
192 // the point is inside item rect and not inside spacing
193 const size_t item = (mnFirstLine + row) * static_cast<size_t>(mnCols) + col;
194 if (item < mItemList.size())
195 {
196 return item;
197 }
198 }
199 }
200
201 return VALUESET_ITEM_NOTFOUND;
202 }
203
ImplGetItem(size_t nPos)204 ValueSetItem* ValueSet::ImplGetItem( size_t nPos )
205 {
206 if (nPos == VALUESET_ITEM_NONEITEM)
207 return mpNoneItem.get();
208 else
209 return (nPos < mItemList.size()) ? mItemList[nPos].get() : nullptr;
210 }
211
ImplGetFirstItem()212 ValueSetItem* ValueSet::ImplGetFirstItem()
213 {
214 return !mItemList.empty() ? mItemList[0].get() : nullptr;
215 }
216
ImplGetVisibleItemCount() const217 sal_uInt16 ValueSet::ImplGetVisibleItemCount() const
218 {
219 sal_uInt16 nRet = 0;
220 const size_t nItemCount = mItemList.size();
221
222 for ( size_t n = 0; n < nItemCount; ++n )
223 {
224 if ( mItemList[n]->mbVisible )
225 ++nRet;
226 }
227
228 return nRet;
229 }
230
ImplFireAccessibleEvent(short nEventId,const Any & rOldValue,const Any & rNewValue)231 void ValueSet::ImplFireAccessibleEvent( short nEventId, const Any& rOldValue, const Any& rNewValue )
232 {
233 ValueSetAcc* pAcc = ValueSetAcc::getImplementation(mxAccessible);
234
235 if( pAcc )
236 pAcc->FireAccessibleEvent( nEventId, rOldValue, rNewValue );
237 }
238
ImplHasAccessibleListeners()239 bool ValueSet::ImplHasAccessibleListeners()
240 {
241 ValueSetAcc* pAcc = ValueSetAcc::getImplementation(mxAccessible);
242 return( pAcc && pAcc->HasAccessibleListeners() );
243 }
244
IMPL_LINK(ValueSet,ImplScrollHdl,weld::ScrolledWindow &,rScrollWin,void)245 IMPL_LINK(ValueSet, ImplScrollHdl, weld::ScrolledWindow&, rScrollWin, void)
246 {
247 auto nNewFirstLine = rScrollWin.vadjustment_get_value();
248 if ( nNewFirstLine != mnFirstLine )
249 {
250 mnFirstLine = nNewFirstLine;
251 mbFormat = true;
252 Invalidate();
253 }
254 }
255
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)256 void ValueSet::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
257 {
258 if (GetStyle() & WB_FLATVALUESET)
259 {
260 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
261 rRenderContext.SetLineColor();
262 rRenderContext.SetFillColor(rStyleSettings.GetFaceColor());
263 tools::Long nOffY = maVirDev->GetOutputSizePixel().Height();
264 Size aWinSize(GetOutputSizePixel());
265 rRenderContext.DrawRect(tools::Rectangle(Point(0, nOffY ), Point( aWinSize.Width(), aWinSize.Height())));
266 }
267
268 ImplDraw(rRenderContext);
269 }
270
GetFocus()271 void ValueSet::GetFocus()
272 {
273 SAL_INFO("svtools", "value set getting focus");
274 Invalidate();
275 CustomWidgetController::GetFocus();
276
277 // Tell the accessible object that we got the focus.
278 ValueSetAcc* pAcc = ValueSetAcc::getImplementation(mxAccessible);
279 if (pAcc)
280 pAcc->GetFocus();
281 }
282
LoseFocus()283 void ValueSet::LoseFocus()
284 {
285 SAL_INFO("svtools", "value set losing focus");
286 Invalidate();
287 CustomWidgetController::LoseFocus();
288
289 // Tell the accessible object that we lost the focus.
290 ValueSetAcc* pAcc = ValueSetAcc::getImplementation(mxAccessible);
291 if( pAcc )
292 pAcc->LoseFocus();
293 }
294
Resize()295 void ValueSet::Resize()
296 {
297 mbFormat = true;
298 if ( IsReallyVisible() && IsUpdateMode() )
299 Invalidate();
300 CustomWidgetController::Resize();
301 }
302
KeyInput(const KeyEvent & rKeyEvent)303 bool ValueSet::KeyInput( const KeyEvent& rKeyEvent )
304 {
305 size_t nLastItem = mItemList.size();
306
307 if ( !nLastItem || !ImplGetFirstItem() )
308 return CustomWidgetController::KeyInput(rKeyEvent);
309
310 if (mbFormat)
311 Invalidate();
312
313 --nLastItem;
314
315 const size_t nCurPos
316 = mnSelItemId ? GetItemPos(mnSelItemId) : (mpNoneItem ? VALUESET_ITEM_NONEITEM : 0);
317 size_t nItemPos = VALUESET_ITEM_NOTFOUND;
318 size_t nVStep = mnCols;
319
320 switch (rKeyEvent.GetKeyCode().GetCode())
321 {
322 case KEY_HOME:
323 nItemPos = mpNoneItem ? VALUESET_ITEM_NONEITEM : 0;
324 break;
325
326 case KEY_END:
327 nItemPos = nLastItem;
328 break;
329
330 case KEY_LEFT:
331 if (nCurPos != VALUESET_ITEM_NONEITEM)
332 {
333 if (nCurPos)
334 {
335 nItemPos = nCurPos-1;
336 }
337 else if (mpNoneItem)
338 {
339 nItemPos = VALUESET_ITEM_NONEITEM;
340 }
341 }
342 break;
343
344 case KEY_RIGHT:
345 if (nCurPos < nLastItem)
346 {
347 if (nCurPos == VALUESET_ITEM_NONEITEM)
348 {
349 nItemPos = 0;
350 }
351 else
352 {
353 nItemPos = nCurPos+1;
354 }
355 }
356 break;
357
358 case KEY_PAGEUP:
359 if (rKeyEvent.GetKeyCode().IsShift() || rKeyEvent.GetKeyCode().IsMod1() || rKeyEvent.GetKeyCode().IsMod2())
360 {
361 return CustomWidgetController::KeyInput(rKeyEvent);
362 }
363 nVStep *= mnVisLines;
364 [[fallthrough]];
365 case KEY_UP:
366 if (nCurPos != VALUESET_ITEM_NONEITEM)
367 {
368 if (nCurPos == nLastItem)
369 {
370 const size_t nCol = mnCols ? nLastItem % mnCols : 0;
371 if (nCol < mnCurCol)
372 {
373 // Move to previous row/page, keeping the old column
374 nVStep -= mnCurCol - nCol;
375 }
376 }
377 if (nCurPos >= nVStep)
378 {
379 // Go up of a whole page
380 nItemPos = nCurPos-nVStep;
381 }
382 else if (mpNoneItem)
383 {
384 nItemPos = VALUESET_ITEM_NONEITEM;
385 }
386 else if (nCurPos > mnCols)
387 {
388 // Go to same column in first row
389 nItemPos = nCurPos % mnCols;
390 }
391 }
392 break;
393
394 case KEY_PAGEDOWN:
395 if (rKeyEvent.GetKeyCode().IsShift() || rKeyEvent.GetKeyCode().IsMod1() || rKeyEvent.GetKeyCode().IsMod2())
396 {
397 return CustomWidgetController::KeyInput(rKeyEvent);
398 }
399 nVStep *= mnVisLines;
400 [[fallthrough]];
401 case KEY_DOWN:
402 if (nCurPos != nLastItem)
403 {
404 if (nCurPos == VALUESET_ITEM_NONEITEM)
405 {
406 nItemPos = nVStep-mnCols+mnCurCol;
407 }
408 else
409 {
410 nItemPos = nCurPos+nVStep;
411 }
412 if (nItemPos > nLastItem)
413 {
414 nItemPos = nLastItem;
415 }
416 }
417 break;
418
419 case KEY_RETURN:
420 if (GetStyle() & WB_NO_DIRECTSELECT)
421 {
422 // tdf#142479 on return select the entry the cursor is in
423 // before calling Select
424 if (nCurPos != VALUESET_ITEM_NONEITEM)
425 {
426 const sal_uInt16 nItemId = GetItemId(nCurPos);
427 if (nItemId != mnSelItemId)
428 SelectItem(nItemId);
429 }
430 Select();
431 break;
432 }
433 [[fallthrough]];
434 default:
435 return CustomWidgetController::KeyInput(rKeyEvent);
436 }
437
438 if ( nItemPos == VALUESET_ITEM_NOTFOUND )
439 return true;
440
441 if ( nItemPos!=VALUESET_ITEM_NONEITEM && nItemPos<nLastItem )
442 {
443 // update current column only in case of a new position
444 // which is also not a "specially" handled one.
445 mnCurCol = mnCols ? nItemPos % mnCols : 0;
446 }
447 const sal_uInt16 nItemId = (nItemPos != VALUESET_ITEM_NONEITEM) ? GetItemId( nItemPos ) : 0;
448 if ( nItemId != mnSelItemId )
449 {
450 SelectItem( nItemId );
451 if (!(GetStyle() & WB_NO_DIRECTSELECT))
452 {
453 // select only if WB_NO_DIRECTSELECT is not set
454 Select();
455 }
456 }
457
458 return true;
459 }
460
ImplTracking(const Point & rPos)461 void ValueSet::ImplTracking(const Point& rPos)
462 {
463 ValueSetItem* pItem = ImplGetItem( ImplGetItem( rPos ) );
464 if ( pItem )
465 {
466 if( GetStyle() & WB_MENUSTYLEVALUESET || GetStyle() & WB_FLATVALUESET )
467 mbHighlight = true;
468
469 ImplHighlightItem( pItem->mnId );
470 }
471 else
472 {
473 if( GetStyle() & WB_MENUSTYLEVALUESET || GetStyle() & WB_FLATVALUESET )
474 mbHighlight = true;
475
476 ImplHighlightItem( mnSelItemId, false );
477 }
478 }
479
MouseButtonDown(const MouseEvent & rMouseEvent)480 bool ValueSet::MouseButtonDown( const MouseEvent& rMouseEvent )
481 {
482 if ( rMouseEvent.IsLeft() )
483 {
484 ValueSetItem* pItem = ImplGetItem( ImplGetItem( rMouseEvent.GetPosPixel() ) );
485 if (pItem && !rMouseEvent.IsMod2())
486 {
487 if (rMouseEvent.GetClicks() == 1)
488 {
489 SelectItem( pItem->mnId );
490 if (!(GetStyle() & WB_NOPOINTERFOCUS))
491 GrabFocus();
492 }
493 else if ( rMouseEvent.GetClicks() == 2 )
494 maDoubleClickHdl.Call( this );
495
496 return true;
497 }
498 }
499
500 return CustomWidgetController::MouseButtonDown( rMouseEvent );
501 }
502
MouseButtonUp(const MouseEvent & rMouseEvent)503 bool ValueSet::MouseButtonUp( const MouseEvent& rMouseEvent )
504 {
505 if (rMouseEvent.IsLeft() && !rMouseEvent.IsMod2())
506 {
507 // tdf#142150 MouseUp seen without previous MouseDown
508 if (mnSelItemId)
509 Select();
510 return true;
511 }
512
513 return CustomWidgetController::MouseButtonUp( rMouseEvent );
514 }
515
MouseMove(const MouseEvent & rMouseEvent)516 bool ValueSet::MouseMove(const MouseEvent& rMouseEvent)
517 {
518 // because of SelectionMode
519 if ((GetStyle() & WB_MENUSTYLEVALUESET) || (GetStyle() & WB_FLATVALUESET))
520 ImplTracking(rMouseEvent.GetPosPixel());
521 return CustomWidgetController::MouseMove(rMouseEvent);
522 }
523
QueueReformat()524 void ValueSet::QueueReformat()
525 {
526 queue_resize();
527 RecalcScrollBar();
528 mbFormat = true;
529 if ( IsReallyVisible() && IsUpdateMode() )
530 Invalidate();
531 }
532
RemoveItem(sal_uInt16 nItemId)533 void ValueSet::RemoveItem( sal_uInt16 nItemId )
534 {
535 size_t nPos = GetItemPos( nItemId );
536
537 if ( nPos == VALUESET_ITEM_NOTFOUND )
538 return;
539
540 if ( nPos < mItemList.size() ) {
541 mItemList.erase( mItemList.begin() + nPos );
542 }
543
544 // reset variables
545 if (mnHighItemId == nItemId || mnSelItemId == nItemId)
546 {
547 mnCurCol = 0;
548 mnHighItemId = 0;
549 mnSelItemId = 0;
550 mbNoSelection = true;
551 }
552
553 QueueReformat();
554 }
555
TurnOffScrollBar()556 bool ValueSet::TurnOffScrollBar()
557 {
558 if (mxScrolledWindow->get_vpolicy() == VclPolicyType::NEVER)
559 return false;
560 mxScrolledWindow->set_vpolicy(VclPolicyType::NEVER);
561 weld::DrawingArea* pDrawingArea = GetDrawingArea();
562 Size aPrefSize(pDrawingArea->get_preferred_size());
563 pDrawingArea->set_size_request(aPrefSize.Width() + GetScrollWidth(), aPrefSize.Height());
564 return true;
565 }
566
TurnOnScrollBar()567 void ValueSet::TurnOnScrollBar()
568 {
569 if (mxScrolledWindow->get_vpolicy() == VclPolicyType::ALWAYS)
570 return;
571 mxScrolledWindow->set_vpolicy(VclPolicyType::ALWAYS);
572 weld::DrawingArea* pDrawingArea = GetDrawingArea();
573 Size aPrefSize(pDrawingArea->get_preferred_size());
574 pDrawingArea->set_size_request(aPrefSize.Width() - GetScrollWidth(), aPrefSize.Height());
575 }
576
RecalcScrollBar()577 void ValueSet::RecalcScrollBar()
578 {
579 if (!mxScrolledWindow)
580 return;
581 const bool bScrollAllowed = GetStyle() & WB_VSCROLL;
582 if (!bScrollAllowed)
583 return;
584 // reset scrolled window state to initial value so it will get configured
585 // to the right adjustment on the next format which we toggle on to happen
586 // if the scrolledwindow wasn't in its initial state already
587 if (TurnOffScrollBar())
588 mbFormat = true;
589 }
590
Clear()591 void ValueSet::Clear()
592 {
593 ImplDeleteItems();
594
595 // reset variables
596 mnFirstLine = 0;
597 mnCurCol = 0;
598 mnHighItemId = 0;
599 mnSelItemId = 0;
600 mbNoSelection = true;
601
602 RecalcScrollBar();
603
604 mbFormat = true;
605 if ( IsReallyVisible() && IsUpdateMode() )
606 Invalidate();
607 }
608
GetItemCount() const609 size_t ValueSet::GetItemCount() const
610 {
611 return mItemList.size();
612 }
613
GetItemPos(sal_uInt16 nItemId) const614 size_t ValueSet::GetItemPos( sal_uInt16 nItemId ) const
615 {
616 for ( size_t i = 0, n = mItemList.size(); i < n; ++i ) {
617 if ( mItemList[i]->mnId == nItemId ) {
618 return i;
619 }
620 }
621 return VALUESET_ITEM_NOTFOUND;
622 }
623
GetItemId(size_t nPos) const624 sal_uInt16 ValueSet::GetItemId( size_t nPos ) const
625 {
626 return ( nPos < mItemList.size() ) ? mItemList[nPos]->mnId : 0 ;
627 }
628
GetItemId(const Point & rPos) const629 sal_uInt16 ValueSet::GetItemId( const Point& rPos ) const
630 {
631 size_t nItemPos = ImplGetItem( rPos );
632 if ( nItemPos != VALUESET_ITEM_NOTFOUND )
633 return GetItemId( nItemPos );
634
635 return 0;
636 }
637
GetItemRect(sal_uInt16 nItemId) const638 tools::Rectangle ValueSet::GetItemRect( sal_uInt16 nItemId ) const
639 {
640 const size_t nPos = GetItemPos( nItemId );
641
642 if ( nPos!=VALUESET_ITEM_NOTFOUND && mItemList[nPos]->mbVisible )
643 return ImplGetItemRect( nPos );
644
645 return tools::Rectangle();
646 }
647
ImplGetItemRect(size_t nPos) const648 tools::Rectangle ValueSet::ImplGetItemRect( size_t nPos ) const
649 {
650 const size_t nVisibleBegin = static_cast<size_t>(mnFirstLine)*mnCols;
651 const size_t nVisibleEnd = nVisibleBegin + static_cast<size_t>(mnVisLines)*mnCols;
652
653 // Check if the item is inside the range of the displayed ones,
654 // taking into account that last row could be incomplete
655 if ( nPos<nVisibleBegin || nPos>=nVisibleEnd || nPos>=mItemList.size() )
656 return tools::Rectangle();
657
658 nPos -= nVisibleBegin;
659
660 const size_t row = mnCols ? nPos/mnCols : 0;
661 const size_t col = mnCols ? nPos%mnCols : 0;
662 const tools::Long x = maItemListRect.Left()+col*(mnItemWidth+mnSpacing);
663 const tools::Long y = maItemListRect.Top()+row*(mnItemHeight+mnSpacing);
664
665 return tools::Rectangle( Point(x, y), Size(mnItemWidth, mnItemHeight) );
666 }
667
ImplHighlightItem(sal_uInt16 nItemId,bool bIsSelection)668 void ValueSet::ImplHighlightItem( sal_uInt16 nItemId, bool bIsSelection )
669 {
670 if ( mnHighItemId == nItemId )
671 return;
672
673 // remember the old item to delete the previous selection
674 mnHighItemId = nItemId;
675
676 // don't draw the selection if nothing is selected
677 if ( !bIsSelection && mbNoSelection )
678 mbDrawSelection = false;
679
680 // remove the old selection and draw the new one
681 Invalidate();
682 mbDrawSelection = true;
683 }
684
ImplDraw(vcl::RenderContext & rRenderContext)685 void ValueSet::ImplDraw(vcl::RenderContext& rRenderContext)
686 {
687 if (mbFormat)
688 Format(rRenderContext);
689
690 Point aDefPos;
691 Size aSize = maVirDev->GetOutputSizePixel();
692
693 rRenderContext.DrawOutDev(aDefPos, aSize, aDefPos, aSize, *maVirDev);
694
695 // draw parting line to the Namefield
696 if (GetStyle() & WB_NAMEFIELD)
697 {
698 if (!(GetStyle() & WB_FLATVALUESET))
699 {
700 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
701 Size aWinSize(GetOutputSizePixel());
702 Point aPos1(NAME_LINE_OFF_X, mnTextOffset + NAME_LINE_OFF_Y);
703 Point aPos2(aWinSize.Width() - (NAME_LINE_OFF_X * 2), mnTextOffset + NAME_LINE_OFF_Y);
704 if (!(rStyleSettings.GetOptions() & StyleSettingsOptions::Mono))
705 {
706 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
707 rRenderContext.DrawLine(aPos1, aPos2);
708 aPos1.AdjustY( 1 );
709 aPos2.AdjustY( 1 );
710 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
711 }
712 else
713 rRenderContext.SetLineColor(rStyleSettings.GetWindowTextColor());
714 rRenderContext.DrawLine(aPos1, aPos2);
715 }
716 }
717
718 ImplDrawSelect(rRenderContext);
719 }
720
721 /**
722 * An inelegant method; sets the item width & height such that
723 * all of the included items and their labels fit; if we can
724 * calculate that.
725 */
RecalculateItemSizes()726 void ValueSet::RecalculateItemSizes()
727 {
728 Size aLargestItem = GetLargestItemSize();
729
730 if ( mnUserItemWidth != aLargestItem.Width() ||
731 mnUserItemHeight != aLargestItem.Height() )
732 {
733 mnUserItemWidth = aLargestItem.Width();
734 mnUserItemHeight = aLargestItem.Height();
735 QueueReformat();
736 }
737 }
738
SetFirstLine(sal_uInt16 nNewFirstLine)739 void ValueSet::SetFirstLine(sal_uInt16 nNewFirstLine)
740 {
741 if (nNewFirstLine != mnFirstLine)
742 {
743 mnFirstLine = nNewFirstLine;
744 if (mxScrolledWindow)
745 mxScrolledWindow->vadjustment_set_value(mnFirstLine);
746 }
747 }
748
SelectItem(sal_uInt16 nItemId)749 void ValueSet::SelectItem( sal_uInt16 nItemId )
750 {
751 size_t nItemPos = 0;
752
753 if ( nItemId )
754 {
755 nItemPos = GetItemPos( nItemId );
756 if ( nItemPos == VALUESET_ITEM_NOTFOUND )
757 return;
758 }
759
760 if ( !((mnSelItemId != nItemId) || mbNoSelection) )
761 return;
762
763 const sal_uInt16 nOldItem = mnSelItemId;
764 mnSelItemId = nItemId;
765 mbNoSelection = false;
766
767 bool bNewOut = !mbFormat && IsReallyVisible() && IsUpdateMode();
768 bool bNewLine = false;
769
770 if (weld::DrawingArea* pNeedsFormatToScroll = !mnCols ? GetDrawingArea() : nullptr)
771 {
772 Format(pNeedsFormatToScroll->get_ref_device());
773 // reset scrollbar so its set to the later calculated mnFirstLine on
774 // the next Format
775 RecalcScrollBar(); // reset scrollbar so its set to the later calculated
776 }
777
778 // if necessary scroll to the visible area
779 if (mbScroll && nItemId && mnCols)
780 {
781 sal_uInt16 nNewLine = static_cast<sal_uInt16>(nItemPos / mnCols);
782 if ( nNewLine < mnFirstLine )
783 {
784 SetFirstLine(nNewLine);
785 bNewLine = true;
786 }
787 else if ( nNewLine > o3tl::make_unsigned(mnFirstLine+mnVisLines-1) )
788 {
789 SetFirstLine(static_cast<sal_uInt16>(nNewLine-mnVisLines+1));
790 bNewLine = true;
791 }
792 }
793
794 if ( bNewOut )
795 {
796 if ( bNewLine )
797 {
798 // redraw everything if the visible area has changed
799 mbFormat = true;
800 }
801 Invalidate();
802 }
803
804 if( !ImplHasAccessibleListeners() )
805 return;
806
807 // focus event (deselect)
808 if( nOldItem )
809 {
810 const size_t nPos = GetItemPos( nItemId );
811
812 if( nPos != VALUESET_ITEM_NOTFOUND )
813 {
814 ValueItemAcc* pItemAcc = ValueItemAcc::getImplementation(
815 mItemList[nPos]->GetAccessible( false/*bIsTransientChildrenDisabled*/ ) );
816
817 if( pItemAcc )
818 {
819 Any aOldAny;
820 Any aNewAny;
821 aOldAny <<= Reference<XInterface>(static_cast<cppu::OWeakObject*>(pItemAcc));
822 ImplFireAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny );
823 }
824 }
825 }
826
827 // focus event (select)
828 const size_t nPos = GetItemPos( mnSelItemId );
829
830 ValueSetItem* pItem;
831 if( nPos != VALUESET_ITEM_NOTFOUND )
832 pItem = mItemList[nPos].get();
833 else
834 pItem = mpNoneItem.get();
835
836 ValueItemAcc* pItemAcc = nullptr;
837 if (pItem != nullptr)
838 pItemAcc = ValueItemAcc::getImplementation( pItem->GetAccessible( false/*bIsTransientChildrenDisabled*/ ) );
839
840 if( pItemAcc )
841 {
842 Any aOldAny;
843 Any aNewAny;
844 aNewAny <<= Reference<XInterface>(static_cast<cppu::OWeakObject*>(pItemAcc));
845 ImplFireAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny);
846 }
847
848 // selection event
849 Any aOldAny;
850 Any aNewAny;
851 ImplFireAccessibleEvent(AccessibleEventId::SELECTION_CHANGED, aOldAny, aNewAny);
852 }
853
SetNoSelection()854 void ValueSet::SetNoSelection()
855 {
856 mbNoSelection = true;
857 mbHighlight = false;
858
859 if (IsReallyVisible() && IsUpdateMode())
860 Invalidate();
861 }
862
SetStyle(WinBits nStyle)863 void ValueSet::SetStyle(WinBits nStyle)
864 {
865 if (nStyle != mnStyle)
866 {
867 mnStyle = nStyle;
868 mbFormat = true;
869 Invalidate();
870 }
871 }
872
Format(vcl::RenderContext const & rRenderContext)873 void ValueSet::Format(vcl::RenderContext const & rRenderContext)
874 {
875 Size aWinSize(GetOutputSizePixel());
876 size_t nItemCount = mItemList.size();
877 WinBits nStyle = GetStyle();
878 tools::Long nTxtHeight = rRenderContext.GetTextHeight();
879 tools::Long nOff;
880 tools::Long nNoneHeight;
881 tools::Long nNoneSpace;
882
883 if (mxScrolledWindow && !(nStyle & WB_VSCROLL) && mxScrolledWindow->get_vpolicy() != VclPolicyType::NEVER)
884 TurnOffScrollBar();
885
886 // calculate item offset
887 if (nStyle & WB_ITEMBORDER)
888 {
889 if (nStyle & WB_DOUBLEBORDER)
890 nOff = ITEM_OFFSET_DOUBLE;
891 else
892 nOff = ITEM_OFFSET;
893 }
894 else
895 nOff = 0;
896
897 // consider size, if NameField does exist
898 if (nStyle & WB_NAMEFIELD)
899 {
900 mnTextOffset = aWinSize.Height() - nTxtHeight - NAME_OFFSET;
901 aWinSize.AdjustHeight( -(nTxtHeight + NAME_OFFSET) );
902
903 if (!(nStyle & WB_FLATVALUESET))
904 {
905 mnTextOffset -= NAME_LINE_HEIGHT + NAME_LINE_OFF_Y;
906 aWinSize.AdjustHeight( -(NAME_LINE_HEIGHT + NAME_LINE_OFF_Y) );
907 }
908 }
909 else
910 mnTextOffset = 0;
911
912 // consider offset and size, if NoneField does exist
913 if (nStyle & WB_NONEFIELD)
914 {
915 nNoneHeight = nTxtHeight + nOff;
916 nNoneSpace = mnSpacing;
917 }
918 else
919 {
920 nNoneHeight = 0;
921 nNoneSpace = 0;
922 mpNoneItem.reset();
923 }
924
925 // calculate number of columns
926 if (!mnUserCols)
927 {
928 if (mnUserItemWidth)
929 {
930 mnCols = static_cast<sal_uInt16>((aWinSize.Width() - mnSpacing) / (mnUserItemWidth + mnSpacing));
931 if (mnCols <= 0)
932 mnCols = 1;
933 }
934 else
935 {
936 mnCols = 1;
937 }
938 }
939 else
940 {
941 mnCols = mnUserCols;
942 }
943
944 // calculate number of rows
945 mbScroll = false;
946
947 auto nOldLines = mnLines;
948 // Floor( (M+N-1)/N )==Ceiling( M/N )
949 mnLines = (static_cast<tools::Long>(nItemCount) + mnCols - 1) / mnCols;
950 if (mnLines <= 0)
951 mnLines = 1;
952
953 bool bAdjustmentOutOfDate = nOldLines != mnLines;
954
955 auto nOldVisLines = mnVisLines;
956
957 tools::Long nCalcHeight = aWinSize.Height() - nNoneHeight;
958 if (mnUserVisLines)
959 {
960 mnVisLines = mnUserVisLines;
961 }
962 else if (mnUserItemHeight)
963 {
964 mnVisLines = (nCalcHeight - nNoneSpace + mnSpacing) / (mnUserItemHeight + mnSpacing);
965 if (!mnVisLines)
966 mnVisLines = 1;
967 }
968 else
969 {
970 mnVisLines = mnLines;
971 }
972
973 bAdjustmentOutOfDate |= nOldVisLines != mnVisLines;
974
975 if (mnLines > mnVisLines)
976 mbScroll = true;
977
978 if (mnLines <= mnVisLines)
979 {
980 SetFirstLine(0);
981 }
982 else
983 {
984 if (mnFirstLine > o3tl::make_unsigned(mnLines - mnVisLines))
985 SetFirstLine(static_cast<sal_uInt16>(mnLines - mnVisLines));
986 }
987
988 // calculate item size
989 const tools::Long nColSpace = (mnCols - 1) * static_cast<tools::Long>(mnSpacing);
990 const tools::Long nLineSpace = ((mnVisLines - 1) * mnSpacing) + nNoneSpace;
991 if (mnUserItemWidth && !mnUserCols)
992 {
993 mnItemWidth = mnUserItemWidth;
994 if (mnItemWidth > aWinSize.Width() - nColSpace)
995 mnItemWidth = aWinSize.Width() - nColSpace;
996 }
997 else
998 mnItemWidth = (aWinSize.Width() - nColSpace) / mnCols;
999 if (mnUserItemHeight && !mnUserVisLines)
1000 {
1001 mnItemHeight = mnUserItemHeight;
1002 if (mnItemHeight > nCalcHeight - nNoneSpace)
1003 mnItemHeight = nCalcHeight - nNoneSpace;
1004 }
1005 else
1006 {
1007 nCalcHeight -= nLineSpace;
1008 mnItemHeight = nCalcHeight / mnVisLines;
1009 }
1010
1011 // Init VirDev
1012 maVirDev->SetSettings(rRenderContext.GetSettings());
1013 maVirDev->SetOutputSizePixel(aWinSize);
1014
1015 // nothing is changed in case of too small items
1016 if ((mnItemWidth <= 0) ||
1017 (mnItemHeight <= ((nStyle & WB_ITEMBORDER) ? 4 : 2)) ||
1018 !nItemCount)
1019 {
1020 mbHasVisibleItems = false;
1021
1022 if ((nStyle & WB_NONEFIELD) && mpNoneItem)
1023 {
1024 mpNoneItem->mbVisible = false;
1025 mpNoneItem->maText = GetText();
1026 }
1027
1028 for (size_t i = 0; i < nItemCount; i++)
1029 {
1030 mItemList[i]->mbVisible = false;
1031 }
1032
1033 if (mxScrolledWindow && mxScrolledWindow->get_vpolicy() != VclPolicyType::NEVER)
1034 TurnOffScrollBar();
1035 }
1036 else
1037 {
1038 mbHasVisibleItems = true;
1039
1040 // determine Frame-Style
1041 if (nStyle & WB_DOUBLEBORDER)
1042 mnFrameStyle = DrawFrameStyle::DoubleIn;
1043 else
1044 mnFrameStyle = DrawFrameStyle::In;
1045
1046 // determine selected color and width
1047 // if necessary change the colors, to make the selection
1048 // better detectable
1049 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1050 Color aHighColor(rStyleSettings.GetHighlightColor());
1051 if (((aHighColor.GetRed() > 0x80) || (aHighColor.GetGreen() > 0x80) ||
1052 (aHighColor.GetBlue() > 0x80)) ||
1053 ((aHighColor.GetRed() == 0x80) && (aHighColor.GetGreen() == 0x80) &&
1054 (aHighColor.GetBlue() == 0x80)))
1055 {
1056 mbBlackSel = true;
1057 }
1058 else
1059 {
1060 mbBlackSel = false;
1061 }
1062 // draw the selection with double width if the items are bigger
1063 if ((nStyle & WB_DOUBLEBORDER) &&
1064 ((mnItemWidth >= 25) && (mnItemHeight >= 20)))
1065 {
1066 mbDoubleSel = true;
1067 }
1068 else
1069 {
1070 mbDoubleSel = false;
1071 }
1072
1073 // calculate offsets
1074 tools::Long nStartX;
1075 tools::Long nStartY;
1076 if (mbFullMode)
1077 {
1078 tools::Long nAllItemWidth = (mnItemWidth * mnCols) + nColSpace;
1079 tools::Long nAllItemHeight = (mnItemHeight * mnVisLines) + nNoneHeight + nLineSpace;
1080 nStartX = (aWinSize.Width() - nAllItemWidth) / 2;
1081 nStartY = (aWinSize.Height() - nAllItemHeight) / 2;
1082 }
1083 else
1084 {
1085 nStartX = 0;
1086 nStartY = 0;
1087 }
1088
1089 // calculate and draw items
1090 maVirDev->SetLineColor();
1091 tools::Long x = nStartX;
1092 tools::Long y = nStartY;
1093
1094 // create NoSelection field and show it
1095 if (nStyle & WB_NONEFIELD)
1096 {
1097 if (!mpNoneItem)
1098 mpNoneItem.reset(new ValueSetItem(*this));
1099
1100 mpNoneItem->mnId = 0;
1101 mpNoneItem->meType = VALUESETITEM_NONE;
1102 mpNoneItem->mbVisible = true;
1103 maNoneItemRect.SetLeft( x );
1104 maNoneItemRect.SetTop( y );
1105 maNoneItemRect.SetRight( maNoneItemRect.Left() + aWinSize.Width() - x - 1 );
1106 maNoneItemRect.SetBottom( y + nNoneHeight - 1 );
1107
1108 ImplFormatItem(rRenderContext, mpNoneItem.get(), maNoneItemRect);
1109
1110 y += nNoneHeight + nNoneSpace;
1111 }
1112
1113 // draw items
1114 sal_uLong nFirstItem = static_cast<sal_uLong>(mnFirstLine) * mnCols;
1115 sal_uLong nLastItem = nFirstItem + (mnVisLines * mnCols);
1116
1117 maItemListRect.SetLeft( x );
1118 maItemListRect.SetTop( y );
1119 maItemListRect.SetRight( x + mnCols * (mnItemWidth + mnSpacing) - mnSpacing - 1 );
1120 maItemListRect.SetBottom( y + mnVisLines * (mnItemHeight + mnSpacing) - mnSpacing - 1 );
1121
1122 if (!mbFullMode)
1123 {
1124 // If want also draw parts of items in the last line,
1125 // then we add one more line if parts of these line are
1126 // visible
1127 if (y + (mnVisLines * (mnItemHeight + mnSpacing)) < aWinSize.Height())
1128 nLastItem += mnCols;
1129 maItemListRect.SetBottom( aWinSize.Height() - y );
1130 }
1131 for (size_t i = 0; i < nItemCount; i++)
1132 {
1133 ValueSetItem* pItem = mItemList[i].get();
1134
1135 if (i >= nFirstItem && i < nLastItem)
1136 {
1137 if (!pItem->mbVisible && ImplHasAccessibleListeners())
1138 {
1139 Any aOldAny;
1140 Any aNewAny;
1141
1142 aNewAny <<= pItem->GetAccessible(false/*bIsTransientChildrenDisabled*/);
1143 ImplFireAccessibleEvent(AccessibleEventId::CHILD, aOldAny, aNewAny);
1144 }
1145
1146 pItem->mbVisible = true;
1147 ImplFormatItem(rRenderContext, pItem, tools::Rectangle(Point(x, y), Size(mnItemWidth, mnItemHeight)));
1148
1149 if (!((i + 1) % mnCols))
1150 {
1151 x = nStartX;
1152 y += mnItemHeight + mnSpacing;
1153 }
1154 else
1155 x += mnItemWidth + mnSpacing;
1156 }
1157 else
1158 {
1159 if (pItem->mbVisible && ImplHasAccessibleListeners())
1160 {
1161 Any aOldAny;
1162 Any aNewAny;
1163
1164 aOldAny <<= pItem->GetAccessible(false/*bIsTransientChildrenDisabled*/);
1165 ImplFireAccessibleEvent(AccessibleEventId::CHILD, aOldAny, aNewAny);
1166 }
1167
1168 pItem->mbVisible = false;
1169 }
1170 }
1171
1172 // arrange ScrollBar, set values and show it
1173 if (mxScrolledWindow && (nStyle & WB_VSCROLL))
1174 {
1175 bool bTurnScrollbarOn = mxScrolledWindow->get_vpolicy() != VclPolicyType::ALWAYS;
1176 if (bAdjustmentOutOfDate || bTurnScrollbarOn)
1177 {
1178 tools::Long nPageSize = mnVisLines;
1179 if (nPageSize < 1)
1180 nPageSize = 1;
1181 mxScrolledWindow->vadjustment_configure(mnFirstLine, 0, mnLines, 1,
1182 mnVisLines, nPageSize);
1183 }
1184
1185 if (bTurnScrollbarOn)
1186 TurnOnScrollBar();
1187 }
1188 }
1189
1190 // waiting for the next since the formatting is finished
1191 mbFormat = false;
1192 }
1193
ImplDrawSelect(vcl::RenderContext & rRenderContext)1194 void ValueSet::ImplDrawSelect(vcl::RenderContext& rRenderContext)
1195 {
1196 if (!IsReallyVisible())
1197 return;
1198
1199 const bool bFocus = HasFocus();
1200 const bool bDrawSel = !((mbNoSelection && !mbHighlight) || (!mbDrawSelection && mbHighlight));
1201
1202 if (!bFocus && !bDrawSel)
1203 {
1204 ImplDrawItemText(rRenderContext, OUString());
1205 return;
1206 }
1207
1208 ImplDrawSelect(rRenderContext, mnSelItemId, bFocus, bDrawSel);
1209 if (mbHighlight)
1210 {
1211 ImplDrawSelect(rRenderContext, mnHighItemId, bFocus, bDrawSel);
1212 }
1213 }
1214
ImplDrawSelect(vcl::RenderContext & rRenderContext,sal_uInt16 nItemId,const bool bFocus,const bool bDrawSel)1215 void ValueSet::ImplDrawSelect(vcl::RenderContext& rRenderContext, sal_uInt16 nItemId, const bool bFocus, const bool bDrawSel )
1216 {
1217 ValueSetItem* pItem;
1218 tools::Rectangle aRect;
1219 if (nItemId)
1220 {
1221 const size_t nPos = GetItemPos( nItemId );
1222 pItem = mItemList[ nPos ].get();
1223 aRect = ImplGetItemRect( nPos );
1224 }
1225 else if (mpNoneItem)
1226 {
1227 pItem = mpNoneItem.get();
1228 aRect = maNoneItemRect;
1229 }
1230 else if (bFocus && (pItem = ImplGetFirstItem()))
1231 {
1232 aRect = ImplGetItemRect(0);
1233 }
1234 else
1235 {
1236 return;
1237 }
1238
1239 if (!pItem->mbVisible)
1240 return;
1241
1242 // draw selection
1243 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1244 rRenderContext.SetFillColor();
1245
1246 Color aDoubleColor(rStyleSettings.GetHighlightColor());
1247 Color aSingleColor(rStyleSettings.GetHighlightTextColor());
1248 if (!mbDoubleSel)
1249 {
1250 /*
1251 * #99777# contrast enhancement for thin mode
1252 */
1253 const Wallpaper& rWall = maVirDev->GetBackground();
1254 if (!rWall.IsBitmap() && ! rWall.IsGradient())
1255 {
1256 const Color& rBack = rWall.GetColor();
1257 if (rBack.IsDark() && ! aDoubleColor.IsBright())
1258 {
1259 aDoubleColor = COL_WHITE;
1260 aSingleColor = COL_BLACK;
1261 }
1262 else if (rBack.IsBright() && !aDoubleColor.IsDark())
1263 {
1264 aDoubleColor = COL_BLACK;
1265 aSingleColor = COL_WHITE;
1266 }
1267 }
1268 }
1269
1270 // specify selection output
1271 WinBits nStyle = GetStyle();
1272 if (nStyle & WB_MENUSTYLEVALUESET)
1273 {
1274 if (bFocus)
1275 InvertFocusRect(rRenderContext, aRect);
1276 if (bDrawSel)
1277 {
1278 rRenderContext.SetLineColor(mbBlackSel ? COL_BLACK : aDoubleColor);
1279 rRenderContext.DrawRect(aRect);
1280 }
1281 }
1282 else
1283 {
1284 if (bDrawSel)
1285 {
1286 rRenderContext.SetLineColor(mbBlackSel ? COL_BLACK : aDoubleColor);
1287 rRenderContext.DrawRect(aRect);
1288 }
1289 if (mbDoubleSel)
1290 {
1291 aRect.AdjustLeft( 1 );
1292 aRect.AdjustTop( 1 );
1293 aRect.AdjustRight( -1 );
1294 aRect.AdjustBottom( -1 );
1295 if (bDrawSel)
1296 rRenderContext.DrawRect(aRect);
1297 }
1298 aRect.AdjustLeft( 1 );
1299 aRect.AdjustTop( 1 );
1300 aRect.AdjustRight( -1 );
1301 aRect.AdjustBottom( -1 );
1302 tools::Rectangle aRect2 = aRect;
1303 aRect.AdjustLeft( 1 );
1304 aRect.AdjustTop( 1 );
1305 aRect.AdjustRight( -1 );
1306 aRect.AdjustBottom( -1 );
1307 if (bDrawSel)
1308 rRenderContext.DrawRect(aRect);
1309 if (mbDoubleSel)
1310 {
1311 aRect.AdjustLeft( 1 );
1312 aRect.AdjustTop( 1 );
1313 aRect.AdjustRight( -1 );
1314 aRect.AdjustBottom( -1 );
1315 if (bDrawSel)
1316 rRenderContext.DrawRect(aRect);
1317 }
1318
1319 if (bDrawSel)
1320 {
1321 rRenderContext.SetLineColor(mbBlackSel ? COL_WHITE : aSingleColor);
1322 }
1323 else
1324 {
1325 rRenderContext.SetLineColor(COL_LIGHTGRAY);
1326 }
1327 rRenderContext.DrawRect(aRect2);
1328 if (bFocus)
1329 InvertFocusRect(rRenderContext, aRect2);
1330 }
1331
1332 ImplDrawItemText(rRenderContext, pItem->maText);
1333 }
1334
ImplFormatItem(vcl::RenderContext const & rRenderContext,ValueSetItem * pItem,tools::Rectangle aRect)1335 void ValueSet::ImplFormatItem(vcl::RenderContext const & rRenderContext, ValueSetItem* pItem, tools::Rectangle aRect)
1336 {
1337 WinBits nStyle = GetStyle();
1338 if (nStyle & WB_ITEMBORDER)
1339 {
1340 aRect.AdjustLeft(1 );
1341 aRect.AdjustTop(1 );
1342 aRect.AdjustRight( -1 );
1343 aRect.AdjustBottom( -1 );
1344
1345 if (nStyle & WB_FLATVALUESET)
1346 {
1347 sal_Int32 nBorder = (nStyle & WB_DOUBLEBORDER) ? 2 : 1;
1348
1349 aRect.AdjustLeft(nBorder );
1350 aRect.AdjustTop(nBorder );
1351 aRect.AdjustRight( -nBorder );
1352 aRect.AdjustBottom( -nBorder );
1353 }
1354 else
1355 {
1356 DecorationView aView(maVirDev.get());
1357 aRect = aView.DrawFrame(aRect, mnFrameStyle);
1358 }
1359 }
1360
1361 if (pItem == mpNoneItem.get())
1362 pItem->maText = GetText();
1363
1364 if ((aRect.GetHeight() <= 0) || (aRect.GetWidth() <= 0))
1365 return;
1366
1367 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1368
1369 if (pItem == mpNoneItem.get())
1370 {
1371 maVirDev->SetFont(rRenderContext.GetFont());
1372 maVirDev->SetTextColor((nStyle & WB_MENUSTYLEVALUESET) ? rStyleSettings.GetMenuTextColor() : rStyleSettings.GetWindowTextColor());
1373 maVirDev->SetTextFillColor();
1374 maVirDev->SetFillColor((nStyle & WB_MENUSTYLEVALUESET) ? rStyleSettings.GetMenuColor() : rStyleSettings.GetWindowColor());
1375 maVirDev->DrawRect(aRect);
1376 Point aTxtPos(aRect.Left() + 2, aRect.Top());
1377 tools::Long nTxtWidth = rRenderContext.GetTextWidth(pItem->maText);
1378 if ((aTxtPos.X() + nTxtWidth) > aRect.Right())
1379 {
1380 maVirDev->SetClipRegion(vcl::Region(aRect));
1381 maVirDev->DrawText(aTxtPos, pItem->maText);
1382 maVirDev->SetClipRegion();
1383 }
1384 else
1385 maVirDev->DrawText(aTxtPos, pItem->maText);
1386 }
1387 else if (pItem->meType == VALUESETITEM_COLOR)
1388 {
1389 maVirDev->SetFillColor(pItem->maColor);
1390 maVirDev->DrawRect(aRect);
1391 }
1392 else
1393 {
1394 if (IsColor())
1395 maVirDev->SetFillColor(maColor);
1396 else if (nStyle & WB_MENUSTYLEVALUESET)
1397 maVirDev->SetFillColor(rStyleSettings.GetMenuColor());
1398 else if (IsEnabled())
1399 maVirDev->SetFillColor(rStyleSettings.GetWindowColor());
1400 else
1401 maVirDev->SetFillColor(rStyleSettings.GetFaceColor());
1402 maVirDev->DrawRect(aRect);
1403
1404 if (pItem->meType == VALUESETITEM_USERDRAW)
1405 {
1406 UserDrawEvent aUDEvt(maVirDev.get(), aRect, pItem->mnId);
1407 UserDraw(aUDEvt);
1408 }
1409 else
1410 {
1411 Size aImageSize = pItem->maImage.GetSizePixel();
1412 Size aRectSize = aRect.GetSize();
1413 Point aPos(aRect.Left(), aRect.Top());
1414 aPos.AdjustX((aRectSize.Width() - aImageSize.Width()) / 2 );
1415
1416 if (pItem->meType != VALUESETITEM_IMAGE_AND_TEXT)
1417 aPos.AdjustY((aRectSize.Height() - aImageSize.Height()) / 2 );
1418
1419 DrawImageFlags nImageStyle = DrawImageFlags::NONE;
1420 if (!IsEnabled())
1421 nImageStyle |= DrawImageFlags::Disable;
1422
1423 if (aImageSize.Width() > aRectSize.Width() ||
1424 aImageSize.Height() > aRectSize.Height())
1425 {
1426 maVirDev->SetClipRegion(vcl::Region(aRect));
1427 maVirDev->DrawImage(aPos, pItem->maImage, nImageStyle);
1428 maVirDev->SetClipRegion();
1429 }
1430 else
1431 maVirDev->DrawImage(aPos, pItem->maImage, nImageStyle);
1432
1433 if (pItem->meType == VALUESETITEM_IMAGE_AND_TEXT)
1434 {
1435 maVirDev->SetFont(rRenderContext.GetFont());
1436 maVirDev->SetTextColor((nStyle & WB_MENUSTYLEVALUESET) ? rStyleSettings.GetMenuTextColor() : rStyleSettings.GetWindowTextColor());
1437 maVirDev->SetTextFillColor();
1438
1439 tools::Long nTxtWidth = maVirDev->GetTextWidth(pItem->maText);
1440
1441 if (nTxtWidth > aRect.GetWidth())
1442 maVirDev->SetClipRegion(vcl::Region(aRect));
1443
1444 maVirDev->DrawText(Point(aRect.Left() +
1445 (aRect.GetWidth() - nTxtWidth) / 2,
1446 aRect.Bottom() - maVirDev->GetTextHeight()),
1447 pItem->maText);
1448
1449 if (nTxtWidth > aRect.GetWidth())
1450 maVirDev->SetClipRegion();
1451 }
1452 }
1453 }
1454
1455 const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);
1456
1457 if (nEdgeBlendingPercent)
1458 {
1459 const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
1460 const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
1461 const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
1462 const BitmapEx aBlendFrame(createBlendFrame(aRect.GetSize(), nAlpha, rTopLeft, rBottomRight));
1463
1464 if (!aBlendFrame.IsEmpty())
1465 {
1466 maVirDev->DrawBitmapEx(aRect.TopLeft(), aBlendFrame);
1467 }
1468 }
1469 }
1470
ImplDrawItemText(vcl::RenderContext & rRenderContext,const OUString & rText)1471 void ValueSet::ImplDrawItemText(vcl::RenderContext& rRenderContext, const OUString& rText)
1472 {
1473 if (!(GetStyle() & WB_NAMEFIELD))
1474 return;
1475
1476 Size aWinSize(GetOutputSizePixel());
1477 tools::Long nTxtWidth = rRenderContext.GetTextWidth(rText);
1478 tools::Long nTxtOffset = mnTextOffset;
1479
1480 // delete rectangle and show text
1481 if (GetStyle() & WB_FLATVALUESET)
1482 {
1483 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1484 rRenderContext.SetLineColor();
1485 rRenderContext.SetFillColor(rStyleSettings.GetFaceColor());
1486 rRenderContext.DrawRect(tools::Rectangle(Point(0, nTxtOffset), Point(aWinSize.Width(), aWinSize.Height())));
1487 rRenderContext.SetTextColor(rStyleSettings.GetButtonTextColor());
1488 }
1489 else
1490 {
1491 nTxtOffset += NAME_LINE_HEIGHT+NAME_LINE_OFF_Y;
1492 rRenderContext.SetBackground(Application::GetSettings().GetStyleSettings().GetFaceColor());
1493 rRenderContext.Erase(tools::Rectangle(Point(0, nTxtOffset), Point(aWinSize.Width(), aWinSize.Height())));
1494 }
1495 rRenderContext.DrawText(Point((aWinSize.Width() - nTxtWidth) / 2, nTxtOffset + (NAME_OFFSET / 2)), rText);
1496 }
1497
StyleUpdated()1498 void ValueSet::StyleUpdated()
1499 {
1500 mbFormat = true;
1501 CustomWidgetController::StyleUpdated();
1502 }
1503
EnableFullItemMode(bool bFullMode)1504 void ValueSet::EnableFullItemMode( bool bFullMode )
1505 {
1506 mbFullMode = bFullMode;
1507 }
1508
SetColCount(sal_uInt16 nNewCols)1509 void ValueSet::SetColCount( sal_uInt16 nNewCols )
1510 {
1511 if ( mnUserCols != nNewCols )
1512 {
1513 mnUserCols = nNewCols;
1514 QueueReformat();
1515 }
1516 }
1517
SetItemImage(sal_uInt16 nItemId,const Image & rImage)1518 void ValueSet::SetItemImage( sal_uInt16 nItemId, const Image& rImage )
1519 {
1520 size_t nPos = GetItemPos( nItemId );
1521
1522 if ( nPos == VALUESET_ITEM_NOTFOUND )
1523 return;
1524
1525 ValueSetItem* pItem = mItemList[nPos].get();
1526 pItem->meType = VALUESETITEM_IMAGE;
1527 pItem->maImage = rImage;
1528
1529 if ( !mbFormat && IsReallyVisible() && IsUpdateMode() )
1530 {
1531 const tools::Rectangle aRect = ImplGetItemRect(nPos);
1532 Invalidate(aRect);
1533 }
1534 else
1535 mbFormat = true;
1536 }
1537
SetItemColor(sal_uInt16 nItemId,const Color & rColor)1538 void ValueSet::SetItemColor( sal_uInt16 nItemId, const Color& rColor )
1539 {
1540 size_t nPos = GetItemPos( nItemId );
1541
1542 if ( nPos == VALUESET_ITEM_NOTFOUND )
1543 return;
1544
1545 ValueSetItem* pItem = mItemList[nPos].get();
1546 pItem->meType = VALUESETITEM_COLOR;
1547 pItem->maColor = rColor;
1548
1549 if ( !mbFormat && IsReallyVisible() && IsUpdateMode() )
1550 {
1551 const tools::Rectangle aRect = ImplGetItemRect(nPos);
1552 Invalidate( aRect );
1553 }
1554 else
1555 mbFormat = true;
1556 }
1557
GetItemColor(sal_uInt16 nItemId) const1558 Color ValueSet::GetItemColor( sal_uInt16 nItemId ) const
1559 {
1560 size_t nPos = GetItemPos( nItemId );
1561
1562 if ( nPos != VALUESET_ITEM_NOTFOUND )
1563 return mItemList[nPos]->maColor;
1564 else
1565 return Color();
1566 }
1567
CalcWindowSizePixel(const Size & rItemSize,sal_uInt16 nDesireCols,sal_uInt16 nDesireLines) const1568 Size ValueSet::CalcWindowSizePixel( const Size& rItemSize, sal_uInt16 nDesireCols,
1569 sal_uInt16 nDesireLines ) const
1570 {
1571 size_t nCalcCols = nDesireCols;
1572 size_t nCalcLines = nDesireLines;
1573
1574 if ( !nCalcCols )
1575 {
1576 if ( mnUserCols )
1577 nCalcCols = mnUserCols;
1578 else
1579 nCalcCols = 1;
1580 }
1581
1582 if ( !nCalcLines )
1583 {
1584 nCalcLines = mnVisLines;
1585
1586 if ( mbFormat )
1587 {
1588 if ( mnUserVisLines )
1589 nCalcLines = mnUserVisLines;
1590 else
1591 {
1592 // Floor( (M+N-1)/N )==Ceiling( M/N )
1593 nCalcLines = (mItemList.size()+nCalcCols-1) / nCalcCols;
1594 if ( !nCalcLines )
1595 nCalcLines = 1;
1596 }
1597 }
1598 }
1599
1600 Size aSize( rItemSize.Width() * nCalcCols, rItemSize.Height() * nCalcLines );
1601 WinBits nStyle = GetStyle();
1602 tools::Long nTxtHeight = GetTextHeight();
1603 tools::Long n;
1604
1605 if ( nStyle & WB_ITEMBORDER )
1606 {
1607 if ( nStyle & WB_DOUBLEBORDER )
1608 n = ITEM_OFFSET_DOUBLE;
1609 else
1610 n = ITEM_OFFSET;
1611
1612 aSize.AdjustWidth(n * nCalcCols );
1613 aSize.AdjustHeight(n * nCalcLines );
1614 }
1615 else
1616 n = 0;
1617
1618 if ( mnSpacing )
1619 {
1620 aSize.AdjustWidth(mnSpacing * (nCalcCols - 1) );
1621 aSize.AdjustHeight(mnSpacing * (nCalcLines - 1) );
1622 }
1623
1624 if ( nStyle & WB_NAMEFIELD )
1625 {
1626 aSize.AdjustHeight(nTxtHeight + NAME_OFFSET );
1627 if ( !(nStyle & WB_FLATVALUESET) )
1628 aSize.AdjustHeight(NAME_LINE_HEIGHT + NAME_LINE_OFF_Y );
1629 }
1630
1631 if ( nStyle & WB_NONEFIELD )
1632 {
1633 aSize.AdjustHeight(nTxtHeight + n + mnSpacing );
1634 }
1635
1636 return aSize;
1637 }
1638
InsertItem(sal_uInt16 nItemId,const Image & rImage)1639 void ValueSet::InsertItem( sal_uInt16 nItemId, const Image& rImage )
1640 {
1641 std::unique_ptr<ValueSetItem> pItem(new ValueSetItem( *this ));
1642 pItem->mnId = nItemId;
1643 pItem->meType = VALUESETITEM_IMAGE;
1644 pItem->maImage = rImage;
1645 ImplInsertItem( std::move(pItem), VALUESET_APPEND );
1646 }
1647
InsertItem(sal_uInt16 nItemId,const Image & rImage,const OUString & rText,size_t nPos,bool bShowLegend)1648 void ValueSet::InsertItem( sal_uInt16 nItemId, const Image& rImage,
1649 const OUString& rText, size_t nPos,
1650 bool bShowLegend )
1651 {
1652 std::unique_ptr<ValueSetItem> pItem(new ValueSetItem( *this ));
1653 pItem->mnId = nItemId;
1654 pItem->meType = bShowLegend ? VALUESETITEM_IMAGE_AND_TEXT : VALUESETITEM_IMAGE;
1655 pItem->maImage = rImage;
1656 pItem->maText = rText;
1657 ImplInsertItem( std::move(pItem), nPos );
1658 }
1659
InsertItem(sal_uInt16 nItemId,size_t nPos)1660 void ValueSet::InsertItem( sal_uInt16 nItemId, size_t nPos )
1661 {
1662 std::unique_ptr<ValueSetItem> pItem(new ValueSetItem( *this ));
1663 pItem->mnId = nItemId;
1664 pItem->meType = VALUESETITEM_USERDRAW;
1665 ImplInsertItem( std::move(pItem), nPos );
1666 }
1667
InsertItem(sal_uInt16 nItemId,const Color & rColor,const OUString & rText)1668 void ValueSet::InsertItem( sal_uInt16 nItemId, const Color& rColor,
1669 const OUString& rText )
1670 {
1671 std::unique_ptr<ValueSetItem> pItem(new ValueSetItem( *this ));
1672 pItem->mnId = nItemId;
1673 pItem->meType = VALUESETITEM_COLOR;
1674 pItem->maColor = rColor;
1675 pItem->maText = rText;
1676 ImplInsertItem( std::move(pItem), VALUESET_APPEND );
1677 }
1678
ImplInsertItem(std::unique_ptr<ValueSetItem> pItem,const size_t nPos)1679 void ValueSet::ImplInsertItem( std::unique_ptr<ValueSetItem> pItem, const size_t nPos )
1680 {
1681 DBG_ASSERT( pItem->mnId, "ValueSet::InsertItem(): ItemId == 0" );
1682 DBG_ASSERT( GetItemPos( pItem->mnId ) == VALUESET_ITEM_NOTFOUND,
1683 "ValueSet::InsertItem(): ItemId already exists" );
1684
1685 if ( nPos < mItemList.size() ) {
1686 mItemList.insert( mItemList.begin() + nPos, std::move(pItem) );
1687 } else {
1688 mItemList.push_back( std::move(pItem) );
1689 }
1690
1691 QueueReformat();
1692 }
1693
GetScrollWidth() const1694 int ValueSet::GetScrollWidth() const
1695 {
1696 if (mxScrolledWindow)
1697 return mxScrolledWindow->get_scroll_thickness();
1698 return 0;
1699 }
1700
SetEdgeBlending(bool bNew)1701 void ValueSet::SetEdgeBlending(bool bNew)
1702 {
1703 if(mbEdgeBlending != bNew)
1704 {
1705 mbEdgeBlending = bNew;
1706 mbFormat = true;
1707
1708 if (GetDrawingArea() && IsReallyVisible() && IsUpdateMode())
1709 {
1710 Invalidate();
1711 }
1712 }
1713 }
1714
CalcItemSizePixel(const Size & rItemSize) const1715 Size ValueSet::CalcItemSizePixel( const Size& rItemSize) const
1716 {
1717 Size aSize = rItemSize;
1718
1719 WinBits nStyle = GetStyle();
1720 if ( nStyle & WB_ITEMBORDER )
1721 {
1722 tools::Long n;
1723
1724 if ( nStyle & WB_DOUBLEBORDER )
1725 n = ITEM_OFFSET_DOUBLE;
1726 else
1727 n = ITEM_OFFSET;
1728
1729 aSize.AdjustWidth(n );
1730 aSize.AdjustHeight(n );
1731 }
1732
1733 return aSize;
1734 }
1735
SetLineCount(sal_uInt16 nNewLines)1736 void ValueSet::SetLineCount( sal_uInt16 nNewLines )
1737 {
1738 if ( mnUserVisLines != nNewLines )
1739 {
1740 mnUserVisLines = nNewLines;
1741 QueueReformat();
1742 }
1743 }
1744
SetItemWidth(tools::Long nNewItemWidth)1745 void ValueSet::SetItemWidth( tools::Long nNewItemWidth )
1746 {
1747 if ( mnUserItemWidth != nNewItemWidth )
1748 {
1749 mnUserItemWidth = nNewItemWidth;
1750 QueueReformat();
1751 }
1752 }
1753
1754 //method to set accessible when the style is user draw.
InsertItem(sal_uInt16 nItemId,const OUString & rText,size_t nPos)1755 void ValueSet::InsertItem( sal_uInt16 nItemId, const OUString& rText, size_t nPos )
1756 {
1757 DBG_ASSERT( nItemId, "ValueSet::InsertItem(): ItemId == 0" );
1758 DBG_ASSERT( GetItemPos( nItemId ) == VALUESET_ITEM_NOTFOUND,
1759 "ValueSet::InsertItem(): ItemId already exists" );
1760 std::unique_ptr<ValueSetItem> pItem(new ValueSetItem( *this ));
1761 pItem->mnId = nItemId;
1762 pItem->meType = VALUESETITEM_USERDRAW;
1763 pItem->maText = rText;
1764 ImplInsertItem( std::move(pItem), nPos );
1765 }
1766
SetItemHeight(tools::Long nNewItemHeight)1767 void ValueSet::SetItemHeight( tools::Long nNewItemHeight )
1768 {
1769 if ( mnUserItemHeight != nNewItemHeight )
1770 {
1771 mnUserItemHeight = nNewItemHeight;
1772 QueueReformat();
1773 }
1774 }
1775
RequestHelp(tools::Rectangle & rHelpRect)1776 OUString ValueSet::RequestHelp(tools::Rectangle& rHelpRect)
1777 {
1778 Point aPos = rHelpRect.TopLeft();
1779 const size_t nItemPos = ImplGetItem( aPos );
1780 OUString sRet;
1781 if (nItemPos != VALUESET_ITEM_NOTFOUND)
1782 {
1783 rHelpRect = ImplGetItemRect(nItemPos);
1784 sRet = GetItemText(ImplGetItem(nItemPos)->mnId);
1785 }
1786 return sRet;
1787 }
1788
GetItemText(sal_uInt16 nItemId) const1789 OUString ValueSet::GetItemText(sal_uInt16 nItemId) const
1790 {
1791 const size_t nPos = GetItemPos(nItemId);
1792
1793 if ( nPos != VALUESET_ITEM_NOTFOUND )
1794 return mItemList[nPos]->maText;
1795
1796 return OUString();
1797 }
1798
SetExtraSpacing(sal_uInt16 nNewSpacing)1799 void ValueSet::SetExtraSpacing( sal_uInt16 nNewSpacing )
1800 {
1801 if ( GetStyle() & WB_ITEMBORDER )
1802 {
1803 mnSpacing = nNewSpacing;
1804 QueueReformat();
1805 }
1806 }
1807
SetFormat()1808 void ValueSet::SetFormat()
1809 {
1810 mbFormat = true;
1811 }
1812
SetItemData(sal_uInt16 nItemId,void * pData)1813 void ValueSet::SetItemData( sal_uInt16 nItemId, void* pData )
1814 {
1815 size_t nPos = GetItemPos( nItemId );
1816
1817 if ( nPos == VALUESET_ITEM_NOTFOUND )
1818 return;
1819
1820 ValueSetItem* pItem = mItemList[nPos].get();
1821 pItem->mpData = pData;
1822
1823 if ( pItem->meType == VALUESETITEM_USERDRAW )
1824 {
1825 if ( !mbFormat && IsReallyVisible() && IsUpdateMode() )
1826 {
1827 const tools::Rectangle aRect = ImplGetItemRect(nPos);
1828 Invalidate(aRect);
1829 }
1830 else
1831 mbFormat = true;
1832 }
1833 }
1834
GetItemData(sal_uInt16 nItemId) const1835 void* ValueSet::GetItemData( sal_uInt16 nItemId ) const
1836 {
1837 size_t nPos = GetItemPos( nItemId );
1838
1839 if ( nPos != VALUESET_ITEM_NOTFOUND )
1840 return mItemList[nPos]->mpData;
1841 else
1842 return nullptr;
1843 }
1844
SetItemText(sal_uInt16 nItemId,const OUString & rText)1845 void ValueSet::SetItemText(sal_uInt16 nItemId, const OUString& rText)
1846 {
1847 size_t nPos = GetItemPos( nItemId );
1848
1849 if ( nPos == VALUESET_ITEM_NOTFOUND )
1850 return;
1851
1852 ValueSetItem* pItem = mItemList[nPos].get();
1853
1854 // Remember old and new name for accessibility event.
1855 Any aOldName;
1856 Any aNewName;
1857 OUString sString (pItem->maText);
1858 aOldName <<= sString;
1859 sString = rText;
1860 aNewName <<= sString;
1861
1862 pItem->maText = rText;
1863
1864 if (!mbFormat && IsReallyVisible() && IsUpdateMode())
1865 {
1866 sal_uInt16 nTempId = mnSelItemId;
1867
1868 if (mbHighlight)
1869 nTempId = mnHighItemId;
1870
1871 if (nTempId == nItemId)
1872 Invalidate();
1873 }
1874
1875 if (ImplHasAccessibleListeners())
1876 {
1877 Reference<XAccessible> xAccessible(pItem->GetAccessible( false/*bIsTransientChildrenDisabled*/));
1878 ValueItemAcc* pValueItemAcc = static_cast<ValueItemAcc*>(xAccessible.get());
1879 pValueItemAcc->FireAccessibleEvent(AccessibleEventId::NAME_CHANGED, aOldName, aNewName);
1880 }
1881 }
1882
GetLargestItemSize()1883 Size ValueSet::GetLargestItemSize()
1884 {
1885 Size aLargestItem;
1886
1887 for (const std::unique_ptr<ValueSetItem>& pItem : mItemList)
1888 {
1889 if (!pItem->mbVisible)
1890 continue;
1891
1892 if (pItem->meType != VALUESETITEM_IMAGE &&
1893 pItem->meType != VALUESETITEM_IMAGE_AND_TEXT)
1894 {
1895 // handle determining an optimal size for this case
1896 continue;
1897 }
1898
1899 Size aSize = pItem->maImage.GetSizePixel();
1900 if (pItem->meType == VALUESETITEM_IMAGE_AND_TEXT)
1901 {
1902 aSize.AdjustHeight(3 * NAME_LINE_HEIGHT +
1903 maVirDev->GetTextHeight() );
1904 aSize.setWidth( std::max(aSize.Width(),
1905 maVirDev->GetTextWidth(pItem->maText) + NAME_OFFSET) );
1906 }
1907
1908 aLargestItem.setWidth( std::max(aLargestItem.Width(), aSize.Width()) );
1909 aLargestItem.setHeight( std::max(aLargestItem.Height(), aSize.Height()) );
1910 }
1911
1912 return aLargestItem;
1913 }
1914
SetOptimalSize()1915 void ValueSet::SetOptimalSize()
1916 {
1917 Size aLargestSize(GetLargestItemSize());
1918 aLargestSize.setWidth(std::max(aLargestSize.Width(), mnUserItemWidth));
1919 aLargestSize.setHeight(std::max(aLargestSize.Height(), mnUserItemHeight));
1920 Size aPrefSize(CalcWindowSizePixel(aLargestSize));
1921 GetDrawingArea()->set_size_request(aPrefSize.Width(), aPrefSize.Height());
1922 }
1923
GetItemImage(sal_uInt16 nItemId) const1924 Image ValueSet::GetItemImage(sal_uInt16 nItemId) const
1925 {
1926 size_t nPos = GetItemPos( nItemId );
1927
1928 if ( nPos != VALUESET_ITEM_NOTFOUND )
1929 return mItemList[nPos]->maImage;
1930 else
1931 return Image();
1932 }
1933
SetColor(const Color & rColor)1934 void ValueSet::SetColor(const Color& rColor)
1935 {
1936 maColor = rColor;
1937 mbFormat = true;
1938 if (IsReallyVisible() && IsUpdateMode())
1939 Invalidate();
1940 }
1941
Show()1942 void ValueSet::Show()
1943 {
1944 if (mxScrolledWindow)
1945 mxScrolledWindow->show();
1946 CustomWidgetController::Show();
1947 }
1948
Hide()1949 void ValueSet::Hide()
1950 {
1951 CustomWidgetController::Hide();
1952 if (mxScrolledWindow)
1953 mxScrolledWindow->hide();
1954 }
1955
GetUITestFactory() const1956 FactoryFunction ValueSet::GetUITestFactory() const
1957 {
1958 return ValueSetUIObject::create;
1959 }
1960
1961 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1962