update credits
[LibreOffice.git] / vcl / source / window / layout.cxx
blob9b1d56f40b5185d9975a548ebddb3070e8d1bfb5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include <com/sun/star/accessibility/AccessibleRole.hpp>
11 #include <vcl/dialog.hxx>
12 #include <vcl/layout.hxx>
13 #include <vcl/msgbox.hxx>
14 #include <vcl/svapp.hxx>
15 #include "window.h"
17 VclContainer::VclContainer(Window *pParent, WinBits nStyle)
18 : Window(WINDOW_CONTAINER)
19 , m_bLayoutDirty(true)
21 ImplInit(pParent, nStyle, NULL);
22 EnableChildTransparentMode();
23 SetPaintTransparent(true);
24 SetBackground();
27 sal_uInt16 VclContainer::getDefaultAccessibleRole() const
29 return com::sun::star::accessibility::AccessibleRole::PANEL;
32 Size VclContainer::GetOptimalSize() const
34 return calculateRequisition();
37 void VclContainer::setLayoutPosSize(Window &rWindow, const Point &rPos, const Size &rSize)
39 sal_Int32 nBorderWidth = rWindow.get_border_width();
40 sal_Int32 nLeft = rWindow.get_margin_left() + nBorderWidth;
41 sal_Int32 nTop = rWindow.get_margin_top() + nBorderWidth;
42 sal_Int32 nRight = rWindow.get_margin_right() + nBorderWidth;
43 sal_Int32 nBottom = rWindow.get_margin_bottom() + nBorderWidth;
44 Point aPos(rPos.X() + nLeft, rPos.Y() + nTop);
45 Size aSize(rSize.Width() - nLeft - nRight, rSize.Height() - nTop - nBottom);
46 rWindow.SetPosSizePixel(aPos, aSize);
49 void VclContainer::setLayoutAllocation(Window &rChild, const Point &rAllocPos, const Size &rChildAlloc)
51 VclAlign eHalign = rChild.get_halign();
52 VclAlign eValign = rChild.get_valign();
54 //typical case
55 if (eHalign == VCL_ALIGN_FILL && eValign == VCL_ALIGN_FILL)
57 setLayoutPosSize(rChild, rAllocPos, rChildAlloc);
58 return;
61 Point aChildPos(rAllocPos);
62 Size aChildSize(rChildAlloc);
63 Size aChildPreferredSize(getLayoutRequisition(rChild));
65 switch (eHalign)
67 case VCL_ALIGN_FILL:
68 break;
69 case VCL_ALIGN_START:
70 if (aChildPreferredSize.Width() < rChildAlloc.Width())
71 aChildSize.Width() = aChildPreferredSize.Width();
72 break;
73 case VCL_ALIGN_END:
74 if (aChildPreferredSize.Width() < rChildAlloc.Width())
75 aChildSize.Width() = aChildPreferredSize.Width();
76 aChildPos.X() += rChildAlloc.Width();
77 aChildPos.X() -= aChildSize.Width();
78 break;
79 case VCL_ALIGN_CENTER:
80 if (aChildPreferredSize.Width() < aChildSize.Width())
81 aChildSize.Width() = aChildPreferredSize.Width();
82 aChildPos.X() += (rChildAlloc.Width() - aChildSize.Width()) / 2;
83 break;
86 switch (eValign)
88 case VCL_ALIGN_FILL:
89 break;
90 case VCL_ALIGN_START:
91 if (aChildPreferredSize.Height() < rChildAlloc.Height())
92 aChildSize.Height() = aChildPreferredSize.Height();
93 break;
94 case VCL_ALIGN_END:
95 if (aChildPreferredSize.Height() < rChildAlloc.Height())
96 aChildSize.Height() = aChildPreferredSize.Height();
97 aChildPos.Y() += rChildAlloc.Height();
98 aChildPos.Y() -= aChildSize.Height();
99 break;
100 case VCL_ALIGN_CENTER:
101 if (aChildPreferredSize.Height() < aChildSize.Height())
102 aChildSize.Height() = aChildPreferredSize.Height();
103 aChildPos.Y() += (rChildAlloc.Height() - aChildSize.Height()) / 2;
104 break;
107 setLayoutPosSize(rChild, aChildPos, aChildSize);
110 Size VclContainer::getLayoutRequisition(const Window &rWindow)
112 sal_Int32 nBorderWidth = rWindow.get_border_width();
113 sal_Int32 nLeft = rWindow.get_margin_left() + nBorderWidth;
114 sal_Int32 nTop = rWindow.get_margin_top() + nBorderWidth;
115 sal_Int32 nRight = rWindow.get_margin_right() + nBorderWidth;
116 sal_Int32 nBottom = rWindow.get_margin_bottom() + nBorderWidth;
117 Size aSize(rWindow.get_preferred_size());
118 return Size(aSize.Width() + nLeft + nRight, aSize.Height() + nTop + nBottom);
121 void VclContainer::SetPosSizePixel(const Point& rAllocPos, const Size& rAllocation)
123 bool bSizeChanged = rAllocation != GetOutputSizePixel();
124 Window::SetPosSizePixel(rAllocPos, rAllocation);
125 if (m_bLayoutDirty || bSizeChanged)
127 m_bLayoutDirty = false;
128 setAllocation(rAllocation);
132 void VclContainer::SetPosPixel(const Point& rAllocPos)
134 Point aAllocPos = rAllocPos;
135 sal_Int32 nBorderWidth = get_border_width();
136 aAllocPos.X() += nBorderWidth + get_margin_left();
137 aAllocPos.Y() += nBorderWidth + get_margin_top();
139 if (aAllocPos != GetPosPixel())
140 Window::SetPosPixel(aAllocPos);
143 void VclContainer::SetSizePixel(const Size& rAllocation)
145 Size aAllocation = rAllocation;
146 sal_Int32 nBorderWidth = get_border_width();
147 aAllocation.Width() -= nBorderWidth*2 + get_margin_left() + get_margin_right();
148 aAllocation.Height() -= nBorderWidth*2 + get_margin_top() + get_margin_bottom();
149 bool bSizeChanged = aAllocation != GetSizePixel();
150 if (bSizeChanged)
151 Window::SetSizePixel(aAllocation);
152 if (m_bLayoutDirty || bSizeChanged)
154 m_bLayoutDirty = false;
155 setAllocation(aAllocation);
159 void VclBox::accumulateMaxes(const Size &rChildSize, Size &rSize) const
161 long nSecondaryChildDimension = getSecondaryDimension(rChildSize);
162 long nSecondaryBoxDimension = getSecondaryDimension(rSize);
163 setSecondaryDimension(rSize, std::max(nSecondaryChildDimension, nSecondaryBoxDimension));
165 long nPrimaryChildDimension = getPrimaryDimension(rChildSize);
166 long nPrimaryBoxDimension = getPrimaryDimension(rSize);
167 if (m_bHomogeneous)
168 setPrimaryDimension(rSize, std::max(nPrimaryBoxDimension, nPrimaryChildDimension));
169 else
170 setPrimaryDimension(rSize, nPrimaryBoxDimension + nPrimaryChildDimension);
173 Size VclBox::calculateRequisition() const
175 sal_uInt16 nVisibleChildren = 0;
177 Size aSize;
178 for (Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
180 if (!pChild->IsVisible())
181 continue;
182 ++nVisibleChildren;
183 Size aChildSize = getLayoutRequisition(*pChild);
185 long nPrimaryDimension = getPrimaryDimension(aChildSize);
186 nPrimaryDimension += pChild->get_padding() * 2;
187 setPrimaryDimension(aChildSize, nPrimaryDimension);
189 accumulateMaxes(aChildSize, aSize);
192 return finalizeMaxes(aSize, nVisibleChildren);
195 void VclBox::setAllocation(const Size &rAllocation)
197 sal_uInt16 nVisibleChildren = 0, nExpandChildren = 0;
198 for (Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
200 if (!pChild->IsVisible())
201 continue;
202 ++nVisibleChildren;
203 bool bExpand = getPrimaryDimensionChildExpand(*pChild);
204 if (bExpand)
205 ++nExpandChildren;
208 if (!nVisibleChildren)
209 return;
211 long nAllocPrimaryDimension = getPrimaryDimension(rAllocation);
213 long nHomogeneousDimension = 0, nExtraSpace = 0;
214 if (m_bHomogeneous)
216 nHomogeneousDimension = ((nAllocPrimaryDimension -
217 (nVisibleChildren - 1) * m_nSpacing)) / nVisibleChildren;
219 else if (nExpandChildren)
221 Size aRequisition = calculateRequisition();
222 nExtraSpace = (getPrimaryDimension(rAllocation) - getPrimaryDimension(aRequisition)) / nExpandChildren;
225 for (sal_Int32 ePackType = VCL_PACK_START; ePackType <= VCL_PACK_END; ++ePackType)
227 Point aPos(0, 0);
228 if (ePackType == VCL_PACK_END)
230 long nPrimaryCoordinate = getPrimaryCoordinate(aPos);
231 setPrimaryCoordinate(aPos, nPrimaryCoordinate + nAllocPrimaryDimension);
234 for (Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
236 if (!pChild->IsVisible())
237 continue;
239 sal_Int32 ePacking = pChild->get_pack_type();
241 if (ePacking != ePackType)
242 continue;
244 long nPadding = pChild->get_padding();
246 Size aBoxSize;
247 if (m_bHomogeneous)
248 setPrimaryDimension(aBoxSize, nHomogeneousDimension);
249 else
251 aBoxSize = getLayoutRequisition(*pChild);
252 long nPrimaryDimension = getPrimaryDimension(aBoxSize);
253 nPrimaryDimension += nPadding * 2;
254 if (getPrimaryDimensionChildExpand(*pChild))
255 nPrimaryDimension += nExtraSpace;
256 setPrimaryDimension(aBoxSize, nPrimaryDimension);
258 setSecondaryDimension(aBoxSize, getSecondaryDimension(rAllocation));
260 Point aChildPos(aPos);
261 Size aChildSize(aBoxSize);
262 long nPrimaryCoordinate = getPrimaryCoordinate(aPos);
264 bool bFill = pChild->get_fill();
265 if (bFill)
267 setPrimaryDimension(aChildSize, std::max(static_cast<long>(1),
268 getPrimaryDimension(aBoxSize) - nPadding * 2));
270 setPrimaryCoordinate(aChildPos, nPrimaryCoordinate + nPadding);
272 else
274 setPrimaryDimension(aChildSize,
275 getPrimaryDimension(getLayoutRequisition(*pChild)));
277 setPrimaryCoordinate(aChildPos, nPrimaryCoordinate +
278 (getPrimaryDimension(aBoxSize) - getPrimaryDimension(aChildSize)) / 2);
281 long nDiff = getPrimaryDimension(aBoxSize) + m_nSpacing;
282 if (ePackType == VCL_PACK_START)
283 setPrimaryCoordinate(aPos, nPrimaryCoordinate + nDiff);
284 else
286 setPrimaryCoordinate(aPos, nPrimaryCoordinate - nDiff);
287 setPrimaryCoordinate(aChildPos, getPrimaryCoordinate(aChildPos) -
288 getPrimaryDimension(aBoxSize));
291 setLayoutAllocation(*pChild, aChildPos, aChildSize);
296 bool VclBox::set_property(const OString &rKey, const OString &rValue)
298 if (rKey == "spacing")
299 set_spacing(rValue.toInt32());
300 else if (rKey == "homogeneous")
301 set_homogeneous(toBool(rValue));
302 else
303 return VclContainer::set_property(rKey, rValue);
304 return true;
307 sal_uInt16 VclBox::getDefaultAccessibleRole() const
309 return com::sun::star::accessibility::AccessibleRole::FILLER;
312 #define DEFAULT_CHILD_MIN_WIDTH 85
313 #define DEFAULT_CHILD_MIN_HEIGHT 27
315 Size VclBox::finalizeMaxes(const Size &rSize, sal_uInt16 nVisibleChildren) const
317 Size aRet;
319 if (nVisibleChildren)
321 long nPrimaryDimension = getPrimaryDimension(rSize);
322 if (m_bHomogeneous)
323 nPrimaryDimension *= nVisibleChildren;
324 setPrimaryDimension(aRet, nPrimaryDimension + m_nSpacing * (nVisibleChildren-1));
325 setSecondaryDimension(aRet, getSecondaryDimension(rSize));
328 return aRet;
331 Size VclButtonBox::addReqGroups(const VclButtonBox::Requisition &rReq) const
333 Size aRet;
335 long nMainGroupDimension = getPrimaryDimension(rReq.m_aMainGroupSize);
336 long nSubGroupDimension = getPrimaryDimension(rReq.m_aSubGroupSize);
338 setPrimaryDimension(aRet, nMainGroupDimension + nSubGroupDimension);
340 setSecondaryDimension(aRet,
341 std::max(getSecondaryDimension(rReq.m_aMainGroupSize),
342 getSecondaryDimension(rReq.m_aSubGroupSize)));
344 return aRet;
347 static long getMaxNonOutlier(const std::vector<long> &rG, long nAvgDimension)
349 long nMaxDimensionNonOutlier = 0;
350 for (std::vector<long>::const_iterator aI = rG.begin(),
351 aEnd = rG.end(); aI != aEnd; ++aI)
353 long nPrimaryChildDimension = *aI;
354 if (nPrimaryChildDimension < nAvgDimension * 1.5)
356 nMaxDimensionNonOutlier = std::max(nPrimaryChildDimension,
357 nMaxDimensionNonOutlier);
360 return nMaxDimensionNonOutlier;
363 static std::vector<long> setButtonSizes(const std::vector<long> &rG,
364 long nAvgDimension, long nMaxNonOutlier, long nMinWidth)
366 std::vector<long> aVec;
367 //set everything < 1.5 times the average to the same width, leave the
368 //outliers un-touched
369 for (std::vector<long>::const_iterator aI = rG.begin(), aEnd = rG.end();
370 aI != aEnd; ++aI)
372 long nPrimaryChildDimension = *aI;
373 if (nPrimaryChildDimension < nAvgDimension * 1.5)
375 aVec.push_back(std::max(nMaxNonOutlier, nMinWidth));
377 else
379 aVec.push_back(std::max(nPrimaryChildDimension, nMinWidth));
382 return aVec;
385 VclButtonBox::Requisition VclButtonBox::calculatePrimarySecondaryRequisitions() const
387 Requisition aReq;
389 Size aMainGroupSize(DEFAULT_CHILD_MIN_WIDTH, DEFAULT_CHILD_MIN_HEIGHT); //to-do, pull from theme
390 Size aSubGroupSize(DEFAULT_CHILD_MIN_WIDTH, DEFAULT_CHILD_MIN_HEIGHT); //to-do, pull from theme
392 long nMinMainGroupPrimary = getPrimaryDimension(aMainGroupSize);
393 long nMinSubGroupPrimary = getPrimaryDimension(aSubGroupSize);
394 long nMainGroupSecondary = getSecondaryDimension(aMainGroupSize);
395 long nSubGroupSecondary = getSecondaryDimension(aSubGroupSize);
397 bool bIgnoreSecondaryPacking = (m_eLayoutStyle == VCL_BUTTONBOX_SPREAD || m_eLayoutStyle == VCL_BUTTONBOX_CENTER);
399 std::vector<long> aMainGroupSizes;
400 std::vector<long> aSubGroupSizes;
402 for (const Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
404 if (!pChild->IsVisible())
405 continue;
406 Size aChildSize = getLayoutRequisition(*pChild);
407 if (bIgnoreSecondaryPacking || !pChild->get_secondary())
409 //set the max secondary dimension
410 nMainGroupSecondary = std::max(nMainGroupSecondary, getSecondaryDimension(aChildSize));
411 //collect the primary dimensions
412 aMainGroupSizes.push_back(getPrimaryDimension(aChildSize));
414 else
416 nSubGroupSecondary = std::max(nSubGroupSecondary, getSecondaryDimension(aChildSize));
417 aSubGroupSizes.push_back(getPrimaryDimension(aChildSize));
421 if (m_bHomogeneous)
423 long nMaxMainDimension = aMainGroupSizes.empty() ? 0 :
424 *std::max_element(aMainGroupSizes.begin(), aMainGroupSizes.end());
425 nMaxMainDimension = std::max(nMaxMainDimension, nMinMainGroupPrimary);
426 long nMaxSubDimension = aSubGroupSizes.empty() ? 0 :
427 *std::max_element(aSubGroupSizes.begin(), aSubGroupSizes.end());
428 nMaxSubDimension = std::max(nMaxSubDimension, nMinSubGroupPrimary);
429 long nMaxDimension = std::max(nMaxMainDimension, nMaxSubDimension);
430 aReq.m_aMainGroupDimensions.resize(aMainGroupSizes.size(), nMaxDimension);
431 aReq.m_aSubGroupDimensions.resize(aSubGroupSizes.size(), nMaxDimension);
433 else
435 //Ideally set everything to the same size, but find outlier widgets
436 //that are way wider than the average and leave them
437 //at their natural size and set the remainder to share the
438 //max size of the remaining members of the buttonbox
439 long nAccDimension = std::accumulate(aMainGroupSizes.begin(),
440 aMainGroupSizes.end(), 0);
441 nAccDimension = std::accumulate(aSubGroupSizes.begin(),
442 aSubGroupSizes.end(), nAccDimension);
444 size_t nTotalSize = aMainGroupSizes.size() + aSubGroupSizes.size();
446 long nAvgDimension = nTotalSize ? nAccDimension / nTotalSize : 0;
448 long nMaxMainNonOutlier = getMaxNonOutlier(aMainGroupSizes,
449 nAvgDimension);
450 long nMaxSubNonOutlier = getMaxNonOutlier(aSubGroupSizes,
451 nAvgDimension);
452 long nMaxNonOutlier = std::max(nMaxMainNonOutlier, nMaxSubNonOutlier);
454 aReq.m_aMainGroupDimensions = setButtonSizes(aMainGroupSizes,
455 nAvgDimension, nMaxNonOutlier, nMinMainGroupPrimary);
456 aReq.m_aSubGroupDimensions = setButtonSizes(aSubGroupSizes,
457 nAvgDimension, nMaxNonOutlier, nMinSubGroupPrimary);
460 if (!aReq.m_aMainGroupDimensions.empty())
462 setSecondaryDimension(aReq.m_aMainGroupSize, nMainGroupSecondary);
463 setPrimaryDimension(aReq.m_aMainGroupSize,
464 std::accumulate(aReq.m_aMainGroupDimensions.begin(),
465 aReq.m_aMainGroupDimensions.end(), 0));
467 if (!aReq.m_aSubGroupDimensions.empty())
469 setSecondaryDimension(aReq.m_aSubGroupSize, nSubGroupSecondary);
470 setPrimaryDimension(aReq.m_aSubGroupSize,
471 std::accumulate(aReq.m_aSubGroupDimensions.begin(),
472 aReq.m_aSubGroupDimensions.end(), 0));
475 return aReq;
478 Size VclButtonBox::addSpacing(const Size &rSize, sal_uInt16 nVisibleChildren) const
480 Size aRet;
482 if (nVisibleChildren)
484 long nPrimaryDimension = getPrimaryDimension(rSize);
485 setPrimaryDimension(aRet,
486 nPrimaryDimension + m_nSpacing * (nVisibleChildren-1));
487 setSecondaryDimension(aRet, getSecondaryDimension(rSize));
490 return aRet;
493 Size VclButtonBox::calculateRequisition() const
495 Requisition aReq(calculatePrimarySecondaryRequisitions());
496 sal_uInt16 nVisibleChildren = aReq.m_aMainGroupDimensions.size() +
497 aReq.m_aSubGroupDimensions.size();
498 return addSpacing(addReqGroups(aReq), nVisibleChildren);
501 bool VclButtonBox::set_property(const OString &rKey, const OString &rValue)
503 if (rKey == "layout-style")
505 VclButtonBoxStyle eStyle = VCL_BUTTONBOX_DEFAULT_STYLE;
506 if (rValue == "spread")
507 eStyle = VCL_BUTTONBOX_SPREAD;
508 else if (rValue == "edge")
509 eStyle = VCL_BUTTONBOX_EDGE;
510 else if (rValue == "start")
511 eStyle = VCL_BUTTONBOX_START;
512 else if (rValue == "end")
513 eStyle = VCL_BUTTONBOX_END;
514 else if (rValue == "center")
515 eStyle = VCL_BUTTONBOX_CENTER;
516 else
518 SAL_WARN("vcl.layout", "unknown layout style " << rValue.getStr());
520 set_layout(eStyle);
522 else
523 return VclBox::set_property(rKey, rValue);
524 return true;
527 void VclButtonBox::setAllocation(const Size &rAllocation)
529 Requisition aReq(calculatePrimarySecondaryRequisitions());
531 if (aReq.m_aMainGroupDimensions.empty() && aReq.m_aSubGroupDimensions.empty())
532 return;
534 long nAllocPrimaryDimension = getPrimaryDimension(rAllocation);
536 Point aMainGroupPos, aOtherGroupPos;
537 int nSpacing = m_nSpacing;
539 //To-Do, other layout styles
540 switch (m_eLayoutStyle)
542 case VCL_BUTTONBOX_START:
543 if (!aReq.m_aSubGroupDimensions.empty())
545 long nOtherPrimaryDimension = getPrimaryDimension(
546 addSpacing(aReq.m_aSubGroupSize, aReq.m_aSubGroupDimensions.size()));
547 setPrimaryCoordinate(aOtherGroupPos,
548 nAllocPrimaryDimension - nOtherPrimaryDimension);
550 break;
551 case VCL_BUTTONBOX_SPREAD:
552 if (!aReq.m_aMainGroupDimensions.empty())
554 long nMainPrimaryDimension = getPrimaryDimension(
555 addSpacing(aReq.m_aMainGroupSize, aReq.m_aMainGroupDimensions.size()));
556 long nExtraSpace = nAllocPrimaryDimension - nMainPrimaryDimension;
557 nExtraSpace += (aReq.m_aMainGroupDimensions.size()-1) * nSpacing;
558 nSpacing = nExtraSpace/(aReq.m_aMainGroupDimensions.size()+1);
559 setPrimaryCoordinate(aMainGroupPos, nSpacing);
561 break;
562 default:
563 SAL_WARN("vcl.layout", "todo unimplemented layout style");
564 case VCL_BUTTONBOX_DEFAULT_STYLE:
565 case VCL_BUTTONBOX_END:
566 if (!aReq.m_aMainGroupDimensions.empty())
568 long nMainPrimaryDimension = getPrimaryDimension(
569 addSpacing(aReq.m_aMainGroupSize, aReq.m_aMainGroupDimensions.size()));
570 setPrimaryCoordinate(aMainGroupPos,
571 nAllocPrimaryDimension - nMainPrimaryDimension);
573 break;
576 Size aChildSize;
577 setSecondaryDimension(aChildSize, getSecondaryDimension(rAllocation));
579 std::vector<long>::const_iterator aPrimaryI = aReq.m_aMainGroupDimensions.begin();
580 std::vector<long>::const_iterator aSecondaryI = aReq.m_aSubGroupDimensions.begin();
581 bool bIgnoreSecondaryPacking = (m_eLayoutStyle == VCL_BUTTONBOX_SPREAD || m_eLayoutStyle == VCL_BUTTONBOX_CENTER);
582 for (Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
584 if (!pChild->IsVisible())
585 continue;
587 if (bIgnoreSecondaryPacking || !pChild->get_secondary())
589 long nMainGroupPrimaryDimension = *aPrimaryI++;
590 setPrimaryDimension(aChildSize, nMainGroupPrimaryDimension);
591 setLayoutAllocation(*pChild, aMainGroupPos, aChildSize);
592 long nPrimaryCoordinate = getPrimaryCoordinate(aMainGroupPos);
593 setPrimaryCoordinate(aMainGroupPos, nPrimaryCoordinate + nMainGroupPrimaryDimension + nSpacing);
595 else
597 long nSubGroupPrimaryDimension = *aSecondaryI++;
598 setPrimaryDimension(aChildSize, nSubGroupPrimaryDimension);
599 setLayoutAllocation(*pChild, aOtherGroupPos, aChildSize);
600 long nPrimaryCoordinate = getPrimaryCoordinate(aOtherGroupPos);
601 setPrimaryCoordinate(aOtherGroupPos, nPrimaryCoordinate + nSubGroupPrimaryDimension + nSpacing);
606 struct ButtonOrder
608 OString m_aType;
609 int m_nPriority;
612 int getButtonPriority(const OString &rType)
614 const size_t N_TYPES = 3;
615 static const ButtonOrder aDiscardCancelSave[N_TYPES] =
617 { "/discard", 0 },
618 { "/cancel", 1 },
619 { "/save", 2 }
622 static const ButtonOrder aSaveDiscardCancel[N_TYPES] =
624 { "/save", 0 },
625 { "/discard", 1 },
626 { "/cancel", 2 }
629 const ButtonOrder* pOrder = &aDiscardCancelSave[0];
631 const OUString &rEnv = Application::GetDesktopEnvironment();
633 if (rEnv.equalsIgnoreAsciiCase("windows") ||
634 rEnv.equalsIgnoreAsciiCase("kde4") ||
635 rEnv.equalsIgnoreAsciiCase("tde") ||
636 rEnv.equalsIgnoreAsciiCase("kde"))
638 pOrder = &aSaveDiscardCancel[0];
641 for (size_t i = 0; i < N_TYPES; ++i, ++pOrder)
643 if (rType.endsWith(pOrder->m_aType))
644 return pOrder->m_nPriority;
647 return -1;
650 class sortButtons
651 : public std::binary_function<const Window*, const Window*, bool>
653 bool m_bVerticalContainer;
654 public:
655 sortButtons(bool bVerticalContainer)
656 : m_bVerticalContainer(bVerticalContainer)
659 bool operator()(const Window *pA, const Window *pB) const;
662 bool sortButtons::operator()(const Window *pA, const Window *pB) const
664 //sort into two groups of pack start and pack end
665 VclPackType ePackA = pA->get_pack_type();
666 VclPackType ePackB = pB->get_pack_type();
667 if (ePackA < ePackB)
668 return true;
669 if (ePackA > ePackB)
670 return false;
671 bool bPackA = pA->get_secondary();
672 bool bPackB = pB->get_secondary();
673 if (!m_bVerticalContainer)
675 //for horizontal boxes group secondaries before primaries
676 if (bPackA > bPackB)
677 return true;
678 if (bPackA < bPackB)
679 return false;
681 else
683 //for vertical boxes group secondaries after primaries
684 if (bPackA < bPackB)
685 return true;
686 if (bPackA > bPackB)
687 return false;
690 //now order within groups according to platform rules
691 return getButtonPriority(pA->GetHelpId()) < getButtonPriority(pB->GetHelpId());
694 void VclButtonBox::sort_native_button_order()
696 std::vector<Window*> aChilds;
697 for (Window* pChild = GetWindow(WINDOW_FIRSTCHILD); pChild;
698 pChild = pChild->GetWindow(WINDOW_NEXT))
700 aChilds.push_back(pChild);
703 //sort child order within parent so that we match the platform
704 //button order
705 std::stable_sort(aChilds.begin(), aChilds.end(), sortButtons(m_bVerticalContainer));
706 VclBuilder::reorderWithinParent(aChilds, true);
709 VclGrid::array_type VclGrid::assembleGrid() const
711 ext_array_type A;
713 for (Window* pChild = GetWindow(WINDOW_FIRSTCHILD); pChild;
714 pChild = pChild->GetWindow(WINDOW_NEXT))
716 sal_Int32 nLeftAttach = pChild->get_grid_left_attach();
717 sal_Int32 nWidth = pChild->get_grid_width();
718 sal_Int32 nMaxXPos = nLeftAttach+nWidth-1;
720 sal_Int32 nTopAttach = pChild->get_grid_top_attach();
721 sal_Int32 nHeight = pChild->get_grid_height();
722 sal_Int32 nMaxYPos = nTopAttach+nHeight-1;
724 sal_Int32 nCurrentMaxXPos = A.shape()[0]-1;
725 sal_Int32 nCurrentMaxYPos = A.shape()[1]-1;
726 if (nMaxXPos > nCurrentMaxXPos || nMaxYPos > nCurrentMaxYPos)
728 nCurrentMaxXPos = std::max(nMaxXPos, nCurrentMaxXPos);
729 nCurrentMaxYPos = std::max(nMaxYPos, nCurrentMaxYPos);
730 A.resize(boost::extents[nCurrentMaxXPos+1][nCurrentMaxYPos+1]);
733 ExtendedGridEntry &rEntry = A[nLeftAttach][nTopAttach];
734 rEntry.pChild = pChild;
735 rEntry.nSpanWidth = nWidth;
736 rEntry.nSpanHeight = nHeight;
737 rEntry.x = nLeftAttach;
738 rEntry.y = nTopAttach;
740 for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
742 for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
744 ExtendedGridEntry &rSpan = A[nLeftAttach+nSpanX][nTopAttach+nSpanY];
745 rSpan.x = nLeftAttach;
746 rSpan.y = nTopAttach;
751 //see if we have any empty rows/cols
752 sal_Int32 nMaxX = A.shape()[0];
753 sal_Int32 nMaxY = A.shape()[1];
755 std::vector<bool> aNonEmptyCols(nMaxX);
756 std::vector<bool> aNonEmptyRows(nMaxY);
758 for (sal_Int32 x = 0; x < nMaxX; ++x)
760 for (sal_Int32 y = 0; y < nMaxY; ++y)
762 const GridEntry &rEntry = A[x][y];
763 const Window *pChild = rEntry.pChild;
764 if (pChild && pChild->IsVisible())
766 aNonEmptyCols[x] = true;
767 aNonEmptyRows[y] = true;
772 //reduce the spans of elements that span empty columns
773 for (sal_Int32 x = 0; x < nMaxX; ++x)
775 std::set<ExtendedGridEntry*> candidates;
776 for (sal_Int32 y = 0; y < nMaxY; ++y)
778 if (aNonEmptyCols[x])
779 continue;
780 ExtendedGridEntry &rSpan = A[x][y];
781 //cell x/y is spanned by the widget at cell rSpan.x/rSpan.y,
782 //just points back to itself if there's no cell spanning
783 if ((rSpan.x == -1) || (rSpan.y == -1))
785 //there is no entry for this cell, i.e. this is a cell
786 //with no widget in it, or spanned by any other widget
787 continue;
789 ExtendedGridEntry &rEntry = A[rSpan.x][rSpan.y];
790 candidates.insert(&rEntry);
792 for (std::set<ExtendedGridEntry*>::iterator aI = candidates.begin(), aEnd = candidates.end();
793 aI != aEnd; ++aI)
795 ExtendedGridEntry *pEntry = *aI;
796 --pEntry->nSpanWidth;
800 //reduce the spans of elements that span empty rows
801 for (sal_Int32 y = 0; y < nMaxY; ++y)
803 std::set<ExtendedGridEntry*> candidates;
804 for (sal_Int32 x = 0; x < nMaxX; ++x)
806 if (aNonEmptyRows[y])
807 continue;
808 ExtendedGridEntry &rSpan = A[x][y];
809 //cell x/y is spanned by the widget at cell rSpan.x/rSpan.y,
810 //just points back to itself if there's no cell spanning
811 if ((rSpan.x == -1) || (rSpan.y == -1))
813 //there is no entry for this cell, i.e. this is a cell
814 //with no widget in it, or spanned by any other widget
815 continue;
817 ExtendedGridEntry &rEntry = A[rSpan.x][rSpan.y];
818 candidates.insert(&rEntry);
820 for (std::set<ExtendedGridEntry*>::iterator aI = candidates.begin(), aEnd = candidates.end();
821 aI != aEnd; ++aI)
823 ExtendedGridEntry *pEntry = *aI;
824 --pEntry->nSpanHeight;
828 sal_Int32 nNonEmptyCols = std::count(aNonEmptyCols.begin(), aNonEmptyCols.end(), true);
829 sal_Int32 nNonEmptyRows = std::count(aNonEmptyRows.begin(), aNonEmptyRows.end(), true);
831 //make new grid without empty rows and columns
832 array_type B(boost::extents[nNonEmptyCols][nNonEmptyRows]);
833 for (sal_Int32 x = 0, x2 = 0; x < nMaxX; ++x)
835 if (aNonEmptyCols[x] == false)
836 continue;
837 for (sal_Int32 y = 0, y2 = 0; y < nMaxY; ++y)
839 if (aNonEmptyRows[y] == false)
840 continue;
841 GridEntry &rEntry = A[x][y];
842 B[x2][y2++] = rEntry;
844 ++x2;
847 return B;
850 bool VclGrid::isNullGrid(const array_type &A) const
852 sal_Int32 nMaxX = A.shape()[0];
853 sal_Int32 nMaxY = A.shape()[1];
855 if (!nMaxX || !nMaxY)
856 return true;
857 return false;
860 void VclGrid::calcMaxs(const array_type &A, std::vector<Value> &rWidths, std::vector<Value> &rHeights) const
862 sal_Int32 nMaxX = A.shape()[0];
863 sal_Int32 nMaxY = A.shape()[1];
865 rWidths.resize(nMaxX);
866 rHeights.resize(nMaxY);
868 //first use the non spanning entries to set default width/heights
869 for (sal_Int32 x = 0; x < nMaxX; ++x)
871 for (sal_Int32 y = 0; y < nMaxY; ++y)
873 const GridEntry &rEntry = A[x][y];
874 const Window *pChild = rEntry.pChild;
875 if (!pChild || !pChild->IsVisible())
876 continue;
878 sal_Int32 nWidth = rEntry.nSpanWidth;
879 sal_Int32 nHeight = rEntry.nSpanHeight;
881 for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
882 rWidths[x+nSpanX].m_bExpand = rWidths[x+nSpanX].m_bExpand | pChild->get_hexpand();
884 for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
885 rHeights[y+nSpanY].m_bExpand = rHeights[y+nSpanY].m_bExpand | pChild->get_vexpand();
887 if (nWidth == 1 || nHeight == 1)
889 Size aChildSize = getLayoutRequisition(*pChild);
890 if (nWidth == 1)
891 rWidths[x].m_nValue = std::max(rWidths[x].m_nValue, aChildSize.Width());
892 if (nHeight == 1)
893 rHeights[y].m_nValue = std::max(rHeights[y].m_nValue, aChildSize.Height());
898 //now use the spanning entries and split any extra sizes across expanding rows/cols
899 //where possible
900 for (sal_Int32 x = 0; x < nMaxX; ++x)
902 for (sal_Int32 y = 0; y < nMaxY; ++y)
904 const GridEntry &rEntry = A[x][y];
905 const Window *pChild = rEntry.pChild;
906 if (!pChild || !pChild->IsVisible())
907 continue;
909 sal_Int32 nWidth = rEntry.nSpanWidth;
910 sal_Int32 nHeight = rEntry.nSpanHeight;
912 if (nWidth == 1 && nHeight == 1)
913 continue;
915 Size aChildSize = getLayoutRequisition(*pChild);
917 if (nWidth > 1)
919 sal_Int32 nExistingWidth = 0;
920 for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
921 nExistingWidth += rWidths[x+nSpanX].m_nValue;
923 sal_Int32 nExtraWidth = aChildSize.Width() - nExistingWidth;
925 if (nExtraWidth > 0)
927 bool bForceExpandAll = false;
928 sal_Int32 nExpandables = 0;
929 for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
930 if (rWidths[x+nSpanX].m_bExpand)
931 ++nExpandables;
932 if (nExpandables == 0)
934 nExpandables = nWidth;
935 bForceExpandAll = true;
938 for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
940 if (rWidths[x+nSpanX].m_bExpand || bForceExpandAll)
941 rWidths[x+nSpanX].m_nValue += nExtraWidth/nExpandables;
946 if (nHeight > 1)
948 sal_Int32 nExistingHeight = 0;
949 for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
950 nExistingHeight += rHeights[y+nSpanY].m_nValue;
952 sal_Int32 nExtraHeight = aChildSize.Height() - nExistingHeight;
954 if (nExtraHeight > 0)
956 bool bForceExpandAll = false;
957 sal_Int32 nExpandables = 0;
958 for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
959 if (rHeights[y+nSpanY].m_bExpand)
960 ++nExpandables;
961 if (nExpandables == 0)
963 nExpandables = nHeight;
964 bForceExpandAll = true;
967 for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
969 if (rHeights[y+nSpanY].m_bExpand || bForceExpandAll)
970 rHeights[y+nSpanY].m_nValue += nExtraHeight/nExpandables;
978 bool compareValues(const VclGrid::Value &i, const VclGrid::Value &j)
980 return i.m_nValue < j.m_nValue;
983 VclGrid::Value accumulateValues(const VclGrid::Value &i, const VclGrid::Value &j)
985 VclGrid::Value aRet;
986 aRet.m_nValue = i.m_nValue + j.m_nValue;
987 aRet.m_bExpand = i.m_bExpand | j.m_bExpand;
988 return aRet;
991 Size VclGrid::calculateRequisition() const
993 return calculateRequisitionForSpacings(get_row_spacing(), get_column_spacing());
996 Size VclGrid::calculateRequisitionForSpacings(sal_Int32 nRowSpacing, sal_Int32 nColSpacing) const
998 array_type A = assembleGrid();
1000 if (isNullGrid(A))
1001 return Size();
1003 std::vector<Value> aWidths;
1004 std::vector<Value> aHeights;
1005 calcMaxs(A, aWidths, aHeights);
1007 long nTotalWidth = 0;
1008 if (get_column_homogeneous())
1010 nTotalWidth = std::max_element(aWidths.begin(), aWidths.end(), compareValues)->m_nValue;
1011 nTotalWidth *= aWidths.size();
1013 else
1015 nTotalWidth = std::accumulate(aWidths.begin(), aWidths.end(), Value(), accumulateValues).m_nValue;
1018 nTotalWidth += nColSpacing * (aWidths.size()-1);
1020 long nTotalHeight = 0;
1021 if (get_row_homogeneous())
1023 nTotalHeight = std::max_element(aHeights.begin(), aHeights.end(), compareValues)->m_nValue;
1024 nTotalHeight *= aHeights.size();
1026 else
1028 nTotalHeight = std::accumulate(aHeights.begin(), aHeights.end(), Value(), accumulateValues).m_nValue;
1031 nTotalHeight += nRowSpacing * (aHeights.size()-1);
1033 return Size(nTotalWidth, nTotalHeight);
1036 void VclGrid::setAllocation(const Size& rAllocation)
1038 array_type A = assembleGrid();
1040 if (isNullGrid(A))
1041 return;
1043 sal_Int32 nMaxX = A.shape()[0];
1044 sal_Int32 nMaxY = A.shape()[1];
1046 Size aRequisition;
1047 std::vector<Value> aWidths(nMaxX);
1048 std::vector<Value> aHeights(nMaxY);
1049 if (!get_column_homogeneous() || !get_row_homogeneous())
1051 aRequisition = calculateRequisition();
1052 calcMaxs(A, aWidths, aHeights);
1055 sal_Int32 nColSpacing(get_column_spacing());
1056 sal_Int32 nRowSpacing(get_row_spacing());
1058 long nAvailableWidth = rAllocation.Width();
1059 if (nMaxX)
1060 nAvailableWidth -= nColSpacing * (nMaxX - 1);
1061 if (get_column_homogeneous())
1063 for (sal_Int32 x = 0; x < nMaxX; ++x)
1064 aWidths[x].m_nValue = nAvailableWidth/nMaxX;
1066 else if (rAllocation.Width() != aRequisition.Width())
1068 sal_Int32 nExpandables = 0;
1069 for (sal_Int32 x = 0; x < nMaxX; ++x)
1070 if (aWidths[x].m_bExpand)
1071 ++nExpandables;
1072 long nExtraWidthForExpanders = nExpandables ? (rAllocation.Width() - aRequisition.Width()) / nExpandables : 0;
1074 //We don't fit and there is no volunteer to be shrunk
1075 if (!nExpandables && rAllocation.Width() < aRequisition.Width())
1077 //first reduce spacing, to a min of 3
1078 while (nColSpacing >= 6)
1080 nColSpacing /= 2;
1081 aRequisition = calculateRequisitionForSpacings(nRowSpacing, nColSpacing);
1082 if (aRequisition.Width() >= rAllocation.Width())
1083 break;
1086 //share out the remaining pain to everyone
1087 long nExtraWidth = (rAllocation.Width() - aRequisition.Width()) / nMaxX;
1089 for (sal_Int32 x = 0; x < nMaxX; ++x)
1090 aWidths[x].m_nValue += nExtraWidth;
1093 if (nExtraWidthForExpanders)
1095 for (sal_Int32 x = 0; x < nMaxX; ++x)
1096 if (aWidths[x].m_bExpand)
1097 aWidths[x].m_nValue += nExtraWidthForExpanders;
1101 long nAvailableHeight = rAllocation.Height();
1102 if (nMaxY)
1103 nAvailableHeight -= nRowSpacing * (nMaxY - 1);
1104 if (get_row_homogeneous())
1106 for (sal_Int32 y = 0; y < nMaxY; ++y)
1107 aHeights[y].m_nValue = nAvailableHeight/nMaxY;
1109 else if (rAllocation.Height() != aRequisition.Height())
1111 sal_Int32 nExpandables = 0;
1112 for (sal_Int32 y = 0; y < nMaxY; ++y)
1113 if (aHeights[y].m_bExpand)
1114 ++nExpandables;
1115 long nExtraHeightForExpanders = nExpandables ? (rAllocation.Height() - aRequisition.Height()) / nExpandables : 0;
1117 //We don't fit and there is no volunteer to be shrunk
1118 if (!nExpandables && rAllocation.Height() < aRequisition.Height())
1120 //first reduce spacing, to a min of 3
1121 while (nRowSpacing >= 6)
1123 nRowSpacing /= 2;
1124 aRequisition = calculateRequisitionForSpacings(nRowSpacing, nColSpacing);
1125 if (aRequisition.Height() >= rAllocation.Height())
1126 break;
1129 //share out the remaining pain to everyone
1130 long nExtraHeight = (rAllocation.Height() - aRequisition.Height()) / nMaxY;
1132 for (sal_Int32 y = 0; y < nMaxY; ++y)
1133 aHeights[y].m_nValue += nExtraHeight;
1136 if (nExtraHeightForExpanders)
1138 for (sal_Int32 y = 0; y < nMaxY; ++y)
1139 if (aHeights[y].m_bExpand)
1140 aHeights[y].m_nValue += nExtraHeightForExpanders;
1144 Point aAllocPos(0, 0);
1145 for (sal_Int32 x = 0; x < nMaxX; ++x)
1147 for (sal_Int32 y = 0; y < nMaxY; ++y)
1149 GridEntry &rEntry = A[x][y];
1150 Window *pChild = rEntry.pChild;
1151 if (pChild)
1153 Size aChildAlloc(0, 0);
1155 sal_Int32 nWidth = rEntry.nSpanWidth;
1156 for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
1157 aChildAlloc.Width() += aWidths[x+nSpanX].m_nValue;
1158 aChildAlloc.Width() += nColSpacing*(nWidth-1);
1160 sal_Int32 nHeight = rEntry.nSpanHeight;
1161 for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
1162 aChildAlloc.Height() += aHeights[y+nSpanY].m_nValue;
1163 aChildAlloc.Height() += nRowSpacing*(nHeight-1);
1165 setLayoutAllocation(*pChild, aAllocPos, aChildAlloc);
1167 aAllocPos.Y() += aHeights[y].m_nValue + nRowSpacing;
1169 aAllocPos.X() += aWidths[x].m_nValue + nColSpacing;
1170 aAllocPos.Y() = 0;
1174 bool toBool(const OString &rValue)
1176 return (rValue[0] == 't' || rValue[0] == 'T' || rValue[0] == '1');
1179 bool VclGrid::set_property(const OString &rKey, const OString &rValue)
1181 if (rKey == "row-spacing")
1182 set_row_spacing(rValue.toInt32());
1183 else if (rKey == "column-spacing")
1184 set_column_spacing(rValue.toInt32());
1185 else if (rKey == "row-homogeneous")
1186 set_row_homogeneous(toBool(rValue));
1187 else if (rKey == "column-homogeneous")
1188 set_column_homogeneous(toBool(rValue));
1189 else if (rKey == "n-rows")
1190 /*nothing to do*/;
1191 else
1192 return VclContainer::set_property(rKey, rValue);
1193 return true;
1196 void setGridAttach(Window &rWidget, sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nWidth, sal_Int32 nHeight)
1198 rWidget.set_grid_left_attach(nLeft);
1199 rWidget.set_grid_top_attach(nTop);
1200 rWidget.set_grid_width(nWidth);
1201 rWidget.set_grid_height(nHeight);
1204 const Window *VclBin::get_child() const
1206 const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1208 return pWindowImpl->mpFirstChild;
1211 Window *VclBin::get_child()
1213 return const_cast<Window*>(const_cast<const VclBin*>(this)->get_child());
1216 Size VclBin::calculateRequisition() const
1218 const Window *pChild = get_child();
1219 if (pChild && pChild->IsVisible())
1220 return getLayoutRequisition(*pChild);
1221 return Size(0, 0);
1224 void VclBin::setAllocation(const Size &rAllocation)
1226 Window *pChild = get_child();
1227 if (pChild && pChild->IsVisible())
1228 setLayoutAllocation(*pChild, Point(0, 0), rAllocation);
1231 //To-Do, hook a DecorationView into VclFrame ?
1233 Size VclFrame::calculateRequisition() const
1235 Size aRet(0, 0);
1237 const Window *pChild = get_child();
1238 const Window *pLabel = get_label_widget();
1240 if (pChild && pChild->IsVisible())
1241 aRet = getLayoutRequisition(*pChild);
1243 if (pLabel && pLabel->IsVisible())
1245 Size aLabelSize = getLayoutRequisition(*pLabel);
1246 aRet.Height() += aLabelSize.Height();
1247 aRet.Width() = std::max(aLabelSize.Width(), aRet.Width());
1250 const FrameStyle &rFrameStyle =
1251 GetSettings().GetStyleSettings().GetFrameStyle();
1252 aRet.Width() += rFrameStyle.left + rFrameStyle.right;
1253 aRet.Height() += rFrameStyle.top + rFrameStyle.bottom;
1255 return aRet;
1258 void VclFrame::setAllocation(const Size &rAllocation)
1260 //SetBackground( Color(0xFF, 0x00, 0xFF) );
1262 const FrameStyle &rFrameStyle =
1263 GetSettings().GetStyleSettings().GetFrameStyle();
1264 Size aAllocation(rAllocation.Width() - rFrameStyle.left - rFrameStyle.right,
1265 rAllocation.Height() - rFrameStyle.top - rFrameStyle.bottom);
1266 Point aChildPos(rFrameStyle.left, rFrameStyle.top);
1268 Window *pChild = get_child();
1269 Window *pLabel = get_label_widget();
1271 if (pLabel && pLabel->IsVisible())
1273 Size aLabelSize = getLayoutRequisition(*pLabel);
1274 aLabelSize.Height() = std::min(aLabelSize.Height(), aAllocation.Height());
1275 aLabelSize.Width() = std::min(aLabelSize.Width(), aAllocation.Width());
1276 setLayoutAllocation(*pLabel, aChildPos, aLabelSize);
1277 aAllocation.Height() -= aLabelSize.Height();
1278 aChildPos.Y() += aLabelSize.Height();
1281 if (pChild && pChild->IsVisible())
1282 setLayoutAllocation(*pChild, aChildPos, aAllocation);
1285 void VclFrame::designate_label(Window *pWindow)
1287 assert(pWindow->GetParent() == this);
1288 m_pLabel = pWindow;
1291 const Window *VclFrame::get_label_widget() const
1293 assert(GetChildCount() == 2);
1294 if (m_pLabel)
1295 return m_pLabel;
1296 //The label widget is normally the first (of two) children
1297 const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1298 if (pWindowImpl->mpFirstChild == pWindowImpl->mpLastChild) //no label exists
1299 return NULL;
1300 return pWindowImpl->mpFirstChild;
1303 Window *VclFrame::get_label_widget()
1305 return const_cast<Window*>(const_cast<const VclFrame*>(this)->get_label_widget());
1308 const Window *VclFrame::get_child() const
1310 assert(GetChildCount() == 2);
1311 //The child widget is the normally the last (of two) children
1312 const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1313 if (!m_pLabel)
1314 return pWindowImpl->mpLastChild;
1315 if (pWindowImpl->mpFirstChild == pWindowImpl->mpLastChild) //only label exists
1316 return NULL;
1317 return pWindowImpl->mpLastChild;
1320 Window *VclFrame::get_child()
1322 return const_cast<Window*>(const_cast<const VclFrame*>(this)->get_child());
1325 void VclFrame::set_label(const OUString &rLabel)
1327 Window *pLabel = get_label_widget();
1328 assert(pLabel);
1329 pLabel->SetText(rLabel);
1332 OUString VclFrame::getDefaultAccessibleName() const
1334 const Window *pLabel = get_label_widget();
1335 if (pLabel)
1336 return pLabel->GetAccessibleName();
1337 return VclBin::getDefaultAccessibleName();
1340 Size VclAlignment::calculateRequisition() const
1342 Size aRet(m_nLeftPadding + m_nRightPadding,
1343 m_nTopPadding + m_nBottomPadding);
1345 const Window *pChild = get_child();
1346 if (pChild && pChild->IsVisible())
1348 Size aChildSize = getLayoutRequisition(*pChild);
1349 aRet.Width() += aChildSize.Width();
1350 aRet.Height() += aChildSize.Height();
1353 return aRet;
1356 void VclAlignment::setAllocation(const Size &rAllocation)
1358 Window *pChild = get_child();
1359 if (!pChild || !pChild->IsVisible())
1360 return;
1362 Point aChildPos(m_nLeftPadding, m_nTopPadding);
1364 Size aAllocation;
1365 aAllocation.Width() = rAllocation.Width() - (m_nLeftPadding + m_nRightPadding);
1366 aAllocation.Height() = rAllocation.Height() - (m_nTopPadding + m_nBottomPadding);
1368 setLayoutAllocation(*pChild, aChildPos, aAllocation);
1371 bool VclAlignment::set_property(const OString &rKey, const OString &rValue)
1373 if (rKey == "bottom-padding")
1374 m_nBottomPadding = rValue.toInt32();
1375 else if (rKey == "left-padding")
1376 m_nLeftPadding = rValue.toInt32();
1377 else if (rKey == "right-padding")
1378 m_nRightPadding = rValue.toInt32();
1379 else if (rKey == "top-padding")
1380 m_nTopPadding = rValue.toInt32();
1381 else if (rKey == "xalign")
1382 m_fXAlign = rValue.toFloat();
1383 else if (rKey == "xscale")
1384 m_fXScale = rValue.toFloat();
1385 else if (rKey == "yalign")
1386 m_fYAlign = rValue.toFloat();
1387 else if (rKey == "yscale")
1388 m_fYScale = rValue.toFloat();
1389 else
1390 return VclBin::set_property(rKey, rValue);
1391 return true;
1394 const Window *VclExpander::get_child() const
1396 const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1398 assert(pWindowImpl->mpFirstChild == &m_aDisclosureButton);
1400 return pWindowImpl->mpFirstChild->GetWindow(WINDOW_NEXT);
1403 Window *VclExpander::get_child()
1405 return const_cast<Window*>(const_cast<const VclExpander*>(this)->get_child());
1408 Size VclExpander::calculateRequisition() const
1410 Size aRet(0, 0);
1412 WindowImpl* pWindowImpl = ImplGetWindowImpl();
1414 const Window *pChild = get_child();
1415 const Window *pLabel = pChild != pWindowImpl->mpLastChild ? pWindowImpl->mpLastChild : NULL;
1417 if (pChild && pChild->IsVisible() && m_aDisclosureButton.IsChecked())
1418 aRet = getLayoutRequisition(*pChild);
1420 Size aExpanderSize = getLayoutRequisition(m_aDisclosureButton);
1422 if (pLabel && pLabel->IsVisible())
1424 Size aLabelSize = getLayoutRequisition(*pLabel);
1425 aExpanderSize.Height() = std::max(aExpanderSize.Height(), aLabelSize.Height());
1426 aExpanderSize.Width() += aLabelSize.Width();
1429 aRet.Height() += aExpanderSize.Height();
1430 aRet.Width() = std::max(aExpanderSize.Width(), aRet.Width());
1432 const FrameStyle &rFrameStyle =
1433 GetSettings().GetStyleSettings().GetFrameStyle();
1434 aRet.Width() += rFrameStyle.left + rFrameStyle.right;
1435 aRet.Height() += rFrameStyle.top + rFrameStyle.bottom;
1437 return aRet;
1440 void VclExpander::setAllocation(const Size &rAllocation)
1442 const FrameStyle &rFrameStyle =
1443 GetSettings().GetStyleSettings().GetFrameStyle();
1444 Size aAllocation(rAllocation.Width() - rFrameStyle.left - rFrameStyle.right,
1445 rAllocation.Height() - rFrameStyle.top - rFrameStyle.bottom);
1446 Point aChildPos(rFrameStyle.left, rFrameStyle.top);
1448 WindowImpl* pWindowImpl = ImplGetWindowImpl();
1450 //The label widget is the last (of two) children
1451 Window *pChild = get_child();
1452 Window *pLabel = pChild != pWindowImpl->mpLastChild ? pWindowImpl->mpLastChild : NULL;
1454 Size aButtonSize = getLayoutRequisition(m_aDisclosureButton);
1455 Size aLabelSize;
1456 Size aExpanderSize = aButtonSize;
1457 if (pLabel && pLabel->IsVisible())
1459 aLabelSize = getLayoutRequisition(*pLabel);
1460 aExpanderSize.Height() = std::max(aExpanderSize.Height(), aLabelSize.Height());
1461 aExpanderSize.Width() += aLabelSize.Width();
1464 aExpanderSize.Height() = std::min(aExpanderSize.Height(), aAllocation.Height());
1465 aExpanderSize.Width() = std::min(aExpanderSize.Width(), aAllocation.Width());
1467 aButtonSize.Height() = std::min(aButtonSize.Height(), aExpanderSize.Height());
1468 aButtonSize.Width() = std::min(aButtonSize.Width(), aExpanderSize.Width());
1470 long nExtraExpanderHeight = aExpanderSize.Height() - aButtonSize.Height();
1471 Point aButtonPos(aChildPos.X(), aChildPos.Y() + nExtraExpanderHeight/2);
1472 setLayoutAllocation(m_aDisclosureButton, aButtonPos, aButtonSize);
1474 if (pLabel && pLabel->IsVisible())
1476 aLabelSize.Height() = std::min(aLabelSize.Height(), aExpanderSize.Height());
1477 aLabelSize.Width() = std::min(aLabelSize.Width(),
1478 aExpanderSize.Width() - aButtonSize.Width());
1480 long nExtraLabelHeight = aExpanderSize.Height() - aLabelSize.Height();
1481 Point aLabelPos(aChildPos.X() + aButtonSize.Width(), aChildPos.Y() + nExtraLabelHeight/2);
1482 setLayoutAllocation(*pLabel, aLabelPos, aLabelSize);
1485 aAllocation.Height() -= aExpanderSize.Height();
1486 aChildPos.Y() += aExpanderSize.Height();
1488 if (pChild && pChild->IsVisible())
1490 if (!m_aDisclosureButton.IsChecked())
1491 aAllocation = Size();
1492 setLayoutAllocation(*pChild, aChildPos, aAllocation);
1496 bool VclExpander::set_property(const OString &rKey, const OString &rValue)
1498 if (rKey == "expanded")
1499 m_aDisclosureButton.Check(toBool(rValue));
1500 else if (rKey == "resize-toplevel")
1501 m_bResizeTopLevel = toBool(rValue);
1502 else
1503 return VclBin::set_property(rKey, rValue);
1504 return true;
1507 void VclExpander::StateChanged(StateChangedType nType)
1509 VclBin::StateChanged( nType );
1511 if (nType == STATE_CHANGE_INITSHOW)
1513 Window *pChild = get_child();
1514 if (pChild)
1515 pChild->Show(m_aDisclosureButton.IsChecked());
1519 IMPL_LINK( VclExpander, ClickHdl, DisclosureButton*, pBtn )
1521 Window *pChild = get_child();
1522 if (pChild)
1524 pChild->Show(pBtn->IsChecked());
1525 queue_resize();
1526 Dialog* pResizeDialog = m_bResizeTopLevel ? GetParentDialog() : NULL;
1527 if (pResizeDialog)
1528 pResizeDialog->setOptimalLayoutSize();
1530 return 0;
1533 const Window *VclScrolledWindow::get_child() const
1535 assert(GetChildCount() == 3);
1536 const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1537 return pWindowImpl->mpLastChild;
1540 Window *VclScrolledWindow::get_child()
1542 return const_cast<Window*>(const_cast<const VclScrolledWindow*>(this)->get_child());
1545 Size VclScrolledWindow::calculateRequisition() const
1547 Size aRet(0, 0);
1549 const Window *pChild = get_child();
1550 if (pChild && pChild->IsVisible())
1551 aRet = getLayoutRequisition(*pChild);
1553 if (m_aVScroll.IsVisible())
1554 aRet.Width() += getLayoutRequisition(m_aVScroll).Width();
1556 if (m_aHScroll.IsVisible())
1557 aRet.Height() += getLayoutRequisition(m_aHScroll).Height();
1559 return aRet;
1562 void VclScrolledWindow::setAllocation(const Size &rAllocation)
1564 Size aChildAllocation(rAllocation);
1565 Size aChildReq;
1567 Window *pChild = get_child();
1568 if (pChild && pChild->IsVisible())
1569 aChildReq = getLayoutRequisition(*pChild);
1571 if (m_aVScroll.IsVisible())
1573 long nScrollBarWidth = getLayoutRequisition(m_aVScroll).Width();
1574 Point aScrollPos(rAllocation.Width() - nScrollBarWidth, 0);
1575 Size aScrollSize(nScrollBarWidth, rAllocation.Height());
1576 setLayoutAllocation(m_aVScroll, aScrollPos, aScrollSize);
1577 aChildAllocation.Width() -= nScrollBarWidth;
1578 aChildAllocation.Height() = aChildReq.Height();
1581 if (m_aHScroll.IsVisible())
1583 long nScrollBarHeight = getLayoutRequisition(m_aHScroll).Height();
1584 Point aScrollPos(0, rAllocation.Height() - nScrollBarHeight);
1585 Size aScrollSize(rAllocation.Width(), nScrollBarHeight);
1586 setLayoutAllocation(m_aHScroll, aScrollPos, aScrollSize);
1587 aChildAllocation.Height() -= nScrollBarHeight;
1588 aChildAllocation.Width() = aChildReq.Width();
1591 if (pChild && pChild->IsVisible())
1593 Point aChildPos(pChild->GetPosPixel());
1594 if (!m_aHScroll.IsVisible())
1595 aChildPos.X() = 0;
1596 if (!m_aVScroll.IsVisible())
1597 aChildPos.Y() = 0;
1598 setLayoutAllocation(*pChild, aChildPos, aChildAllocation);
1602 Size VclScrolledWindow::getVisibleChildSize() const
1604 Size aRet(GetSizePixel());
1605 if (m_aVScroll.IsVisible())
1606 aRet.Width() -= m_aVScroll.GetSizePixel().Width();
1607 if (m_aHScroll.IsVisible())
1608 aRet.Height() -= m_aHScroll.GetSizePixel().Height();
1609 return aRet;
1612 bool VclScrolledWindow::set_property(const OString &rKey, const OString &rValue)
1614 bool bRet = VclBin::set_property(rKey, rValue);
1615 m_aVScroll.Show((GetStyle() & WB_VSCROLL) != 0);
1616 m_aHScroll.Show((GetStyle() & WB_HSCROLL) != 0);
1617 return bRet;
1620 const Window *VclEventBox::get_child() const
1622 const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1624 assert(pWindowImpl->mpFirstChild == &m_aEventBoxHelper);
1626 return pWindowImpl->mpFirstChild->GetWindow(WINDOW_NEXT);
1629 Window *VclEventBox::get_child()
1631 return const_cast<Window*>(const_cast<const VclEventBox*>(this)->get_child());
1634 void VclEventBox::setAllocation(const Size& rAllocation)
1636 Point aChildPos(0, 0);
1637 for (Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
1639 if (!pChild->IsVisible())
1640 continue;
1641 setLayoutAllocation(*pChild, aChildPos, rAllocation);
1645 Size VclEventBox::calculateRequisition() const
1647 Size aRet(0, 0);
1649 for (const Window* pChild = get_child(); pChild;
1650 pChild = pChild->GetWindow(WINDOW_NEXT))
1652 if (!pChild->IsVisible())
1653 continue;
1654 Size aChildSize = getLayoutRequisition(*pChild);
1655 aRet.Width() = std::max(aRet.Width(), aChildSize.Width());
1656 aRet.Height() = std::max(aRet.Height(), aChildSize.Height());
1659 return aRet;
1662 void VclEventBox::Command(const CommandEvent&)
1664 //discard events by default to block them reaching children
1667 void VclSizeGroup::trigger_queue_resize()
1669 //sufficient to trigger one widget to trigger all of them
1670 if (!m_aWindows.empty())
1672 Window *pWindow = *m_aWindows.begin();
1673 pWindow->queue_resize();
1677 void VclSizeGroup::set_ignore_hidden(bool bIgnoreHidden)
1679 if (bIgnoreHidden != m_bIgnoreHidden)
1681 m_bIgnoreHidden = bIgnoreHidden;
1682 trigger_queue_resize();
1686 void VclSizeGroup::set_mode(VclSizeGroupMode eMode)
1688 if (eMode != m_eMode)
1690 m_eMode = eMode;
1691 trigger_queue_resize();
1696 bool VclSizeGroup::set_property(const OString &rKey, const OString &rValue)
1698 if (rKey == "ignore-hidden")
1699 set_ignore_hidden(toBool(rValue));
1700 else if (rKey == "mode")
1702 VclSizeGroupMode eMode = VCL_SIZE_GROUP_HORIZONTAL;
1703 if (rValue.equals("none"))
1704 eMode = VCL_SIZE_GROUP_NONE;
1705 else if (rValue.equals("horizontal"))
1706 eMode = VCL_SIZE_GROUP_HORIZONTAL;
1707 else if (rValue.equals("vertical"))
1708 eMode = VCL_SIZE_GROUP_VERTICAL;
1709 else if (rValue.equals("both"))
1710 eMode = VCL_SIZE_GROUP_BOTH;
1711 else
1713 SAL_WARN("vcl.layout", "unknown size group mode" << rValue.getStr());
1715 set_mode(eMode);
1717 else
1719 SAL_INFO("vcl.layout", "unhandled property: " << rKey.getStr());
1720 return false;
1722 return true;
1725 MessageDialog::MessageDialog(Window* pParent, WinBits nStyle)
1726 : Dialog(pParent, nStyle)
1727 , m_pGrid(NULL)
1728 , m_pImage(NULL)
1729 , m_pPrimaryMessage(NULL)
1730 , m_pSecondaryMessage(NULL)
1732 SetType(WINDOW_MESSBOX);
1735 MessageDialog::MessageDialog(Window* pParent, const OString& rID, const OUString& rUIXMLDescription)
1736 : Dialog(pParent, rID, rUIXMLDescription, WINDOW_MESSBOX)
1737 , m_pGrid(NULL)
1738 , m_pImage(NULL)
1739 , m_pPrimaryMessage(NULL)
1740 , m_pSecondaryMessage(NULL)
1744 MessageDialog::~MessageDialog()
1746 delete m_pSecondaryMessage;
1747 delete m_pPrimaryMessage;
1748 delete m_pImage;
1749 delete m_pGrid;
1752 IMPL_LINK(MessageDialog, ButtonHdl, Button *, pButton)
1754 //for now insist that we have a builder, we can relax that in
1755 //the future if we need it
1756 assert(m_pUIBuilder);
1757 EndDialog(m_pUIBuilder->get_response(pButton));
1758 return 0;
1761 void MessageDialog::setButtonHandlers()
1763 SAL_WARN_IF(!m_pUIBuilder, "vcl.layout", "MessageDialog non-ui load button responses not implemented yet");
1764 if (!m_pUIBuilder)
1765 return;
1766 VclButtonBox *pButtonBox = get_action_area();
1767 assert(pButtonBox);
1768 for (Window* pChild = pButtonBox->GetWindow(WINDOW_FIRSTCHILD); pChild;
1769 pChild = pChild->GetWindow(WINDOW_NEXT))
1771 switch (pChild->GetType())
1773 case WINDOW_PUSHBUTTON:
1775 PushButton* pButton = (PushButton*)pChild;
1776 pButton->SetClickHdl(LINK(this, MessageDialog, ButtonHdl));
1777 break;
1779 //for now at least, insist that the response ids match
1780 //the default actions for those widgets, and leave
1781 //their default handlers in place
1782 case WINDOW_OKBUTTON:
1783 assert(m_pUIBuilder->get_response(pChild) == RET_OK);
1784 break;
1785 case WINDOW_CANCELBUTTON:
1786 assert(m_pUIBuilder->get_response(pChild) == RET_CANCEL);
1787 break;
1788 case WINDOW_HELPBUTTON:
1789 assert(m_pUIBuilder->get_response(pChild) == RET_HELP);
1790 break;
1791 default:
1792 SAL_WARN("vcl.layout", "The type of widget " <<
1793 pChild->GetHelpId() << " is currently not handled");
1794 break;
1796 //The default is to stick the focus into the first widget
1797 //that accepts it, and if that happens and its a button
1798 //then that becomes the new default button, so explicitly
1799 //put the focus into the default button
1800 if (pChild->GetStyle() & WB_DEFBUTTON)
1801 pChild->GrabFocus();
1805 short MessageDialog::Execute()
1807 setDeferredProperties();
1809 if (!m_pGrid)
1811 VclContainer *pContainer = get_content_area();
1812 assert(pContainer);
1814 m_pGrid = new VclGrid(pContainer);
1815 m_pGrid->set_column_spacing(12);
1817 m_pImage = new FixedImage(m_pGrid, WB_CENTER | WB_VCENTER | WB_3DLOOK);
1818 m_pImage->SetImage(WarningBox::GetStandardImage());
1819 m_pImage->set_grid_left_attach(0);
1820 m_pImage->set_grid_top_attach(0);
1821 m_pImage->set_valign(VCL_ALIGN_START);
1822 m_pImage->Show();
1824 WinBits nWinStyle = WB_LEFT | WB_VCENTER | WB_NOLABEL | WB_NOTABSTOP;
1826 m_pPrimaryMessage = new VclMultiLineEdit(m_pGrid, nWinStyle);
1827 m_pPrimaryMessage->SetPaintTransparent(true);
1828 m_pPrimaryMessage->EnableCursor(false);
1829 Font aFont = GetSettings().GetStyleSettings().GetLabelFont();
1830 aFont.SetSize( Size( 0, aFont.GetSize().Height() * 1.2 ) );
1831 aFont.SetWeight(WEIGHT_BOLD);
1832 m_pPrimaryMessage->SetControlFont(aFont);
1833 m_pPrimaryMessage->set_grid_left_attach(1);
1834 m_pPrimaryMessage->set_grid_top_attach(0);
1835 m_pPrimaryMessage->set_hexpand(true);
1836 m_pPrimaryMessage->SetText(m_sPrimaryString);
1837 m_pPrimaryMessage->Show(!m_sPrimaryString.isEmpty());
1838 m_pPrimaryMessage->SetMaxTextWidth(m_pPrimaryMessage->approximate_char_width() * 60);
1840 m_pSecondaryMessage = new VclMultiLineEdit(m_pGrid, nWinStyle);
1841 m_pSecondaryMessage->SetPaintTransparent(true);
1842 m_pSecondaryMessage->EnableCursor(false);
1843 m_pSecondaryMessage->set_grid_left_attach(1);
1844 m_pSecondaryMessage->set_grid_top_attach(1);
1845 m_pSecondaryMessage->set_hexpand(true);
1846 m_pSecondaryMessage->SetText(m_sSecondaryString);
1847 m_pSecondaryMessage->Show(!m_sSecondaryString.isEmpty());
1848 m_pSecondaryMessage->SetMaxTextWidth(m_pSecondaryMessage->approximate_char_width() * 80);
1850 m_pGrid->Show();
1852 setButtonHandlers();
1854 VclButtonBox *pButtonBox = get_action_area();
1855 assert(pButtonBox);
1856 pButtonBox->sort_native_button_order();
1859 return Dialog::Execute();
1862 OUString MessageDialog::get_primary_text() const
1864 const_cast<MessageDialog*>(this)->setDeferredProperties();
1866 return m_sPrimaryString;
1869 OUString MessageDialog::get_secondary_text() const
1871 const_cast<MessageDialog*>(this)->setDeferredProperties();
1873 return m_sSecondaryString;
1876 bool MessageDialog::set_property(const OString &rKey, const OString &rValue)
1878 if (rKey == "text")
1879 set_primary_text(OStringToOUString(rValue, RTL_TEXTENCODING_UTF8));
1880 else if (rKey == "secondary-text")
1881 set_secondary_text(OStringToOUString(rValue, RTL_TEXTENCODING_UTF8));
1882 else
1883 return Dialog::set_property(rKey, rValue);
1884 return true;
1887 void MessageDialog::set_primary_text(const OUString &rPrimaryString)
1889 m_sPrimaryString = rPrimaryString;
1890 if (m_pPrimaryMessage)
1892 m_pPrimaryMessage->SetText(m_sPrimaryString);
1893 m_pPrimaryMessage->Show(!m_sPrimaryString.isEmpty());
1897 void MessageDialog::set_secondary_text(const OUString &rSecondaryString)
1899 m_sSecondaryString = rSecondaryString;
1900 if (m_pSecondaryMessage)
1902 m_pSecondaryMessage->SetText(OUString("\n") + m_sSecondaryString);
1903 m_pSecondaryMessage->Show(!m_sSecondaryString.isEmpty());
1907 Size getLegacyBestSizeForChildren(const Window &rWindow)
1909 Rectangle aBounds;
1911 for (const Window* pChild = rWindow.GetWindow(WINDOW_FIRSTCHILD); pChild;
1912 pChild = pChild->GetWindow(WINDOW_NEXT))
1914 if (!pChild->IsVisible())
1915 continue;
1917 Rectangle aChildBounds(pChild->GetPosPixel(), pChild->GetSizePixel());
1918 aBounds.Union(aChildBounds);
1921 if (aBounds.IsEmpty())
1922 return rWindow.GetSizePixel();
1924 Size aRet(aBounds.GetSize());
1925 Point aTopLeft(aBounds.TopLeft());
1926 aRet.Width() += aTopLeft.X()*2;
1927 aRet.Height() += aTopLeft.Y()*2;
1929 return aRet;
1932 Window* getNonLayoutParent(Window *pWindow)
1934 while (pWindow)
1936 pWindow = pWindow->GetParent();
1937 if (!pWindow || !isContainerWindow(*pWindow))
1938 break;
1940 return pWindow;
1943 Window* getNonLayoutRealParent(Window *pWindow)
1945 while (pWindow)
1947 pWindow = pWindow->ImplGetParent();
1948 if (!pWindow || !isContainerWindow(*pWindow))
1949 break;
1951 return pWindow;
1954 bool isVisibleInLayout(const Window *pWindow)
1956 bool bVisible = true;
1957 while (bVisible)
1959 bVisible = pWindow->IsVisible();
1960 pWindow = pWindow->GetParent();
1961 if (!pWindow || !isContainerWindow(*pWindow))
1962 break;
1964 return bVisible;
1967 bool isEnabledInLayout(const Window *pWindow)
1969 bool bEnabled = true;
1970 while (bEnabled)
1972 bEnabled = pWindow->IsEnabled();
1973 pWindow = pWindow->GetParent();
1974 if (!pWindow || !isContainerWindow(*pWindow))
1975 break;
1977 return bEnabled;
1980 bool isLayoutEnabled(const Window *pWindow)
1982 //Child is a container => we're layout enabled
1983 const Window *pChild = pWindow ? pWindow->GetWindow(WINDOW_FIRSTCHILD) : NULL;
1984 return pChild && isContainerWindow(*pChild) && !pChild->GetWindow(WINDOW_NEXT);
1987 bool isInitialLayout(const Window *pWindow)
1989 Dialog *pParentDialog = pWindow ? pWindow->GetParentDialog() : NULL;
1990 return pParentDialog && pParentDialog->isCalculatingInitialLayoutSize();
1993 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */