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/dialog.hxx>
14 #include <vcl/IPrioritable.hxx>
15 #include <vcl/layout.hxx>
16 #include <vcl/msgbox.hxx>
17 #include <vcl/svapp.hxx>
18 #include <vcl/settings.hxx>
20 #include <boost/multi_array.hpp>
21 #include <officecfg/Office/Common.hxx>
22 #include <vcl/abstdlg.hxx>
24 VclContainer::VclContainer(vcl::Window
*pParent
, WinBits nStyle
)
25 : Window(WINDOW_CONTAINER
)
27 , m_bLayoutDirty(true)
29 ImplInit(pParent
, nStyle
, nullptr);
30 EnableChildTransparentMode();
31 SetPaintTransparent(true);
35 sal_uInt16
VclContainer::getDefaultAccessibleRole() const
37 return css::accessibility::AccessibleRole::PANEL
;
40 Size
VclContainer::GetOptimalSize() const
42 return calculateRequisition();
45 void VclContainer::setLayoutPosSize(vcl::Window
&rWindow
, const Point
&rPos
, const Size
&rSize
)
47 sal_Int32 nBorderWidth
= rWindow
.get_border_width();
48 sal_Int32 nLeft
= rWindow
.get_margin_left() + nBorderWidth
;
49 sal_Int32 nTop
= rWindow
.get_margin_top() + nBorderWidth
;
50 sal_Int32 nRight
= rWindow
.get_margin_right() + nBorderWidth
;
51 sal_Int32 nBottom
= rWindow
.get_margin_bottom() + nBorderWidth
;
52 Point
aPos(rPos
.X() + nLeft
, rPos
.Y() + nTop
);
53 Size
aSize(rSize
.Width() - nLeft
- nRight
, rSize
.Height() - nTop
- nBottom
);
54 rWindow
.SetPosSizePixel(aPos
, aSize
);
57 void VclContainer::setLayoutAllocation(vcl::Window
&rChild
, const Point
&rAllocPos
, const Size
&rChildAlloc
)
59 VclAlign eHalign
= rChild
.get_halign();
60 VclAlign eValign
= rChild
.get_valign();
63 if (eHalign
== VclAlign::Fill
&& eValign
== VclAlign::Fill
)
65 setLayoutPosSize(rChild
, rAllocPos
, rChildAlloc
);
69 Point
aChildPos(rAllocPos
);
70 Size
aChildSize(rChildAlloc
);
71 Size
aChildPreferredSize(getLayoutRequisition(rChild
));
78 if (aChildPreferredSize
.Width() < rChildAlloc
.Width())
79 aChildSize
.Width() = aChildPreferredSize
.Width();
82 if (aChildPreferredSize
.Width() < rChildAlloc
.Width())
83 aChildSize
.Width() = aChildPreferredSize
.Width();
84 aChildPos
.X() += rChildAlloc
.Width();
85 aChildPos
.X() -= aChildSize
.Width();
87 case VclAlign::Center
:
88 if (aChildPreferredSize
.Width() < aChildSize
.Width())
89 aChildSize
.Width() = aChildPreferredSize
.Width();
90 aChildPos
.X() += (rChildAlloc
.Width() - aChildSize
.Width()) / 2;
99 if (aChildPreferredSize
.Height() < rChildAlloc
.Height())
100 aChildSize
.Height() = aChildPreferredSize
.Height();
103 if (aChildPreferredSize
.Height() < rChildAlloc
.Height())
104 aChildSize
.Height() = aChildPreferredSize
.Height();
105 aChildPos
.Y() += rChildAlloc
.Height();
106 aChildPos
.Y() -= aChildSize
.Height();
108 case VclAlign::Center
:
109 if (aChildPreferredSize
.Height() < aChildSize
.Height())
110 aChildSize
.Height() = aChildPreferredSize
.Height();
111 aChildPos
.Y() += (rChildAlloc
.Height() - aChildSize
.Height()) / 2;
115 setLayoutPosSize(rChild
, aChildPos
, aChildSize
);
120 Size
subtractBorder(const vcl::Window
&rWindow
, const Size
& rSize
)
122 sal_Int32 nBorderWidth
= rWindow
.get_border_width();
123 sal_Int32 nLeft
= rWindow
.get_margin_left() + nBorderWidth
;
124 sal_Int32 nTop
= rWindow
.get_margin_top() + nBorderWidth
;
125 sal_Int32 nRight
= rWindow
.get_margin_right() + nBorderWidth
;
126 sal_Int32 nBottom
= rWindow
.get_margin_bottom() + nBorderWidth
;
128 return Size(aSize
.Width() + nLeft
+ nRight
, aSize
.Height() + nTop
+ nBottom
);
132 Size
VclContainer::getLayoutRequisition(const vcl::Window
&rWindow
)
134 return subtractBorder(rWindow
, rWindow
.get_preferred_size());
137 void VclContainer::SetPosSizePixel(const Point
& rAllocPos
, const Size
& rAllocation
)
139 bool bSizeChanged
= rAllocation
!= GetOutputSizePixel();
140 Window::SetPosSizePixel(rAllocPos
, rAllocation
);
141 if (m_bLayoutDirty
|| bSizeChanged
)
143 m_bLayoutDirty
= false;
144 setAllocation(rAllocation
);
148 void VclContainer::SetPosPixel(const Point
& rAllocPos
)
150 Point aAllocPos
= rAllocPos
;
151 sal_Int32 nBorderWidth
= get_border_width();
152 aAllocPos
.X() += nBorderWidth
+ get_margin_left();
153 aAllocPos
.Y() += nBorderWidth
+ get_margin_top();
155 if (aAllocPos
!= GetPosPixel())
156 Window::SetPosPixel(aAllocPos
);
159 void VclContainer::SetSizePixel(const Size
& rAllocation
)
161 Size aAllocation
= rAllocation
;
162 sal_Int32 nBorderWidth
= get_border_width();
163 aAllocation
.Width() -= nBorderWidth
*2 + get_margin_left() + get_margin_right();
164 aAllocation
.Height() -= nBorderWidth
*2 + get_margin_top() + get_margin_bottom();
165 bool bSizeChanged
= aAllocation
!= GetSizePixel();
167 Window::SetSizePixel(aAllocation
);
168 if (m_bLayoutDirty
|| bSizeChanged
)
170 m_bLayoutDirty
= false;
171 setAllocation(aAllocation
);
175 void VclContainer::queue_resize(StateChangedType eReason
)
177 m_bLayoutDirty
= true;
178 Window::queue_resize(eReason
);
182 Button
* isVisibleButtonWithText(vcl::Window
* pCandidate
)
187 if (!pCandidate
->IsVisible())
190 if (pCandidate
->GetText().isEmpty())
193 return dynamic_cast<Button
*>(pCandidate
);
196 // evtl. support for screenshot context menu
197 void VclContainer::Command(const CommandEvent
& rCEvt
)
199 if (rCEvt
.IsMouseEvent() && CommandEventId::ContextMenu
== rCEvt
.GetCommand())
201 const bool bScreenshotMode(officecfg::Office::Common::Misc::ScreenshotMode::get());
205 bool bVisibleChildren(false);
206 vcl::Window
* pChild(nullptr);
208 for (pChild
= GetWindow(GetWindowType::FirstChild
); !bVisibleChildren
&& pChild
; pChild
= pChild
->GetWindow(GetWindowType::Next
))
210 Button
* pCandidate
= isVisibleButtonWithText(pChild
);
212 if (nullptr == pCandidate
)
215 bVisibleChildren
= true;
218 if (bVisibleChildren
)
220 static bool bAddButtonsToMenu(true);
221 static bool bAddScreenshotButtonToMenu(true);
223 if (bAddButtonsToMenu
|| bAddScreenshotButtonToMenu
)
225 const Point
aMenuPos(rCEvt
.GetMousePosPixel());
226 ScopedVclPtrInstance
<PopupMenu
> aMenu
;
227 sal_uInt16
nLocalID(1);
228 sal_uInt16
nScreenshotButtonID(0);
230 if (bAddButtonsToMenu
)
232 for (pChild
= GetWindow(GetWindowType::FirstChild
); pChild
; pChild
= pChild
->GetWindow(GetWindowType::Next
))
234 Button
* pCandidate
= isVisibleButtonWithText(pChild
);
236 if (nullptr == pCandidate
)
244 pChild
->GetHelpText());
247 pChild
->GetHelpId());
250 pChild
->IsEnabled());
255 if (bAddScreenshotButtonToMenu
)
259 aMenu
->InsertSeparator();
267 "Go into interactive screenshot annotation mode");
270 "InteractiveScreenshotMode");
273 nScreenshotButtonID
= nLocalID
;
276 const sal_uInt16
nId(aMenu
->Execute(this, aMenuPos
));
278 // 0 == no selection (so not usable as ID)
281 if (bAddButtonsToMenu
&& nId
< nLocalID
)
285 for (pChild
= GetWindow(GetWindowType::FirstChild
); pChild
; pChild
= pChild
->GetWindow(GetWindowType::Next
))
287 Button
* pCandidate
= isVisibleButtonWithText(pChild
);
289 if (nullptr == pCandidate
)
292 if (nLocalID
++ == nId
)
294 // pCandidate is the selected button, trigger it
301 if (bAddScreenshotButtonToMenu
&& nId
== nScreenshotButtonID
)
303 // screenshot was selected, access parent dialog (needed for
304 // screenshot and other data access)
305 Dialog
* pParentDialog
= GetParentDialog();
309 // open screenshot annotation dialog
310 VclAbstractDialogFactory
* pFact
= VclAbstractDialogFactory::Create();
311 VclPtr
<AbstractScreenshotAnnotationDlg
> pTmp
= pFact
->CreateScreenshotAnnotationDlg(
312 Application::GetDefDialogParent(),
314 ScopedVclPtr
<AbstractScreenshotAnnotationDlg
> pDialog(pTmp
);
318 // currently just execute the dialog, no need to do
319 // different things for ok/cancel. This may change later,
320 // for that case use 'if (pDlg->Execute() == RET_OK)'
327 // consume event when:
328 // - CommandEventId::ContextMenu
330 // - bVisibleChildren
337 // call parent (do not consume)
338 Window::Command(rCEvt
);
341 void VclBox::accumulateMaxes(const Size
&rChildSize
, Size
&rSize
) const
343 long nSecondaryChildDimension
= getSecondaryDimension(rChildSize
);
344 long nSecondaryBoxDimension
= getSecondaryDimension(rSize
);
345 setSecondaryDimension(rSize
, std::max(nSecondaryChildDimension
, nSecondaryBoxDimension
));
347 long nPrimaryChildDimension
= getPrimaryDimension(rChildSize
);
348 long nPrimaryBoxDimension
= getPrimaryDimension(rSize
);
350 setPrimaryDimension(rSize
, std::max(nPrimaryBoxDimension
, nPrimaryChildDimension
));
352 setPrimaryDimension(rSize
, nPrimaryBoxDimension
+ nPrimaryChildDimension
);
355 Size
VclBox::calculateRequisition() const
357 sal_uInt16 nVisibleChildren
= 0;
360 for (vcl::Window
*pChild
= GetWindow(GetWindowType::FirstChild
); pChild
; pChild
= pChild
->GetWindow(GetWindowType::Next
))
362 if (!pChild
->IsVisible())
365 Size aChildSize
= getLayoutRequisition(*pChild
);
367 long nPrimaryDimension
= getPrimaryDimension(aChildSize
);
368 nPrimaryDimension
+= pChild
->get_padding() * 2;
369 setPrimaryDimension(aChildSize
, nPrimaryDimension
);
371 accumulateMaxes(aChildSize
, aSize
);
374 return finalizeMaxes(aSize
, nVisibleChildren
);
377 void VclBox::setAllocation(const Size
&rAllocation
)
379 sal_uInt16 nVisibleChildren
= 0, nExpandChildren
= 0;
380 for (vcl::Window
*pChild
= GetWindow(GetWindowType::FirstChild
); pChild
; pChild
= pChild
->GetWindow(GetWindowType::Next
))
382 if (!pChild
->IsVisible())
385 bool bExpand
= getPrimaryDimensionChildExpand(*pChild
);
390 if (!nVisibleChildren
)
393 long nAllocPrimaryDimension
= getPrimaryDimension(rAllocation
);
395 long nHomogeneousDimension
= 0, nExtraSpace
= 0;
398 nHomogeneousDimension
= ((nAllocPrimaryDimension
-
399 (nVisibleChildren
- 1) * m_nSpacing
)) / nVisibleChildren
;
401 else if (nExpandChildren
)
403 Size aRequisition
= calculateRequisition();
404 nExtraSpace
= (getPrimaryDimension(rAllocation
) - getPrimaryDimension(aRequisition
)) / nExpandChildren
;
407 //Split into those we pack from the start onwards, and those we pack from the end backwards
408 o3tl::enumarray
<VclPackType
,std::vector
<vcl::Window
*>> aWindows
;
409 for (vcl::Window
*pChild
= GetWindow(GetWindowType::FirstChild
); pChild
; pChild
= pChild
->GetWindow(GetWindowType::Next
))
411 if (!pChild
->IsVisible())
414 VclPackType ePacking
= pChild
->get_pack_type();
415 aWindows
[ePacking
].push_back(pChild
);
418 //See VclBuilder::sortIntoBestTabTraversalOrder for why they are in visual
419 //order under the parent which requires us to reverse them here to
420 //pack from the end back
421 std::reverse(aWindows
[VclPackType::End
].begin(),aWindows
[VclPackType::End
].end());
423 for (VclPackType ePackType
: o3tl::enumrange
<VclPackType
>())
426 if (ePackType
== VclPackType::End
)
428 long nPrimaryCoordinate
= getPrimaryCoordinate(aPos
);
429 setPrimaryCoordinate(aPos
, nPrimaryCoordinate
+ nAllocPrimaryDimension
);
432 for (std::vector
<vcl::Window
*>::iterator aI
= aWindows
[ePackType
].begin(), aEnd
= aWindows
[ePackType
].end(); aI
!= aEnd
; ++aI
)
434 vcl::Window
*pChild
= *aI
;
436 long nPadding
= pChild
->get_padding();
440 setPrimaryDimension(aBoxSize
, nHomogeneousDimension
);
443 aBoxSize
= getLayoutRequisition(*pChild
);
444 long nPrimaryDimension
= getPrimaryDimension(aBoxSize
);
445 nPrimaryDimension
+= nPadding
* 2;
446 if (getPrimaryDimensionChildExpand(*pChild
))
447 nPrimaryDimension
+= nExtraSpace
;
448 setPrimaryDimension(aBoxSize
, nPrimaryDimension
);
450 setSecondaryDimension(aBoxSize
, getSecondaryDimension(rAllocation
));
452 Point
aChildPos(aPos
);
453 Size
aChildSize(aBoxSize
);
454 long nPrimaryCoordinate
= getPrimaryCoordinate(aPos
);
456 bool bFill
= pChild
->get_fill();
459 setPrimaryDimension(aChildSize
, std::max(static_cast<long>(1),
460 getPrimaryDimension(aBoxSize
) - nPadding
* 2));
462 setPrimaryCoordinate(aChildPos
, nPrimaryCoordinate
+ nPadding
);
466 setPrimaryDimension(aChildSize
,
467 getPrimaryDimension(getLayoutRequisition(*pChild
)));
469 setPrimaryCoordinate(aChildPos
, nPrimaryCoordinate
+
470 (getPrimaryDimension(aBoxSize
) - getPrimaryDimension(aChildSize
)) / 2);
473 long nDiff
= getPrimaryDimension(aBoxSize
) + m_nSpacing
;
474 if (ePackType
== VclPackType::Start
)
475 setPrimaryCoordinate(aPos
, nPrimaryCoordinate
+ nDiff
);
478 setPrimaryCoordinate(aPos
, nPrimaryCoordinate
- nDiff
);
479 setPrimaryCoordinate(aChildPos
, getPrimaryCoordinate(aChildPos
) -
480 getPrimaryDimension(aBoxSize
));
483 setLayoutAllocation(*pChild
, aChildPos
, aChildSize
);
488 bool VclBox::set_property(const OString
&rKey
, const OString
&rValue
)
490 if (rKey
== "spacing")
491 set_spacing(rValue
.toInt32());
492 else if (rKey
== "homogeneous")
493 set_homogeneous(toBool(rValue
));
495 return VclContainer::set_property(rKey
, rValue
);
499 sal_uInt16
VclBox::getDefaultAccessibleRole() const
502 //fdo#74284 call Boxes Panels, keep then as "Filler" under
503 //at least Linux seeing as that's what Gtk does for GtkBoxes
504 return css::accessibility::AccessibleRole::PANEL
;
506 return css::accessibility::AccessibleRole::FILLER
;
510 #define DEFAULT_CHILD_MIN_WIDTH 85
511 #define DEFAULT_CHILD_MIN_HEIGHT 27
513 Size
VclBox::finalizeMaxes(const Size
&rSize
, sal_uInt16 nVisibleChildren
) const
517 if (nVisibleChildren
)
519 long nPrimaryDimension
= getPrimaryDimension(rSize
);
521 nPrimaryDimension
*= nVisibleChildren
;
522 setPrimaryDimension(aRet
, nPrimaryDimension
+ m_nSpacing
* (nVisibleChildren
-1));
523 setSecondaryDimension(aRet
, getSecondaryDimension(rSize
));
529 Size
VclButtonBox::addReqGroups(const VclButtonBox::Requisition
&rReq
) const
533 long nMainGroupDimension
= getPrimaryDimension(rReq
.m_aMainGroupSize
);
534 long nSubGroupDimension
= getPrimaryDimension(rReq
.m_aSubGroupSize
);
536 setPrimaryDimension(aRet
, nMainGroupDimension
+ nSubGroupDimension
);
538 setSecondaryDimension(aRet
,
539 std::max(getSecondaryDimension(rReq
.m_aMainGroupSize
),
540 getSecondaryDimension(rReq
.m_aSubGroupSize
)));
545 static long getMaxNonOutlier(const std::vector
<long> &rG
, long nAvgDimension
)
547 long nMaxDimensionNonOutlier
= 0;
548 for (std::vector
<long>::const_iterator aI
= rG
.begin(),
549 aEnd
= rG
.end(); aI
!= aEnd
; ++aI
)
551 long nPrimaryChildDimension
= *aI
;
552 if (nPrimaryChildDimension
< nAvgDimension
* 1.5)
554 nMaxDimensionNonOutlier
= std::max(nPrimaryChildDimension
,
555 nMaxDimensionNonOutlier
);
558 return nMaxDimensionNonOutlier
;
561 static std::vector
<long> setButtonSizes(const std::vector
<long> &rG
,
562 const std::vector
<bool> &rNonHomogeneous
,
563 long nAvgDimension
, long nMaxNonOutlier
, long nMinWidth
)
565 std::vector
<long> aVec
;
566 //set everything < 1.5 times the average to the same width, leave the
567 //outliers un-touched
568 std::vector
<bool>::const_iterator aJ
= rNonHomogeneous
.begin();
569 for (std::vector
<long>::const_iterator aI
= rG
.begin(), aEnd
= rG
.end();
570 aI
!= aEnd
; ++aI
, ++aJ
)
572 long nPrimaryChildDimension
= *aI
;
573 bool bNonHomogeneous
= *aJ
;
574 if (!bNonHomogeneous
&& nPrimaryChildDimension
< nAvgDimension
* 1.5)
576 aVec
.push_back(std::max(nMaxNonOutlier
, nMinWidth
));
580 aVec
.push_back(std::max(nPrimaryChildDimension
, nMinWidth
));
586 VclButtonBox::Requisition
VclButtonBox::calculatePrimarySecondaryRequisitions() const
590 Size
aMainGroupSize(DEFAULT_CHILD_MIN_WIDTH
, DEFAULT_CHILD_MIN_HEIGHT
); //to-do, pull from theme
591 Size
aSubGroupSize(DEFAULT_CHILD_MIN_WIDTH
, DEFAULT_CHILD_MIN_HEIGHT
); //to-do, pull from theme
593 long nMinMainGroupPrimary
= getPrimaryDimension(aMainGroupSize
);
594 long nMinSubGroupPrimary
= getPrimaryDimension(aSubGroupSize
);
595 long nMainGroupSecondary
= getSecondaryDimension(aMainGroupSize
);
596 long nSubGroupSecondary
= getSecondaryDimension(aSubGroupSize
);
598 bool bIgnoreSecondaryPacking
= (m_eLayoutStyle
== VCL_BUTTONBOX_SPREAD
|| m_eLayoutStyle
== VCL_BUTTONBOX_CENTER
);
600 std::vector
<long> aMainGroupSizes
;
601 std::vector
<bool> aMainGroupNonHomogeneous
;
602 std::vector
<long> aSubGroupSizes
;
603 std::vector
<bool> aSubGroupNonHomogeneous
;
605 for (const vcl::Window
*pChild
= GetWindow(GetWindowType::FirstChild
); pChild
; pChild
= pChild
->GetWindow(GetWindowType::Next
))
607 if (!pChild
->IsVisible())
609 Size aChildSize
= getLayoutRequisition(*pChild
);
610 if (bIgnoreSecondaryPacking
|| !pChild
->get_secondary())
612 //set the max secondary dimension
613 nMainGroupSecondary
= std::max(nMainGroupSecondary
, getSecondaryDimension(aChildSize
));
614 //collect the primary dimensions
615 aMainGroupSizes
.push_back(getPrimaryDimension(aChildSize
));
616 aMainGroupNonHomogeneous
.push_back(pChild
->get_non_homogeneous());
620 nSubGroupSecondary
= std::max(nSubGroupSecondary
, getSecondaryDimension(aChildSize
));
621 aSubGroupSizes
.push_back(getPrimaryDimension(aChildSize
));
622 aSubGroupNonHomogeneous
.push_back(pChild
->get_non_homogeneous());
628 long nMaxMainDimension
= aMainGroupSizes
.empty() ? 0 :
629 *std::max_element(aMainGroupSizes
.begin(), aMainGroupSizes
.end());
630 nMaxMainDimension
= std::max(nMaxMainDimension
, nMinMainGroupPrimary
);
631 long nMaxSubDimension
= aSubGroupSizes
.empty() ? 0 :
632 *std::max_element(aSubGroupSizes
.begin(), aSubGroupSizes
.end());
633 nMaxSubDimension
= std::max(nMaxSubDimension
, nMinSubGroupPrimary
);
634 long nMaxDimension
= std::max(nMaxMainDimension
, nMaxSubDimension
);
635 aReq
.m_aMainGroupDimensions
.resize(aMainGroupSizes
.size(), nMaxDimension
);
636 aReq
.m_aSubGroupDimensions
.resize(aSubGroupSizes
.size(), nMaxDimension
);
640 //Ideally set everything to the same size, but find outlier widgets
641 //that are way wider than the average and leave them
642 //at their natural size and set the remainder to share the
643 //max size of the remaining members of the buttonbox
644 long nAccDimension
= std::accumulate(aMainGroupSizes
.begin(),
645 aMainGroupSizes
.end(), 0);
646 nAccDimension
= std::accumulate(aSubGroupSizes
.begin(),
647 aSubGroupSizes
.end(), nAccDimension
);
649 size_t nTotalSize
= aMainGroupSizes
.size() + aSubGroupSizes
.size();
651 long nAvgDimension
= nTotalSize
? nAccDimension
/ nTotalSize
: 0;
653 long nMaxMainNonOutlier
= getMaxNonOutlier(aMainGroupSizes
,
655 long nMaxSubNonOutlier
= getMaxNonOutlier(aSubGroupSizes
,
657 long nMaxNonOutlier
= std::max(nMaxMainNonOutlier
, nMaxSubNonOutlier
);
659 aReq
.m_aMainGroupDimensions
= setButtonSizes(aMainGroupSizes
,
660 aMainGroupNonHomogeneous
,
661 nAvgDimension
, nMaxNonOutlier
, nMinMainGroupPrimary
);
662 aReq
.m_aSubGroupDimensions
= setButtonSizes(aSubGroupSizes
,
663 aSubGroupNonHomogeneous
,
664 nAvgDimension
, nMaxNonOutlier
, nMinSubGroupPrimary
);
667 if (!aReq
.m_aMainGroupDimensions
.empty())
669 setSecondaryDimension(aReq
.m_aMainGroupSize
, nMainGroupSecondary
);
670 setPrimaryDimension(aReq
.m_aMainGroupSize
,
671 std::accumulate(aReq
.m_aMainGroupDimensions
.begin(),
672 aReq
.m_aMainGroupDimensions
.end(), 0));
674 if (!aReq
.m_aSubGroupDimensions
.empty())
676 setSecondaryDimension(aReq
.m_aSubGroupSize
, nSubGroupSecondary
);
677 setPrimaryDimension(aReq
.m_aSubGroupSize
,
678 std::accumulate(aReq
.m_aSubGroupDimensions
.begin(),
679 aReq
.m_aSubGroupDimensions
.end(), 0));
685 Size
VclButtonBox::addSpacing(const Size
&rSize
, sal_uInt16 nVisibleChildren
) const
689 if (nVisibleChildren
)
691 long nPrimaryDimension
= getPrimaryDimension(rSize
);
692 setPrimaryDimension(aRet
,
693 nPrimaryDimension
+ m_nSpacing
* (nVisibleChildren
-1));
694 setSecondaryDimension(aRet
, getSecondaryDimension(rSize
));
700 Size
VclButtonBox::calculateRequisition() const
702 Requisition
aReq(calculatePrimarySecondaryRequisitions());
703 sal_uInt16 nVisibleChildren
= aReq
.m_aMainGroupDimensions
.size() +
704 aReq
.m_aSubGroupDimensions
.size();
705 return addSpacing(addReqGroups(aReq
), nVisibleChildren
);
708 bool VclButtonBox::set_property(const OString
&rKey
, const OString
&rValue
)
710 if (rKey
== "layout-style")
712 VclButtonBoxStyle eStyle
= VCL_BUTTONBOX_DEFAULT_STYLE
;
713 if (rValue
== "spread")
714 eStyle
= VCL_BUTTONBOX_SPREAD
;
715 else if (rValue
== "edge")
716 eStyle
= VCL_BUTTONBOX_EDGE
;
717 else if (rValue
== "start")
718 eStyle
= VCL_BUTTONBOX_START
;
719 else if (rValue
== "end")
720 eStyle
= VCL_BUTTONBOX_END
;
721 else if (rValue
== "center")
722 eStyle
= VCL_BUTTONBOX_CENTER
;
725 SAL_WARN("vcl.layout", "unknown layout style " << rValue
.getStr());
727 m_eLayoutStyle
= eStyle
;
730 return VclBox::set_property(rKey
, rValue
);
734 void VclButtonBox::setAllocation(const Size
&rAllocation
)
736 Requisition
aReq(calculatePrimarySecondaryRequisitions());
738 if (aReq
.m_aMainGroupDimensions
.empty() && aReq
.m_aSubGroupDimensions
.empty())
741 long nAllocPrimaryDimension
= getPrimaryDimension(rAllocation
);
743 Point aMainGroupPos
, aOtherGroupPos
;
744 int nSpacing
= m_nSpacing
;
746 //To-Do, other layout styles
747 switch (m_eLayoutStyle
)
749 case VCL_BUTTONBOX_START
:
750 if (!aReq
.m_aSubGroupDimensions
.empty())
752 long nOtherPrimaryDimension
= getPrimaryDimension(
753 addSpacing(aReq
.m_aSubGroupSize
, aReq
.m_aSubGroupDimensions
.size()));
754 setPrimaryCoordinate(aOtherGroupPos
,
755 nAllocPrimaryDimension
- nOtherPrimaryDimension
);
758 case VCL_BUTTONBOX_SPREAD
:
759 if (!aReq
.m_aMainGroupDimensions
.empty())
761 long nMainPrimaryDimension
= getPrimaryDimension(
762 addSpacing(aReq
.m_aMainGroupSize
, aReq
.m_aMainGroupDimensions
.size()));
763 long nExtraSpace
= nAllocPrimaryDimension
- nMainPrimaryDimension
;
764 nExtraSpace
+= (aReq
.m_aMainGroupDimensions
.size()-1) * nSpacing
;
765 nSpacing
= nExtraSpace
/(aReq
.m_aMainGroupDimensions
.size()+1);
766 setPrimaryCoordinate(aMainGroupPos
, nSpacing
);
769 case VCL_BUTTONBOX_CENTER
:
770 if (!aReq
.m_aMainGroupDimensions
.empty())
772 long nMainPrimaryDimension
= getPrimaryDimension(
773 addSpacing(aReq
.m_aMainGroupSize
, aReq
.m_aMainGroupDimensions
.size()));
774 long nExtraSpace
= nAllocPrimaryDimension
- nMainPrimaryDimension
;
775 setPrimaryCoordinate(aMainGroupPos
, nExtraSpace
/2);
779 SAL_WARN("vcl.layout", "todo unimplemented layout style");
781 case VCL_BUTTONBOX_DEFAULT_STYLE
:
782 case VCL_BUTTONBOX_END
:
783 if (!aReq
.m_aMainGroupDimensions
.empty())
785 long nMainPrimaryDimension
= getPrimaryDimension(
786 addSpacing(aReq
.m_aMainGroupSize
, aReq
.m_aMainGroupDimensions
.size()));
787 setPrimaryCoordinate(aMainGroupPos
,
788 nAllocPrimaryDimension
- nMainPrimaryDimension
);
794 setSecondaryDimension(aChildSize
, getSecondaryDimension(rAllocation
));
796 std::vector
<long>::const_iterator aPrimaryI
= aReq
.m_aMainGroupDimensions
.begin();
797 std::vector
<long>::const_iterator aSecondaryI
= aReq
.m_aSubGroupDimensions
.begin();
798 bool bIgnoreSecondaryPacking
= (m_eLayoutStyle
== VCL_BUTTONBOX_SPREAD
|| m_eLayoutStyle
== VCL_BUTTONBOX_CENTER
);
799 for (vcl::Window
*pChild
= GetWindow(GetWindowType::FirstChild
); pChild
; pChild
= pChild
->GetWindow(GetWindowType::Next
))
801 if (!pChild
->IsVisible())
804 if (bIgnoreSecondaryPacking
|| !pChild
->get_secondary())
806 long nMainGroupPrimaryDimension
= *aPrimaryI
++;
807 setPrimaryDimension(aChildSize
, nMainGroupPrimaryDimension
);
808 setLayoutAllocation(*pChild
, aMainGroupPos
, aChildSize
);
809 long nPrimaryCoordinate
= getPrimaryCoordinate(aMainGroupPos
);
810 setPrimaryCoordinate(aMainGroupPos
, nPrimaryCoordinate
+ nMainGroupPrimaryDimension
+ nSpacing
);
814 long nSubGroupPrimaryDimension
= *aSecondaryI
++;
815 setPrimaryDimension(aChildSize
, nSubGroupPrimaryDimension
);
816 setLayoutAllocation(*pChild
, aOtherGroupPos
, aChildSize
);
817 long nPrimaryCoordinate
= getPrimaryCoordinate(aOtherGroupPos
);
818 setPrimaryCoordinate(aOtherGroupPos
, nPrimaryCoordinate
+ nSubGroupPrimaryDimension
+ nSpacing
);
829 static int getButtonPriority(const OString
&rType
)
831 static const size_t N_TYPES
= 3;
832 static const ButtonOrder aDiscardCancelSave
[N_TYPES
] =
839 static const ButtonOrder aSaveDiscardCancel
[N_TYPES
] =
846 const ButtonOrder
* pOrder
= &aDiscardCancelSave
[0];
848 const OUString
&rEnv
= Application::GetDesktopEnvironment();
850 if (rEnv
.equalsIgnoreAsciiCase("windows") ||
851 rEnv
.equalsIgnoreAsciiCase("kde5") ||
852 rEnv
.equalsIgnoreAsciiCase("kde4") ||
853 rEnv
.equalsIgnoreAsciiCase("tde") ||
854 rEnv
.equalsIgnoreAsciiCase("kde"))
856 pOrder
= &aSaveDiscardCancel
[0];
859 for (size_t i
= 0; i
< N_TYPES
; ++i
, ++pOrder
)
861 if (rType
.endsWith(pOrder
->m_aType
))
862 return pOrder
->m_nPriority
;
869 : public std::binary_function
<const vcl::Window
*, const vcl::Window
*, bool>
871 bool m_bVerticalContainer
;
873 explicit sortButtons(bool bVerticalContainer
)
874 : m_bVerticalContainer(bVerticalContainer
)
877 bool operator()(const vcl::Window
*pA
, const vcl::Window
*pB
) const;
880 bool sortButtons::operator()(const vcl::Window
*pA
, const vcl::Window
*pB
) const
882 //sort into two groups of pack start and pack end
883 VclPackType ePackA
= pA
->get_pack_type();
884 VclPackType ePackB
= pB
->get_pack_type();
889 bool bPackA
= pA
->get_secondary();
890 bool bPackB
= pB
->get_secondary();
891 if (!m_bVerticalContainer
)
893 //for horizontal boxes group secondaries before primaries
901 //for vertical boxes group secondaries after primaries
908 //now order within groups according to platform rules
909 return getButtonPriority(pA
->GetHelpId()) < getButtonPriority(pB
->GetHelpId());
912 void VclButtonBox::sort_native_button_order()
914 std::vector
<vcl::Window
*> aChilds
;
915 for (vcl::Window
* pChild
= GetWindow(GetWindowType::FirstChild
); pChild
;
916 pChild
= pChild
->GetWindow(GetWindowType::Next
))
918 aChilds
.push_back(pChild
);
921 //sort child order within parent so that we match the platform
923 std::stable_sort(aChilds
.begin(), aChilds
.end(), sortButtons(m_bVerticalContainer
));
924 VclBuilder::reorderWithinParent(aChilds
, true);
929 VclPtr
<vcl::Window
> pChild
;
930 sal_Int32 nSpanWidth
;
931 sal_Int32 nSpanHeight
;
944 typedef boost::multi_array
<GridEntry
, 2> array_type
;
946 static array_type
assembleGrid(const VclGrid
&rGrid
);
947 static bool isNullGrid(const array_type
& A
);
948 static void calcMaxs(const array_type
&A
, std::vector
<VclGrid::Value
> &rWidths
, std::vector
<VclGrid::Value
> &rHeights
);
950 array_type
assembleGrid(const VclGrid
&rGrid
)
954 for (vcl::Window
* pChild
= rGrid
.GetWindow(GetWindowType::FirstChild
); pChild
;
955 pChild
= pChild
->GetWindow(GetWindowType::Next
))
957 sal_Int32 nLeftAttach
= std::max
<sal_Int32
>(pChild
->get_grid_left_attach(), 0);
958 sal_Int32 nWidth
= pChild
->get_grid_width();
959 sal_Int32 nMaxXPos
= nLeftAttach
+nWidth
-1;
961 sal_Int32 nTopAttach
= std::max
<sal_Int32
>(pChild
->get_grid_top_attach(), 0);
962 sal_Int32 nHeight
= pChild
->get_grid_height();
963 sal_Int32 nMaxYPos
= nTopAttach
+nHeight
-1;
965 sal_Int32 nCurrentMaxXPos
= A
.shape()[0]-1;
966 sal_Int32 nCurrentMaxYPos
= A
.shape()[1]-1;
967 if (nMaxXPos
> nCurrentMaxXPos
|| nMaxYPos
> nCurrentMaxYPos
)
969 nCurrentMaxXPos
= std::max(nMaxXPos
, nCurrentMaxXPos
);
970 nCurrentMaxYPos
= std::max(nMaxYPos
, nCurrentMaxYPos
);
971 A
.resize(boost::extents
[nCurrentMaxXPos
+1][nCurrentMaxYPos
+1]);
974 GridEntry
&rEntry
= A
[nLeftAttach
][nTopAttach
];
975 rEntry
.pChild
= pChild
;
976 rEntry
.nSpanWidth
= nWidth
;
977 rEntry
.nSpanHeight
= nHeight
;
978 rEntry
.x
= nLeftAttach
;
979 rEntry
.y
= nTopAttach
;
981 for (sal_Int32 nSpanX
= 0; nSpanX
< nWidth
; ++nSpanX
)
983 for (sal_Int32 nSpanY
= 0; nSpanY
< nHeight
; ++nSpanY
)
985 GridEntry
&rSpan
= A
[nLeftAttach
+nSpanX
][nTopAttach
+nSpanY
];
986 rSpan
.x
= nLeftAttach
;
987 rSpan
.y
= nTopAttach
;
992 //see if we have any empty rows/cols
993 sal_Int32 nMaxX
= A
.shape()[0];
994 sal_Int32 nMaxY
= A
.shape()[1];
996 std::vector
<bool> aNonEmptyCols(nMaxX
);
997 std::vector
<bool> aNonEmptyRows(nMaxY
);
999 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1001 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1003 const GridEntry
&rEntry
= A
[x
][y
];
1004 const vcl::Window
*pChild
= rEntry
.pChild
;
1005 if (pChild
&& pChild
->IsVisible())
1007 aNonEmptyCols
[x
] = true;
1008 if (rGrid
.get_column_homogeneous())
1010 for (sal_Int32 nSpanX
= 1; nSpanX
< rEntry
.nSpanWidth
; ++nSpanX
)
1011 aNonEmptyCols
[x
+nSpanX
] = true;
1013 aNonEmptyRows
[y
] = true;
1014 if (rGrid
.get_row_homogeneous())
1016 for (sal_Int32 nSpanY
= 1; nSpanY
< rEntry
.nSpanHeight
; ++nSpanY
)
1017 aNonEmptyRows
[y
+nSpanY
] = true;
1023 if (!rGrid
.get_column_homogeneous())
1025 //reduce the spans of elements that span empty columns
1026 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1028 std::set
<GridEntry
*> candidates
;
1029 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1031 if (aNonEmptyCols
[x
])
1033 GridEntry
&rSpan
= A
[x
][y
];
1034 //cell x/y is spanned by the widget at cell rSpan.x/rSpan.y,
1035 //just points back to itself if there's no cell spanning
1036 if ((rSpan
.x
== -1) || (rSpan
.y
== -1))
1038 //there is no entry for this cell, i.e. this is a cell
1039 //with no widget in it, or spanned by any other widget
1042 GridEntry
&rEntry
= A
[rSpan
.x
][rSpan
.y
];
1043 candidates
.insert(&rEntry
);
1045 for (std::set
<GridEntry
*>::iterator aI
= candidates
.begin(), aEnd
= candidates
.end();
1048 GridEntry
*pEntry
= *aI
;
1049 --pEntry
->nSpanWidth
;
1054 if (!rGrid
.get_row_homogeneous())
1056 //reduce the spans of elements that span empty rows
1057 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1059 std::set
<GridEntry
*> candidates
;
1060 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1062 if (aNonEmptyRows
[y
])
1064 GridEntry
&rSpan
= A
[x
][y
];
1065 //cell x/y is spanned by the widget at cell rSpan.x/rSpan.y,
1066 //just points back to itself if there's no cell spanning
1067 if ((rSpan
.x
== -1) || (rSpan
.y
== -1))
1069 //there is no entry for this cell, i.e. this is a cell
1070 //with no widget in it, or spanned by any other widget
1073 GridEntry
&rEntry
= A
[rSpan
.x
][rSpan
.y
];
1074 candidates
.insert(&rEntry
);
1076 for (std::set
<GridEntry
*>::iterator aI
= candidates
.begin(), aEnd
= candidates
.end();
1079 GridEntry
*pEntry
= *aI
;
1080 --pEntry
->nSpanHeight
;
1085 sal_Int32 nNonEmptyCols
= std::count(aNonEmptyCols
.begin(), aNonEmptyCols
.end(), true);
1086 sal_Int32 nNonEmptyRows
= std::count(aNonEmptyRows
.begin(), aNonEmptyRows
.end(), true);
1088 //make new grid without empty rows and columns
1089 array_type
B(boost::extents
[nNonEmptyCols
][nNonEmptyRows
]);
1090 for (sal_Int32 x
= 0, x2
= 0; x
< nMaxX
; ++x
)
1092 if (!aNonEmptyCols
[x
])
1094 for (sal_Int32 y
= 0, y2
= 0; y
< nMaxY
; ++y
)
1096 if (!aNonEmptyRows
[y
])
1098 GridEntry
&rEntry
= A
[x
][y
];
1099 B
[x2
][y2
++] = rEntry
;
1107 static bool isNullGrid(const array_type
&A
)
1109 sal_Int32 nMaxX
= A
.shape()[0];
1110 sal_Int32 nMaxY
= A
.shape()[1];
1112 if (!nMaxX
|| !nMaxY
)
1117 static void calcMaxs(const array_type
&A
, std::vector
<VclGrid::Value
> &rWidths
, std::vector
<VclGrid::Value
> &rHeights
)
1119 sal_Int32 nMaxX
= A
.shape()[0];
1120 sal_Int32 nMaxY
= A
.shape()[1];
1122 rWidths
.resize(nMaxX
);
1123 rHeights
.resize(nMaxY
);
1125 //first use the non spanning entries to set default width/heights
1126 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1128 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1130 const GridEntry
&rEntry
= A
[x
][y
];
1131 const vcl::Window
*pChild
= rEntry
.pChild
;
1132 if (!pChild
|| !pChild
->IsVisible())
1135 sal_Int32 nWidth
= rEntry
.nSpanWidth
;
1136 sal_Int32 nHeight
= rEntry
.nSpanHeight
;
1138 for (sal_Int32 nSpanX
= 0; nSpanX
< nWidth
; ++nSpanX
)
1139 rWidths
[x
+nSpanX
].m_bExpand
|= pChild
->get_hexpand();
1141 for (sal_Int32 nSpanY
= 0; nSpanY
< nHeight
; ++nSpanY
)
1142 rHeights
[y
+nSpanY
].m_bExpand
|= pChild
->get_vexpand();
1144 if (nWidth
== 1 || nHeight
== 1)
1146 Size aChildSize
= VclContainer::getLayoutRequisition(*pChild
);
1148 rWidths
[x
].m_nValue
= std::max(rWidths
[x
].m_nValue
, aChildSize
.Width());
1150 rHeights
[y
].m_nValue
= std::max(rHeights
[y
].m_nValue
, aChildSize
.Height());
1155 //now use the spanning entries and split any extra sizes across expanding rows/cols
1157 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1159 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1161 const GridEntry
&rEntry
= A
[x
][y
];
1162 const vcl::Window
*pChild
= rEntry
.pChild
;
1163 if (!pChild
|| !pChild
->IsVisible())
1166 sal_Int32 nWidth
= rEntry
.nSpanWidth
;
1167 sal_Int32 nHeight
= rEntry
.nSpanHeight
;
1169 if (nWidth
== 1 && nHeight
== 1)
1172 Size aChildSize
= VclContainer::getLayoutRequisition(*pChild
);
1176 sal_Int32 nExistingWidth
= 0;
1177 for (sal_Int32 nSpanX
= 0; nSpanX
< nWidth
; ++nSpanX
)
1178 nExistingWidth
+= rWidths
[x
+nSpanX
].m_nValue
;
1180 sal_Int32 nExtraWidth
= aChildSize
.Width() - nExistingWidth
;
1182 if (nExtraWidth
> 0)
1184 bool bForceExpandAll
= false;
1185 sal_Int32 nExpandables
= 0;
1186 for (sal_Int32 nSpanX
= 0; nSpanX
< nWidth
; ++nSpanX
)
1187 if (rWidths
[x
+nSpanX
].m_bExpand
)
1189 if (nExpandables
== 0)
1191 nExpandables
= nWidth
;
1192 bForceExpandAll
= true;
1195 for (sal_Int32 nSpanX
= 0; nSpanX
< nWidth
; ++nSpanX
)
1197 if (rWidths
[x
+nSpanX
].m_bExpand
|| bForceExpandAll
)
1198 rWidths
[x
+nSpanX
].m_nValue
+= nExtraWidth
/nExpandables
;
1205 sal_Int32 nExistingHeight
= 0;
1206 for (sal_Int32 nSpanY
= 0; nSpanY
< nHeight
; ++nSpanY
)
1207 nExistingHeight
+= rHeights
[y
+nSpanY
].m_nValue
;
1209 sal_Int32 nExtraHeight
= aChildSize
.Height() - nExistingHeight
;
1211 if (nExtraHeight
> 0)
1213 bool bForceExpandAll
= false;
1214 sal_Int32 nExpandables
= 0;
1215 for (sal_Int32 nSpanY
= 0; nSpanY
< nHeight
; ++nSpanY
)
1216 if (rHeights
[y
+nSpanY
].m_bExpand
)
1218 if (nExpandables
== 0)
1220 nExpandables
= nHeight
;
1221 bForceExpandAll
= true;
1224 for (sal_Int32 nSpanY
= 0; nSpanY
< nHeight
; ++nSpanY
)
1226 if (rHeights
[y
+nSpanY
].m_bExpand
|| bForceExpandAll
)
1227 rHeights
[y
+nSpanY
].m_nValue
+= nExtraHeight
/nExpandables
;
1235 bool compareValues(const VclGrid::Value
&i
, const VclGrid::Value
&j
)
1237 return i
.m_nValue
< j
.m_nValue
;
1240 VclGrid::Value
accumulateValues(const VclGrid::Value
&i
, const VclGrid::Value
&j
)
1242 VclGrid::Value aRet
;
1243 aRet
.m_nValue
= i
.m_nValue
+ j
.m_nValue
;
1244 aRet
.m_bExpand
= i
.m_bExpand
|| j
.m_bExpand
;
1248 Size
VclGrid::calculateRequisition() const
1250 return calculateRequisitionForSpacings(get_row_spacing(), get_column_spacing());
1253 Size
VclGrid::calculateRequisitionForSpacings(sal_Int32 nRowSpacing
, sal_Int32 nColSpacing
) const
1255 array_type A
= assembleGrid(*this);
1260 std::vector
<Value
> aWidths
;
1261 std::vector
<Value
> aHeights
;
1262 calcMaxs(A
, aWidths
, aHeights
);
1264 long nTotalWidth
= 0;
1265 if (get_column_homogeneous())
1267 nTotalWidth
= std::max_element(aWidths
.begin(), aWidths
.end(), compareValues
)->m_nValue
;
1268 nTotalWidth
*= aWidths
.size();
1272 nTotalWidth
= std::accumulate(aWidths
.begin(), aWidths
.end(), Value(), accumulateValues
).m_nValue
;
1275 nTotalWidth
+= nColSpacing
* (aWidths
.size()-1);
1277 long nTotalHeight
= 0;
1278 if (get_row_homogeneous())
1280 nTotalHeight
= std::max_element(aHeights
.begin(), aHeights
.end(), compareValues
)->m_nValue
;
1281 nTotalHeight
*= aHeights
.size();
1285 nTotalHeight
= std::accumulate(aHeights
.begin(), aHeights
.end(), Value(), accumulateValues
).m_nValue
;
1288 nTotalHeight
+= nRowSpacing
* (aHeights
.size()-1);
1290 return Size(nTotalWidth
, nTotalHeight
);
1293 void VclGrid::setAllocation(const Size
& rAllocation
)
1295 array_type A
= assembleGrid(*this);
1300 sal_Int32 nMaxX
= A
.shape()[0];
1301 sal_Int32 nMaxY
= A
.shape()[1];
1304 std::vector
<Value
> aWidths(nMaxX
);
1305 std::vector
<Value
> aHeights(nMaxY
);
1306 if (!get_column_homogeneous() || !get_row_homogeneous())
1308 aRequisition
= calculateRequisition();
1309 calcMaxs(A
, aWidths
, aHeights
);
1312 sal_Int32
nColSpacing(get_column_spacing());
1313 sal_Int32
nRowSpacing(get_row_spacing());
1315 long nAvailableWidth
= rAllocation
.Width();
1317 nAvailableWidth
-= nColSpacing
* (nMaxX
- 1);
1318 if (get_column_homogeneous())
1320 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1321 aWidths
[x
].m_nValue
= nAvailableWidth
/nMaxX
;
1323 else if (rAllocation
.Width() != aRequisition
.Width())
1325 sal_Int32 nExpandables
= 0;
1326 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1327 if (aWidths
[x
].m_bExpand
)
1329 long nExtraWidthForExpanders
= nExpandables
? (rAllocation
.Width() - aRequisition
.Width()) / nExpandables
: 0;
1331 //We don't fit and there is no volunteer to be shrunk
1332 if (!nExpandables
&& rAllocation
.Width() < aRequisition
.Width())
1334 //first reduce spacing
1338 aRequisition
= calculateRequisitionForSpacings(nRowSpacing
, nColSpacing
);
1339 if (aRequisition
.Width() <= rAllocation
.Width())
1343 //share out the remaining pain to everyone
1344 long nExtraWidth
= (rAllocation
.Width() - aRequisition
.Width()) / nMaxX
;
1346 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1347 aWidths
[x
].m_nValue
+= nExtraWidth
;
1350 if (nExtraWidthForExpanders
)
1352 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1353 if (aWidths
[x
].m_bExpand
)
1354 aWidths
[x
].m_nValue
+= nExtraWidthForExpanders
;
1358 long nAvailableHeight
= rAllocation
.Height();
1360 nAvailableHeight
-= nRowSpacing
* (nMaxY
- 1);
1361 if (get_row_homogeneous())
1363 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1364 aHeights
[y
].m_nValue
= nAvailableHeight
/nMaxY
;
1366 else if (rAllocation
.Height() != aRequisition
.Height())
1368 sal_Int32 nExpandables
= 0;
1369 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1370 if (aHeights
[y
].m_bExpand
)
1372 long nExtraHeightForExpanders
= nExpandables
? (rAllocation
.Height() - aRequisition
.Height()) / nExpandables
: 0;
1374 //We don't fit and there is no volunteer to be shrunk
1375 if (!nExpandables
&& rAllocation
.Height() < aRequisition
.Height())
1377 //first reduce spacing
1381 aRequisition
= calculateRequisitionForSpacings(nRowSpacing
, nColSpacing
);
1382 if (aRequisition
.Height() <= rAllocation
.Height())
1386 //share out the remaining pain to everyone
1387 long nExtraHeight
= (rAllocation
.Height() - aRequisition
.Height()) / nMaxY
;
1389 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1390 aHeights
[y
].m_nValue
+= nExtraHeight
;
1393 if (nExtraHeightForExpanders
)
1395 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1396 if (aHeights
[y
].m_bExpand
)
1397 aHeights
[y
].m_nValue
+= nExtraHeightForExpanders
;
1401 Point
aAllocPos(0, 0);
1402 for (sal_Int32 x
= 0; x
< nMaxX
; ++x
)
1404 for (sal_Int32 y
= 0; y
< nMaxY
; ++y
)
1406 GridEntry
&rEntry
= A
[x
][y
];
1407 vcl::Window
*pChild
= rEntry
.pChild
;
1410 Size
aChildAlloc(0, 0);
1412 sal_Int32 nWidth
= rEntry
.nSpanWidth
;
1413 for (sal_Int32 nSpanX
= 0; nSpanX
< nWidth
; ++nSpanX
)
1414 aChildAlloc
.Width() += aWidths
[x
+nSpanX
].m_nValue
;
1415 aChildAlloc
.Width() += nColSpacing
*(nWidth
-1);
1417 sal_Int32 nHeight
= rEntry
.nSpanHeight
;
1418 for (sal_Int32 nSpanY
= 0; nSpanY
< nHeight
; ++nSpanY
)
1419 aChildAlloc
.Height() += aHeights
[y
+nSpanY
].m_nValue
;
1420 aChildAlloc
.Height() += nRowSpacing
*(nHeight
-1);
1422 setLayoutAllocation(*pChild
, aAllocPos
, aChildAlloc
);
1424 aAllocPos
.Y() += aHeights
[y
].m_nValue
+ nRowSpacing
;
1426 aAllocPos
.X() += aWidths
[x
].m_nValue
+ nColSpacing
;
1431 bool toBool(const OString
&rValue
)
1433 return (!rValue
.isEmpty() && (rValue
[0] == 't' || rValue
[0] == 'T' || rValue
[0] == '1'));
1436 bool VclGrid::set_property(const OString
&rKey
, const OString
&rValue
)
1438 if (rKey
== "row-spacing")
1439 set_row_spacing(rValue
.toInt32());
1440 else if (rKey
== "column-spacing")
1441 set_column_spacing(rValue
.toInt32());
1442 else if (rKey
== "row-homogeneous")
1443 m_bRowHomogeneous
= toBool(rValue
);
1444 else if (rKey
== "column-homogeneous")
1445 m_bColumnHomogeneous
= toBool(rValue
);
1446 else if (rKey
== "n-rows")
1449 return VclContainer::set_property(rKey
, rValue
);
1453 const vcl::Window
*VclBin::get_child() const
1455 const WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
1457 return pWindowImpl
->mpFirstChild
;
1460 vcl::Window
*VclBin::get_child()
1462 return const_cast<vcl::Window
*>(const_cast<const VclBin
*>(this)->get_child());
1465 Size
VclBin::calculateRequisition() const
1467 const vcl::Window
*pChild
= get_child();
1468 if (pChild
&& pChild
->IsVisible())
1469 return getLayoutRequisition(*pChild
);
1473 void VclBin::setAllocation(const Size
&rAllocation
)
1475 vcl::Window
*pChild
= get_child();
1476 if (pChild
&& pChild
->IsVisible())
1477 setLayoutAllocation(*pChild
, Point(0, 0), rAllocation
);
1480 VclFrame::~VclFrame()
1485 void VclFrame::dispose()
1491 //To-Do, hook a DecorationView into VclFrame ?
1493 Size
VclFrame::calculateRequisition() const
1497 const vcl::Window
*pChild
= get_child();
1498 const vcl::Window
*pLabel
= get_label_widget();
1500 if (pChild
&& pChild
->IsVisible())
1501 aRet
= getLayoutRequisition(*pChild
);
1503 if (pLabel
&& pLabel
->IsVisible())
1505 Size aLabelSize
= getLayoutRequisition(*pLabel
);
1506 aRet
.Height() += aLabelSize
.Height();
1507 aRet
.Width() = std::max(aLabelSize
.Width(), aRet
.Width());
1510 const FrameStyle
&rFrameStyle
=
1511 GetSettings().GetStyleSettings().GetFrameStyle();
1512 aRet
.Width() += rFrameStyle
.left
+ rFrameStyle
.right
;
1513 aRet
.Height() += rFrameStyle
.top
+ rFrameStyle
.bottom
;
1518 void VclFrame::setAllocation(const Size
&rAllocation
)
1520 //SetBackground( Color(0xFF, 0x00, 0xFF) );
1522 const FrameStyle
&rFrameStyle
=
1523 GetSettings().GetStyleSettings().GetFrameStyle();
1524 Size
aAllocation(rAllocation
.Width() - rFrameStyle
.left
- rFrameStyle
.right
,
1525 rAllocation
.Height() - rFrameStyle
.top
- rFrameStyle
.bottom
);
1526 Point
aChildPos(rFrameStyle
.left
, rFrameStyle
.top
);
1528 vcl::Window
*pChild
= get_child();
1529 vcl::Window
*pLabel
= get_label_widget();
1531 if (pLabel
&& pLabel
->IsVisible())
1533 Size aLabelSize
= getLayoutRequisition(*pLabel
);
1534 aLabelSize
.Height() = std::min(aLabelSize
.Height(), aAllocation
.Height());
1535 aLabelSize
.Width() = std::min(aLabelSize
.Width(), aAllocation
.Width());
1536 setLayoutAllocation(*pLabel
, aChildPos
, aLabelSize
);
1537 aAllocation
.Height() -= aLabelSize
.Height();
1538 aChildPos
.Y() += aLabelSize
.Height();
1541 if (pChild
&& pChild
->IsVisible())
1542 setLayoutAllocation(*pChild
, aChildPos
, aAllocation
);
1545 IMPL_LINK(VclFrame
, WindowEventListener
, VclWindowEvent
&, rEvent
, void)
1547 if (rEvent
.GetId() == VCLEVENT_OBJECT_DYING
)
1548 designate_label(nullptr);
1551 void VclFrame::designate_label(vcl::Window
*pWindow
)
1553 assert(!pWindow
|| pWindow
->GetParent() == this);
1555 m_pLabel
->RemoveEventListener(LINK(this, VclFrame
, WindowEventListener
));
1558 m_pLabel
->AddEventListener(LINK(this, VclFrame
, WindowEventListener
));
1561 const vcl::Window
*VclFrame::get_label_widget() const
1563 assert(GetChildCount() == 2);
1566 //The label widget is normally the first (of two) children
1567 const WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
1568 if (pWindowImpl
->mpFirstChild
== pWindowImpl
->mpLastChild
) //no label exists
1570 return pWindowImpl
->mpFirstChild
;
1573 vcl::Window
*VclFrame::get_label_widget()
1575 return const_cast<vcl::Window
*>(const_cast<const VclFrame
*>(this)->get_label_widget());
1578 const vcl::Window
*VclFrame::get_child() const
1580 assert(GetChildCount() == 2);
1581 //The child widget is the normally the last (of two) children
1582 const WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
1584 return pWindowImpl
->mpLastChild
;
1585 if (pWindowImpl
->mpFirstChild
== pWindowImpl
->mpLastChild
) //only label exists
1587 return pWindowImpl
->mpLastChild
;
1590 vcl::Window
*VclFrame::get_child()
1592 return const_cast<vcl::Window
*>(const_cast<const VclFrame
*>(this)->get_child());
1595 void VclFrame::set_label(const OUString
&rLabel
)
1597 vcl::Window
*pLabel
= get_label_widget();
1599 pLabel
->SetText(rLabel
);
1602 OUString
VclFrame::get_label() const
1604 const vcl::Window
*pLabel
= get_label_widget();
1606 return pLabel
->GetText();
1609 OUString
VclFrame::getDefaultAccessibleName() const
1611 const vcl::Window
*pLabel
= get_label_widget();
1613 return pLabel
->GetAccessibleName();
1614 return VclBin::getDefaultAccessibleName();
1617 Size
VclAlignment::calculateRequisition() const
1619 Size
aRet(m_nLeftPadding
+ m_nRightPadding
,
1620 m_nTopPadding
+ m_nBottomPadding
);
1622 const vcl::Window
*pChild
= get_child();
1623 if (pChild
&& pChild
->IsVisible())
1625 Size aChildSize
= getLayoutRequisition(*pChild
);
1626 aRet
.Width() += aChildSize
.Width();
1627 aRet
.Height() += aChildSize
.Height();
1633 void VclAlignment::setAllocation(const Size
&rAllocation
)
1635 vcl::Window
*pChild
= get_child();
1636 if (!pChild
|| !pChild
->IsVisible())
1639 Point
aChildPos(m_nLeftPadding
, m_nTopPadding
);
1642 aAllocation
.Width() = rAllocation
.Width() - (m_nLeftPadding
+ m_nRightPadding
);
1643 aAllocation
.Height() = rAllocation
.Height() - (m_nTopPadding
+ m_nBottomPadding
);
1645 setLayoutAllocation(*pChild
, aChildPos
, aAllocation
);
1648 bool VclAlignment::set_property(const OString
&rKey
, const OString
&rValue
)
1650 if (rKey
== "bottom-padding")
1651 m_nBottomPadding
= rValue
.toInt32();
1652 else if (rKey
== "left-padding")
1653 m_nLeftPadding
= rValue
.toInt32();
1654 else if (rKey
== "right-padding")
1655 m_nRightPadding
= rValue
.toInt32();
1656 else if (rKey
== "top-padding")
1657 m_nTopPadding
= rValue
.toInt32();
1658 else if (rKey
== "xalign")
1659 m_fXAlign
= rValue
.toFloat();
1660 else if (rKey
== "xscale")
1661 m_fXScale
= rValue
.toFloat();
1662 else if (rKey
== "yalign")
1663 m_fYAlign
= rValue
.toFloat();
1664 else if (rKey
== "yscale")
1665 m_fYScale
= rValue
.toFloat();
1667 return VclBin::set_property(rKey
, rValue
);
1671 void VclExpander::dispose()
1673 m_pDisclosureButton
.disposeAndClear();
1677 const vcl::Window
*VclExpander::get_child() const
1679 const WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
1681 assert(pWindowImpl
->mpFirstChild
== m_pDisclosureButton
);
1683 return pWindowImpl
->mpFirstChild
->GetWindow(GetWindowType::Next
);
1686 vcl::Window
*VclExpander::get_child()
1688 return const_cast<vcl::Window
*>(const_cast<const VclExpander
*>(this)->get_child());
1691 Size
VclExpander::calculateRequisition() const
1695 WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
1697 const vcl::Window
*pChild
= get_child();
1698 const vcl::Window
*pLabel
= pChild
!= pWindowImpl
->mpLastChild
? pWindowImpl
->mpLastChild
.get() : nullptr;
1700 if (pChild
&& pChild
->IsVisible() && m_pDisclosureButton
->IsChecked())
1701 aRet
= getLayoutRequisition(*pChild
);
1703 Size aExpanderSize
= getLayoutRequisition(*m_pDisclosureButton
);
1705 if (pLabel
&& pLabel
->IsVisible())
1707 Size aLabelSize
= getLayoutRequisition(*pLabel
);
1708 aExpanderSize
.Height() = std::max(aExpanderSize
.Height(), aLabelSize
.Height());
1709 aExpanderSize
.Width() += aLabelSize
.Width();
1712 aRet
.Height() += aExpanderSize
.Height();
1713 aRet
.Width() = std::max(aExpanderSize
.Width(), aRet
.Width());
1715 const FrameStyle
&rFrameStyle
=
1716 GetSettings().GetStyleSettings().GetFrameStyle();
1717 aRet
.Width() += rFrameStyle
.left
+ rFrameStyle
.right
;
1718 aRet
.Height() += rFrameStyle
.top
+ rFrameStyle
.bottom
;
1723 void VclExpander::setAllocation(const Size
&rAllocation
)
1725 const FrameStyle
&rFrameStyle
=
1726 GetSettings().GetStyleSettings().GetFrameStyle();
1727 Size
aAllocation(rAllocation
.Width() - rFrameStyle
.left
- rFrameStyle
.right
,
1728 rAllocation
.Height() - rFrameStyle
.top
- rFrameStyle
.bottom
);
1729 Point
aChildPos(rFrameStyle
.left
, rFrameStyle
.top
);
1731 WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
1733 //The label widget is the last (of two) children
1734 vcl::Window
*pChild
= get_child();
1735 vcl::Window
*pLabel
= pChild
!= pWindowImpl
->mpLastChild
.get() ? pWindowImpl
->mpLastChild
.get() : nullptr;
1737 Size aButtonSize
= getLayoutRequisition(*m_pDisclosureButton
);
1739 Size aExpanderSize
= aButtonSize
;
1740 if (pLabel
&& pLabel
->IsVisible())
1742 aLabelSize
= getLayoutRequisition(*pLabel
);
1743 aExpanderSize
.Height() = std::max(aExpanderSize
.Height(), aLabelSize
.Height());
1744 aExpanderSize
.Width() += aLabelSize
.Width();
1747 aExpanderSize
.Height() = std::min(aExpanderSize
.Height(), aAllocation
.Height());
1748 aExpanderSize
.Width() = std::min(aExpanderSize
.Width(), aAllocation
.Width());
1750 aButtonSize
.Height() = std::min(aButtonSize
.Height(), aExpanderSize
.Height());
1751 aButtonSize
.Width() = std::min(aButtonSize
.Width(), aExpanderSize
.Width());
1753 long nExtraExpanderHeight
= aExpanderSize
.Height() - aButtonSize
.Height();
1754 Point
aButtonPos(aChildPos
.X(), aChildPos
.Y() + nExtraExpanderHeight
/2);
1755 setLayoutAllocation(*m_pDisclosureButton
, aButtonPos
, aButtonSize
);
1757 if (pLabel
&& pLabel
->IsVisible())
1759 aLabelSize
.Height() = std::min(aLabelSize
.Height(), aExpanderSize
.Height());
1760 aLabelSize
.Width() = std::min(aLabelSize
.Width(),
1761 aExpanderSize
.Width() - aButtonSize
.Width());
1763 long nExtraLabelHeight
= aExpanderSize
.Height() - aLabelSize
.Height();
1764 Point
aLabelPos(aChildPos
.X() + aButtonSize
.Width(), aChildPos
.Y() + nExtraLabelHeight
/2);
1765 setLayoutAllocation(*pLabel
, aLabelPos
, aLabelSize
);
1768 aAllocation
.Height() -= aExpanderSize
.Height();
1769 aChildPos
.Y() += aExpanderSize
.Height();
1771 if (pChild
&& pChild
->IsVisible())
1773 if (!m_pDisclosureButton
->IsChecked())
1774 aAllocation
= Size();
1775 setLayoutAllocation(*pChild
, aChildPos
, aAllocation
);
1779 bool VclExpander::set_property(const OString
&rKey
, const OString
&rValue
)
1781 if (rKey
== "expanded")
1782 set_expanded(toBool(rValue
));
1783 else if (rKey
== "resize-toplevel")
1784 m_bResizeTopLevel
= toBool(rValue
);
1786 return VclBin::set_property(rKey
, rValue
);
1790 void VclExpander::StateChanged(StateChangedType nType
)
1792 VclBin::StateChanged( nType
);
1794 if (nType
== StateChangedType::InitShow
)
1796 vcl::Window
*pChild
= get_child();
1798 pChild
->Show(m_pDisclosureButton
->IsChecked());
1802 IMPL_LINK( VclExpander
, ClickHdl
, CheckBox
&, rBtn
, void )
1804 vcl::Window
*pChild
= get_child();
1807 pChild
->Show(rBtn
.IsChecked());
1809 Dialog
* pResizeDialog
= m_bResizeTopLevel
? GetParentDialog() : nullptr;
1811 pResizeDialog
->setOptimalLayoutSize();
1813 maExpandedHdl
.Call(*this);
1816 VclScrolledWindow::VclScrolledWindow(vcl::Window
*pParent
)
1817 : VclBin(pParent
, WB_HIDE
| WB_CLIPCHILDREN
| WB_AUTOHSCROLL
| WB_AUTOVSCROLL
| WB_TABSTOP
)
1818 , m_bUserManagedScrolling(false)
1819 , m_pVScroll(VclPtr
<ScrollBar
>::Create(this, WB_HIDE
| WB_VERT
))
1820 , m_pHScroll(VclPtr
<ScrollBar
>::Create(this, WB_HIDE
| WB_HORZ
))
1821 , m_aScrollBarBox(VclPtr
<ScrollBarBox
>::Create(this, WB_HIDE
))
1823 SetType(WINDOW_SCROLLWINDOW
);
1825 Link
<ScrollBar
*,void> aLink( LINK( this, VclScrolledWindow
, ScrollBarHdl
) );
1826 m_pVScroll
->SetScrollHdl(aLink
);
1827 m_pHScroll
->SetScrollHdl(aLink
);
1830 void VclScrolledWindow::dispose()
1832 m_pVScroll
.disposeAndClear();
1833 m_pHScroll
.disposeAndClear();
1834 m_aScrollBarBox
.disposeAndClear();
1838 IMPL_LINK_NOARG(VclScrolledWindow
, ScrollBarHdl
, ScrollBar
*, void)
1840 vcl::Window
*pChild
= get_child();
1844 assert(dynamic_cast<VclViewport
*>(pChild
) && "scrolledwindow child should be a Viewport");
1846 pChild
= pChild
->GetWindow(GetWindowType::FirstChild
);
1853 if (m_pHScroll
->IsVisible())
1855 aWinPos
.X() = -m_pHScroll
->GetThumbPos();
1858 if (m_pVScroll
->IsVisible())
1860 aWinPos
.Y() = -m_pVScroll
->GetThumbPos();
1863 pChild
->SetPosPixel(aWinPos
);
1866 const vcl::Window
*VclScrolledWindow::get_child() const
1868 assert(GetChildCount() == 4);
1869 const WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
1870 return pWindowImpl
->mpLastChild
;
1873 vcl::Window
*VclScrolledWindow::get_child()
1875 return const_cast<vcl::Window
*>(const_cast<const VclScrolledWindow
*>(this)->get_child());
1878 Size
VclScrolledWindow::calculateRequisition() const
1882 const vcl::Window
*pChild
= get_child();
1883 if (pChild
&& pChild
->IsVisible())
1884 aRet
= getLayoutRequisition(*pChild
);
1886 if (GetStyle() & WB_VSCROLL
)
1887 aRet
.Width() += getLayoutRequisition(*m_pVScroll
).Width();
1889 if (GetStyle() & WB_HSCROLL
)
1890 aRet
.Height() += getLayoutRequisition(*m_pHScroll
).Height();
1895 void VclScrolledWindow::InitScrollBars(const Size
&rRequest
)
1897 const vcl::Window
*pChild
= get_child();
1898 if (!pChild
|| !pChild
->IsVisible())
1901 Size
aOutSize(getVisibleChildSize());
1903 if (m_pVScroll
->IsVisible())
1905 m_pVScroll
->SetRangeMax(rRequest
.Height());
1906 m_pVScroll
->SetVisibleSize(aOutSize
.Height());
1907 m_pVScroll
->SetPageSize(16);
1910 if (m_pHScroll
->IsVisible())
1912 m_pHScroll
->SetRangeMax(rRequest
.Width());
1913 m_pHScroll
->SetVisibleSize(aOutSize
.Width());
1914 m_pHScroll
->SetPageSize(16);
1918 void VclScrolledWindow::setAllocation(const Size
&rAllocation
)
1920 Size
aChildAllocation(rAllocation
);
1923 vcl::Window
*pChild
= get_child();
1924 if (pChild
&& pChild
->IsVisible())
1925 aChildReq
= getLayoutRequisition(*pChild
);
1927 long nAvailHeight
= rAllocation
.Height();
1928 long nAvailWidth
= rAllocation
.Width();
1930 if (GetStyle() & WB_AUTOVSCROLL
)
1932 m_pVScroll
->Show(nAvailHeight
< aChildReq
.Height());
1935 if (m_pVScroll
->IsVisible())
1936 nAvailWidth
-= getLayoutRequisition(*m_pVScroll
).Width();
1939 if (GetStyle() & WB_AUTOHSCROLL
)
1941 bool bShowHScroll
= nAvailWidth
< aChildReq
.Width();
1942 m_pHScroll
->Show(bShowHScroll
);
1945 nAvailHeight
-= getLayoutRequisition(*m_pHScroll
).Height();
1947 if (GetStyle() & WB_AUTOVSCROLL
)
1948 m_pVScroll
->Show(nAvailHeight
< aChildReq
.Height());
1951 Size
aInnerSize(aChildAllocation
);
1952 long nScrollBarWidth
= 0, nScrollBarHeight
= 0;
1954 if (m_pVScroll
->IsVisible())
1956 nScrollBarWidth
= getLayoutRequisition(*m_pVScroll
).Width();
1957 Point
aScrollPos(rAllocation
.Width() - nScrollBarWidth
, 0);
1958 Size
aScrollSize(nScrollBarWidth
, rAllocation
.Height());
1959 setLayoutAllocation(*m_pVScroll
, aScrollPos
, aScrollSize
);
1960 aChildAllocation
.Width() -= nScrollBarWidth
;
1961 aInnerSize
.Width() -= nScrollBarWidth
;
1962 aChildAllocation
.Height() = aChildReq
.Height();
1965 if (m_pHScroll
->IsVisible())
1967 nScrollBarHeight
= getLayoutRequisition(*m_pHScroll
).Height();
1968 Point
aScrollPos(0, rAllocation
.Height() - nScrollBarHeight
);
1969 Size
aScrollSize(rAllocation
.Width(), nScrollBarHeight
);
1970 setLayoutAllocation(*m_pHScroll
, aScrollPos
, aScrollSize
);
1971 aChildAllocation
.Height() -= nScrollBarHeight
;
1972 aInnerSize
.Height() -= nScrollBarHeight
;
1973 aChildAllocation
.Width() = aChildReq
.Width();
1976 if (m_pVScroll
->IsVisible() && m_pHScroll
->IsVisible())
1978 Point
aBoxPos(aInnerSize
.Width(), aInnerSize
.Height());
1979 m_aScrollBarBox
->SetPosSizePixel(aBoxPos
, Size(nScrollBarWidth
, nScrollBarHeight
));
1980 m_aScrollBarBox
->Show();
1984 m_aScrollBarBox
->Hide();
1987 if (pChild
&& pChild
->IsVisible())
1989 assert(dynamic_cast<VclViewport
*>(pChild
) && "scrolledwindow child should be a Viewport");
1990 setLayoutAllocation(*pChild
, Point(0, 0), aInnerSize
);
1993 if (!m_bUserManagedScrolling
)
1994 InitScrollBars(aChildReq
);
1997 Size
VclScrolledWindow::getVisibleChildSize() const
1999 Size
aRet(GetSizePixel());
2000 if (m_pVScroll
->IsVisible())
2001 aRet
.Width() -= m_pVScroll
->GetSizePixel().Width();
2002 if (m_pHScroll
->IsVisible())
2003 aRet
.Height() -= m_pHScroll
->GetSizePixel().Height();
2007 bool VclScrolledWindow::set_property(const OString
&rKey
, const OString
&rValue
)
2009 bool bRet
= VclBin::set_property(rKey
, rValue
);
2010 m_pVScroll
->Show((GetStyle() & WB_VSCROLL
) != 0);
2011 m_pHScroll
->Show((GetStyle() & WB_HSCROLL
) != 0);
2015 bool VclScrolledWindow::EventNotify(NotifyEvent
& rNEvt
)
2018 if ( rNEvt
.GetType() == MouseNotifyEvent::COMMAND
)
2020 const CommandEvent
& rCEvt
= *rNEvt
.GetCommandEvent();
2021 if ( rCEvt
.GetCommand() == CommandEventId::Wheel
)
2023 const CommandWheelData
* pData
= rCEvt
.GetWheelData();
2024 if( !pData
->GetModifier() && ( pData
->GetMode() == CommandWheelMode::SCROLL
) )
2026 bDone
= HandleScrollCommand(rCEvt
, m_pHScroll
, m_pVScroll
);
2031 return bDone
|| VclBin::EventNotify( rNEvt
);
2034 void VclViewport::setAllocation(const Size
&rAllocation
)
2036 vcl::Window
*pChild
= get_child();
2037 if (pChild
&& pChild
->IsVisible())
2039 Size
aReq(getLayoutRequisition(*pChild
));
2040 aReq
.Width() = std::max(aReq
.Width(), rAllocation
.Width());
2041 aReq
.Height() = std::max(aReq
.Height(), rAllocation
.Height());
2042 setLayoutAllocation(*pChild
, Point(0, 0), aReq
);
2046 const vcl::Window
*VclEventBox::get_child() const
2048 const WindowImpl
* pWindowImpl
= ImplGetWindowImpl();
2050 assert(pWindowImpl
->mpFirstChild
.get() == m_aEventBoxHelper
.get());
2052 return pWindowImpl
->mpFirstChild
->GetWindow(GetWindowType::Next
);
2055 vcl::Window
*VclEventBox::get_child()
2057 return const_cast<vcl::Window
*>(const_cast<const VclEventBox
*>(this)->get_child());
2060 void VclEventBox::setAllocation(const Size
& rAllocation
)
2062 Point
aChildPos(0, 0);
2063 for (vcl::Window
*pChild
= GetWindow(GetWindowType::FirstChild
); pChild
; pChild
= pChild
->GetWindow(GetWindowType::Next
))
2065 if (!pChild
->IsVisible())
2067 setLayoutAllocation(*pChild
, aChildPos
, rAllocation
);
2071 Size
VclEventBox::calculateRequisition() const
2075 for (const vcl::Window
* pChild
= get_child(); pChild
;
2076 pChild
= pChild
->GetWindow(GetWindowType::Next
))
2078 if (!pChild
->IsVisible())
2080 Size aChildSize
= getLayoutRequisition(*pChild
);
2081 aRet
.Width() = std::max(aRet
.Width(), aChildSize
.Width());
2082 aRet
.Height() = std::max(aRet
.Height(), aChildSize
.Height());
2088 void VclEventBox::Command(const CommandEvent
&)
2090 //discard events by default to block them reaching children
2093 VclEventBox::~VclEventBox()
2098 void VclEventBox::dispose()
2100 m_aEventBoxHelper
.disposeAndClear();
2104 void VclSizeGroup::trigger_queue_resize()
2106 //sufficient to trigger one widget to trigger all of them
2107 if (!m_aWindows
.empty())
2109 (*m_aWindows
.begin())->queue_resize();
2113 void VclSizeGroup::set_ignore_hidden(bool bIgnoreHidden
)
2115 if (bIgnoreHidden
!= m_bIgnoreHidden
)
2117 m_bIgnoreHidden
= bIgnoreHidden
;
2118 trigger_queue_resize();
2122 void VclSizeGroup::set_mode(VclSizeGroupMode eMode
)
2124 if (eMode
!= m_eMode
)
2127 trigger_queue_resize();
2132 bool VclSizeGroup::set_property(const OString
&rKey
, const OString
&rValue
)
2134 if (rKey
== "ignore-hidden")
2135 set_ignore_hidden(toBool(rValue
));
2136 else if (rKey
== "mode")
2138 VclSizeGroupMode eMode
= VCL_SIZE_GROUP_HORIZONTAL
;
2139 if (rValue
.equals("none"))
2140 eMode
= VCL_SIZE_GROUP_NONE
;
2141 else if (rValue
.equals("horizontal"))
2142 eMode
= VCL_SIZE_GROUP_HORIZONTAL
;
2143 else if (rValue
.equals("vertical"))
2144 eMode
= VCL_SIZE_GROUP_VERTICAL
;
2145 else if (rValue
.equals("both"))
2146 eMode
= VCL_SIZE_GROUP_BOTH
;
2149 SAL_WARN("vcl.layout", "unknown size group mode" << rValue
.getStr());
2155 SAL_INFO("vcl.layout", "unhandled property: " << rKey
.getStr());
2161 void MessageDialog::create_owned_areas()
2163 set_border_width(12);
2164 m_pOwnedContentArea
.set(VclPtr
<VclVBox
>::Create(this, false, 24));
2165 set_content_area(m_pOwnedContentArea
);
2166 m_pOwnedContentArea
->Show();
2167 m_pOwnedActionArea
.set( VclPtr
<VclHButtonBox
>::Create(m_pOwnedContentArea
) );
2168 set_action_area(m_pOwnedActionArea
);
2169 m_pOwnedActionArea
->Show();
2172 MessageDialog::MessageDialog(vcl::Window
* pParent
, WinBits nStyle
)
2173 : Dialog(pParent
, nStyle
)
2174 , m_eButtonsType(VCL_BUTTONS_NONE
)
2175 , m_eMessageType(VclMessageType::Info
)
2176 , m_pOwnedContentArea(nullptr)
2177 , m_pOwnedActionArea(nullptr)
2180 , m_pPrimaryMessage(nullptr)
2181 , m_pSecondaryMessage(nullptr)
2183 SetType(WINDOW_MESSBOX
);
2186 MessageDialog::MessageDialog(vcl::Window
* pParent
,
2187 const OUString
&rMessage
,
2188 VclMessageType eMessageType
,
2189 VclButtonsType eButtonsType
)
2190 : Dialog(pParent
, WB_MOVEABLE
| WB_3DLOOK
| WB_CLOSEABLE
)
2191 , m_eButtonsType(eButtonsType
)
2192 , m_eMessageType(eMessageType
)
2195 , m_pPrimaryMessage(nullptr)
2196 , m_pSecondaryMessage(nullptr)
2197 , m_sPrimaryString(rMessage
)
2199 SetType(WINDOW_MESSBOX
);
2200 create_owned_areas();
2203 MessageDialog::MessageDialog(vcl::Window
* pParent
, const OString
& rID
, const OUString
& rUIXMLDescription
)
2204 : Dialog(pParent
, OStringToOUString(rID
, RTL_TEXTENCODING_UTF8
), rUIXMLDescription
, WINDOW_MESSBOX
)
2205 , m_eButtonsType(VCL_BUTTONS_NONE
)
2206 , m_eMessageType(VclMessageType::Info
)
2207 , m_pOwnedContentArea(nullptr)
2208 , m_pOwnedActionArea(nullptr)
2211 , m_pPrimaryMessage(nullptr)
2212 , m_pSecondaryMessage(nullptr)
2216 void MessageDialog::dispose()
2218 for (VclPtr
<PushButton
> & pOwnedButton
: m_aOwnedButtons
)
2219 pOwnedButton
.disposeAndClear();
2220 m_aOwnedButtons
.clear();
2222 m_pPrimaryMessage
.disposeAndClear();
2223 m_pSecondaryMessage
.disposeAndClear();
2224 m_pImage
.disposeAndClear();
2225 m_pGrid
.disposeAndClear();
2226 m_pOwnedActionArea
.disposeAndClear();
2227 m_pOwnedContentArea
.disposeAndClear();
2228 m_aResponses
.clear();
2232 MessageDialog::~MessageDialog()
2237 void MessageDialog::response(short nResponseId
)
2239 EndDialog(nResponseId
);
2242 IMPL_LINK(MessageDialog
, ButtonHdl
, Button
*, pButton
, void)
2244 response(get_response(pButton
));
2247 short MessageDialog::get_response(const vcl::Window
*pWindow
) const
2249 auto aFind
= m_aResponses
.find(pWindow
);
2250 if (aFind
!= m_aResponses
.end())
2251 return aFind
->second
;
2254 return m_pUIBuilder
->get_response(pWindow
);
2257 void MessageDialog::setButtonHandlers(VclButtonBox
*pButtonBox
)
2260 for (vcl::Window
* pChild
= pButtonBox
->GetWindow(GetWindowType::FirstChild
); pChild
;
2261 pChild
= pChild
->GetWindow(GetWindowType::Next
))
2263 switch (pChild
->GetType())
2265 case WINDOW_PUSHBUTTON
:
2267 PushButton
* pButton
= static_cast<PushButton
*>(pChild
);
2268 pButton
->SetClickHdl(LINK(this, MessageDialog
, ButtonHdl
));
2271 //insist that the response ids match the default actions for those
2272 //widgets, and leave their default handlers in place
2273 case WINDOW_OKBUTTON
:
2274 assert(get_response(pChild
) == RET_OK
);
2276 case WINDOW_CANCELBUTTON
:
2277 assert(get_response(pChild
) == RET_CANCEL
);
2279 case WINDOW_HELPBUTTON
:
2280 assert(get_response(pChild
) == RET_HELP
);
2283 SAL_WARN("vcl.layout", "The type of widget " <<
2284 pChild
->GetHelpId() << " is currently not handled");
2287 //The default is to stick the focus into the first widget
2288 //that accepts it, and if that happens and it's a button
2289 //then that becomes the new default button, so explicitly
2290 //put the focus into the default button
2291 if (pChild
->GetStyle() & WB_DEFBUTTON
)
2292 pChild
->GrabFocus();
2296 void MessageDialog::SetMessagesWidths(vcl::Window
*pParent
,
2297 VclMultiLineEdit
*pPrimaryMessage
, VclMultiLineEdit
*pSecondaryMessage
)
2299 if (pSecondaryMessage
)
2301 assert(pPrimaryMessage
);
2302 vcl::Font aFont
= pParent
->GetSettings().GetStyleSettings().GetLabelFont();
2303 aFont
.SetFontSize(Size(0, aFont
.GetFontSize().Height() * 1.2));
2304 aFont
.SetWeight(WEIGHT_BOLD
);
2305 pPrimaryMessage
->SetControlFont(aFont
);
2306 pPrimaryMessage
->SetMaxTextWidth(pPrimaryMessage
->approximate_char_width() * 44);
2307 pSecondaryMessage
->SetMaxTextWidth(pSecondaryMessage
->approximate_char_width() * 60);
2310 pPrimaryMessage
->SetMaxTextWidth(pPrimaryMessage
->approximate_char_width() * 60);
2313 void MessageDialog::InitExecute()
2315 setDeferredProperties();
2319 VclContainer
*pContainer
= get_content_area();
2322 m_pGrid
.set( VclPtr
<VclGrid
>::Create(pContainer
) );
2323 m_pGrid
->reorderWithinParent(0);
2324 m_pGrid
->set_column_spacing(12);
2325 m_pGrid
->set_row_spacing(GetTextHeight());
2327 m_pImage
= VclPtr
<FixedImage
>::Create(m_pGrid
, WB_CENTER
| WB_VCENTER
| WB_3DLOOK
);
2328 switch (m_eMessageType
)
2330 case VclMessageType::Info
:
2331 m_pImage
->SetImage(InfoBox::GetStandardImage());
2333 case VclMessageType::Warning
:
2334 m_pImage
->SetImage(WarningBox::GetStandardImage());
2336 case VclMessageType::Question
:
2337 m_pImage
->SetImage(QueryBox::GetStandardImage());
2339 case VclMessageType::Error
:
2340 m_pImage
->SetImage(ErrorBox::GetStandardImage());
2343 m_pImage
->set_grid_left_attach(0);
2344 m_pImage
->set_grid_top_attach(0);
2345 m_pImage
->set_valign(VclAlign::Start
);
2348 WinBits nWinStyle
= WB_CLIPCHILDREN
| WB_LEFT
| WB_VCENTER
| WB_NOLABEL
| WB_NOTABSTOP
;
2350 bool bHasSecondaryText
= !m_sSecondaryString
.isEmpty();
2352 m_pPrimaryMessage
= VclPtr
<VclMultiLineEdit
>::Create(m_pGrid
, nWinStyle
);
2353 m_pPrimaryMessage
->SetPaintTransparent(true);
2354 m_pPrimaryMessage
->EnableCursor(false);
2356 m_pPrimaryMessage
->set_grid_left_attach(1);
2357 m_pPrimaryMessage
->set_grid_top_attach(0);
2358 m_pPrimaryMessage
->set_hexpand(true);
2359 m_pPrimaryMessage
->SetText(m_sPrimaryString
);
2360 m_pPrimaryMessage
->Show(!m_sPrimaryString
.isEmpty());
2362 m_pSecondaryMessage
= VclPtr
<VclMultiLineEdit
>::Create(m_pGrid
, nWinStyle
);
2363 m_pSecondaryMessage
->SetPaintTransparent(true);
2364 m_pSecondaryMessage
->EnableCursor(false);
2365 m_pSecondaryMessage
->set_grid_left_attach(1);
2366 m_pSecondaryMessage
->set_grid_top_attach(1);
2367 m_pSecondaryMessage
->set_hexpand(true);
2368 m_pSecondaryMessage
->SetText(m_sSecondaryString
);
2369 m_pSecondaryMessage
->Show(bHasSecondaryText
);
2371 MessageDialog::SetMessagesWidths(this, m_pPrimaryMessage
, bHasSecondaryText
? m_pSecondaryMessage
.get() : nullptr);
2373 VclButtonBox
*pButtonBox
= get_action_area();
2376 VclPtr
<PushButton
> pBtn
;
2377 switch (m_eButtonsType
)
2379 case VCL_BUTTONS_NONE
:
2381 case VCL_BUTTONS_OK
:
2382 pBtn
.set( VclPtr
<OKButton
>::Create(pButtonBox
) );
2383 pBtn
->SetStyle(pBtn
->GetStyle() & WB_DEFBUTTON
);
2386 m_aOwnedButtons
.push_back(pBtn
);
2387 m_aResponses
[pBtn
] = RET_OK
;
2389 case VCL_BUTTONS_CLOSE
:
2390 pBtn
.set( VclPtr
<CloseButton
>::Create(pButtonBox
) );
2391 pBtn
->SetStyle(pBtn
->GetStyle() & WB_DEFBUTTON
);
2393 pBtn
->set_id("close");
2394 m_aOwnedButtons
.push_back(pBtn
);
2395 m_aResponses
[pBtn
] = RET_CLOSE
;
2397 case VCL_BUTTONS_CANCEL
:
2398 pBtn
.set( VclPtr
<CancelButton
>::Create(pButtonBox
) );
2399 pBtn
->SetStyle(pBtn
->GetStyle() & WB_DEFBUTTON
);
2400 pBtn
->set_id("cancel");
2401 m_aOwnedButtons
.push_back(pBtn
);
2402 m_aResponses
[pBtn
] = RET_CANCEL
;
2404 case VCL_BUTTONS_YES_NO
:
2405 pBtn
= VclPtr
<PushButton
>::Create(pButtonBox
);
2406 pBtn
->SetText(Button::GetStandardText(StandardButtonType::Yes
));
2408 pBtn
->set_id("yes");
2409 m_aOwnedButtons
.push_back(pBtn
);
2410 m_aResponses
[pBtn
] = RET_YES
;
2412 pBtn
.set( VclPtr
<PushButton
>::Create(pButtonBox
) );
2413 pBtn
->SetStyle(pBtn
->GetStyle() & WB_DEFBUTTON
);
2414 pBtn
->SetText(Button::GetStandardText(StandardButtonType::No
));
2417 m_aOwnedButtons
.push_back(pBtn
);
2418 m_aResponses
[pBtn
] = RET_NO
;
2420 case VCL_BUTTONS_OK_CANCEL
:
2421 pBtn
.set( VclPtr
<OKButton
>::Create(pButtonBox
) );
2424 m_aOwnedButtons
.push_back(pBtn
);
2425 m_aResponses
[pBtn
] = RET_OK
;
2427 pBtn
.set( VclPtr
<CancelButton
>::Create(pButtonBox
) );
2428 pBtn
->SetStyle(pBtn
->GetStyle() & WB_DEFBUTTON
);
2430 pBtn
->set_id("cancel");
2431 m_aOwnedButtons
.push_back(pBtn
);
2432 m_aResponses
[pBtn
] = RET_CANCEL
;
2435 setButtonHandlers(pButtonBox
);
2436 pButtonBox
->sort_native_button_order();
2441 bool MessageDialog::StartExecuteAsync(const std::function
<void(sal_Int32
)> &rEndDialogFn
)
2444 return Dialog::StartExecuteAsync(rEndDialogFn
);
2447 short MessageDialog::Execute()
2450 return Dialog::Execute();
2453 OUString
const & MessageDialog::get_primary_text() const
2455 const_cast<MessageDialog
*>(this)->setDeferredProperties();
2457 return m_sPrimaryString
;
2460 OUString
const & MessageDialog::get_secondary_text() const
2462 const_cast<MessageDialog
*>(this)->setDeferredProperties();
2464 return m_sSecondaryString
;
2467 bool MessageDialog::set_property(const OString
&rKey
, const OString
&rValue
)
2470 set_primary_text(OStringToOUString(rValue
, RTL_TEXTENCODING_UTF8
));
2471 else if (rKey
== "secondary-text")
2472 set_secondary_text(OStringToOUString(rValue
, RTL_TEXTENCODING_UTF8
));
2473 else if (rKey
== "message-type")
2475 VclMessageType eMode
= VclMessageType::Info
;
2476 if (rValue
.equals("info"))
2477 eMode
= VclMessageType::Info
;
2478 else if (rValue
.equals("warning"))
2479 eMode
= VclMessageType::Warning
;
2480 else if (rValue
.equals("question"))
2481 eMode
= VclMessageType::Question
;
2482 else if (rValue
.equals("error"))
2483 eMode
= VclMessageType::Error
;
2486 SAL_WARN("vcl.layout", "unknown message type mode" << rValue
.getStr());
2488 m_eMessageType
= eMode
;
2490 else if (rKey
== "buttons")
2492 VclButtonsType eMode
= VCL_BUTTONS_NONE
;
2493 if (rValue
.equals("none"))
2494 eMode
= VCL_BUTTONS_NONE
;
2495 else if (rValue
.equals("ok"))
2496 eMode
= VCL_BUTTONS_OK
;
2497 else if (rValue
.equals("cancel"))
2498 eMode
= VCL_BUTTONS_CANCEL
;
2499 else if (rValue
.equals("close"))
2500 eMode
= VCL_BUTTONS_CLOSE
;
2501 else if (rValue
.equals("yes-no"))
2502 eMode
= VCL_BUTTONS_YES_NO
;
2503 else if (rValue
.equals("ok-cancel"))
2504 eMode
= VCL_BUTTONS_OK_CANCEL
;
2507 SAL_WARN("vcl.layout", "unknown buttons type mode" << rValue
.getStr());
2509 m_eButtonsType
= eMode
;
2512 return Dialog::set_property(rKey
, rValue
);
2516 void MessageDialog::set_primary_text(const OUString
&rPrimaryString
)
2518 m_sPrimaryString
= rPrimaryString
;
2519 if (m_pPrimaryMessage
)
2521 m_pPrimaryMessage
->SetText(m_sPrimaryString
);
2522 m_pPrimaryMessage
->Show(!m_sPrimaryString
.isEmpty());
2526 void MessageDialog::set_secondary_text(const OUString
&rSecondaryString
)
2528 m_sSecondaryString
= rSecondaryString
;
2529 if (m_pSecondaryMessage
)
2531 m_pSecondaryMessage
->SetText("\n" + m_sSecondaryString
);
2532 m_pSecondaryMessage
->Show(!m_sSecondaryString
.isEmpty());
2536 VclVPaned::VclVPaned(vcl::Window
*pParent
, WinBits nStyle
)
2537 : VclContainer(pParent
, nStyle
)
2538 , m_pSplitter(VclPtr
<Splitter
>::Create(this, WB_VSCROLL
))
2541 m_pSplitter
->SetSplitHdl(LINK(this, VclVPaned
, SplitHdl
));
2542 m_pSplitter
->SetBackground(Wallpaper(Application::GetSettings().GetStyleSettings().GetFaceColor()));
2543 m_pSplitter
->Show();
2546 void VclVPaned::dispose()
2548 m_pSplitter
.disposeAndClear();
2549 VclContainer::dispose();
2552 IMPL_LINK(VclVPaned
, SplitHdl
, Splitter
*, pSplitter
, void)
2554 double nSize
= pSplitter
->GetSplitPosPixel();
2555 Size
aSplitterSize(m_pSplitter
->GetSizePixel());
2556 Size
aAllocation(GetSizePixel());
2557 arrange(aAllocation
, nSize
, aAllocation
.Height() - nSize
- aSplitterSize
.Height());
2560 void VclVPaned::arrange(const Size
& rAllocation
, long nFirstHeight
, long nSecondHeight
)
2562 Size
aSplitterSize(rAllocation
.Width(), getLayoutRequisition(*m_pSplitter
).Height());
2563 Size
aFirstChildSize(rAllocation
.Width(), nFirstHeight
);
2564 Size
aSecondChildSize(rAllocation
.Width(), nSecondHeight
);
2566 for (vcl::Window
* pChild
= GetWindow(GetWindowType::FirstChild
); pChild
;
2567 pChild
= pChild
->GetWindow(GetWindowType::Next
))
2569 if (!pChild
->IsVisible())
2573 Point
aSplitterPos(0, aFirstChildSize
.Height());
2574 setLayoutAllocation(*m_pSplitter
, aSplitterPos
, aSplitterSize
);
2575 set_position(aSplitterPos
.Y() + aSplitterSize
.Height() / 2);
2577 else if (nElement
== 1)
2579 Point
aChildPos(0, 0);
2580 setLayoutAllocation(*pChild
, aChildPos
, aFirstChildSize
);
2582 else if (nElement
== 2)
2584 Point
aChildPos(0, aFirstChildSize
.Height() + aSplitterSize
.Height());
2585 setLayoutAllocation(*pChild
, aChildPos
, aSecondChildSize
);
2591 void VclVPaned::setAllocation(const Size
& rAllocation
)
2593 //supporting "shrink" could be done by adjusting the allowed drag rectangle
2594 m_pSplitter
->SetDragRectPixel(Rectangle(Point(0, 0), rAllocation
));
2595 Size
aSplitterSize(rAllocation
.Width(), getLayoutRequisition(*m_pSplitter
).Height());
2596 const long nHeight
= rAllocation
.Height() - aSplitterSize
.Height();
2598 long nFirstHeight
= 0;
2599 long nSecondHeight
= 0;
2600 bool bFirstCanResize
= true;
2601 bool bSecondCanResize
= true;
2602 const bool bInitialAllocation
= get_position() < 0;
2604 for (const vcl::Window
* pChild
= GetWindow(GetWindowType::FirstChild
); pChild
;
2605 pChild
= pChild
->GetWindow(GetWindowType::Next
))
2607 if (!pChild
->IsVisible())
2611 if (bInitialAllocation
)
2612 nFirstHeight
= getLayoutRequisition(*pChild
).Height();
2614 nFirstHeight
= pChild
->GetSizePixel().Height();
2615 bFirstCanResize
= pChild
->get_expand();
2617 else if (nElement
== 2)
2619 if (bInitialAllocation
)
2620 nSecondHeight
= getLayoutRequisition(*pChild
).Height();
2622 nSecondHeight
= pChild
->GetSizePixel().Height();
2623 bSecondCanResize
= pChild
->get_expand();
2627 long nHeightRequest
= nFirstHeight
+ nSecondHeight
;
2628 long nHeightDiff
= nHeight
- nHeightRequest
;
2629 if (bFirstCanResize
== bSecondCanResize
)
2630 nFirstHeight
+= nHeightDiff
/2;
2631 else if (bFirstCanResize
)
2632 nFirstHeight
+= nHeightDiff
;
2633 arrange(rAllocation
, nFirstHeight
, nSecondHeight
);
2636 Size
VclVPaned::calculateRequisition() const
2640 for (const vcl::Window
* pChild
= GetWindow(GetWindowType::FirstChild
); pChild
;
2641 pChild
= pChild
->GetWindow(GetWindowType::Next
))
2643 if (!pChild
->IsVisible())
2645 Size aChildSize
= getLayoutRequisition(*pChild
);
2646 aRet
.Width() = std::max(aRet
.Width(), aChildSize
.Width());
2647 aRet
.Height() += aChildSize
.Height();
2653 Size
getLegacyBestSizeForChildren(const vcl::Window
&rWindow
)
2657 for (const vcl::Window
* pChild
= rWindow
.GetWindow(GetWindowType::FirstChild
); pChild
;
2658 pChild
= pChild
->GetWindow(GetWindowType::Next
))
2660 if (!pChild
->IsVisible())
2663 Rectangle
aChildBounds(pChild
->GetPosPixel(), pChild
->GetSizePixel());
2664 aBounds
.Union(aChildBounds
);
2667 if (aBounds
.IsEmpty())
2668 return rWindow
.GetSizePixel();
2670 Size
aRet(aBounds
.GetSize());
2671 Point
aTopLeft(aBounds
.TopLeft());
2672 aRet
.Width() += aTopLeft
.X()*2;
2673 aRet
.Height() += aTopLeft
.Y()*2;
2678 vcl::Window
* getNonLayoutParent(vcl::Window
*pWindow
)
2682 pWindow
= pWindow
->GetParent();
2683 if (!pWindow
|| !isContainerWindow(*pWindow
))
2689 bool isVisibleInLayout(const vcl::Window
*pWindow
)
2691 bool bVisible
= true;
2694 bVisible
= pWindow
->IsVisible();
2695 pWindow
= pWindow
->GetParent();
2696 if (!pWindow
|| !isContainerWindow(*pWindow
))
2702 bool isEnabledInLayout(const vcl::Window
*pWindow
)
2704 bool bEnabled
= true;
2707 bEnabled
= pWindow
->IsEnabled();
2708 pWindow
= pWindow
->GetParent();
2709 if (!pWindow
|| !isContainerWindow(*pWindow
))
2715 bool isLayoutEnabled(const vcl::Window
*pWindow
)
2717 //Child is a container => we're layout enabled
2718 const vcl::Window
*pChild
= pWindow
? pWindow
->GetWindow(GetWindowType::FirstChild
) : nullptr;
2719 return pChild
&& isContainerWindow(*pChild
) && !pChild
->GetWindow(GetWindowType::Next
);
2722 bool isInitialLayout(const vcl::Window
*pWindow
)
2724 Dialog
*pParentDialog
= pWindow
? pWindow
->GetParentDialog() : nullptr;
2725 return pParentDialog
&& pParentDialog
->isCalculatingInitialLayoutSize();
2728 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */