1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <com/sun/star/accessibility/AccessibleRole.hpp>
11 #include <o3tl/enumarray.hxx>
12 #include <o3tl/enumrange.hxx>
13 #include <vcl/decoview.hxx>
14 #include <vcl/dialog.hxx>
15 #include <vcl/layout.hxx>
16 #include <vcl/stdtext.hxx>
17 #include <vcl/svapp.hxx>
18 #include <vcl/settings.hxx>
19 #include <messagedialog.hxx>
21 #include <boost/multi_array.hpp>
22 #include <boost/property_tree/ptree.hpp>
23 #include <vcl/vclmedit.hxx>
24 #include <sal/log.hxx>
26 VclContainer::VclContainer(vcl::Window
*pParent
, WinBits nStyle
)
27 : Window(WindowType::CONTAINER
)
28 , m_bLayoutDirty(true)
30 ImplInit(pParent
, nStyle
, nullptr);
31 EnableChildTransparentMode();
32 SetPaintTransparent(true);
36 sal_uInt16
VclContainer::getDefaultAccessibleRole() const
38 return css::accessibility::AccessibleRole::PANEL
;
41 Size
VclContainer::GetOptimalSize() const
43 return calculateRequisition();
46 void VclContainer::setLayoutPosSize(vcl::Window
&rWindow
, const Point
&rPos
, const Size
&rSize
)
48 sal_Int32 nBorderWidth
= rWindow
.get_border_width();
49 sal_Int32 nLeft
= rWindow
.get_margin_left() + nBorderWidth
;
50 sal_Int32 nTop
= rWindow
.get_margin_top() + nBorderWidth
;
51 sal_Int32 nRight
= rWindow
.get_margin_right() + nBorderWidth
;
52 sal_Int32 nBottom
= rWindow
.get_margin_bottom() + nBorderWidth
;
53 Point
aPos(rPos
.X() + nLeft
, rPos
.Y() + nTop
);
54 Size
aSize(rSize
.Width() - nLeft
- nRight
, rSize
.Height() - nTop
- nBottom
);
55 rWindow
.SetPosSizePixel(aPos
, aSize
);
58 void VclContainer::setLayoutAllocation(vcl::Window
&rChild
, const Point
&rAllocPos
, const Size
&rChildAlloc
)
60 VclAlign eHalign
= rChild
.get_halign();
61 VclAlign eValign
= rChild
.get_valign();
64 if (eHalign
== VclAlign::Fill
&& eValign
== VclAlign::Fill
)
66 setLayoutPosSize(rChild
, rAllocPos
, rChildAlloc
);
70 Point
aChildPos(rAllocPos
);
71 Size
aChildSize(rChildAlloc
);
72 Size
aChildPreferredSize(getLayoutRequisition(rChild
));
79 if (aChildPreferredSize
.Width() < rChildAlloc
.Width())
80 aChildSize
.setWidth( aChildPreferredSize
.Width() );
83 if (aChildPreferredSize
.Width() < rChildAlloc
.Width())
84 aChildSize
.setWidth( aChildPreferredSize
.Width() );
85 aChildPos
.AdjustX(rChildAlloc
.Width() );
86 aChildPos
.AdjustX( -(aChildSize
.Width()) );
88 case VclAlign::Center
:
89 if (aChildPreferredSize
.Width() < aChildSize
.Width())
90 aChildSize
.setWidth( aChildPreferredSize
.Width() );
91 aChildPos
.AdjustX((rChildAlloc
.Width() - aChildSize
.Width()) / 2 );
100 if (aChildPreferredSize
.Height() < rChildAlloc
.Height())
101 aChildSize
.setHeight( aChildPreferredSize
.Height() );
104 if (aChildPreferredSize
.Height() < rChildAlloc
.Height())
105 aChildSize
.setHeight( aChildPreferredSize
.Height() );
106 aChildPos
.AdjustY(rChildAlloc
.Height() );
107 aChildPos
.AdjustY( -(aChildSize
.Height()) );
109 case VclAlign::Center
:
110 if (aChildPreferredSize
.Height() < aChildSize
.Height())
111 aChildSize
.setHeight( aChildPreferredSize
.Height() );
112 aChildPos
.AdjustY((rChildAlloc
.Height() - aChildSize
.Height()) / 2 );
116 setLayoutPosSize(rChild
, aChildPos
, aChildSize
);
121 Size
subtractBorder(const vcl::Window
&rWindow
, const Size
& rSize
)
123 sal_Int32 nBorderWidth
= rWindow
.get_border_width();
124 sal_Int32 nLeft
= rWindow
.get_margin_left() + nBorderWidth
;
125 sal_Int32 nTop
= rWindow
.get_margin_top() + nBorderWidth
;
126 sal_Int32 nRight
= rWindow
.get_margin_right() + nBorderWidth
;
127 sal_Int32 nBottom
= rWindow
.get_margin_bottom() + nBorderWidth
;
129 return Size(aSize
.Width() + nLeft
+ nRight
, aSize
.Height() + nTop
+ nBottom
);
133 Size
VclContainer::getLayoutRequisition(const vcl::Window
&rWindow
)
135 return subtractBorder(rWindow
, rWindow
.get_preferred_size());
138 void VclContainer::SetPosSizePixel(const Point
& rAllocPos
, const Size
& rAllocation
)
140 bool bSizeChanged
= rAllocation
!= GetOutputSizePixel();
141 Window::SetPosSizePixel(rAllocPos
, rAllocation
);
142 if (m_bLayoutDirty
|| bSizeChanged
)
144 m_bLayoutDirty
= false;
145 setAllocation(rAllocation
);
149 void VclContainer::SetPosPixel(const Point
& rAllocPos
)
151 Point aAllocPos
= rAllocPos
;
152 sal_Int32 nBorderWidth
= get_border_width();
153 aAllocPos
.AdjustX(nBorderWidth
+ get_margin_left() );
154 aAllocPos
.AdjustY(nBorderWidth
+ get_margin_top() );
156 if (aAllocPos
!= GetPosPixel())
157 Window::SetPosPixel(aAllocPos
);
160 void VclContainer::SetSizePixel(const Size
& rAllocation
)
162 Size aAllocation
= rAllocation
;
163 sal_Int32 nBorderWidth
= get_border_width();
164 aAllocation
.AdjustWidth( -(nBorderWidth
*2 + get_margin_left() + get_margin_right()) );
165 aAllocation
.AdjustHeight( -(nBorderWidth
*2 + get_margin_top() + get_margin_bottom()) );
166 bool bSizeChanged
= aAllocation
!= GetSizePixel();
168 Window::SetSizePixel(aAllocation
);
169 if (m_bLayoutDirty
|| bSizeChanged
)
171 m_bLayoutDirty
= false;
172 setAllocation(aAllocation
);
176 void VclContainer::queue_resize(StateChangedType eReason
)
178 m_bLayoutDirty
= true;
179 Window::queue_resize(eReason
);
182 // support for screenshot context menu
183 void VclContainer::Command(const CommandEvent
& rCEvt
)
185 if (CommandEventId::ContextMenu
== rCEvt
.GetCommand())
187 auto pParent
= GetParent();
190 CommandEvent
aCEvt(rCEvt
.GetMousePosPixel() + GetPosPixel(), rCEvt
.GetCommand(), rCEvt
.IsMouseEvent(), rCEvt
.GetEventData());
191 pParent
->Command(aCEvt
);
196 // call parent (do not consume)
197 Window::Command(rCEvt
);
200 void VclBox::accumulateMaxes(const Size
&rChildSize
, Size
&rSize
) const
202 long nSecondaryChildDimension
= getSecondaryDimension(rChildSize
);
203 long nSecondaryBoxDimension
= getSecondaryDimension(rSize
);
204 setSecondaryDimension(rSize
, std::max(nSecondaryChildDimension
, nSecondaryBoxDimension
));
206 long nPrimaryChildDimension
= getPrimaryDimension(rChildSize
);
207 long nPrimaryBoxDimension
= getPrimaryDimension(rSize
);
209 setPrimaryDimension(rSize
, std::max(nPrimaryBoxDimension
, nPrimaryChildDimension
));
211 setPrimaryDimension(rSize
, nPrimaryBoxDimension
+ nPrimaryChildDimension
);
214 Size
VclBox::calculateRequisition() const
216 sal_uInt16 nVisibleChildren
= 0;
219 for (vcl::Window
*pChild
= GetWindow(GetWindowType::FirstChild
); pChild
; pChild
= pChild
->GetWindow(GetWindowType::Next
))
221 if (!pChild
->IsVisible())
224 Size aChildSize
= getLayoutRequisition(*pChild
);
226 long nPrimaryDimension
= getPrimaryDimension(aChildSize
);
227 nPrimaryDimension
+= pChild
->get_padding() * 2;
228 setPrimaryDimension(aChildSize
, nPrimaryDimension
);
230 accumulateMaxes(aChildSize
, aSize
);
233 return finalizeMaxes(aSize
, nVisibleChildren
);
236 void VclBox::setAllocation(const Size
&rAllocation
)
238 sal_uInt16 nVisibleChildren
= 0, nExpandChildren
= 0;
239 for (vcl::Window
*pChild
= GetWindow(GetWindowType::FirstChild
); pChild
; pChild
= pChild
->GetWindow(GetWindowType::Next
))
241 if (!pChild
->IsVisible())
244 bool bExpand
= getPrimaryDimensionChildExpand(*pChild
);
249 if (!nVisibleChildren
)
252 long nAllocPrimaryDimension
= getPrimaryDimension(rAllocation
);
254 long nHomogeneousDimension
= 0, nExtraSpace
= 0;
257 nHomogeneousDimension
= (nAllocPrimaryDimension
-
258 (nVisibleChildren
- 1) * m_nSpacing
) / nVisibleChildren
;
260 else if (nExpandChildren
)
262 Size aRequisition
= calculateRequisition();
263 nExtraSpace
= (getPrimaryDimension(rAllocation
) - getPrimaryDimension(aRequisition
)) / nExpandChildren
;
266 //Split into those we pack from the start onwards, and those we pack from the end backwards
267 o3tl::enumarray
<VclPackType
,std::vector
<vcl::Window
*>> aWindows
;
268 for (vcl::Window
*pChild
= GetWindow(GetWindowType::FirstChild
); pChild
; pChild
= pChild
->GetWindow(GetWindowType::Next
))
270 if (!pChild
->IsVisible())
273 VclPackType ePacking
= pChild
->get_pack_type();
274 aWindows
[ePacking
].push_back(pChild
);
277 //See VclBuilder::sortIntoBestTabTraversalOrder for why they are in visual
278 //order under the parent which requires us to reverse them here to
279 //pack from the end back
280 std::reverse(aWindows
[VclPackType::End
].begin(),aWindows
[VclPackType::End
].end());
282 for (VclPackType ePackType
: o3tl::enumrange
<VclPackType
>())
285 if (ePackType
== VclPackType::End
)
287 long nPrimaryCoordinate
= getPrimaryCoordinate(aPos
);
288 setPrimaryCoordinate(aPos
, nPrimaryCoordinate
+ nAllocPrimaryDimension
);
291 for (auto const& window
: aWindows
[ePackType
])
293 vcl::Window
*pChild
= window
;
295 long nPadding
= pChild
->get_padding();
299 setPrimaryDimension(aBoxSize
, nHomogeneousDimension
);
302 aBoxSize
= getLayoutRequisition(*pChild
);
303 long nPrimaryDimension
= getPrimaryDimension(aBoxSize
);
304 nPrimaryDimension
+= nPadding
* 2;
305 if (getPrimaryDimensionChildExpand(*pChild
))
306 nPrimaryDimension
+= nExtraSpace
;
307 setPrimaryDimension(aBoxSize
, nPrimaryDimension
);
309 setSecondaryDimension(aBoxSize
, getSecondaryDimension(rAllocation
));
311 Point
aChildPos(aPos
);
312 Size
aChildSize(aBoxSize
);
313 long nPrimaryCoordinate
= getPrimaryCoordinate(aPos
);
315 bool bFill
= pChild
->get_fill();
318 setPrimaryDimension(aChildSize
, std::max(static_cast<long>(1),
319 getPrimaryDimension(aBoxSize
) - nPadding
* 2));
321 setPrimaryCoordinate(aChildPos
, nPrimaryCoordinate
+ nPadding
);
325 setPrimaryDimension(aChildSize
,
326 getPrimaryDimension(getLayoutRequisition(*pChild
)));
328 setPrimaryCoordinate(aChildPos
, nPrimaryCoordinate
+
329 (getPrimaryDimension(aBoxSize
) - getPrimaryDimension(aChildSize
)) / 2);
332 long nDiff
= getPrimaryDimension(aBoxSize
) + m_nSpacing
;
333 if (ePackType
== VclPackType::Start
)
334 setPrimaryCoordinate(aPos
, nPrimaryCoordinate
+ nDiff
);
337 setPrimaryCoordinate(aPos
, nPrimaryCoordinate
- nDiff
);
338 setPrimaryCoordinate(aChildPos
, getPrimaryCoordinate(aChildPos
) -
339 getPrimaryDimension(aBoxSize
));
342 setLayoutAllocation(*pChild
, aChildPos
, aChildSize
);
347 bool VclBox::set_property(const OString
&rKey
, const OUString
&rValue
)
349 if (rKey
== "spacing")
350 set_spacing(rValue
.toInt32());
351 else if (rKey
== "homogeneous")
352 set_homogeneous(toBool(rValue
));
354 return VclContainer::set_property(rKey
, rValue
);
358 boost::property_tree::ptree
VclBox::DumpAsPropertyTree()
360 boost::property_tree::ptree
aTree(VclContainer::DumpAsPropertyTree());
361 aTree
.put("vertical", m_bVerticalContainer
);
365 sal_uInt16
VclBox::getDefaultAccessibleRole() const
368 //fdo#74284 call Boxes Panels, keep then as "Filler" under
369 //at least Linux seeing as that's what Gtk does for GtkBoxes
370 return css::accessibility::AccessibleRole::PANEL
;
372 return css::accessibility::AccessibleRole::FILLER
;
376 #define DEFAULT_CHILD_MIN_WIDTH 85
377 #define DEFAULT_CHILD_MIN_HEIGHT 27
379 Size
VclBox::finalizeMaxes(const Size
&rSize
, sal_uInt16 nVisibleChildren
) const
383 if (nVisibleChildren
)
385 long nPrimaryDimension
= getPrimaryDimension(rSize
);
387 nPrimaryDimension
*= nVisibleChildren
;
388 setPrimaryDimension(aRet
, nPrimaryDimension
+ m_nSpacing
* (nVisibleChildren
-1));
389 setSecondaryDimension(aRet
, getSecondaryDimension(rSize
));
395 Size
VclButtonBox::addReqGroups(const VclButtonBox::Requisition
&rReq
) const
399 long nMainGroupDimension
= getPrimaryDimension(rReq
.m_aMainGroupSize
);
400 long nSubGroupDimension
= getPrimaryDimension(rReq
.m_aSubGroupSize
);
402 setPrimaryDimension(aRet
, nMainGroupDimension
+ nSubGroupDimension
);
404 setSecondaryDimension(aRet
,
405 std::max(getSecondaryDimension(rReq
.m_aMainGroupSize
),
406 getSecondaryDimension(rReq
.m_aSubGroupSize
)));
411 static long getMaxNonOutlier(const std::vector
<long> &rG
, long nAvgDimension
)
413 long nMaxDimensionNonOutlier
= 0;
414 for (auto const& nPrimaryChildDimension
: rG
)
416 if (nPrimaryChildDimension
< nAvgDimension
* 1.5)
418 nMaxDimensionNonOutlier
= std::max(nPrimaryChildDimension
,
419 nMaxDimensionNonOutlier
);
422 return nMaxDimensionNonOutlier
;
425 static std::vector
<long> setButtonSizes(const std::vector
<long> &rG
,
426 const std::vector
<bool> &rNonHomogeneous
,
427 long nAvgDimension
, long nMaxNonOutlier
, long nMinWidth
)
429 std::vector
<long> aVec
;
430 //set everything < 1.5 times the average to the same width, leave the
431 //outliers un-touched
432 std::vector
<bool>::const_iterator aJ
= rNonHomogeneous
.begin();
433 auto nNonOutlierWidth
= std::max(nMaxNonOutlier
, nMinWidth
);
434 for (auto const& nPrimaryChildDimension
: rG
)
436 bool bNonHomogeneous
= *aJ
;
437 if (!bNonHomogeneous
&& nPrimaryChildDimension
< nAvgDimension
* 1.5)
439 aVec
.push_back(nNonOutlierWidth
);
443 aVec
.push_back(std::max(nPrimaryChildDimension
, nMinWidth
));
450 VclButtonBox::Requisition
VclButtonBox::calculatePrimarySecondaryRequisitions() const
454 Size
aMainGroupSize(DEFAULT_CHILD_MIN_WIDTH
, DEFAULT_CHILD_MIN_HEIGHT
); //to-do, pull from theme
455 Size
aSubGroupSize(DEFAULT_CHILD_MIN_WIDTH
, DEFAULT_CHILD_MIN_HEIGHT
); //to-do, pull from theme
457 long nMinMainGroupPrimary
= getPrimaryDimension(aMainGroupSize
);
458 long nMinSubGroupPrimary
= getPrimaryDimension(aSubGroupSize
);
459 long nMainGroupSecondary
= getSecondaryDimension(aMainGroupSize
);
460 long nSubGroupSecondary
= getSecondaryDimension(aSubGroupSize
);
462 bool bIgnoreSecondaryPacking
= (m_eLayoutStyle
== VclButtonBoxStyle::Spread
|| m_eLayoutStyle
== VclButtonBoxStyle::Center
);
464 std::vector
<long> aMainGroupSizes
;
465 std::vector
<bool> aMainGroupNonHomogeneous
;
466 std::vector
<long> aSubGroupSizes
;
467 std::vector
<bool> aSubGroupNonHomogeneous
;
469 for (const vcl::Window
*pChild
= GetWindow(GetWindowType::FirstChild
); pChild
; pChild
= pChild
->GetWindow(GetWindowType::Next
))
471 if (!pChild
->IsVisible())
473 Size aChildSize
= getLayoutRequisition(*pChild
);
474 if (bIgnoreSecondaryPacking
|| !pChild
->get_secondary())
476 //set the max secondary dimension
477 nMainGroupSecondary
= std::max(nMainGroupSecondary
, getSecondaryDimension(aChildSize
));
478 //collect the primary dimensions
479 aMainGroupSizes
.push_back(getPrimaryDimension(aChildSize
));
480 aMainGroupNonHomogeneous
.push_back(pChild
->get_non_homogeneous());
484 nSubGroupSecondary
= std::max(nSubGroupSecondary
, getSecondaryDimension(aChildSize
));
485 aSubGroupSizes
.push_back(getPrimaryDimension(aChildSize
));
486 aSubGroupNonHomogeneous
.push_back(pChild
->get_non_homogeneous());
492 long nMaxMainDimension
= aMainGroupSizes
.empty() ? 0 :
493 *std::max_element(aMainGroupSizes
.begin(), aMainGroupSizes
.end());
494 nMaxMainDimension
= std::max(nMaxMainDimension
, nMinMainGroupPrimary
);
495 long nMaxSubDimension
= aSubGroupSizes
.empty() ? 0 :
496 *std::max_element(aSubGroupSizes
.begin(), aSubGroupSizes
.end());
497 nMaxSubDimension
= std::max(nMaxSubDimension
, nMinSubGroupPrimary
);
498 long nMaxDimension
= std::max(nMaxMainDimension
, nMaxSubDimension
);
499 aReq
.m_aMainGroupDimensions
.resize(aMainGroupSizes
.size(), nMaxDimension
);
500 aReq
.m_aSubGroupDimensions
.resize(aSubGroupSizes
.size(), nMaxDimension
);
504 //Ideally set everything to the same size, but find outlier widgets
505 //that are way wider than the average and leave them
506 //at their natural size and set the remainder to share the
507 //max size of the remaining members of the buttonbox
508 long nAccDimension
= std::accumulate(aMainGroupSizes
.begin(),
509 aMainGroupSizes
.end(), 0);
510 nAccDimension
= std::accumulate(aSubGroupSizes
.begin(),
511 aSubGroupSizes
.end(), nAccDimension
);
513 size_t nTotalSize
= aMainGroupSizes
.size() + aSubGroupSizes
.size();
515 long nAvgDimension
= nTotalSize
? nAccDimension
/ nTotalSize
: 0;
517 long nMaxMainNonOutlier
= getMaxNonOutlier(aMainGroupSizes
,
519 long nMaxSubNonOutlier
= getMaxNonOutlier(aSubGroupSizes
,
521 long nMaxNonOutlier
= std::max(nMaxMainNonOutlier
, nMaxSubNonOutlier
);
523 aReq
.m_aMainGroupDimensions
= setButtonSizes(aMainGroupSizes
,
524 aMainGroupNonHomogeneous
,
525 nAvgDimension
, nMaxNonOutlier
, nMinMainGroupPrimary
);
526 aReq
.m_aSubGroupDimensions
= setButtonSizes(aSubGroupSizes
,
527 aSubGroupNonHomogeneous
,
528 nAvgDimension
, nMaxNonOutlier
, nMinSubGroupPrimary
);
531 if (!aReq
.m_aMainGroupDimensions
.empty())
533 setSecondaryDimension(aReq
.m_aMainGroupSize
, nMainGroupSecondary
);
534 setPrimaryDimension(aReq
.m_aMainGroupSize
,
535 std::accumulate(aReq
.m_aMainGroupDimensions
.begin(),
536 aReq
.m_aMainGroupDimensions
.end(), 0));
538 if (!aReq
.m_aSubGroupDimensions
.empty())
540 setSecondaryDimension(aReq
.m_aSubGroupSize
, nSubGroupSecondary
);
541 setPrimaryDimension(aReq
.m_aSubGroupSize
,
542 std::accumulate(aReq
.m_aSubGroupDimensions
.begin(),
543 aReq
.m_aSubGroupDimensions
.end(), 0));
549 Size
VclButtonBox::addSpacing(const Size
&rSize
, sal_uInt16 nVisibleChildren
) const
553 if (nVisibleChildren
)
555 long nPrimaryDimension
= getPrimaryDimension(rSize
);
556 setPrimaryDimension(aRet
,
557 nPrimaryDimension
+ m_nSpacing
* (nVisibleChildren
-1));
558 setSecondaryDimension(aRet
, getSecondaryDimension(rSize
));
564 Size
VclButtonBox::calculateRequisition() const
566 Requisition
aReq(calculatePrimarySecondaryRequisitions());
567 sal_uInt16 nVisibleChildren
= aReq
.m_aMainGroupDimensions
.size() +
568 aReq
.m_aSubGroupDimensions
.size();
569 return addSpacing(addReqGroups(aReq
), nVisibleChildren
);
572 bool VclButtonBox::set_property(const OString
&rKey
, const OUString
&rValue
)
574 if (rKey
== "layout-style")
576 VclButtonBoxStyle eStyle
= VclButtonBoxStyle::Default
;
577 if (rValue
== "spread")
578 eStyle
= VclButtonBoxStyle::Spread
;
579 else if (rValue
== "edge")
580 eStyle
= VclButtonBoxStyle::Edge
;
581 else if (rValue
== "start")
582 eStyle
= VclButtonBoxStyle::Start
;
583 else if (rValue
== "end")
584 eStyle
= VclButtonBoxStyle::End
;
585 else if (rValue
== "center")
586 eStyle
= VclButtonBoxStyle::Center
;
589 SAL_WARN("vcl.layout", "unknown layout style " << rValue
);
591 m_eLayoutStyle
= eStyle
;
594 return VclBox::set_property(rKey
, rValue
);
598 void VclButtonBox::setAllocation(const Size
&rAllocation
)
600 Requisition
aReq(calculatePrimarySecondaryRequisitions());
602 if (aReq
.m_aMainGroupDimensions
.empty() && aReq
.m_aSubGroupDimensions
.empty())
605 long nAllocPrimaryDimension
= getPrimaryDimension(rAllocation
);
607 Point aMainGroupPos
, aOtherGroupPos
;
608 int nSpacing
= m_nSpacing
;
610 //To-Do, other layout styles
611 switch (m_eLayoutStyle
)
613 case VclButtonBoxStyle::Start
:
614 if (!aReq
.m_aSubGroupDimensions
.empty())
616 long nOtherPrimaryDimension
= getPrimaryDimension(
617 addSpacing(aReq
.m_aSubGroupSize
, aReq
.m_aSubGroupDimensions
.size()));
618 setPrimaryCoordinate(aOtherGroupPos
,
619 nAllocPrimaryDimension
- nOtherPrimaryDimension
);
622 case VclButtonBoxStyle::Spread
:
623 if (!aReq
.m_aMainGroupDimensions
.empty())
625 long nMainPrimaryDimension
= getPrimaryDimension(
626 addSpacing(aReq
.m_aMainGroupSize
, aReq
.m_aMainGroupDimensions
.size()));
627 long nExtraSpace
= nAllocPrimaryDimension
- nMainPrimaryDimension
;
628 nExtraSpace
+= (aReq
.m_aMainGroupDimensions
.size()-1) * nSpacing
;
629 nSpacing
= nExtraSpace
/(aReq
.m_aMainGroupDimensions
.size()+1);
630 setPrimaryCoordinate(aMainGroupPos
, nSpacing
);
633 case VclButtonBoxStyle::Center
:
634 if (!aReq
.m_aMainGroupDimensions
.empty())
636 long nMainPrimaryDimension
= getPrimaryDimension(
637 addSpacing(aReq
.m_aMainGroupSize
, aReq
.m_aMainGroupDimensions
.size()));
638 long nExtraSpace
= nAllocPrimaryDimension
- nMainPrimaryDimension
;
639 setPrimaryCoordinate(aMainGroupPos
, nExtraSpace
/2);
643 SAL_WARN("vcl.layout", "todo unimplemented layout style");
645 case VclButtonBoxStyle::Default
:
646 case VclButtonBoxStyle::End
:
647 if (!aReq
.m_aMainGroupDimensions
.empty())
649 long nMainPrimaryDimension
= getPrimaryDimension(
650 addSpacing(aReq
.m_aMainGroupSize
, aReq
.m_aMainGroupDimensions
.size()));
651 setPrimaryCoordinate(aMainGroupPos
,
652 nAllocPrimaryDimension
- nMainPrimaryDimension
);
658 setSecondaryDimension(aChildSize
, getSecondaryDimension(rAllocation
));
660 std::vector
<long>::const_iterator aPrimaryI
= aReq
.m_aMainGroupDimensions
.begin();
661 std::vector
<long>::const_iterator aSecondaryI
= aReq
.m_aSubGroupDimensions
.begin();
662 bool bIgnoreSecondaryPacking
= (m_eLayoutStyle
== VclButtonBoxStyle::Spread
|| m_eLayoutStyle
== VclButtonBoxStyle::Center
);
663 for (vcl::Window
*pChild
= GetWindow(GetWindowType::FirstChild
); pChild
; pChild
= pChild
->GetWindow(GetWindowType::Next
))
665 if (!pChild
->IsVisible())
668 if (bIgnoreSecondaryPacking
|| !pChild
->get_secondary())
670 long nMainGroupPrimaryDimension
= *aPrimaryI
++;
671 setPrimaryDimension(aChildSize
, nMainGroupPrimaryDimension
);
672 setLayoutAllocation(*pChild
, aMainGroupPos
, aChildSize
);
673 long nPrimaryCoordinate
= getPrimaryCoordinate(aMainGroupPos
);
674 setPrimaryCoordinate(aMainGroupPos
, nPrimaryCoordinate
+ nMainGroupPrimaryDimension
+ nSpacing
);
678 long nSubGroupPrimaryDimension
= *aSecondaryI
++;
679 setPrimaryDimension(aChildSize
, nSubGroupPrimaryDimension
);
680 setLayoutAllocation(*pChild
, aOtherGroupPos
, aChildSize
);
681 long nPrimaryCoordinate
= getPrimaryCoordinate(aOtherGroupPos
);
682 setPrimaryCoordinate(aOtherGroupPos
, nPrimaryCoordinate
+ nSubGroupPrimaryDimension
+ nSpacing
);
690 int const m_nPriority
;
693 static int getButtonPriority(const OString
&rType
)
695 static const size_t N_TYPES
= 6;
696 static const ButtonOrder aDiscardCancelSave
[N_TYPES
] =
706 static const ButtonOrder aSaveDiscardCancel
[N_TYPES
] =
716 const ButtonOrder
* pOrder
= &aDiscardCancelSave
[0];
718 const OUString
&rEnv
= Application::GetDesktopEnvironment();
720 if (rEnv
.equalsIgnoreAsciiCase("windows") ||
721 rEnv
.equalsIgnoreAsciiCase("tde") ||
722 rEnv
.startsWithIgnoreAsciiCase("kde"))
724 pOrder
= &aSaveDiscardCancel
[0];
727 for (size_t i
= 0; i
< N_TYPES
; ++i
, ++pOrder
)
729 if (rType
.endsWith(pOrder
->m_aType
))
730 return pOrder
->m_nPriority
;
738 bool const m_bVerticalContainer
;
740 explicit sortButtons(bool bVerticalContainer
)
741 : m_bVerticalContainer(bVerticalContainer
)
744 bool operator()(const vcl::Window
*pA
, const vcl::Window
*pB
) const;
747 bool sortButtons::operator()(const vcl::Window
*pA
, const vcl::Window
*pB
) const
749 //sort into two groups of pack start and pack end
750 VclPackType ePackA
= pA
->get_pack_type();
751 VclPackType ePackB
= pB
->get_pack_type();
756 bool bPackA
= pA
->get_secondary();
757 bool bPackB
= pB
->get_secondary();
758 if (!m_bVerticalContainer
)
760 //for horizontal boxes group secondaries before primaries
768 //for vertical boxes group secondaries after primaries
775 //now order within groups according to platform rules
776 return getButtonPriority(pA
->GetHelpId()) < getButtonPriority(pB
->GetHelpId());
779 void VclButtonBox::sort_native_button_order()
781 std::vector
<vcl::Window
*> aChilds
;
782 for (vcl::Window
* pChild
= GetWindow(GetWindowType::FirstChild
); pChild
;
783 pChild
= pChild
->GetWindow(GetWindowType::Next
))
785 aChilds
.push_back(pChild
);
788 //sort child order within parent so that we match the platform
790 std::stable_sort(aChilds
.begin(), aChilds
.end(), sortButtons(m_bVerticalContainer
));
791 BuilderUtils::reorderWithinParent(aChilds
, true);
796 VclPtr
<vcl::Window
> pChild
;
797 sal_Int32 nSpanWidth
;
798 sal_Int32 nSpanHeight
;
811 typedef boost::multi_array
<GridEntry
, 2> array_type
;
813 static array_type
assembleGrid(const VclGrid
&rGrid
);
814 static bool isNullGrid(const array_type
& A
);
815 static void calcMaxs(const array_type
&A
, std::vector
<VclGrid::Value
> &rWidths
, std::vector
<VclGrid::Value
> &rHeights
);
817 array_type
assembleGrid(const VclGrid
&rGrid
)
821 for (vcl::Window
* pChild
= rGrid
.GetWindow(GetWindowType::FirstChild
); pChild
;
822 pChild
= pChild
->GetWindow(GetWindowType::Next
))
824 sal_Int32 nLeftAttach
= std::max
<sal_Int32
>(pChild
->get_grid_left_attach(), 0);
825 sal_Int32 nWidth
= pChild
->get_grid_width();
826 sal_Int32 nMaxXPos
= nLeftAttach
+nWidth
-1;
828 sal_Int32 nTopAttach
= std::max
<sal_Int32
>(pChild
->get_grid_top_attach(), 0);
829 sal_Int32 nHeight
= pChild
->get_grid_height();
830 sal_Int32 nMaxYPos
= nTopAttach
+nHeight
-1;
832 sal_Int32 nCurrentMaxXPos
= A
.shape()[0]-1;
833 sal_Int32 nCurrentMaxYPos
= A
.shape()[1]-1;
834 if (nMaxXPos
> nCurrentMaxXPos
|| nMaxYPos
> nCurrentMaxYPos
)
836 nCurrentMaxXPos
= std::max(nMaxXPos
, nCurrentMaxXPos
);
837 nCurrentMaxYPos
= std::max(nMaxYPos
, nCurrentMaxYPos
);
838 A
.resize(boost::extents
[nCurrentMaxXPos
+1][nCurrentMaxYPos
+1]);
841 GridEntry
&rEntry
= A
[nLeftAttach
][nTopAttach
];
842 rEntry
.pChild
= pChild
;
843 rEntry
.nSpanWidth
= nWidth
;
844 rEntry
.nSpanHeight
= nHeight
;
845 rEntry
.x
= nLeftAttach
;
846 rEntry
.y
= nTopAttach
;
848 for (sal_Int32 nSpanX
= 0; nSpanX
< nWidth
; ++nSpanX
)
850 for (sal_Int32 nSpanY
= 0; nSpanY
< nHeight
; ++nSpanY
)
852 GridEntry
&rSpan
= A
[nLeftAttach
+nSpanX
][nTopAttach
+nSpanY
];
853 rSpan
.x
= nLeftAttach
;
854 rSpan
.y
= nTopAttach
;
859 //see if we have any empty rows/cols
860 sal_Int32 nMaxX
= A
.shape()[0];
861 sal_Int32 nMaxY
= A
.shape()[1];
863 std::vector
<bool> aNonEmptyCols(nMaxX
);
864 std::vector
<bool> aNonEmptyRows(nMaxY
);
866 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
868 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
870 const GridEntry
&rEntry
= A
[x
][y
];
871 const vcl::Window
*pChild
= rEntry
.pChild
;
872 if (pChild
&& pChild
->IsVisible())
874 aNonEmptyCols
[x
] = true;
875 if (rGrid
.get_column_homogeneous())
877 for (sal_Int32 nSpanX
= 1; nSpanX
< rEntry
.nSpanWidth
; ++nSpanX
)
878 aNonEmptyCols
[x
+nSpanX
] = true;
880 aNonEmptyRows
[y
] = true;
881 if (rGrid
.get_row_homogeneous())
883 for (sal_Int32 nSpanY
= 1; nSpanY
< rEntry
.nSpanHeight
; ++nSpanY
)
884 aNonEmptyRows
[y
+nSpanY
] = true;
890 if (!rGrid
.get_column_homogeneous())
892 //reduce the spans of elements that span empty columns
893 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
895 std::set
<GridEntry
*> candidates
;
896 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
898 if (aNonEmptyCols
[x
])
900 GridEntry
&rSpan
= A
[x
][y
];
901 //cell x/y is spanned by the widget at cell rSpan.x/rSpan.y,
902 //just points back to itself if there's no cell spanning
903 if ((rSpan
.x
== -1) || (rSpan
.y
== -1))
905 //there is no entry for this cell, i.e. this is a cell
906 //with no widget in it, or spanned by any other widget
909 GridEntry
&rEntry
= A
[rSpan
.x
][rSpan
.y
];
910 candidates
.insert(&rEntry
);
912 for (auto const& candidate
: candidates
)
914 GridEntry
*pEntry
= candidate
;
915 --pEntry
->nSpanWidth
;
920 if (!rGrid
.get_row_homogeneous())
922 //reduce the spans of elements that span empty rows
923 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
925 std::set
<GridEntry
*> candidates
;
926 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
928 if (aNonEmptyRows
[y
])
930 GridEntry
&rSpan
= A
[x
][y
];
931 //cell x/y is spanned by the widget at cell rSpan.x/rSpan.y,
932 //just points back to itself if there's no cell spanning
933 if ((rSpan
.x
== -1) || (rSpan
.y
== -1))
935 //there is no entry for this cell, i.e. this is a cell
936 //with no widget in it, or spanned by any other widget
939 GridEntry
&rEntry
= A
[rSpan
.x
][rSpan
.y
];
940 candidates
.insert(&rEntry
);
942 for (auto const& candidate
: candidates
)
944 GridEntry
*pEntry
= candidate
;
945 --pEntry
->nSpanHeight
;
950 sal_Int32 nNonEmptyCols
= std::count(aNonEmptyCols
.begin(), aNonEmptyCols
.end(), true);
951 sal_Int32 nNonEmptyRows
= std::count(aNonEmptyRows
.begin(), aNonEmptyRows
.end(), true);
953 //make new grid without empty rows and columns
954 array_type
B(boost::extents
[nNonEmptyCols
][nNonEmptyRows
]);
955 for (sal_Int32 x
= 0, x2
= 0; x
< nMaxX
; ++x
)
957 if (!aNonEmptyCols
[x
])
959 for (sal_Int32 y
= 0, y2
= 0; y
< nMaxY
; ++y
)
961 if (!aNonEmptyRows
[y
])
963 GridEntry
&rEntry
= A
[x
][y
];
964 B
[x2
][y2
++] = rEntry
;
972 static bool isNullGrid(const array_type
&A
)
974 sal_Int32 nMaxX
= A
.shape()[0];
975 sal_Int32 nMaxY
= A
.shape()[1];
977 return !nMaxX
|| !nMaxY
;
980 static void calcMaxs(const array_type
&A
, std::vector
<VclGrid::Value
> &rWidths
, std::vector
<VclGrid::Value
> &rHeights
)
982 sal_Int32 nMaxX
= A
.shape()[0];
983 sal_Int32 nMaxY
= A
.shape()[1];
985 rWidths
.resize(nMaxX
);
986 rHeights
.resize(nMaxY
);
988 //first use the non spanning entries to set default width/heights
989 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
991 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
993 const GridEntry
&rEntry
= A
[x
][y
];
994 const vcl::Window
*pChild
= rEntry
.pChild
;
995 if (!pChild
|| !pChild
->IsVisible())
998 sal_Int32 nWidth
= rEntry
.nSpanWidth
;
999 sal_Int32 nHeight
= rEntry
.nSpanHeight
;
1001 for (sal_Int32 nSpanX
= 0; nSpanX
< nWidth
; ++nSpanX
)
1002 rWidths
[x
+nSpanX
].m_bExpand
|= pChild
->get_hexpand();
1004 for (sal_Int32 nSpanY
= 0; nSpanY
< nHeight
; ++nSpanY
)
1005 rHeights
[y
+nSpanY
].m_bExpand
|= pChild
->get_vexpand();
1007 if (nWidth
== 1 || nHeight
== 1)
1009 Size aChildSize
= VclContainer::getLayoutRequisition(*pChild
);
1011 rWidths
[x
].m_nValue
= std::max(rWidths
[x
].m_nValue
, aChildSize
.Width());
1013 rHeights
[y
].m_nValue
= std::max(rHeights
[y
].m_nValue
, aChildSize
.Height());
1018 //now use the spanning entries and split any extra sizes across expanding rows/cols
1020 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1022 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1024 const GridEntry
&rEntry
= A
[x
][y
];
1025 const vcl::Window
*pChild
= rEntry
.pChild
;
1026 if (!pChild
|| !pChild
->IsVisible())
1029 sal_Int32 nWidth
= rEntry
.nSpanWidth
;
1030 sal_Int32 nHeight
= rEntry
.nSpanHeight
;
1032 if (nWidth
== 1 && nHeight
== 1)
1035 Size aChildSize
= VclContainer::getLayoutRequisition(*pChild
);
1039 sal_Int32 nExistingWidth
= 0;
1040 for (sal_Int32 nSpanX
= 0; nSpanX
< nWidth
; ++nSpanX
)
1041 nExistingWidth
+= rWidths
[x
+nSpanX
].m_nValue
;
1043 sal_Int32 nExtraWidth
= aChildSize
.Width() - nExistingWidth
;
1045 if (nExtraWidth
> 0)
1047 bool bForceExpandAll
= false;
1048 sal_Int32 nExpandables
= 0;
1049 for (sal_Int32 nSpanX
= 0; nSpanX
< nWidth
; ++nSpanX
)
1050 if (rWidths
[x
+nSpanX
].m_bExpand
)
1052 if (nExpandables
== 0)
1054 nExpandables
= nWidth
;
1055 bForceExpandAll
= true;
1058 for (sal_Int32 nSpanX
= 0; nSpanX
< nWidth
; ++nSpanX
)
1060 if (rWidths
[x
+nSpanX
].m_bExpand
|| bForceExpandAll
)
1061 rWidths
[x
+nSpanX
].m_nValue
+= nExtraWidth
/nExpandables
;
1068 sal_Int32 nExistingHeight
= 0;
1069 for (sal_Int32 nSpanY
= 0; nSpanY
< nHeight
; ++nSpanY
)
1070 nExistingHeight
+= rHeights
[y
+nSpanY
].m_nValue
;
1072 sal_Int32 nExtraHeight
= aChildSize
.Height() - nExistingHeight
;
1074 if (nExtraHeight
> 0)
1076 bool bForceExpandAll
= false;
1077 sal_Int32 nExpandables
= 0;
1078 for (sal_Int32 nSpanY
= 0; nSpanY
< nHeight
; ++nSpanY
)
1079 if (rHeights
[y
+nSpanY
].m_bExpand
)
1081 if (nExpandables
== 0)
1083 nExpandables
= nHeight
;
1084 bForceExpandAll
= true;
1087 for (sal_Int32 nSpanY
= 0; nSpanY
< nHeight
; ++nSpanY
)
1089 if (rHeights
[y
+nSpanY
].m_bExpand
|| bForceExpandAll
)
1090 rHeights
[y
+nSpanY
].m_nValue
+= nExtraHeight
/nExpandables
;
1098 static bool compareValues(const VclGrid::Value
&i
, const VclGrid::Value
&j
)
1100 return i
.m_nValue
< j
.m_nValue
;
1103 static VclGrid::Value
accumulateValues(const VclGrid::Value
&i
, const VclGrid::Value
&j
)
1105 VclGrid::Value aRet
;
1106 aRet
.m_nValue
= i
.m_nValue
+ j
.m_nValue
;
1107 aRet
.m_bExpand
= i
.m_bExpand
|| j
.m_bExpand
;
1111 Size
VclGrid::calculateRequisition() const
1113 return calculateRequisitionForSpacings(get_row_spacing(), get_column_spacing());
1116 Size
VclGrid::calculateRequisitionForSpacings(sal_Int32 nRowSpacing
, sal_Int32 nColSpacing
) const
1118 array_type A
= assembleGrid(*this);
1123 std::vector
<Value
> aWidths
;
1124 std::vector
<Value
> aHeights
;
1125 calcMaxs(A
, aWidths
, aHeights
);
1127 long nTotalWidth
= 0;
1128 if (get_column_homogeneous())
1130 nTotalWidth
= std::max_element(aWidths
.begin(), aWidths
.end(), compareValues
)->m_nValue
;
1131 nTotalWidth
*= aWidths
.size();
1135 nTotalWidth
= std::accumulate(aWidths
.begin(), aWidths
.end(), Value(), accumulateValues
).m_nValue
;
1138 nTotalWidth
+= nColSpacing
* (aWidths
.size()-1);
1140 long nTotalHeight
= 0;
1141 if (get_row_homogeneous())
1143 nTotalHeight
= std::max_element(aHeights
.begin(), aHeights
.end(), compareValues
)->m_nValue
;
1144 nTotalHeight
*= aHeights
.size();
1148 nTotalHeight
= std::accumulate(aHeights
.begin(), aHeights
.end(), Value(), accumulateValues
).m_nValue
;
1151 nTotalHeight
+= nRowSpacing
* (aHeights
.size()-1);
1153 return Size(nTotalWidth
, nTotalHeight
);
1156 void VclGrid::setAllocation(const Size
& rAllocation
)
1158 array_type A
= assembleGrid(*this);
1163 sal_Int32 nMaxX
= A
.shape()[0];
1164 sal_Int32 nMaxY
= A
.shape()[1];
1167 std::vector
<Value
> aWidths(nMaxX
);
1168 std::vector
<Value
> aHeights(nMaxY
);
1169 if (!get_column_homogeneous() || !get_row_homogeneous())
1171 aRequisition
= calculateRequisition();
1172 calcMaxs(A
, aWidths
, aHeights
);
1175 sal_Int32
nColSpacing(get_column_spacing());
1176 sal_Int32
nRowSpacing(get_row_spacing());
1178 long nAvailableWidth
= rAllocation
.Width();
1180 nAvailableWidth
-= nColSpacing
* (nMaxX
- 1);
1181 if (get_column_homogeneous())
1183 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1184 aWidths
[x
].m_nValue
= nAvailableWidth
/nMaxX
;
1186 else if (rAllocation
.Width() != aRequisition
.Width())
1188 sal_Int32 nExpandables
= 0;
1189 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1190 if (aWidths
[x
].m_bExpand
)
1192 long nExtraWidthForExpanders
= nExpandables
? (rAllocation
.Width() - aRequisition
.Width()) / nExpandables
: 0;
1194 //We don't fit and there is no volunteer to be shrunk
1195 if (!nExpandables
&& rAllocation
.Width() < aRequisition
.Width())
1197 //first reduce spacing
1201 aRequisition
= calculateRequisitionForSpacings(nRowSpacing
, nColSpacing
);
1202 if (aRequisition
.Width() <= rAllocation
.Width())
1206 //share out the remaining pain to everyone
1207 long nExtraWidth
= (rAllocation
.Width() - aRequisition
.Width()) / nMaxX
;
1209 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1210 aWidths
[x
].m_nValue
+= nExtraWidth
;
1213 if (nExtraWidthForExpanders
)
1215 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1216 if (aWidths
[x
].m_bExpand
)
1217 aWidths
[x
].m_nValue
+= nExtraWidthForExpanders
;
1221 long nAvailableHeight
= rAllocation
.Height();
1223 nAvailableHeight
-= nRowSpacing
* (nMaxY
- 1);
1224 if (get_row_homogeneous())
1226 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1227 aHeights
[y
].m_nValue
= nAvailableHeight
/nMaxY
;
1229 else if (rAllocation
.Height() != aRequisition
.Height())
1231 sal_Int32 nExpandables
= 0;
1232 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1233 if (aHeights
[y
].m_bExpand
)
1235 long nExtraHeightForExpanders
= nExpandables
? (rAllocation
.Height() - aRequisition
.Height()) / nExpandables
: 0;
1237 //We don't fit and there is no volunteer to be shrunk
1238 if (!nExpandables
&& rAllocation
.Height() < aRequisition
.Height())
1240 //first reduce spacing
1244 aRequisition
= calculateRequisitionForSpacings(nRowSpacing
, nColSpacing
);
1245 if (aRequisition
.Height() <= rAllocation
.Height())
1249 //share out the remaining pain to everyone
1250 long nExtraHeight
= (rAllocation
.Height() - aRequisition
.Height()) / nMaxY
;
1252 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1253 aHeights
[y
].m_nValue
+= nExtraHeight
;
1256 if (nExtraHeightForExpanders
)
1258 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1259 if (aHeights
[y
].m_bExpand
)
1260 aHeights
[y
].m_nValue
+= nExtraHeightForExpanders
;
1264 Point
aAllocPos(0, 0);
1265 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1267 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1269 GridEntry
&rEntry
= A
[x
][y
];
1270 vcl::Window
*pChild
= rEntry
.pChild
;
1273 Size
aChildAlloc(0, 0);
1275 sal_Int32 nWidth
= rEntry
.nSpanWidth
;
1276 for (sal_Int32 nSpanX
= 0; nSpanX
< nWidth
; ++nSpanX
)
1277 aChildAlloc
.AdjustWidth(aWidths
[x
+nSpanX
].m_nValue
);
1278 aChildAlloc
.AdjustWidth(nColSpacing
*(nWidth
-1) );
1280 sal_Int32 nHeight
= rEntry
.nSpanHeight
;
1281 for (sal_Int32 nSpanY
= 0; nSpanY
< nHeight
; ++nSpanY
)
1282 aChildAlloc
.AdjustHeight(aHeights
[y
+nSpanY
].m_nValue
);
1283 aChildAlloc
.AdjustHeight(nRowSpacing
*(nHeight
-1) );
1285 setLayoutAllocation(*pChild
, aAllocPos
, aChildAlloc
);
1287 aAllocPos
.AdjustY(aHeights
[y
].m_nValue
+ nRowSpacing
);
1289 aAllocPos
.AdjustX(aWidths
[x
].m_nValue
+ nColSpacing
);
1290 aAllocPos
.setY( 0 );
1294 boost::property_tree::ptree
VclGrid::DumpAsPropertyTree()
1296 boost::property_tree::ptree
aTree(VclContainer::DumpAsPropertyTree());
1297 aTree
.put("type", "grid");
1301 bool toBool(const OUString
&rValue
)
1303 return (!rValue
.isEmpty() && (rValue
[0] == 't' || rValue
[0] == 'T' || rValue
[0] == '1'));
1306 bool VclGrid::set_property(const OString
&rKey
, const OUString
&rValue
)
1308 if (rKey
== "row-spacing")
1309 set_row_spacing(rValue
.toInt32());
1310 else if (rKey
== "column-spacing")
1311 set_column_spacing(rValue
.toInt32());
1312 else if (rKey
== "row-homogeneous")
1313 m_bRowHomogeneous
= toBool(rValue
);
1314 else if (rKey
== "column-homogeneous")
1315 m_bColumnHomogeneous
= toBool(rValue
);
1316 else if (rKey
== "n-rows")
1319 return VclContainer::set_property(rKey
, rValue
);
1323 const vcl::Window
*VclBin::get_child() const
1325 const WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
1327 return pWindowImpl
->mpFirstChild
;
1330 vcl::Window
*VclBin::get_child()
1332 return const_cast<vcl::Window
*>(const_cast<const VclBin
*>(this)->get_child());
1335 Size
VclBin::calculateRequisition() const
1337 const vcl::Window
*pChild
= get_child();
1338 if (pChild
&& pChild
->IsVisible())
1339 return getLayoutRequisition(*pChild
);
1343 void VclBin::setAllocation(const Size
&rAllocation
)
1345 vcl::Window
*pChild
= get_child();
1346 if (pChild
&& pChild
->IsVisible())
1347 setLayoutAllocation(*pChild
, Point(0, 0), rAllocation
);
1350 VclFrame::~VclFrame()
1355 void VclFrame::dispose()
1361 //To-Do, hook a DecorationView into VclFrame ?
1363 Size
VclFrame::calculateRequisition() const
1367 const vcl::Window
*pChild
= get_child();
1368 const vcl::Window
*pLabel
= get_label_widget();
1370 if (pChild
&& pChild
->IsVisible())
1371 aRet
= getLayoutRequisition(*pChild
);
1373 if (pLabel
&& pLabel
->IsVisible())
1375 Size aLabelSize
= getLayoutRequisition(*pLabel
);
1376 aRet
.AdjustHeight(aLabelSize
.Height() );
1377 aRet
.setWidth( std::max(aLabelSize
.Width(), aRet
.Width()) );
1383 void VclFrame::setAllocation(const Size
&rAllocation
)
1385 //SetBackground( Color(0xFF, 0x00, 0xFF) );
1387 Size
aAllocation(rAllocation
);
1390 vcl::Window
*pChild
= get_child();
1391 vcl::Window
*pLabel
= get_label_widget();
1393 if (pLabel
&& pLabel
->IsVisible())
1395 Size aLabelSize
= getLayoutRequisition(*pLabel
);
1396 aLabelSize
.setHeight( std::min(aLabelSize
.Height(), aAllocation
.Height()) );
1397 aLabelSize
.setWidth( std::min(aLabelSize
.Width(), aAllocation
.Width()) );
1398 setLayoutAllocation(*pLabel
, aChildPos
, aLabelSize
);
1399 aAllocation
.AdjustHeight( -(aLabelSize
.Height()) );
1400 aChildPos
.AdjustY(aLabelSize
.Height() );
1403 if (pChild
&& pChild
->IsVisible())
1404 setLayoutAllocation(*pChild
, aChildPos
, aAllocation
);
1407 IMPL_LINK(VclFrame
, WindowEventListener
, VclWindowEvent
&, rEvent
, void)
1409 if (rEvent
.GetId() == VclEventId::ObjectDying
)
1410 designate_label(nullptr);
1413 void VclFrame::designate_label(vcl::Window
*pWindow
)
1415 assert(!pWindow
|| pWindow
->GetParent() == this);
1417 m_pLabel
->RemoveEventListener(LINK(this, VclFrame
, WindowEventListener
));
1420 m_pLabel
->AddEventListener(LINK(this, VclFrame
, WindowEventListener
));
1423 const vcl::Window
*VclFrame::get_label_widget() const
1425 assert(GetChildCount() == 2);
1428 //The label widget is normally the first (of two) children
1429 const WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
1430 if (pWindowImpl
->mpFirstChild
== pWindowImpl
->mpLastChild
) //no label exists
1432 return pWindowImpl
->mpFirstChild
;
1435 vcl::Window
*VclFrame::get_label_widget()
1437 return const_cast<vcl::Window
*>(const_cast<const VclFrame
*>(this)->get_label_widget());
1440 const vcl::Window
*VclFrame::get_child() const
1442 //The child widget is the normally the last (of two) children
1443 const WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
1444 assert(GetChildCount() == 2 || pWindowImpl
->mbInDispose
);
1446 return pWindowImpl
->mpLastChild
;
1447 if (pWindowImpl
->mpFirstChild
== pWindowImpl
->mpLastChild
) //only label exists
1449 return pWindowImpl
->mpLastChild
;
1452 vcl::Window
*VclFrame::get_child()
1454 return const_cast<vcl::Window
*>(const_cast<const VclFrame
*>(this)->get_child());
1457 void VclFrame::set_label(const OUString
&rLabel
)
1459 vcl::Window
*pLabel
= get_label_widget();
1461 pLabel
->SetText(rLabel
);
1464 OUString
VclFrame::get_label() const
1466 const vcl::Window
*pLabel
= get_label_widget();
1468 return pLabel
->GetText();
1471 OUString
VclFrame::getDefaultAccessibleName() const
1473 const vcl::Window
*pLabel
= get_label_widget();
1475 return pLabel
->GetAccessibleName();
1476 return VclBin::getDefaultAccessibleName();
1479 boost::property_tree::ptree
VclFrame::DumpAsPropertyTree()
1481 boost::property_tree::ptree
aTree(VclBin::DumpAsPropertyTree());
1482 aTree
.put("type", "frame");
1486 Size
VclAlignment::calculateRequisition() const
1488 Size
aRet(m_nLeftPadding
+ m_nRightPadding
,
1489 m_nTopPadding
+ m_nBottomPadding
);
1491 const vcl::Window
*pChild
= get_child();
1492 if (pChild
&& pChild
->IsVisible())
1494 Size aChildSize
= getLayoutRequisition(*pChild
);
1495 aRet
.AdjustWidth(aChildSize
.Width() );
1496 aRet
.AdjustHeight(aChildSize
.Height() );
1502 void VclAlignment::setAllocation(const Size
&rAllocation
)
1504 vcl::Window
*pChild
= get_child();
1505 if (!pChild
|| !pChild
->IsVisible())
1508 Point
aChildPos(m_nLeftPadding
, m_nTopPadding
);
1511 aAllocation
.setWidth( rAllocation
.Width() - (m_nLeftPadding
+ m_nRightPadding
) );
1512 aAllocation
.setHeight( rAllocation
.Height() - (m_nTopPadding
+ m_nBottomPadding
) );
1514 setLayoutAllocation(*pChild
, aChildPos
, aAllocation
);
1517 bool VclAlignment::set_property(const OString
&rKey
, const OUString
&rValue
)
1519 if (rKey
== "bottom-padding")
1520 m_nBottomPadding
= rValue
.toInt32();
1521 else if (rKey
== "left-padding")
1522 m_nLeftPadding
= rValue
.toInt32();
1523 else if (rKey
== "right-padding")
1524 m_nRightPadding
= rValue
.toInt32();
1525 else if (rKey
== "top-padding")
1526 m_nTopPadding
= rValue
.toInt32();
1528 return VclBin::set_property(rKey
, rValue
);
1532 void VclExpander::dispose()
1534 m_pDisclosureButton
.disposeAndClear();
1538 const vcl::Window
*VclExpander::get_child() const
1540 const WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
1542 assert(pWindowImpl
->mpFirstChild
== m_pDisclosureButton
);
1544 return pWindowImpl
->mpFirstChild
->GetWindow(GetWindowType::Next
);
1547 vcl::Window
*VclExpander::get_child()
1549 return const_cast<vcl::Window
*>(const_cast<const VclExpander
*>(this)->get_child());
1552 Size
VclExpander::calculateRequisition() const
1556 WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
1558 const vcl::Window
*pChild
= get_child();
1559 const vcl::Window
*pLabel
= pChild
!= pWindowImpl
->mpLastChild
? pWindowImpl
->mpLastChild
.get() : nullptr;
1561 if (pChild
&& pChild
->IsVisible() && m_pDisclosureButton
->IsChecked())
1562 aRet
= getLayoutRequisition(*pChild
);
1564 Size aExpanderSize
= getLayoutRequisition(*m_pDisclosureButton
);
1566 if (pLabel
&& pLabel
->IsVisible())
1568 Size aLabelSize
= getLayoutRequisition(*pLabel
);
1569 aExpanderSize
.setHeight( std::max(aExpanderSize
.Height(), aLabelSize
.Height()) );
1570 aExpanderSize
.AdjustWidth(aLabelSize
.Width() );
1573 aRet
.AdjustHeight(aExpanderSize
.Height() );
1574 aRet
.setWidth( std::max(aExpanderSize
.Width(), aRet
.Width()) );
1579 void VclExpander::setAllocation(const Size
&rAllocation
)
1581 Size
aAllocation(rAllocation
);
1584 WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
1586 //The label widget is the last (of two) children
1587 vcl::Window
*pChild
= get_child();
1588 vcl::Window
*pLabel
= pChild
!= pWindowImpl
->mpLastChild
.get() ? pWindowImpl
->mpLastChild
.get() : nullptr;
1590 Size aButtonSize
= getLayoutRequisition(*m_pDisclosureButton
);
1592 Size aExpanderSize
= aButtonSize
;
1593 if (pLabel
&& pLabel
->IsVisible())
1595 aLabelSize
= getLayoutRequisition(*pLabel
);
1596 aExpanderSize
.setHeight( std::max(aExpanderSize
.Height(), aLabelSize
.Height()) );
1597 aExpanderSize
.AdjustWidth(aLabelSize
.Width() );
1600 aExpanderSize
.setHeight( std::min(aExpanderSize
.Height(), aAllocation
.Height()) );
1601 aExpanderSize
.setWidth( std::min(aExpanderSize
.Width(), aAllocation
.Width()) );
1603 aButtonSize
.setHeight( std::min(aButtonSize
.Height(), aExpanderSize
.Height()) );
1604 aButtonSize
.setWidth( std::min(aButtonSize
.Width(), aExpanderSize
.Width()) );
1606 long nExtraExpanderHeight
= aExpanderSize
.Height() - aButtonSize
.Height();
1607 Point
aButtonPos(aChildPos
.X(), aChildPos
.Y() + nExtraExpanderHeight
/2);
1608 setLayoutAllocation(*m_pDisclosureButton
, aButtonPos
, aButtonSize
);
1610 if (pLabel
&& pLabel
->IsVisible())
1612 aLabelSize
.setHeight( std::min(aLabelSize
.Height(), aExpanderSize
.Height()) );
1613 aLabelSize
.setWidth( std::min(aLabelSize
.Width(),
1614 aExpanderSize
.Width() - aButtonSize
.Width()) );
1616 long nExtraLabelHeight
= aExpanderSize
.Height() - aLabelSize
.Height();
1617 Point
aLabelPos(aChildPos
.X() + aButtonSize
.Width(), aChildPos
.Y() + nExtraLabelHeight
/2);
1618 setLayoutAllocation(*pLabel
, aLabelPos
, aLabelSize
);
1621 aAllocation
.AdjustHeight( -(aExpanderSize
.Height()) );
1622 aChildPos
.AdjustY(aExpanderSize
.Height() );
1624 if (pChild
&& pChild
->IsVisible())
1626 if (!m_pDisclosureButton
->IsChecked())
1627 aAllocation
= Size();
1628 setLayoutAllocation(*pChild
, aChildPos
, aAllocation
);
1632 bool VclExpander::set_property(const OString
&rKey
, const OUString
&rValue
)
1634 if (rKey
== "expanded")
1635 set_expanded(toBool(rValue
));
1636 else if (rKey
== "resize-toplevel")
1637 m_bResizeTopLevel
= toBool(rValue
);
1639 return VclBin::set_property(rKey
, rValue
);
1643 void VclExpander::StateChanged(StateChangedType nType
)
1645 VclBin::StateChanged( nType
);
1647 if (nType
== StateChangedType::InitShow
)
1649 vcl::Window
*pChild
= get_child();
1651 pChild
->Show(m_pDisclosureButton
->IsChecked());
1655 IMPL_LINK( VclExpander
, ClickHdl
, CheckBox
&, rBtn
, void )
1657 vcl::Window
*pChild
= get_child();
1660 pChild
->Show(rBtn
.IsChecked());
1662 Dialog
* pResizeDialog
= m_bResizeTopLevel
? GetParentDialog() : nullptr;
1664 pResizeDialog
->setOptimalLayoutSize();
1666 maExpandedHdl
.Call(*this);
1669 VclScrolledWindow::VclScrolledWindow(vcl::Window
*pParent
)
1670 : VclBin(pParent
, WB_HIDE
| WB_CLIPCHILDREN
| WB_AUTOHSCROLL
| WB_AUTOVSCROLL
| WB_TABSTOP
)
1671 , m_bUserManagedScrolling(false)
1672 , m_pVScroll(VclPtr
<ScrollBar
>::Create(this, WB_HIDE
| WB_VERT
))
1673 , m_pHScroll(VclPtr
<ScrollBar
>::Create(this, WB_HIDE
| WB_HORZ
))
1674 , m_aScrollBarBox(VclPtr
<ScrollBarBox
>::Create(this, WB_HIDE
))
1676 SetType(WindowType::SCROLLWINDOW
);
1678 Link
<ScrollBar
*,void> aLink( LINK( this, VclScrolledWindow
, ScrollBarHdl
) );
1679 m_pVScroll
->SetScrollHdl(aLink
);
1680 m_pHScroll
->SetScrollHdl(aLink
);
1683 void VclScrolledWindow::dispose()
1685 m_pVScroll
.disposeAndClear();
1686 m_pHScroll
.disposeAndClear();
1687 m_aScrollBarBox
.disposeAndClear();
1691 IMPL_LINK_NOARG(VclScrolledWindow
, ScrollBarHdl
, ScrollBar
*, void)
1693 vcl::Window
*pChild
= get_child();
1697 assert(dynamic_cast<VclViewport
*>(pChild
) && "scrolledwindow child should be a Viewport");
1699 pChild
= pChild
->GetWindow(GetWindowType::FirstChild
);
1704 Point
aWinPos(-m_pHScroll
->GetThumbPos(), -m_pVScroll
->GetThumbPos());
1705 pChild
->SetPosPixel(aWinPos
);
1708 const vcl::Window
*VclScrolledWindow::get_child() const
1710 const WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
1711 assert(GetChildCount() == 4 || pWindowImpl
->mbInDispose
);
1712 return pWindowImpl
->mpLastChild
;
1715 vcl::Window
*VclScrolledWindow::get_child()
1717 return const_cast<vcl::Window
*>(const_cast<const VclScrolledWindow
*>(this)->get_child());
1720 Size
VclScrolledWindow::calculateRequisition() const
1724 const vcl::Window
*pChild
= get_child();
1725 if (pChild
&& pChild
->IsVisible())
1726 aRet
= getLayoutRequisition(*pChild
);
1728 if (GetStyle() & WB_VSCROLL
)
1729 aRet
.AdjustWidth(getLayoutRequisition(*m_pVScroll
).Width() );
1731 if (GetStyle() & WB_HSCROLL
)
1732 aRet
.AdjustHeight(getLayoutRequisition(*m_pHScroll
).Height() );
1734 aRet
.AdjustHeight(2);
1735 aRet
.AdjustWidth(2);
1740 void VclScrolledWindow::InitScrollBars(const Size
&rRequest
)
1742 const vcl::Window
*pChild
= get_child();
1743 if (!pChild
|| !pChild
->IsVisible())
1746 Size
aOutSize(getVisibleChildSize());
1748 m_pVScroll
->SetRangeMax(rRequest
.Height());
1749 m_pVScroll
->SetVisibleSize(aOutSize
.Height());
1750 m_pVScroll
->SetPageSize(16);
1752 m_pHScroll
->SetRangeMax(rRequest
.Width());
1753 m_pHScroll
->SetVisibleSize(aOutSize
.Width());
1754 m_pHScroll
->SetPageSize(16);
1756 m_pVScroll
->Scroll();
1757 m_pHScroll
->Scroll();
1760 void VclScrolledWindow::doSetAllocation(const Size
&rAllocation
, bool bRetryOnFailure
)
1764 vcl::Window
*pChild
= get_child();
1765 if (pChild
&& pChild
->IsVisible())
1766 aChildReq
= getLayoutRequisition(*pChild
);
1768 long nAvailHeight
= rAllocation
.Height() - 2;
1769 long nAvailWidth
= rAllocation
.Width() - 2;
1771 if (GetStyle() & WB_AUTOVSCROLL
)
1773 m_pVScroll
->Show(nAvailHeight
< aChildReq
.Height());
1775 else if (m_pVScroll
->IsVisible() != bool(GetStyle() & WB_VSCROLL
))
1776 m_pVScroll
->Show((GetStyle() & WB_VSCROLL
) != 0);
1778 if (m_pVScroll
->IsVisible())
1779 nAvailWidth
-= getLayoutRequisition(*m_pVScroll
).Width();
1782 if (GetStyle() & WB_AUTOHSCROLL
)
1784 bool bShowHScroll
= nAvailWidth
< aChildReq
.Width();
1785 m_pHScroll
->Show(bShowHScroll
);
1788 nAvailHeight
-= getLayoutRequisition(*m_pHScroll
).Height();
1790 if (GetStyle() & WB_AUTOVSCROLL
)
1791 m_pVScroll
->Show(nAvailHeight
< aChildReq
.Height());
1793 else if (m_pHScroll
->IsVisible() != bool(GetStyle() & WB_HSCROLL
))
1794 m_pHScroll
->Show((GetStyle() & WB_HSCROLL
) != 0);
1796 Size
aInnerSize(rAllocation
);
1797 aInnerSize
.AdjustWidth(-2);
1798 aInnerSize
.AdjustHeight(-2);
1800 bool bBothVisible
= m_pVScroll
->IsVisible() && m_pHScroll
->IsVisible();
1801 auto nScrollBarWidth
= getLayoutRequisition(*m_pVScroll
).Width();
1802 auto nScrollBarHeight
= getLayoutRequisition(*m_pHScroll
).Height();
1804 if (m_pVScroll
->IsVisible())
1806 Point
aScrollPos(rAllocation
.Width() - nScrollBarWidth
- 2, 1);
1807 Size
aScrollSize(nScrollBarWidth
, rAllocation
.Height() - 2);
1809 aScrollSize
.AdjustHeight(-nScrollBarHeight
);
1810 setLayoutAllocation(*m_pVScroll
, aScrollPos
, aScrollSize
);
1811 aInnerSize
.AdjustWidth( -nScrollBarWidth
);
1814 if (m_pHScroll
->IsVisible())
1816 Point
aScrollPos(1, rAllocation
.Height() - nScrollBarHeight
);
1817 Size
aScrollSize(rAllocation
.Width() - 2, nScrollBarHeight
);
1819 aScrollSize
.AdjustWidth(-nScrollBarWidth
);
1820 setLayoutAllocation(*m_pHScroll
, aScrollPos
, aScrollSize
);
1821 aInnerSize
.AdjustHeight( -nScrollBarHeight
);
1826 Point
aBoxPos(aInnerSize
.Width() + 1, aInnerSize
.Height() + 1);
1827 m_aScrollBarBox
->SetPosSizePixel(aBoxPos
, Size(nScrollBarWidth
, nScrollBarHeight
));
1828 m_aScrollBarBox
->Show();
1832 m_aScrollBarBox
->Hide();
1835 if (pChild
&& pChild
->IsVisible())
1837 assert(dynamic_cast<VclViewport
*>(pChild
) && "scrolledwindow child should be a Viewport");
1839 WinBits nOldBits
= (GetStyle() & (WB_AUTOVSCROLL
| WB_VSCROLL
| WB_AUTOHSCROLL
| WB_HSCROLL
));
1841 setLayoutAllocation(*pChild
, Point(1, 1), aInnerSize
);
1843 // tdf#128758 if the layout allocation triggered some callback that
1844 // immediately invalidates the layout by adding scrollbars then
1845 // normally this would simply retrigger layout and another toplevel
1846 // attempt is made later. But the initial layout attempt blocks
1847 // relayouts, so just make another single effort here.
1848 WinBits nNewBits
= (GetStyle() & (WB_AUTOVSCROLL
| WB_VSCROLL
| WB_AUTOHSCROLL
| WB_HSCROLL
));
1849 if (nOldBits
!= nNewBits
&& bRetryOnFailure
)
1851 doSetAllocation(rAllocation
, false);
1856 if (!m_bUserManagedScrolling
)
1857 InitScrollBars(aChildReq
);
1860 void VclScrolledWindow::setAllocation(const Size
&rAllocation
)
1862 doSetAllocation(rAllocation
, true);
1865 Size
VclScrolledWindow::getVisibleChildSize() const
1867 Size
aRet(GetSizePixel());
1868 if (m_pVScroll
->IsVisible())
1869 aRet
.AdjustWidth( -(m_pVScroll
->GetSizePixel().Width()) );
1870 if (m_pHScroll
->IsVisible())
1871 aRet
.AdjustHeight( -(m_pHScroll
->GetSizePixel().Height()) );
1872 aRet
.AdjustHeight(-2);
1873 aRet
.AdjustWidth(-2);
1877 bool VclScrolledWindow::set_property(const OString
&rKey
, const OUString
&rValue
)
1879 bool bRet
= VclBin::set_property(rKey
, rValue
);
1880 m_pVScroll
->Show((GetStyle() & WB_VSCROLL
) != 0);
1881 m_pHScroll
->Show((GetStyle() & WB_HSCROLL
) != 0);
1885 bool VclScrolledWindow::EventNotify(NotifyEvent
& rNEvt
)
1888 if ( rNEvt
.GetType() == MouseNotifyEvent::COMMAND
)
1890 const CommandEvent
& rCEvt
= *rNEvt
.GetCommandEvent();
1891 if ( rCEvt
.GetCommand() == CommandEventId::Wheel
)
1893 const CommandWheelData
* pData
= rCEvt
.GetWheelData();
1894 if( !pData
->GetModifier() && ( pData
->GetMode() == CommandWheelMode::SCROLL
) )
1896 bDone
= HandleScrollCommand(rCEvt
, m_pHScroll
, m_pVScroll
);
1901 return bDone
|| VclBin::EventNotify( rNEvt
);
1904 void VclScrolledWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
)
1906 VclBin::Paint(rRenderContext
, rRect
);
1907 DecorationView
aDecoView(&rRenderContext
);
1908 aDecoView
.DrawFrame(tools::Rectangle(Point(0,0), GetSizePixel()));
1911 void VclViewport::setAllocation(const Size
&rAllocation
)
1913 vcl::Window
*pChild
= get_child();
1914 if (pChild
&& pChild
->IsVisible())
1916 Size
aReq(getLayoutRequisition(*pChild
));
1917 aReq
.setWidth( std::max(aReq
.Width(), rAllocation
.Width()) );
1918 aReq
.setHeight( std::max(aReq
.Height(), rAllocation
.Height()) );
1919 Point
aKeepPos(pChild
->GetPosPixel());
1920 if (m_bInitialAllocation
)
1922 aKeepPos
= Point(0, 0);
1923 m_bInitialAllocation
= false;
1925 setLayoutAllocation(*pChild
, aKeepPos
, aReq
);
1929 const vcl::Window
*VclEventBox::get_child() const
1931 const WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
1933 assert(pWindowImpl
->mpFirstChild
.get() == m_aEventBoxHelper
.get());
1935 return pWindowImpl
->mpFirstChild
->GetWindow(GetWindowType::Next
);
1938 vcl::Window
*VclEventBox::get_child()
1940 return const_cast<vcl::Window
*>(const_cast<const VclEventBox
*>(this)->get_child());
1943 void VclEventBox::setAllocation(const Size
& rAllocation
)
1945 Point
aChildPos(0, 0);
1946 for (vcl::Window
*pChild
= GetWindow(GetWindowType::FirstChild
); pChild
; pChild
= pChild
->GetWindow(GetWindowType::Next
))
1948 if (!pChild
->IsVisible())
1950 setLayoutAllocation(*pChild
, aChildPos
, rAllocation
);
1954 Size
VclEventBox::calculateRequisition() const
1958 for (const vcl::Window
* pChild
= get_child(); pChild
;
1959 pChild
= pChild
->GetWindow(GetWindowType::Next
))
1961 if (!pChild
->IsVisible())
1963 Size aChildSize
= getLayoutRequisition(*pChild
);
1964 aRet
.setWidth( std::max(aRet
.Width(), aChildSize
.Width()) );
1965 aRet
.setHeight( std::max(aRet
.Height(), aChildSize
.Height()) );
1971 void VclEventBox::Command(const CommandEvent
&)
1973 //discard events by default to block them reaching children
1976 VclEventBox::~VclEventBox()
1981 void VclEventBox::dispose()
1983 m_aEventBoxHelper
.disposeAndClear();
1987 void VclSizeGroup::trigger_queue_resize()
1989 //sufficient to trigger one widget to trigger all of them
1990 if (!m_aWindows
.empty())
1992 (*m_aWindows
.begin())->queue_resize();
1996 void VclSizeGroup::set_ignore_hidden(bool bIgnoreHidden
)
1998 if (bIgnoreHidden
!= m_bIgnoreHidden
)
2000 m_bIgnoreHidden
= bIgnoreHidden
;
2001 trigger_queue_resize();
2005 void VclSizeGroup::set_mode(VclSizeGroupMode eMode
)
2007 if (eMode
!= m_eMode
)
2010 trigger_queue_resize();
2015 void VclSizeGroup::set_property(const OString
&rKey
, const OUString
&rValue
)
2017 if (rKey
== "ignore-hidden")
2018 set_ignore_hidden(toBool(rValue
));
2019 else if (rKey
== "mode")
2021 VclSizeGroupMode eMode
= VclSizeGroupMode::Horizontal
;
2022 if (rValue
== "none")
2023 eMode
= VclSizeGroupMode::NONE
;
2024 else if (rValue
== "horizontal")
2025 eMode
= VclSizeGroupMode::Horizontal
;
2026 else if (rValue
== "vertical")
2027 eMode
= VclSizeGroupMode::Vertical
;
2028 else if (rValue
== "both")
2029 eMode
= VclSizeGroupMode::Both
;
2032 SAL_WARN("vcl.layout", "unknown size group mode" << rValue
);
2038 SAL_INFO("vcl.layout", "unhandled property: " << rKey
);
2042 void MessageDialog::create_message_area()
2044 setDeferredProperties();
2048 VclContainer
*pContainer
= get_content_area();
2051 m_pGrid
.set( VclPtr
<VclGrid
>::Create(pContainer
) );
2052 m_pGrid
->reorderWithinParent(0);
2053 m_pGrid
->set_column_spacing(12);
2054 m_pMessageBox
.set(VclPtr
<VclVBox
>::Create(m_pGrid
));
2055 m_pMessageBox
->set_grid_left_attach(1);
2056 m_pMessageBox
->set_grid_top_attach(0);
2057 m_pMessageBox
->set_spacing(GetTextHeight());
2059 m_pImage
= VclPtr
<FixedImage
>::Create(m_pGrid
, WB_CENTER
| WB_VCENTER
| WB_3DLOOK
);
2060 switch (m_eMessageType
)
2062 case VclMessageType::Info
:
2063 m_pImage
->SetImage(GetStandardInfoBoxImage());
2065 case VclMessageType::Warning
:
2066 m_pImage
->SetImage(GetStandardWarningBoxImage());
2068 case VclMessageType::Question
:
2069 m_pImage
->SetImage(GetStandardQueryBoxImage());
2071 case VclMessageType::Error
:
2072 m_pImage
->SetImage(GetStandardErrorBoxImage());
2075 m_pImage
->set_grid_left_attach(0);
2076 m_pImage
->set_grid_top_attach(0);
2077 m_pImage
->set_valign(VclAlign::Start
);
2080 WinBits nWinStyle
= WB_CLIPCHILDREN
| WB_LEFT
| WB_VCENTER
| WB_NOLABEL
| WB_NOTABSTOP
;
2082 bool bHasSecondaryText
= !m_sSecondaryString
.isEmpty();
2084 m_pPrimaryMessage
= VclPtr
<VclMultiLineEdit
>::Create(m_pMessageBox
, nWinStyle
);
2085 m_pPrimaryMessage
->SetPaintTransparent(true);
2086 m_pPrimaryMessage
->EnableCursor(false);
2088 m_pPrimaryMessage
->set_hexpand(true);
2089 m_pPrimaryMessage
->SetText(m_sPrimaryString
);
2090 m_pPrimaryMessage
->Show(!m_sPrimaryString
.isEmpty());
2092 m_pSecondaryMessage
= VclPtr
<VclMultiLineEdit
>::Create(m_pMessageBox
, nWinStyle
);
2093 m_pSecondaryMessage
->SetPaintTransparent(true);
2094 m_pSecondaryMessage
->EnableCursor(false);
2095 m_pSecondaryMessage
->set_hexpand(true);
2096 m_pSecondaryMessage
->SetText(m_sSecondaryString
);
2097 m_pSecondaryMessage
->Show(bHasSecondaryText
);
2099 MessageDialog::SetMessagesWidths(this, m_pPrimaryMessage
, bHasSecondaryText
? m_pSecondaryMessage
.get() : nullptr);
2101 VclButtonBox
*pButtonBox
= get_action_area();
2104 VclPtr
<PushButton
> pBtn
;
2105 short nDefaultResponse
= get_default_response();
2106 switch (m_eButtonsType
)
2108 case VclButtonsType::NONE
:
2110 case VclButtonsType::Ok
:
2111 pBtn
.set( VclPtr
<OKButton
>::Create(pButtonBox
) );
2112 pBtn
->SetStyle(pBtn
->GetStyle() & WB_DEFBUTTON
);
2115 add_button(pBtn
, RET_OK
, true);
2116 nDefaultResponse
= RET_OK
;
2118 case VclButtonsType::Close
:
2119 pBtn
.set( VclPtr
<CloseButton
>::Create(pButtonBox
) );
2120 pBtn
->SetStyle(pBtn
->GetStyle() & WB_DEFBUTTON
);
2122 pBtn
->set_id("close");
2123 add_button(pBtn
, RET_CLOSE
, true);
2124 nDefaultResponse
= RET_CLOSE
;
2126 case VclButtonsType::Cancel
:
2127 pBtn
.set( VclPtr
<CancelButton
>::Create(pButtonBox
) );
2128 pBtn
->SetStyle(pBtn
->GetStyle() & WB_DEFBUTTON
);
2130 pBtn
->set_id("cancel");
2131 add_button(pBtn
, RET_CANCEL
, true);
2132 nDefaultResponse
= RET_CANCEL
;
2134 case VclButtonsType::YesNo
:
2135 pBtn
= VclPtr
<PushButton
>::Create(pButtonBox
);
2136 pBtn
->SetText(GetStandardText(StandardButtonType::Yes
));
2138 pBtn
->set_id("yes");
2139 add_button(pBtn
, RET_YES
, true);
2141 pBtn
.set( VclPtr
<PushButton
>::Create(pButtonBox
) );
2142 pBtn
->SetText(GetStandardText(StandardButtonType::No
));
2145 add_button(pBtn
, RET_NO
, true);
2146 nDefaultResponse
= RET_NO
;
2148 case VclButtonsType::OkCancel
:
2149 pBtn
.set( VclPtr
<OKButton
>::Create(pButtonBox
) );
2152 add_button(pBtn
, RET_OK
, true);
2154 pBtn
.set( VclPtr
<CancelButton
>::Create(pButtonBox
) );
2156 pBtn
->set_id("cancel");
2157 add_button(pBtn
, RET_CANCEL
, true);
2158 nDefaultResponse
= RET_CANCEL
;
2161 set_default_response(nDefaultResponse
);
2162 pButtonBox
->sort_native_button_order();
2163 m_pMessageBox
->Show();
2168 void MessageDialog::create_owned_areas()
2171 set_border_width(3);
2173 set_border_width(12);
2175 m_pOwnedContentArea
.set(VclPtr
<VclVBox
>::Create(this, false, 24));
2176 set_content_area(m_pOwnedContentArea
);
2177 m_pOwnedContentArea
->Show();
2178 m_pOwnedActionArea
.set( VclPtr
<VclHButtonBox
>::Create(m_pOwnedContentArea
) );
2179 set_action_area(m_pOwnedActionArea
);
2180 m_pOwnedActionArea
->Show();
2183 MessageDialog::MessageDialog(vcl::Window
* pParent
, WinBits nStyle
)
2184 : Dialog(pParent
, nStyle
)
2185 , m_eButtonsType(VclButtonsType::NONE
)
2186 , m_eMessageType(VclMessageType::Info
)
2187 , m_pOwnedContentArea(nullptr)
2188 , m_pOwnedActionArea(nullptr)
2190 , m_pMessageBox(nullptr)
2192 , m_pPrimaryMessage(nullptr)
2193 , m_pSecondaryMessage(nullptr)
2195 SetType(WindowType::MESSBOX
);
2198 MessageDialog::MessageDialog(vcl::Window
* pParent
,
2199 const OUString
&rMessage
,
2200 VclMessageType eMessageType
,
2201 VclButtonsType eButtonsType
)
2202 : Dialog(pParent
, WB_MOVEABLE
| WB_3DLOOK
| WB_CLOSEABLE
)
2203 , m_eButtonsType(eButtonsType
)
2204 , m_eMessageType(eMessageType
)
2206 , m_pMessageBox(nullptr)
2208 , m_pPrimaryMessage(nullptr)
2209 , m_pSecondaryMessage(nullptr)
2210 , m_sPrimaryString(rMessage
)
2212 SetType(WindowType::MESSBOX
);
2213 create_owned_areas();
2214 create_message_area();
2216 switch (m_eMessageType
)
2218 case VclMessageType::Info
:
2219 SetText(GetStandardInfoBoxText());
2221 case VclMessageType::Warning
:
2222 SetText(GetStandardWarningBoxText());
2224 case VclMessageType::Question
:
2225 SetText(GetStandardQueryBoxText());
2227 case VclMessageType::Error
:
2228 SetText(GetStandardErrorBoxText());
2233 void MessageDialog::dispose()
2235 disposeOwnedButtons();
2236 m_pPrimaryMessage
.disposeAndClear();
2237 m_pSecondaryMessage
.disposeAndClear();
2238 m_pImage
.disposeAndClear();
2239 m_pMessageBox
.disposeAndClear();
2240 m_pGrid
.disposeAndClear();
2241 m_pOwnedActionArea
.disposeAndClear();
2242 m_pOwnedContentArea
.disposeAndClear();
2246 MessageDialog::~MessageDialog()
2251 void MessageDialog::SetMessagesWidths(vcl::Window
const *pParent
,
2252 VclMultiLineEdit
*pPrimaryMessage
, VclMultiLineEdit
*pSecondaryMessage
)
2254 if (pSecondaryMessage
)
2256 assert(pPrimaryMessage
);
2257 vcl::Font aFont
= pParent
->GetSettings().GetStyleSettings().GetLabelFont();
2258 aFont
.SetFontSize(Size(0, aFont
.GetFontSize().Height() * 1.2));
2259 aFont
.SetWeight(WEIGHT_BOLD
);
2260 pPrimaryMessage
->SetControlFont(aFont
);
2261 pPrimaryMessage
->SetMaxTextWidth(pPrimaryMessage
->approximate_char_width() * 44);
2262 pSecondaryMessage
->SetMaxTextWidth(pSecondaryMessage
->approximate_char_width() * 60);
2265 pPrimaryMessage
->SetMaxTextWidth(pPrimaryMessage
->approximate_char_width() * 60);
2268 OUString
const & MessageDialog::get_primary_text() const
2270 const_cast<MessageDialog
*>(this)->setDeferredProperties();
2272 return m_sPrimaryString
;
2275 OUString
const & MessageDialog::get_secondary_text() const
2277 const_cast<MessageDialog
*>(this)->setDeferredProperties();
2279 return m_sSecondaryString
;
2282 bool MessageDialog::set_property(const OString
&rKey
, const OUString
&rValue
)
2285 set_primary_text(rValue
);
2286 else if (rKey
== "secondary-text")
2287 set_secondary_text(rValue
);
2288 else if (rKey
== "message-type")
2290 VclMessageType eMode
= VclMessageType::Info
;
2291 if (rValue
== "info")
2292 eMode
= VclMessageType::Info
;
2293 else if (rValue
== "warning")
2294 eMode
= VclMessageType::Warning
;
2295 else if (rValue
== "question")
2296 eMode
= VclMessageType::Question
;
2297 else if (rValue
== "error")
2298 eMode
= VclMessageType::Error
;
2301 SAL_WARN("vcl.layout", "unknown message type mode" << rValue
);
2303 m_eMessageType
= eMode
;
2305 else if (rKey
== "buttons")
2307 VclButtonsType eMode
= VclButtonsType::NONE
;
2308 if (rValue
== "none")
2309 eMode
= VclButtonsType::NONE
;
2310 else if (rValue
== "ok")
2311 eMode
= VclButtonsType::Ok
;
2312 else if (rValue
== "cancel")
2313 eMode
= VclButtonsType::Cancel
;
2314 else if (rValue
== "close")
2315 eMode
= VclButtonsType::Close
;
2316 else if (rValue
== "yes-no")
2317 eMode
= VclButtonsType::YesNo
;
2318 else if (rValue
== "ok-cancel")
2319 eMode
= VclButtonsType::OkCancel
;
2322 SAL_WARN("vcl.layout", "unknown buttons type mode" << rValue
);
2324 m_eButtonsType
= eMode
;
2327 return Dialog::set_property(rKey
, rValue
);
2331 void MessageDialog::set_primary_text(const OUString
&rPrimaryString
)
2333 m_sPrimaryString
= rPrimaryString
;
2334 if (m_pPrimaryMessage
)
2336 m_pPrimaryMessage
->SetText(m_sPrimaryString
);
2337 m_pPrimaryMessage
->Show(!m_sPrimaryString
.isEmpty());
2338 MessageDialog::SetMessagesWidths(this, m_pPrimaryMessage
, !m_sSecondaryString
.isEmpty() ? m_pSecondaryMessage
.get() : nullptr);
2342 void MessageDialog::set_secondary_text(const OUString
&rSecondaryString
)
2344 m_sSecondaryString
= rSecondaryString
;
2345 if (m_pSecondaryMessage
)
2347 m_pSecondaryMessage
->SetText("\n" + m_sSecondaryString
);
2348 m_pSecondaryMessage
->Show(!m_sSecondaryString
.isEmpty());
2349 MessageDialog::SetMessagesWidths(this, m_pPrimaryMessage
, !m_sSecondaryString
.isEmpty() ? m_pSecondaryMessage
.get() : nullptr);
2353 void MessageDialog::StateChanged(StateChangedType nType
)
2355 Dialog::StateChanged(nType
);
2356 if (nType
== StateChangedType::InitShow
)
2358 // MessageBox should be at least as wide as to see the title
2359 auto nTitleWidth
= CalcTitleWidth();
2360 // Extra-Width for Close button
2361 nTitleWidth
+= mpWindowImpl
->mnTopBorder
;
2362 if (get_preferred_size().Width() < nTitleWidth
)
2364 set_width_request(nTitleWidth
);
2370 VclPaned::VclPaned(vcl::Window
*pParent
, bool bVertical
)
2371 : VclContainer(pParent
, WB_HIDE
| WB_CLIPCHILDREN
)
2372 , m_pSplitter(VclPtr
<Splitter
>::Create(this, bVertical
? WB_VSCROLL
: WB_HSCROLL
))
2375 m_pSplitter
->SetBackground(Wallpaper(Application::GetSettings().GetStyleSettings().GetFaceColor()));
2376 m_pSplitter
->Show();
2379 void VclPaned::dispose()
2381 m_pSplitter
.disposeAndClear();
2382 VclContainer::dispose();
2385 VclVPaned::VclVPaned(vcl::Window
*pParent
)
2386 : VclPaned(pParent
, true)
2388 m_pSplitter
->SetSplitHdl(LINK(this, VclVPaned
, SplitHdl
));
2391 IMPL_LINK(VclVPaned
, SplitHdl
, Splitter
*, pSplitter
, void)
2393 long nSize
= pSplitter
->GetSplitPosPixel();
2394 Size
aSplitterSize(m_pSplitter
->GetSizePixel());
2395 Size
aAllocation(GetSizePixel());
2396 arrange(aAllocation
, nSize
, aAllocation
.Height() - nSize
- aSplitterSize
.Height());
2399 void VclVPaned::arrange(const Size
& rAllocation
, long nFirstHeight
, long nSecondHeight
)
2401 Size
aSplitterSize(rAllocation
.Width(), getLayoutRequisition(*m_pSplitter
).Height());
2402 Size
aFirstChildSize(rAllocation
.Width(), nFirstHeight
);
2403 Size
aSecondChildSize(rAllocation
.Width(), nSecondHeight
);
2405 for (vcl::Window
* pChild
= GetWindow(GetWindowType::FirstChild
); pChild
;
2406 pChild
= pChild
->GetWindow(GetWindowType::Next
))
2408 if (!pChild
->IsVisible())
2412 Point
aSplitterPos(0, aFirstChildSize
.Height());
2413 setLayoutAllocation(*m_pSplitter
, aSplitterPos
, aSplitterSize
);
2414 set_position(aSplitterPos
.Y() + aSplitterSize
.Height() / 2);
2416 else if (nElement
== 1)
2418 Point
aChildPos(0, 0);
2419 setLayoutAllocation(*pChild
, aChildPos
, aFirstChildSize
);
2421 else if (nElement
== 2)
2423 Point
aChildPos(0, aFirstChildSize
.Height() + aSplitterSize
.Height());
2424 setLayoutAllocation(*pChild
, aChildPos
, aSecondChildSize
);
2430 void VclVPaned::setAllocation(const Size
& rAllocation
)
2432 //supporting "shrink" could be done by adjusting the allowed drag rectangle
2433 m_pSplitter
->SetDragRectPixel(tools::Rectangle(Point(0, 0), rAllocation
));
2434 Size
aSplitterSize(rAllocation
.Width(), getLayoutRequisition(*m_pSplitter
).Height());
2435 const long nHeight
= rAllocation
.Height() - aSplitterSize
.Height();
2437 long nFirstHeight
= 0;
2438 long nSecondHeight
= 0;
2439 bool bFirstCanResize
= true;
2440 bool bSecondCanResize
= true;
2441 const bool bInitialAllocation
= get_position() < 0;
2443 for (const vcl::Window
* pChild
= GetWindow(GetWindowType::FirstChild
); pChild
;
2444 pChild
= pChild
->GetWindow(GetWindowType::Next
))
2446 if (!pChild
->IsVisible())
2450 if (bInitialAllocation
)
2451 nFirstHeight
= getLayoutRequisition(*pChild
).Height();
2453 nFirstHeight
= pChild
->GetSizePixel().Height();
2454 bFirstCanResize
= pChild
->get_expand();
2456 else if (nElement
== 2)
2458 if (bInitialAllocation
)
2459 nSecondHeight
= getLayoutRequisition(*pChild
).Height();
2461 nSecondHeight
= pChild
->GetSizePixel().Height();
2462 bSecondCanResize
= pChild
->get_expand();
2466 long nHeightRequest
= nFirstHeight
+ nSecondHeight
;
2467 long nHeightDiff
= nHeight
- nHeightRequest
;
2468 if (bFirstCanResize
== bSecondCanResize
)
2469 nFirstHeight
+= nHeightDiff
/2;
2470 else if (bFirstCanResize
)
2471 nFirstHeight
+= nHeightDiff
;
2472 arrange(rAllocation
, nFirstHeight
, rAllocation
.Height() - nFirstHeight
- aSplitterSize
.Height());
2475 Size
VclVPaned::calculateRequisition() const
2479 for (const vcl::Window
* pChild
= GetWindow(GetWindowType::FirstChild
); pChild
;
2480 pChild
= pChild
->GetWindow(GetWindowType::Next
))
2482 if (!pChild
->IsVisible())
2484 Size aChildSize
= getLayoutRequisition(*pChild
);
2485 aRet
.setWidth( std::max(aRet
.Width(), aChildSize
.Width()) );
2486 aRet
.AdjustHeight(aChildSize
.Height() );
2492 VclHPaned::VclHPaned(vcl::Window
*pParent
)
2493 : VclPaned(pParent
, false)
2495 m_pSplitter
->SetSplitHdl(LINK(this, VclHPaned
, SplitHdl
));
2498 IMPL_LINK(VclHPaned
, SplitHdl
, Splitter
*, pSplitter
, void)
2500 long nSize
= pSplitter
->GetSplitPosPixel();
2501 Size
aSplitterSize(m_pSplitter
->GetSizePixel());
2502 Size
aAllocation(GetSizePixel());
2503 arrange(aAllocation
, nSize
, aAllocation
.Width() - nSize
- aSplitterSize
.Width());
2506 void VclHPaned::arrange(const Size
& rAllocation
, long nFirstWidth
, long nSecondWidth
)
2508 Size
aSplitterSize(getLayoutRequisition(*m_pSplitter
).Width(), rAllocation
.Height());
2509 Size
aFirstChildSize(nFirstWidth
, rAllocation
.Height());
2510 Size
aSecondChildSize(nSecondWidth
, rAllocation
.Height());
2512 for (vcl::Window
* pChild
= GetWindow(GetWindowType::FirstChild
); pChild
;
2513 pChild
= pChild
->GetWindow(GetWindowType::Next
))
2515 if (!pChild
->IsVisible())
2519 Point
aSplitterPos(aFirstChildSize
.Width(), 0);
2520 setLayoutAllocation(*m_pSplitter
, aSplitterPos
, aSplitterSize
);
2521 set_position(aSplitterPos
.X() + aSplitterSize
.Width() / 2);
2523 else if (nElement
== 1)
2525 Point
aChildPos(0, 0);
2526 setLayoutAllocation(*pChild
, aChildPos
, aFirstChildSize
);
2528 else if (nElement
== 2)
2530 Point
aChildPos(aFirstChildSize
.Width() + aSplitterSize
.Width(), 0);
2531 setLayoutAllocation(*pChild
, aChildPos
, aSecondChildSize
);
2537 void VclHPaned::setAllocation(const Size
& rAllocation
)
2539 //supporting "shrink" could be done by adjusting the allowed drag rectangle
2540 m_pSplitter
->SetDragRectPixel(tools::Rectangle(Point(0, 0), rAllocation
));
2541 Size
aSplitterSize(getLayoutRequisition(*m_pSplitter
).Width(), rAllocation
.Height());
2542 const long nWidth
= rAllocation
.Width() - aSplitterSize
.Width();
2544 long nFirstWidth
= 0;
2545 long nSecondWidth
= 0;
2546 bool bFirstCanResize
= true;
2547 bool bSecondCanResize
= true;
2548 const bool bInitialAllocation
= get_position() < 0;
2550 for (const vcl::Window
* pChild
= GetWindow(GetWindowType::FirstChild
); pChild
;
2551 pChild
= pChild
->GetWindow(GetWindowType::Next
))
2553 if (!pChild
->IsVisible())
2557 if (bInitialAllocation
)
2558 nFirstWidth
= getLayoutRequisition(*pChild
).Width();
2560 nFirstWidth
= pChild
->GetSizePixel().Width();
2561 bFirstCanResize
= pChild
->get_expand();
2563 else if (nElement
== 2)
2565 if (bInitialAllocation
)
2566 nSecondWidth
= getLayoutRequisition(*pChild
).Width();
2568 nSecondWidth
= pChild
->GetSizePixel().Width();
2569 bSecondCanResize
= pChild
->get_expand();
2573 long nWidthRequest
= nFirstWidth
+ nSecondWidth
;
2574 long nWidthDiff
= nWidth
- nWidthRequest
;
2575 if (bFirstCanResize
== bSecondCanResize
)
2576 nFirstWidth
+= nWidthDiff
/2;
2577 else if (bFirstCanResize
)
2578 nFirstWidth
+= nWidthDiff
;
2579 arrange(rAllocation
, nFirstWidth
, rAllocation
.Width() - nFirstWidth
- aSplitterSize
.Width());
2582 Size
VclHPaned::calculateRequisition() const
2586 for (const vcl::Window
* pChild
= GetWindow(GetWindowType::FirstChild
); pChild
;
2587 pChild
= pChild
->GetWindow(GetWindowType::Next
))
2589 if (!pChild
->IsVisible())
2591 Size aChildSize
= getLayoutRequisition(*pChild
);
2592 aRet
.setHeight( std::max(aRet
.Height(), aChildSize
.Height()) );
2593 aRet
.AdjustWidth(aChildSize
.Width() );
2599 Size
getLegacyBestSizeForChildren(const vcl::Window
&rWindow
)
2601 tools::Rectangle aBounds
;
2603 for (const vcl::Window
* pChild
= rWindow
.GetWindow(GetWindowType::FirstChild
); pChild
;
2604 pChild
= pChild
->GetWindow(GetWindowType::Next
))
2606 if (!pChild
->IsVisible())
2609 tools::Rectangle
aChildBounds(pChild
->GetPosPixel(), pChild
->GetSizePixel());
2610 aBounds
.Union(aChildBounds
);
2613 if (aBounds
.IsEmpty())
2614 return rWindow
.GetSizePixel();
2616 Size
aRet(aBounds
.GetSize());
2617 Point
aTopLeft(aBounds
.TopLeft());
2618 aRet
.AdjustWidth(aTopLeft
.X()*2 );
2619 aRet
.AdjustHeight(aTopLeft
.Y()*2 );
2624 vcl::Window
* getNonLayoutParent(vcl::Window
*pWindow
)
2628 pWindow
= pWindow
->GetParent();
2629 if (!pWindow
|| !isContainerWindow(*pWindow
))
2635 bool isVisibleInLayout(const vcl::Window
*pWindow
)
2637 bool bVisible
= true;
2640 bVisible
= pWindow
->IsVisible();
2641 pWindow
= pWindow
->GetParent();
2642 if (!pWindow
|| !isContainerWindow(*pWindow
))
2648 bool isEnabledInLayout(const vcl::Window
*pWindow
)
2650 bool bEnabled
= true;
2653 bEnabled
= pWindow
->IsEnabled();
2654 pWindow
= pWindow
->GetParent();
2655 if (!pWindow
|| !isContainerWindow(*pWindow
))
2661 bool isLayoutEnabled(const vcl::Window
*pWindow
)
2663 //Child is a container => we're layout enabled
2664 const vcl::Window
*pChild
= pWindow
? pWindow
->GetWindow(GetWindowType::FirstChild
) : nullptr;
2665 return pChild
&& isContainerWindow(*pChild
) && !pChild
->GetWindow(GetWindowType::Next
);
2668 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */