Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
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 <vcl/settings.hxx>
16 : #include "window.h"
17 :
18 11160 : VclContainer::VclContainer(vcl::Window *pParent, WinBits nStyle)
19 : : Window(WINDOW_CONTAINER)
20 11160 : , m_bLayoutDirty(true)
21 : {
22 11160 : ImplInit(pParent, nStyle, NULL);
23 11160 : EnableChildTransparentMode();
24 11160 : SetPaintTransparent(true);
25 11160 : SetBackground();
26 11160 : }
27 :
28 6 : sal_uInt16 VclContainer::getDefaultAccessibleRole() const
29 : {
30 6 : return com::sun::star::accessibility::AccessibleRole::PANEL;
31 : }
32 :
33 11992 : Size VclContainer::GetOptimalSize() const
34 : {
35 11992 : return calculateRequisition();
36 : }
37 :
38 64747 : void VclContainer::setLayoutPosSize(vcl::Window &rWindow, const Point &rPos, const Size &rSize)
39 : {
40 64747 : sal_Int32 nBorderWidth = rWindow.get_border_width();
41 64747 : sal_Int32 nLeft = rWindow.get_margin_left() + nBorderWidth;
42 64747 : sal_Int32 nTop = rWindow.get_margin_top() + nBorderWidth;
43 64747 : sal_Int32 nRight = rWindow.get_margin_right() + nBorderWidth;
44 64747 : sal_Int32 nBottom = rWindow.get_margin_bottom() + nBorderWidth;
45 64747 : Point aPos(rPos.X() + nLeft, rPos.Y() + nTop);
46 64747 : Size aSize(rSize.Width() - nLeft - nRight, rSize.Height() - nTop - nBottom);
47 64747 : rWindow.SetPosSizePixel(aPos, aSize);
48 64747 : }
49 :
50 64747 : void VclContainer::setLayoutAllocation(vcl::Window &rChild, const Point &rAllocPos, const Size &rChildAlloc)
51 : {
52 64747 : VclAlign eHalign = rChild.get_halign();
53 64747 : VclAlign eValign = rChild.get_valign();
54 :
55 : //typical case
56 64747 : if (eHalign == VCL_ALIGN_FILL && eValign == VCL_ALIGN_FILL)
57 : {
58 52264 : setLayoutPosSize(rChild, rAllocPos, rChildAlloc);
59 117011 : return;
60 : }
61 :
62 12483 : Point aChildPos(rAllocPos);
63 12483 : Size aChildSize(rChildAlloc);
64 12483 : Size aChildPreferredSize(getLayoutRequisition(rChild));
65 :
66 12483 : switch (eHalign)
67 : {
68 : case VCL_ALIGN_FILL:
69 0 : break;
70 : case VCL_ALIGN_START:
71 1478 : if (aChildPreferredSize.Width() < rChildAlloc.Width())
72 0 : aChildSize.Width() = aChildPreferredSize.Width();
73 1478 : break;
74 : case VCL_ALIGN_END:
75 2195 : if (aChildPreferredSize.Width() < rChildAlloc.Width())
76 742 : aChildSize.Width() = aChildPreferredSize.Width();
77 2195 : aChildPos.X() += rChildAlloc.Width();
78 2195 : aChildPos.X() -= aChildSize.Width();
79 2195 : break;
80 : case VCL_ALIGN_CENTER:
81 8810 : if (aChildPreferredSize.Width() < aChildSize.Width())
82 0 : aChildSize.Width() = aChildPreferredSize.Width();
83 8810 : aChildPos.X() += (rChildAlloc.Width() - aChildSize.Width()) / 2;
84 8810 : break;
85 : }
86 :
87 12483 : switch (eValign)
88 : {
89 : case VCL_ALIGN_FILL:
90 5103 : break;
91 : case VCL_ALIGN_START:
92 0 : if (aChildPreferredSize.Height() < rChildAlloc.Height())
93 0 : aChildSize.Height() = aChildPreferredSize.Height();
94 0 : break;
95 : case VCL_ALIGN_END:
96 0 : if (aChildPreferredSize.Height() < rChildAlloc.Height())
97 0 : aChildSize.Height() = aChildPreferredSize.Height();
98 0 : aChildPos.Y() += rChildAlloc.Height();
99 0 : aChildPos.Y() -= aChildSize.Height();
100 0 : break;
101 : case VCL_ALIGN_CENTER:
102 7380 : if (aChildPreferredSize.Height() < aChildSize.Height())
103 7380 : aChildSize.Height() = aChildPreferredSize.Height();
104 7380 : aChildPos.Y() += (rChildAlloc.Height() - aChildSize.Height()) / 2;
105 7380 : break;
106 : }
107 :
108 12483 : setLayoutPosSize(rChild, aChildPos, aChildSize);
109 : }
110 :
111 149127 : Size VclContainer::getLayoutRequisition(const vcl::Window &rWindow)
112 : {
113 149127 : sal_Int32 nBorderWidth = rWindow.get_border_width();
114 149127 : sal_Int32 nLeft = rWindow.get_margin_left() + nBorderWidth;
115 149127 : sal_Int32 nTop = rWindow.get_margin_top() + nBorderWidth;
116 149127 : sal_Int32 nRight = rWindow.get_margin_right() + nBorderWidth;
117 149127 : sal_Int32 nBottom = rWindow.get_margin_bottom() + nBorderWidth;
118 149127 : Size aSize(rWindow.get_preferred_size());
119 149127 : return Size(aSize.Width() + nLeft + nRight, aSize.Height() + nTop + nBottom);
120 : }
121 :
122 23131 : void VclContainer::SetPosSizePixel(const Point& rAllocPos, const Size& rAllocation)
123 : {
124 23131 : bool bSizeChanged = rAllocation != GetOutputSizePixel();
125 23131 : Window::SetPosSizePixel(rAllocPos, rAllocation);
126 23131 : if (m_bLayoutDirty || bSizeChanged)
127 : {
128 21611 : m_bLayoutDirty = false;
129 21611 : setAllocation(rAllocation);
130 : }
131 23131 : }
132 :
133 0 : void VclContainer::SetPosPixel(const Point& rAllocPos)
134 : {
135 0 : Point aAllocPos = rAllocPos;
136 0 : sal_Int32 nBorderWidth = get_border_width();
137 0 : aAllocPos.X() += nBorderWidth + get_margin_left();
138 0 : aAllocPos.Y() += nBorderWidth + get_margin_top();
139 :
140 0 : if (aAllocPos != GetPosPixel())
141 0 : Window::SetPosPixel(aAllocPos);
142 0 : }
143 :
144 0 : void VclContainer::SetSizePixel(const Size& rAllocation)
145 : {
146 0 : Size aAllocation = rAllocation;
147 0 : sal_Int32 nBorderWidth = get_border_width();
148 0 : aAllocation.Width() -= nBorderWidth*2 + get_margin_left() + get_margin_right();
149 0 : aAllocation.Height() -= nBorderWidth*2 + get_margin_top() + get_margin_bottom();
150 0 : bool bSizeChanged = aAllocation != GetSizePixel();
151 0 : if (bSizeChanged)
152 0 : Window::SetSizePixel(aAllocation);
153 0 : if (m_bLayoutDirty || bSizeChanged)
154 : {
155 0 : m_bLayoutDirty = false;
156 0 : setAllocation(aAllocation);
157 : }
158 0 : }
159 :
160 454522 : void VclContainer::queue_resize(StateChangedType eReason)
161 : {
162 454522 : markLayoutDirty();
163 454522 : Window::queue_resize(eReason);
164 454522 : }
165 :
166 46024 : void VclBox::accumulateMaxes(const Size &rChildSize, Size &rSize) const
167 : {
168 46024 : long nSecondaryChildDimension = getSecondaryDimension(rChildSize);
169 46024 : long nSecondaryBoxDimension = getSecondaryDimension(rSize);
170 46024 : setSecondaryDimension(rSize, std::max(nSecondaryChildDimension, nSecondaryBoxDimension));
171 :
172 46024 : long nPrimaryChildDimension = getPrimaryDimension(rChildSize);
173 46024 : long nPrimaryBoxDimension = getPrimaryDimension(rSize);
174 46024 : if (m_bHomogeneous)
175 4 : setPrimaryDimension(rSize, std::max(nPrimaryBoxDimension, nPrimaryChildDimension));
176 : else
177 46020 : setPrimaryDimension(rSize, nPrimaryBoxDimension + nPrimaryChildDimension);
178 46024 : }
179 :
180 20072 : Size VclBox::calculateRequisition() const
181 : {
182 20072 : sal_uInt16 nVisibleChildren = 0;
183 :
184 20072 : Size aSize;
185 68878 : for (vcl::Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
186 : {
187 48806 : if (!pChild->IsVisible())
188 2782 : continue;
189 46024 : ++nVisibleChildren;
190 46024 : Size aChildSize = getLayoutRequisition(*pChild);
191 :
192 46024 : long nPrimaryDimension = getPrimaryDimension(aChildSize);
193 46024 : nPrimaryDimension += pChild->get_padding() * 2;
194 46024 : setPrimaryDimension(aChildSize, nPrimaryDimension);
195 :
196 46024 : accumulateMaxes(aChildSize, aSize);
197 : }
198 :
199 20072 : return finalizeMaxes(aSize, nVisibleChildren);
200 : }
201 :
202 19350 : void VclBox::setAllocation(const Size &rAllocation)
203 : {
204 19350 : sal_uInt16 nVisibleChildren = 0, nExpandChildren = 0;
205 73404 : for (vcl::Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
206 : {
207 54054 : if (!pChild->IsVisible())
208 4998 : continue;
209 49056 : ++nVisibleChildren;
210 49056 : bool bExpand = getPrimaryDimensionChildExpand(*pChild);
211 49056 : if (bExpand)
212 8892 : ++nExpandChildren;
213 : }
214 :
215 19350 : if (!nVisibleChildren)
216 19350 : return;
217 :
218 19350 : long nAllocPrimaryDimension = getPrimaryDimension(rAllocation);
219 :
220 19350 : long nHomogeneousDimension = 0, nExtraSpace = 0;
221 19350 : if (m_bHomogeneous)
222 : {
223 4 : nHomogeneousDimension = ((nAllocPrimaryDimension -
224 8 : (nVisibleChildren - 1) * m_nSpacing)) / nVisibleChildren;
225 : }
226 19346 : else if (nExpandChildren)
227 : {
228 8886 : Size aRequisition = calculateRequisition();
229 8886 : nExtraSpace = (getPrimaryDimension(rAllocation) - getPrimaryDimension(aRequisition)) / nExpandChildren;
230 : }
231 :
232 : //Split into those we pack from the start onwards, and those we pack from the end backwards
233 58050 : std::vector<vcl::Window*> aWindows[2];
234 73404 : for (vcl::Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
235 : {
236 54054 : if (!pChild->IsVisible())
237 4998 : continue;
238 :
239 49056 : sal_Int32 ePacking = pChild->get_pack_type();
240 49056 : aWindows[ePacking].push_back(pChild);
241 : }
242 :
243 : //See VclBuilder::sortIntoBestTabTraversalOrder for why they are in visual
244 : //order under the parent which requires us to reverse them here to
245 : //pack from the end back
246 19350 : std::reverse(aWindows[VCL_PACK_END].begin(),aWindows[VCL_PACK_END].end());
247 :
248 58050 : for (sal_Int32 ePackType = VCL_PACK_START; ePackType <= VCL_PACK_END; ++ePackType)
249 : {
250 38700 : Point aPos(0, 0);
251 38700 : if (ePackType == VCL_PACK_END)
252 : {
253 19350 : long nPrimaryCoordinate = getPrimaryCoordinate(aPos);
254 19350 : setPrimaryCoordinate(aPos, nPrimaryCoordinate + nAllocPrimaryDimension);
255 : }
256 :
257 87756 : for (std::vector<vcl::Window*>::iterator aI = aWindows[ePackType].begin(), aEnd = aWindows[ePackType].end(); aI != aEnd; ++aI)
258 : {
259 49056 : vcl::Window *pChild = *aI;
260 :
261 49056 : long nPadding = pChild->get_padding();
262 :
263 49056 : Size aBoxSize;
264 49056 : if (m_bHomogeneous)
265 8 : setPrimaryDimension(aBoxSize, nHomogeneousDimension);
266 : else
267 : {
268 49048 : aBoxSize = getLayoutRequisition(*pChild);
269 49048 : long nPrimaryDimension = getPrimaryDimension(aBoxSize);
270 49048 : nPrimaryDimension += nPadding * 2;
271 49048 : if (getPrimaryDimensionChildExpand(*pChild))
272 8892 : nPrimaryDimension += nExtraSpace;
273 49048 : setPrimaryDimension(aBoxSize, nPrimaryDimension);
274 : }
275 49056 : setSecondaryDimension(aBoxSize, getSecondaryDimension(rAllocation));
276 :
277 49056 : Point aChildPos(aPos);
278 49056 : Size aChildSize(aBoxSize);
279 49056 : long nPrimaryCoordinate = getPrimaryCoordinate(aPos);
280 :
281 49056 : bool bFill = pChild->get_fill();
282 49056 : if (bFill)
283 : {
284 : setPrimaryDimension(aChildSize, std::max(static_cast<long>(1),
285 49056 : getPrimaryDimension(aBoxSize) - nPadding * 2));
286 :
287 49056 : setPrimaryCoordinate(aChildPos, nPrimaryCoordinate + nPadding);
288 : }
289 : else
290 : {
291 : setPrimaryDimension(aChildSize,
292 0 : getPrimaryDimension(getLayoutRequisition(*pChild)));
293 :
294 : setPrimaryCoordinate(aChildPos, nPrimaryCoordinate +
295 0 : (getPrimaryDimension(aBoxSize) - getPrimaryDimension(aChildSize)) / 2);
296 : }
297 :
298 49056 : long nDiff = getPrimaryDimension(aBoxSize) + m_nSpacing;
299 49056 : if (ePackType == VCL_PACK_START)
300 43114 : setPrimaryCoordinate(aPos, nPrimaryCoordinate + nDiff);
301 : else
302 : {
303 5942 : setPrimaryCoordinate(aPos, nPrimaryCoordinate - nDiff);
304 5942 : setPrimaryCoordinate(aChildPos, getPrimaryCoordinate(aChildPos) -
305 11884 : getPrimaryDimension(aBoxSize));
306 : }
307 :
308 49056 : setLayoutAllocation(*pChild, aChildPos, aChildSize);
309 : }
310 58050 : }
311 : }
312 :
313 28994 : bool VclBox::set_property(const OString &rKey, const OString &rValue)
314 : {
315 28994 : if (rKey == "spacing")
316 8860 : set_spacing(rValue.toInt32());
317 20134 : else if (rKey == "homogeneous")
318 2 : set_homogeneous(toBool(rValue));
319 : else
320 20132 : return VclContainer::set_property(rKey, rValue);
321 8862 : return true;
322 : }
323 :
324 150 : sal_uInt16 VclBox::getDefaultAccessibleRole() const
325 : {
326 : #if defined(WNT)
327 : //fdo#74284 call Boxes Panels, keep then as "Filler" under
328 : //at least Linux seeing as that's what Gtk does for GtkBoxes
329 : return com::sun::star::accessibility::AccessibleRole::PANEL;
330 : #else
331 150 : return com::sun::star::accessibility::AccessibleRole::FILLER;
332 : #endif
333 : }
334 :
335 : #define DEFAULT_CHILD_MIN_WIDTH 85
336 : #define DEFAULT_CHILD_MIN_HEIGHT 27
337 :
338 20072 : Size VclBox::finalizeMaxes(const Size &rSize, sal_uInt16 nVisibleChildren) const
339 : {
340 20072 : Size aRet;
341 :
342 20072 : if (nVisibleChildren)
343 : {
344 20072 : long nPrimaryDimension = getPrimaryDimension(rSize);
345 20072 : if (m_bHomogeneous)
346 2 : nPrimaryDimension *= nVisibleChildren;
347 20072 : setPrimaryDimension(aRet, nPrimaryDimension + m_nSpacing * (nVisibleChildren-1));
348 20072 : setSecondaryDimension(aRet, getSecondaryDimension(rSize));
349 : }
350 :
351 20072 : return aRet;
352 : }
353 :
354 0 : Size VclButtonBox::addReqGroups(const VclButtonBox::Requisition &rReq) const
355 : {
356 0 : Size aRet;
357 :
358 0 : long nMainGroupDimension = getPrimaryDimension(rReq.m_aMainGroupSize);
359 0 : long nSubGroupDimension = getPrimaryDimension(rReq.m_aSubGroupSize);
360 :
361 0 : setPrimaryDimension(aRet, nMainGroupDimension + nSubGroupDimension);
362 :
363 : setSecondaryDimension(aRet,
364 0 : std::max(getSecondaryDimension(rReq.m_aMainGroupSize),
365 0 : getSecondaryDimension(rReq.m_aSubGroupSize)));
366 :
367 0 : return aRet;
368 : }
369 :
370 0 : static long getMaxNonOutlier(const std::vector<long> &rG, long nAvgDimension)
371 : {
372 0 : long nMaxDimensionNonOutlier = 0;
373 0 : for (std::vector<long>::const_iterator aI = rG.begin(),
374 0 : aEnd = rG.end(); aI != aEnd; ++aI)
375 : {
376 0 : long nPrimaryChildDimension = *aI;
377 0 : if (nPrimaryChildDimension < nAvgDimension * 1.5)
378 : {
379 : nMaxDimensionNonOutlier = std::max(nPrimaryChildDimension,
380 0 : nMaxDimensionNonOutlier);
381 : }
382 : }
383 0 : return nMaxDimensionNonOutlier;
384 : }
385 :
386 0 : static std::vector<long> setButtonSizes(const std::vector<long> &rG,
387 : const std::vector<bool> &rNonHomogeneous,
388 : long nAvgDimension, long nMaxNonOutlier, long nMinWidth)
389 : {
390 0 : std::vector<long> aVec;
391 : //set everything < 1.5 times the average to the same width, leave the
392 : //outliers un-touched
393 0 : std::vector<bool>::const_iterator aJ = rNonHomogeneous.begin();
394 0 : for (std::vector<long>::const_iterator aI = rG.begin(), aEnd = rG.end();
395 : aI != aEnd; ++aI, ++aJ)
396 : {
397 0 : long nPrimaryChildDimension = *aI;
398 0 : bool bNonHomogeneous = *aJ;
399 0 : if (!bNonHomogeneous && nPrimaryChildDimension < nAvgDimension * 1.5)
400 : {
401 0 : aVec.push_back(std::max(nMaxNonOutlier, nMinWidth));
402 : }
403 : else
404 : {
405 0 : aVec.push_back(std::max(nPrimaryChildDimension, nMinWidth));
406 : }
407 : }
408 0 : return aVec;
409 : }
410 :
411 0 : VclButtonBox::Requisition VclButtonBox::calculatePrimarySecondaryRequisitions() const
412 : {
413 0 : Requisition aReq;
414 :
415 0 : Size aMainGroupSize(DEFAULT_CHILD_MIN_WIDTH, DEFAULT_CHILD_MIN_HEIGHT); //to-do, pull from theme
416 0 : Size aSubGroupSize(DEFAULT_CHILD_MIN_WIDTH, DEFAULT_CHILD_MIN_HEIGHT); //to-do, pull from theme
417 :
418 0 : long nMinMainGroupPrimary = getPrimaryDimension(aMainGroupSize);
419 0 : long nMinSubGroupPrimary = getPrimaryDimension(aSubGroupSize);
420 0 : long nMainGroupSecondary = getSecondaryDimension(aMainGroupSize);
421 0 : long nSubGroupSecondary = getSecondaryDimension(aSubGroupSize);
422 :
423 0 : bool bIgnoreSecondaryPacking = (m_eLayoutStyle == VCL_BUTTONBOX_SPREAD || m_eLayoutStyle == VCL_BUTTONBOX_CENTER);
424 :
425 0 : std::vector<long> aMainGroupSizes;
426 0 : std::vector<bool> aMainGroupNonHomogeneous;
427 0 : std::vector<long> aSubGroupSizes;
428 0 : std::vector<bool> aSubGroupNonHomogeneous;
429 :
430 0 : for (const vcl::Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
431 : {
432 0 : if (!pChild->IsVisible())
433 0 : continue;
434 0 : Size aChildSize = getLayoutRequisition(*pChild);
435 0 : if (bIgnoreSecondaryPacking || !pChild->get_secondary())
436 : {
437 : //set the max secondary dimension
438 0 : nMainGroupSecondary = std::max(nMainGroupSecondary, getSecondaryDimension(aChildSize));
439 : //collect the primary dimensions
440 0 : aMainGroupSizes.push_back(getPrimaryDimension(aChildSize));
441 0 : aMainGroupNonHomogeneous.push_back(pChild->get_non_homogeneous());
442 : }
443 : else
444 : {
445 0 : nSubGroupSecondary = std::max(nSubGroupSecondary, getSecondaryDimension(aChildSize));
446 0 : aSubGroupSizes.push_back(getPrimaryDimension(aChildSize));
447 0 : aSubGroupNonHomogeneous.push_back(pChild->get_non_homogeneous());
448 : }
449 : }
450 :
451 0 : if (m_bHomogeneous)
452 : {
453 0 : long nMaxMainDimension = aMainGroupSizes.empty() ? 0 :
454 0 : *std::max_element(aMainGroupSizes.begin(), aMainGroupSizes.end());
455 0 : nMaxMainDimension = std::max(nMaxMainDimension, nMinMainGroupPrimary);
456 0 : long nMaxSubDimension = aSubGroupSizes.empty() ? 0 :
457 0 : *std::max_element(aSubGroupSizes.begin(), aSubGroupSizes.end());
458 0 : nMaxSubDimension = std::max(nMaxSubDimension, nMinSubGroupPrimary);
459 0 : long nMaxDimension = std::max(nMaxMainDimension, nMaxSubDimension);
460 0 : aReq.m_aMainGroupDimensions.resize(aMainGroupSizes.size(), nMaxDimension);
461 0 : aReq.m_aSubGroupDimensions.resize(aSubGroupSizes.size(), nMaxDimension);
462 : }
463 : else
464 : {
465 : //Ideally set everything to the same size, but find outlier widgets
466 : //that are way wider than the average and leave them
467 : //at their natural size and set the remainder to share the
468 : //max size of the remaining members of the buttonbox
469 : long nAccDimension = std::accumulate(aMainGroupSizes.begin(),
470 0 : aMainGroupSizes.end(), 0);
471 : nAccDimension = std::accumulate(aSubGroupSizes.begin(),
472 0 : aSubGroupSizes.end(), nAccDimension);
473 :
474 0 : size_t nTotalSize = aMainGroupSizes.size() + aSubGroupSizes.size();
475 :
476 0 : long nAvgDimension = nTotalSize ? nAccDimension / nTotalSize : 0;
477 :
478 : long nMaxMainNonOutlier = getMaxNonOutlier(aMainGroupSizes,
479 0 : nAvgDimension);
480 : long nMaxSubNonOutlier = getMaxNonOutlier(aSubGroupSizes,
481 0 : nAvgDimension);
482 0 : long nMaxNonOutlier = std::max(nMaxMainNonOutlier, nMaxSubNonOutlier);
483 :
484 0 : aReq.m_aMainGroupDimensions = setButtonSizes(aMainGroupSizes,
485 : aMainGroupNonHomogeneous,
486 0 : nAvgDimension, nMaxNonOutlier, nMinMainGroupPrimary);
487 0 : aReq.m_aSubGroupDimensions = setButtonSizes(aSubGroupSizes,
488 : aSubGroupNonHomogeneous,
489 0 : nAvgDimension, nMaxNonOutlier, nMinSubGroupPrimary);
490 : }
491 :
492 0 : if (!aReq.m_aMainGroupDimensions.empty())
493 : {
494 0 : setSecondaryDimension(aReq.m_aMainGroupSize, nMainGroupSecondary);
495 : setPrimaryDimension(aReq.m_aMainGroupSize,
496 : std::accumulate(aReq.m_aMainGroupDimensions.begin(),
497 0 : aReq.m_aMainGroupDimensions.end(), 0));
498 : }
499 0 : if (!aReq.m_aSubGroupDimensions.empty())
500 : {
501 0 : setSecondaryDimension(aReq.m_aSubGroupSize, nSubGroupSecondary);
502 : setPrimaryDimension(aReq.m_aSubGroupSize,
503 : std::accumulate(aReq.m_aSubGroupDimensions.begin(),
504 0 : aReq.m_aSubGroupDimensions.end(), 0));
505 : }
506 :
507 0 : return aReq;
508 : }
509 :
510 0 : Size VclButtonBox::addSpacing(const Size &rSize, sal_uInt16 nVisibleChildren) const
511 : {
512 0 : Size aRet;
513 :
514 0 : if (nVisibleChildren)
515 : {
516 0 : long nPrimaryDimension = getPrimaryDimension(rSize);
517 : setPrimaryDimension(aRet,
518 0 : nPrimaryDimension + m_nSpacing * (nVisibleChildren-1));
519 0 : setSecondaryDimension(aRet, getSecondaryDimension(rSize));
520 : }
521 :
522 0 : return aRet;
523 : }
524 :
525 0 : Size VclButtonBox::calculateRequisition() const
526 : {
527 0 : Requisition aReq(calculatePrimarySecondaryRequisitions());
528 0 : sal_uInt16 nVisibleChildren = aReq.m_aMainGroupDimensions.size() +
529 0 : aReq.m_aSubGroupDimensions.size();
530 0 : return addSpacing(addReqGroups(aReq), nVisibleChildren);
531 : }
532 :
533 0 : bool VclButtonBox::set_property(const OString &rKey, const OString &rValue)
534 : {
535 0 : if (rKey == "layout-style")
536 : {
537 0 : VclButtonBoxStyle eStyle = VCL_BUTTONBOX_DEFAULT_STYLE;
538 0 : if (rValue == "spread")
539 0 : eStyle = VCL_BUTTONBOX_SPREAD;
540 0 : else if (rValue == "edge")
541 0 : eStyle = VCL_BUTTONBOX_EDGE;
542 0 : else if (rValue == "start")
543 0 : eStyle = VCL_BUTTONBOX_START;
544 0 : else if (rValue == "end")
545 0 : eStyle = VCL_BUTTONBOX_END;
546 0 : else if (rValue == "center")
547 0 : eStyle = VCL_BUTTONBOX_CENTER;
548 : else
549 : {
550 : SAL_WARN("vcl.layout", "unknown layout style " << rValue.getStr());
551 : }
552 0 : set_layout(eStyle);
553 : }
554 : else
555 0 : return VclBox::set_property(rKey, rValue);
556 0 : return true;
557 : }
558 :
559 0 : void VclButtonBox::setAllocation(const Size &rAllocation)
560 : {
561 0 : Requisition aReq(calculatePrimarySecondaryRequisitions());
562 :
563 0 : if (aReq.m_aMainGroupDimensions.empty() && aReq.m_aSubGroupDimensions.empty())
564 0 : return;
565 :
566 0 : long nAllocPrimaryDimension = getPrimaryDimension(rAllocation);
567 :
568 0 : Point aMainGroupPos, aOtherGroupPos;
569 0 : int nSpacing = m_nSpacing;
570 :
571 : //To-Do, other layout styles
572 0 : switch (m_eLayoutStyle)
573 : {
574 : case VCL_BUTTONBOX_START:
575 0 : if (!aReq.m_aSubGroupDimensions.empty())
576 : {
577 : long nOtherPrimaryDimension = getPrimaryDimension(
578 0 : addSpacing(aReq.m_aSubGroupSize, aReq.m_aSubGroupDimensions.size()));
579 : setPrimaryCoordinate(aOtherGroupPos,
580 0 : nAllocPrimaryDimension - nOtherPrimaryDimension);
581 : }
582 0 : break;
583 : case VCL_BUTTONBOX_SPREAD:
584 0 : if (!aReq.m_aMainGroupDimensions.empty())
585 : {
586 : long nMainPrimaryDimension = getPrimaryDimension(
587 0 : addSpacing(aReq.m_aMainGroupSize, aReq.m_aMainGroupDimensions.size()));
588 0 : long nExtraSpace = nAllocPrimaryDimension - nMainPrimaryDimension;
589 0 : nExtraSpace += (aReq.m_aMainGroupDimensions.size()-1) * nSpacing;
590 0 : nSpacing = nExtraSpace/(aReq.m_aMainGroupDimensions.size()+1);
591 0 : setPrimaryCoordinate(aMainGroupPos, nSpacing);
592 : }
593 0 : break;
594 : case VCL_BUTTONBOX_CENTER:
595 0 : if (!aReq.m_aMainGroupDimensions.empty())
596 : {
597 : long nMainPrimaryDimension = getPrimaryDimension(
598 0 : addSpacing(aReq.m_aMainGroupSize, aReq.m_aMainGroupDimensions.size()));
599 0 : long nExtraSpace = nAllocPrimaryDimension - nMainPrimaryDimension;
600 0 : setPrimaryCoordinate(aMainGroupPos, nExtraSpace/2);
601 : }
602 0 : break;
603 : default:
604 : SAL_WARN("vcl.layout", "todo unimplemented layout style");
605 : //fall-through
606 : case VCL_BUTTONBOX_DEFAULT_STYLE:
607 : case VCL_BUTTONBOX_END:
608 0 : if (!aReq.m_aMainGroupDimensions.empty())
609 : {
610 : long nMainPrimaryDimension = getPrimaryDimension(
611 0 : addSpacing(aReq.m_aMainGroupSize, aReq.m_aMainGroupDimensions.size()));
612 : setPrimaryCoordinate(aMainGroupPos,
613 0 : nAllocPrimaryDimension - nMainPrimaryDimension);
614 : }
615 0 : break;
616 : }
617 :
618 0 : Size aChildSize;
619 0 : setSecondaryDimension(aChildSize, getSecondaryDimension(rAllocation));
620 :
621 0 : std::vector<long>::const_iterator aPrimaryI = aReq.m_aMainGroupDimensions.begin();
622 0 : std::vector<long>::const_iterator aSecondaryI = aReq.m_aSubGroupDimensions.begin();
623 0 : bool bIgnoreSecondaryPacking = (m_eLayoutStyle == VCL_BUTTONBOX_SPREAD || m_eLayoutStyle == VCL_BUTTONBOX_CENTER);
624 0 : for (vcl::Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
625 : {
626 0 : if (!pChild->IsVisible())
627 0 : continue;
628 :
629 0 : if (bIgnoreSecondaryPacking || !pChild->get_secondary())
630 : {
631 0 : long nMainGroupPrimaryDimension = *aPrimaryI++;
632 0 : setPrimaryDimension(aChildSize, nMainGroupPrimaryDimension);
633 0 : setLayoutAllocation(*pChild, aMainGroupPos, aChildSize);
634 0 : long nPrimaryCoordinate = getPrimaryCoordinate(aMainGroupPos);
635 0 : setPrimaryCoordinate(aMainGroupPos, nPrimaryCoordinate + nMainGroupPrimaryDimension + nSpacing);
636 : }
637 : else
638 : {
639 0 : long nSubGroupPrimaryDimension = *aSecondaryI++;
640 0 : setPrimaryDimension(aChildSize, nSubGroupPrimaryDimension);
641 0 : setLayoutAllocation(*pChild, aOtherGroupPos, aChildSize);
642 0 : long nPrimaryCoordinate = getPrimaryCoordinate(aOtherGroupPos);
643 0 : setPrimaryCoordinate(aOtherGroupPos, nPrimaryCoordinate + nSubGroupPrimaryDimension + nSpacing);
644 : }
645 0 : }
646 : }
647 :
648 0 : struct ButtonOrder
649 : {
650 : OString m_aType;
651 : int m_nPriority;
652 : };
653 :
654 0 : static int getButtonPriority(const OString &rType)
655 : {
656 : static const size_t N_TYPES = 3;
657 : static const ButtonOrder aDiscardCancelSave[N_TYPES] =
658 : {
659 : { "/discard", 0 },
660 : { "/cancel", 1 },
661 : { "/save", 2 }
662 0 : };
663 :
664 : static const ButtonOrder aSaveDiscardCancel[N_TYPES] =
665 : {
666 : { "/save", 0 },
667 : { "/discard", 1 },
668 : { "/cancel", 2 }
669 0 : };
670 :
671 0 : const ButtonOrder* pOrder = &aDiscardCancelSave[0];
672 :
673 0 : const OUString &rEnv = Application::GetDesktopEnvironment();
674 :
675 0 : if (rEnv.equalsIgnoreAsciiCase("windows") ||
676 0 : rEnv.equalsIgnoreAsciiCase("kde4") ||
677 0 : rEnv.equalsIgnoreAsciiCase("tde") ||
678 0 : rEnv.equalsIgnoreAsciiCase("kde"))
679 : {
680 0 : pOrder = &aSaveDiscardCancel[0];
681 : }
682 :
683 0 : for (size_t i = 0; i < N_TYPES; ++i, ++pOrder)
684 : {
685 0 : if (rType.endsWith(pOrder->m_aType))
686 0 : return pOrder->m_nPriority;
687 : }
688 :
689 0 : return -1;
690 : }
691 :
692 : class sortButtons
693 : : public std::binary_function<const vcl::Window*, const vcl::Window*, bool>
694 : {
695 : bool m_bVerticalContainer;
696 : public:
697 0 : sortButtons(bool bVerticalContainer)
698 0 : : m_bVerticalContainer(bVerticalContainer)
699 : {
700 0 : }
701 : bool operator()(const vcl::Window *pA, const vcl::Window *pB) const;
702 : };
703 :
704 0 : bool sortButtons::operator()(const vcl::Window *pA, const vcl::Window *pB) const
705 : {
706 : //sort into two groups of pack start and pack end
707 0 : VclPackType ePackA = pA->get_pack_type();
708 0 : VclPackType ePackB = pB->get_pack_type();
709 0 : if (ePackA < ePackB)
710 0 : return true;
711 0 : if (ePackA > ePackB)
712 0 : return false;
713 0 : bool bPackA = pA->get_secondary();
714 0 : bool bPackB = pB->get_secondary();
715 0 : if (!m_bVerticalContainer)
716 : {
717 : //for horizontal boxes group secondaries before primaries
718 0 : if (bPackA > bPackB)
719 0 : return true;
720 0 : if (bPackA < bPackB)
721 0 : return false;
722 : }
723 : else
724 : {
725 : //for vertical boxes group secondaries after primaries
726 0 : if (bPackA < bPackB)
727 0 : return true;
728 0 : if (bPackA > bPackB)
729 0 : return false;
730 : }
731 :
732 : //now order within groups according to platform rules
733 0 : return getButtonPriority(pA->GetHelpId()) < getButtonPriority(pB->GetHelpId());
734 : }
735 :
736 0 : void VclButtonBox::sort_native_button_order()
737 : {
738 0 : std::vector<vcl::Window*> aChilds;
739 0 : for (vcl::Window* pChild = GetWindow(WINDOW_FIRSTCHILD); pChild;
740 0 : pChild = pChild->GetWindow(WINDOW_NEXT))
741 : {
742 0 : aChilds.push_back(pChild);
743 : }
744 :
745 : //sort child order within parent so that we match the platform
746 : //button order
747 0 : std::stable_sort(aChilds.begin(), aChilds.end(), sortButtons(m_bVerticalContainer));
748 0 : VclBuilder::reorderWithinParent(aChilds, true);
749 0 : }
750 :
751 7473 : VclGrid::array_type VclGrid::assembleGrid() const
752 : {
753 7473 : ext_array_type A;
754 :
755 40855 : for (vcl::Window* pChild = GetWindow(WINDOW_FIRSTCHILD); pChild;
756 : pChild = pChild->GetWindow(WINDOW_NEXT))
757 : {
758 33382 : sal_Int32 nLeftAttach = pChild->get_grid_left_attach();
759 33382 : sal_Int32 nWidth = pChild->get_grid_width();
760 33382 : sal_Int32 nMaxXPos = nLeftAttach+nWidth-1;
761 :
762 33382 : sal_Int32 nTopAttach = pChild->get_grid_top_attach();
763 33382 : sal_Int32 nHeight = pChild->get_grid_height();
764 33382 : sal_Int32 nMaxYPos = nTopAttach+nHeight-1;
765 :
766 33382 : sal_Int32 nCurrentMaxXPos = A.shape()[0]-1;
767 33382 : sal_Int32 nCurrentMaxYPos = A.shape()[1]-1;
768 33382 : if (nMaxXPos > nCurrentMaxXPos || nMaxYPos > nCurrentMaxYPos)
769 : {
770 25994 : nCurrentMaxXPos = std::max(nMaxXPos, nCurrentMaxXPos);
771 25994 : nCurrentMaxYPos = std::max(nMaxYPos, nCurrentMaxYPos);
772 25994 : A.resize(boost::extents[nCurrentMaxXPos+1][nCurrentMaxYPos+1]);
773 : }
774 :
775 33382 : ExtendedGridEntry &rEntry = A[nLeftAttach][nTopAttach];
776 33382 : rEntry.pChild = pChild;
777 33382 : rEntry.nSpanWidth = nWidth;
778 33382 : rEntry.nSpanHeight = nHeight;
779 33382 : rEntry.x = nLeftAttach;
780 33382 : rEntry.y = nTopAttach;
781 :
782 70458 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
783 : {
784 74152 : for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
785 : {
786 37076 : ExtendedGridEntry &rSpan = A[nLeftAttach+nSpanX][nTopAttach+nSpanY];
787 37076 : rSpan.x = nLeftAttach;
788 37076 : rSpan.y = nTopAttach;
789 : }
790 : }
791 : }
792 :
793 : //see if we have any empty rows/cols
794 7473 : sal_Int32 nMaxX = A.shape()[0];
795 7473 : sal_Int32 nMaxY = A.shape()[1];
796 :
797 14946 : std::vector<bool> aNonEmptyCols(nMaxX);
798 14946 : std::vector<bool> aNonEmptyRows(nMaxY);
799 :
800 29365 : for (sal_Int32 x = 0; x < nMaxX; ++x)
801 : {
802 58968 : for (sal_Int32 y = 0; y < nMaxY; ++y)
803 : {
804 37076 : const GridEntry &rEntry = A[x][y];
805 37076 : const vcl::Window *pChild = rEntry.pChild;
806 37076 : if (pChild && pChild->IsVisible())
807 : {
808 33382 : aNonEmptyCols[x] = true;
809 33382 : if (get_column_homogeneous())
810 : {
811 36464 : for (sal_Int32 nSpanX = 1; nSpanX < rEntry.nSpanWidth; ++nSpanX)
812 3694 : aNonEmptyCols[x+nSpanX] = true;
813 : }
814 33382 : aNonEmptyRows[y] = true;
815 33382 : if (get_row_homogeneous())
816 : {
817 0 : for (sal_Int32 nSpanY = 1; nSpanY < rEntry.nSpanHeight; ++nSpanY)
818 0 : aNonEmptyRows[y+nSpanY] = true;
819 : }
820 : }
821 : }
822 : }
823 :
824 7473 : if (!get_column_homogeneous())
825 : {
826 : //reduce the spans of elements that span empty columns
827 408 : for (sal_Int32 x = 0; x < nMaxX; ++x)
828 : {
829 204 : std::set<ExtendedGridEntry*> candidates;
830 816 : for (sal_Int32 y = 0; y < nMaxY; ++y)
831 : {
832 612 : if (aNonEmptyCols[x])
833 612 : continue;
834 0 : ExtendedGridEntry &rSpan = A[x][y];
835 : //cell x/y is spanned by the widget at cell rSpan.x/rSpan.y,
836 : //just points back to itself if there's no cell spanning
837 0 : if ((rSpan.x == -1) || (rSpan.y == -1))
838 : {
839 : //there is no entry for this cell, i.e. this is a cell
840 : //with no widget in it, or spanned by any other widget
841 0 : continue;
842 : }
843 0 : ExtendedGridEntry &rEntry = A[rSpan.x][rSpan.y];
844 0 : candidates.insert(&rEntry);
845 : }
846 204 : for (std::set<ExtendedGridEntry*>::iterator aI = candidates.begin(), aEnd = candidates.end();
847 : aI != aEnd; ++aI)
848 : {
849 0 : ExtendedGridEntry *pEntry = *aI;
850 0 : --pEntry->nSpanWidth;
851 : }
852 204 : }
853 : }
854 :
855 7473 : if (!get_row_homogeneous())
856 : {
857 : //reduce the spans of elements that span empty rows
858 22742 : for (sal_Int32 y = 0; y < nMaxY; ++y)
859 : {
860 15269 : std::set<ExtendedGridEntry*> candidates;
861 52345 : for (sal_Int32 x = 0; x < nMaxX; ++x)
862 : {
863 37076 : if (aNonEmptyRows[y])
864 37076 : continue;
865 0 : ExtendedGridEntry &rSpan = A[x][y];
866 : //cell x/y is spanned by the widget at cell rSpan.x/rSpan.y,
867 : //just points back to itself if there's no cell spanning
868 0 : if ((rSpan.x == -1) || (rSpan.y == -1))
869 : {
870 : //there is no entry for this cell, i.e. this is a cell
871 : //with no widget in it, or spanned by any other widget
872 0 : continue;
873 : }
874 0 : ExtendedGridEntry &rEntry = A[rSpan.x][rSpan.y];
875 0 : candidates.insert(&rEntry);
876 : }
877 15269 : for (std::set<ExtendedGridEntry*>::iterator aI = candidates.begin(), aEnd = candidates.end();
878 : aI != aEnd; ++aI)
879 : {
880 0 : ExtendedGridEntry *pEntry = *aI;
881 0 : --pEntry->nSpanHeight;
882 : }
883 15269 : }
884 : }
885 :
886 7473 : sal_Int32 nNonEmptyCols = std::count(aNonEmptyCols.begin(), aNonEmptyCols.end(), true);
887 7473 : sal_Int32 nNonEmptyRows = std::count(aNonEmptyRows.begin(), aNonEmptyRows.end(), true);
888 :
889 : //make new grid without empty rows and columns
890 7473 : array_type B(boost::extents[nNonEmptyCols][nNonEmptyRows]);
891 29365 : for (sal_Int32 x = 0, x2 = 0; x < nMaxX; ++x)
892 : {
893 21892 : if (aNonEmptyCols[x] == false)
894 0 : continue;
895 58968 : for (sal_Int32 y = 0, y2 = 0; y < nMaxY; ++y)
896 : {
897 37076 : if (aNonEmptyRows[y] == false)
898 0 : continue;
899 37076 : GridEntry &rEntry = A[x][y];
900 37076 : B[x2][y2++] = rEntry;
901 : }
902 21892 : ++x2;
903 : }
904 :
905 14946 : return B;
906 : }
907 :
908 7473 : bool VclGrid::isNullGrid(const array_type &A) const
909 : {
910 7473 : sal_Int32 nMaxX = A.shape()[0];
911 7473 : sal_Int32 nMaxY = A.shape()[1];
912 :
913 7473 : if (!nMaxX || !nMaxY)
914 0 : return true;
915 7473 : return false;
916 : }
917 :
918 7473 : void VclGrid::calcMaxs(const array_type &A, std::vector<Value> &rWidths, std::vector<Value> &rHeights) const
919 : {
920 7473 : sal_Int32 nMaxX = A.shape()[0];
921 7473 : sal_Int32 nMaxY = A.shape()[1];
922 :
923 7473 : rWidths.resize(nMaxX);
924 7473 : rHeights.resize(nMaxY);
925 :
926 : //first use the non spanning entries to set default width/heights
927 29365 : for (sal_Int32 x = 0; x < nMaxX; ++x)
928 : {
929 58968 : for (sal_Int32 y = 0; y < nMaxY; ++y)
930 : {
931 37076 : const GridEntry &rEntry = A[x][y];
932 37076 : const vcl::Window *pChild = rEntry.pChild;
933 37076 : if (!pChild || !pChild->IsVisible())
934 3694 : continue;
935 :
936 33382 : sal_Int32 nWidth = rEntry.nSpanWidth;
937 33382 : sal_Int32 nHeight = rEntry.nSpanHeight;
938 :
939 70458 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
940 37076 : rWidths[x+nSpanX].m_bExpand |= pChild->get_hexpand();
941 :
942 66764 : for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
943 33382 : rHeights[y+nSpanY].m_bExpand |= pChild->get_vexpand();
944 :
945 33382 : if (nWidth == 1 || nHeight == 1)
946 : {
947 33382 : Size aChildSize = getLayoutRequisition(*pChild);
948 33382 : if (nWidth == 1)
949 29688 : rWidths[x].m_nValue = std::max(rWidths[x].m_nValue, aChildSize.Width());
950 33382 : if (nHeight == 1)
951 33382 : rHeights[y].m_nValue = std::max(rHeights[y].m_nValue, aChildSize.Height());
952 : }
953 : }
954 : }
955 :
956 : //now use the spanning entries and split any extra sizes across expanding rows/cols
957 : //where possible
958 29365 : for (sal_Int32 x = 0; x < nMaxX; ++x)
959 : {
960 58968 : for (sal_Int32 y = 0; y < nMaxY; ++y)
961 : {
962 37076 : const GridEntry &rEntry = A[x][y];
963 37076 : const vcl::Window *pChild = rEntry.pChild;
964 37076 : if (!pChild || !pChild->IsVisible())
965 37076 : continue;
966 :
967 33382 : sal_Int32 nWidth = rEntry.nSpanWidth;
968 33382 : sal_Int32 nHeight = rEntry.nSpanHeight;
969 :
970 33382 : if (nWidth == 1 && nHeight == 1)
971 29688 : continue;
972 :
973 3694 : Size aChildSize = getLayoutRequisition(*pChild);
974 :
975 3694 : if (nWidth > 1)
976 : {
977 3694 : sal_Int32 nExistingWidth = 0;
978 11082 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
979 7388 : nExistingWidth += rWidths[x+nSpanX].m_nValue;
980 :
981 3694 : sal_Int32 nExtraWidth = aChildSize.Width() - nExistingWidth;
982 :
983 3694 : if (nExtraWidth > 0)
984 : {
985 4 : bool bForceExpandAll = false;
986 4 : sal_Int32 nExpandables = 0;
987 12 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
988 8 : if (rWidths[x+nSpanX].m_bExpand)
989 0 : ++nExpandables;
990 4 : if (nExpandables == 0)
991 : {
992 4 : nExpandables = nWidth;
993 4 : bForceExpandAll = true;
994 : }
995 :
996 12 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
997 : {
998 8 : if (rWidths[x+nSpanX].m_bExpand || bForceExpandAll)
999 8 : rWidths[x+nSpanX].m_nValue += nExtraWidth/nExpandables;
1000 : }
1001 : }
1002 : }
1003 :
1004 3694 : if (nHeight > 1)
1005 : {
1006 0 : sal_Int32 nExistingHeight = 0;
1007 0 : for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
1008 0 : nExistingHeight += rHeights[y+nSpanY].m_nValue;
1009 :
1010 0 : sal_Int32 nExtraHeight = aChildSize.Height() - nExistingHeight;
1011 :
1012 0 : if (nExtraHeight > 0)
1013 : {
1014 0 : bool bForceExpandAll = false;
1015 0 : sal_Int32 nExpandables = 0;
1016 0 : for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
1017 0 : if (rHeights[y+nSpanY].m_bExpand)
1018 0 : ++nExpandables;
1019 0 : if (nExpandables == 0)
1020 : {
1021 0 : nExpandables = nHeight;
1022 0 : bForceExpandAll = true;
1023 : }
1024 :
1025 0 : for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
1026 : {
1027 0 : if (rHeights[y+nSpanY].m_bExpand || bForceExpandAll)
1028 0 : rHeights[y+nSpanY].m_nValue += nExtraHeight/nExpandables;
1029 : }
1030 : }
1031 : }
1032 : }
1033 : }
1034 7473 : }
1035 :
1036 10796 : bool compareValues(const VclGrid::Value &i, const VclGrid::Value &j)
1037 : {
1038 10796 : return i.m_nValue < j.m_nValue;
1039 : }
1040 :
1041 10052 : VclGrid::Value accumulateValues(const VclGrid::Value &i, const VclGrid::Value &j)
1042 : {
1043 10052 : VclGrid::Value aRet;
1044 10052 : aRet.m_nValue = i.m_nValue + j.m_nValue;
1045 10052 : aRet.m_bExpand = i.m_bExpand || j.m_bExpand;
1046 10052 : return aRet;
1047 : }
1048 :
1049 3067 : Size VclGrid::calculateRequisition() const
1050 : {
1051 3067 : return calculateRequisitionForSpacings(get_row_spacing(), get_column_spacing());
1052 : }
1053 :
1054 5212 : Size VclGrid::calculateRequisitionForSpacings(sal_Int32 nRowSpacing, sal_Int32 nColSpacing) const
1055 : {
1056 5212 : array_type A = assembleGrid();
1057 :
1058 5212 : if (isNullGrid(A))
1059 0 : return Size();
1060 :
1061 10424 : std::vector<Value> aWidths;
1062 10424 : std::vector<Value> aHeights;
1063 5212 : calcMaxs(A, aWidths, aHeights);
1064 :
1065 5212 : long nTotalWidth = 0;
1066 5212 : if (get_column_homogeneous())
1067 : {
1068 5076 : nTotalWidth = std::max_element(aWidths.begin(), aWidths.end(), compareValues)->m_nValue;
1069 5076 : nTotalWidth *= aWidths.size();
1070 : }
1071 : else
1072 : {
1073 136 : nTotalWidth = std::accumulate(aWidths.begin(), aWidths.end(), Value(), accumulateValues).m_nValue;
1074 : }
1075 :
1076 5212 : nTotalWidth += nColSpacing * (aWidths.size()-1);
1077 :
1078 5212 : long nTotalHeight = 0;
1079 5212 : if (get_row_homogeneous())
1080 : {
1081 0 : nTotalHeight = std::max_element(aHeights.begin(), aHeights.end(), compareValues)->m_nValue;
1082 0 : nTotalHeight *= aHeights.size();
1083 : }
1084 : else
1085 : {
1086 5212 : nTotalHeight = std::accumulate(aHeights.begin(), aHeights.end(), Value(), accumulateValues).m_nValue;
1087 : }
1088 :
1089 5212 : nTotalHeight += nRowSpacing * (aHeights.size()-1);
1090 :
1091 10424 : return Size(nTotalWidth, nTotalHeight);
1092 : }
1093 :
1094 2261 : void VclGrid::setAllocation(const Size& rAllocation)
1095 : {
1096 2261 : array_type A = assembleGrid();
1097 :
1098 2261 : if (isNullGrid(A))
1099 2261 : return;
1100 :
1101 2261 : sal_Int32 nMaxX = A.shape()[0];
1102 2261 : sal_Int32 nMaxY = A.shape()[1];
1103 :
1104 2261 : Size aRequisition;
1105 4522 : std::vector<Value> aWidths(nMaxX);
1106 4522 : std::vector<Value> aHeights(nMaxY);
1107 2261 : if (!get_column_homogeneous() || !get_row_homogeneous())
1108 : {
1109 2261 : aRequisition = calculateRequisition();
1110 2261 : calcMaxs(A, aWidths, aHeights);
1111 : }
1112 :
1113 2261 : sal_Int32 nColSpacing(get_column_spacing());
1114 2261 : sal_Int32 nRowSpacing(get_row_spacing());
1115 :
1116 2261 : long nAvailableWidth = rAllocation.Width();
1117 2261 : if (nMaxX)
1118 2261 : nAvailableWidth -= nColSpacing * (nMaxX - 1);
1119 2261 : if (get_column_homogeneous())
1120 : {
1121 8009 : for (sal_Int32 x = 0; x < nMaxX; ++x)
1122 5816 : aWidths[x].m_nValue = nAvailableWidth/nMaxX;
1123 : }
1124 68 : else if (rAllocation.Width() != aRequisition.Width())
1125 : {
1126 0 : sal_Int32 nExpandables = 0;
1127 0 : for (sal_Int32 x = 0; x < nMaxX; ++x)
1128 0 : if (aWidths[x].m_bExpand)
1129 0 : ++nExpandables;
1130 0 : long nExtraWidthForExpanders = nExpandables ? (rAllocation.Width() - aRequisition.Width()) / nExpandables : 0;
1131 :
1132 : //We don't fit and there is no volunteer to be shrunk
1133 0 : if (!nExpandables && rAllocation.Width() < aRequisition.Width())
1134 : {
1135 : //first reduce spacing
1136 0 : while (nColSpacing)
1137 : {
1138 0 : nColSpacing /= 2;
1139 0 : aRequisition = calculateRequisitionForSpacings(nRowSpacing, nColSpacing);
1140 0 : if (aRequisition.Width() <= rAllocation.Width())
1141 0 : break;
1142 : }
1143 :
1144 : //share out the remaining pain to everyone
1145 0 : long nExtraWidth = (rAllocation.Width() - aRequisition.Width()) / nMaxX;
1146 :
1147 0 : for (sal_Int32 x = 0; x < nMaxX; ++x)
1148 0 : aWidths[x].m_nValue += nExtraWidth;
1149 : }
1150 :
1151 0 : if (nExtraWidthForExpanders)
1152 : {
1153 0 : for (sal_Int32 x = 0; x < nMaxX; ++x)
1154 0 : if (aWidths[x].m_bExpand)
1155 0 : aWidths[x].m_nValue += nExtraWidthForExpanders;
1156 : }
1157 : }
1158 :
1159 2261 : long nAvailableHeight = rAllocation.Height();
1160 2261 : if (nMaxY)
1161 2261 : nAvailableHeight -= nRowSpacing * (nMaxY - 1);
1162 2261 : if (get_row_homogeneous())
1163 : {
1164 0 : for (sal_Int32 y = 0; y < nMaxY; ++y)
1165 0 : aHeights[y].m_nValue = nAvailableHeight/nMaxY;
1166 : }
1167 2261 : else if (rAllocation.Height() != aRequisition.Height())
1168 : {
1169 715 : sal_Int32 nExpandables = 0;
1170 1430 : for (sal_Int32 y = 0; y < nMaxY; ++y)
1171 715 : if (aHeights[y].m_bExpand)
1172 0 : ++nExpandables;
1173 715 : long nExtraHeightForExpanders = nExpandables ? (rAllocation.Height() - aRequisition.Height()) / nExpandables : 0;
1174 :
1175 : //We don't fit and there is no volunteer to be shrunk
1176 715 : if (!nExpandables && rAllocation.Height() < aRequisition.Height())
1177 : {
1178 : //first reduce spacing
1179 3575 : while (nRowSpacing)
1180 : {
1181 2145 : nRowSpacing /= 2;
1182 2145 : aRequisition = calculateRequisitionForSpacings(nRowSpacing, nColSpacing);
1183 2145 : if (aRequisition.Height() <= rAllocation.Height())
1184 0 : break;
1185 : }
1186 :
1187 : //share out the remaining pain to everyone
1188 715 : long nExtraHeight = (rAllocation.Height() - aRequisition.Height()) / nMaxY;
1189 :
1190 1430 : for (sal_Int32 y = 0; y < nMaxY; ++y)
1191 715 : aHeights[y].m_nValue += nExtraHeight;
1192 : }
1193 :
1194 715 : if (nExtraHeightForExpanders)
1195 : {
1196 0 : for (sal_Int32 y = 0; y < nMaxY; ++y)
1197 0 : if (aHeights[y].m_bExpand)
1198 0 : aHeights[y].m_nValue += nExtraHeightForExpanders;
1199 : }
1200 : }
1201 :
1202 2261 : Point aAllocPos(0, 0);
1203 8145 : for (sal_Int32 x = 0; x < nMaxX; ++x)
1204 : {
1205 17816 : for (sal_Int32 y = 0; y < nMaxY; ++y)
1206 : {
1207 11932 : GridEntry &rEntry = A[x][y];
1208 11932 : vcl::Window *pChild = rEntry.pChild;
1209 11932 : if (pChild)
1210 : {
1211 10454 : Size aChildAlloc(0, 0);
1212 :
1213 10454 : sal_Int32 nWidth = rEntry.nSpanWidth;
1214 22386 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
1215 11932 : aChildAlloc.Width() += aWidths[x+nSpanX].m_nValue;
1216 10454 : aChildAlloc.Width() += nColSpacing*(nWidth-1);
1217 :
1218 10454 : sal_Int32 nHeight = rEntry.nSpanHeight;
1219 20908 : for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
1220 10454 : aChildAlloc.Height() += aHeights[y+nSpanY].m_nValue;
1221 10454 : aChildAlloc.Height() += nRowSpacing*(nHeight-1);
1222 :
1223 10454 : setLayoutAllocation(*pChild, aAllocPos, aChildAlloc);
1224 : }
1225 11932 : aAllocPos.Y() += aHeights[y].m_nValue + nRowSpacing;
1226 : }
1227 5884 : aAllocPos.X() += aWidths[x].m_nValue + nColSpacing;
1228 5884 : aAllocPos.Y() = 0;
1229 2261 : }
1230 : }
1231 :
1232 76872 : bool toBool(const OString &rValue)
1233 : {
1234 76872 : return (!rValue.isEmpty() && (rValue[0] == 't' || rValue[0] == 'T' || rValue[0] == '1'));
1235 : }
1236 :
1237 9792 : bool VclGrid::set_property(const OString &rKey, const OString &rValue)
1238 : {
1239 9792 : if (rKey == "row-spacing")
1240 1514 : set_row_spacing(rValue.toInt32());
1241 8278 : else if (rKey == "column-spacing")
1242 1480 : set_column_spacing(rValue.toInt32());
1243 6798 : else if (rKey == "row-homogeneous")
1244 0 : set_row_homogeneous(toBool(rValue));
1245 6798 : else if (rKey == "column-homogeneous")
1246 1480 : set_column_homogeneous(toBool(rValue));
1247 5318 : else if (rKey == "n-rows")
1248 : /*nothing to do*/;
1249 : else
1250 5318 : return VclContainer::set_property(rKey, rValue);
1251 4474 : return true;
1252 : }
1253 :
1254 0 : void setGridAttach(vcl::Window &rWidget, sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nWidth, sal_Int32 nHeight)
1255 : {
1256 0 : rWidget.set_grid_left_attach(nLeft);
1257 0 : rWidget.set_grid_top_attach(nTop);
1258 0 : rWidget.set_grid_width(nWidth);
1259 0 : rWidget.set_grid_height(nHeight);
1260 0 : }
1261 :
1262 0 : const vcl::Window *VclBin::get_child() const
1263 : {
1264 0 : const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1265 :
1266 0 : return pWindowImpl->mpFirstChild;
1267 : }
1268 :
1269 0 : vcl::Window *VclBin::get_child()
1270 : {
1271 0 : return const_cast<vcl::Window*>(const_cast<const VclBin*>(this)->get_child());
1272 : }
1273 :
1274 0 : Size VclBin::calculateRequisition() const
1275 : {
1276 0 : const vcl::Window *pChild = get_child();
1277 0 : if (pChild && pChild->IsVisible())
1278 0 : return getLayoutRequisition(*pChild);
1279 0 : return Size(0, 0);
1280 : }
1281 :
1282 0 : void VclBin::setAllocation(const Size &rAllocation)
1283 : {
1284 0 : vcl::Window *pChild = get_child();
1285 0 : if (pChild && pChild->IsVisible())
1286 0 : setLayoutAllocation(*pChild, Point(0, 0), rAllocation);
1287 0 : }
1288 :
1289 : //To-Do, hook a DecorationView into VclFrame ?
1290 :
1291 0 : Size VclFrame::calculateRequisition() const
1292 : {
1293 0 : Size aRet(0, 0);
1294 :
1295 0 : const vcl::Window *pChild = get_child();
1296 0 : const vcl::Window *pLabel = get_label_widget();
1297 :
1298 0 : if (pChild && pChild->IsVisible())
1299 0 : aRet = getLayoutRequisition(*pChild);
1300 :
1301 0 : if (pLabel && pLabel->IsVisible())
1302 : {
1303 0 : Size aLabelSize = getLayoutRequisition(*pLabel);
1304 0 : aRet.Height() += aLabelSize.Height();
1305 0 : aRet.Width() = std::max(aLabelSize.Width(), aRet.Width());
1306 : }
1307 :
1308 : const FrameStyle &rFrameStyle =
1309 0 : GetSettings().GetStyleSettings().GetFrameStyle();
1310 0 : aRet.Width() += rFrameStyle.left + rFrameStyle.right;
1311 0 : aRet.Height() += rFrameStyle.top + rFrameStyle.bottom;
1312 :
1313 0 : return aRet;
1314 : }
1315 :
1316 0 : void VclFrame::setAllocation(const Size &rAllocation)
1317 : {
1318 : //SetBackground( Color(0xFF, 0x00, 0xFF) );
1319 :
1320 : const FrameStyle &rFrameStyle =
1321 0 : GetSettings().GetStyleSettings().GetFrameStyle();
1322 0 : Size aAllocation(rAllocation.Width() - rFrameStyle.left - rFrameStyle.right,
1323 0 : rAllocation.Height() - rFrameStyle.top - rFrameStyle.bottom);
1324 0 : Point aChildPos(rFrameStyle.left, rFrameStyle.top);
1325 :
1326 0 : vcl::Window *pChild = get_child();
1327 0 : vcl::Window *pLabel = get_label_widget();
1328 :
1329 0 : if (pLabel && pLabel->IsVisible())
1330 : {
1331 0 : Size aLabelSize = getLayoutRequisition(*pLabel);
1332 0 : aLabelSize.Height() = std::min(aLabelSize.Height(), aAllocation.Height());
1333 0 : aLabelSize.Width() = std::min(aLabelSize.Width(), aAllocation.Width());
1334 0 : setLayoutAllocation(*pLabel, aChildPos, aLabelSize);
1335 0 : aAllocation.Height() -= aLabelSize.Height();
1336 0 : aChildPos.Y() += aLabelSize.Height();
1337 : }
1338 :
1339 0 : if (pChild && pChild->IsVisible())
1340 0 : setLayoutAllocation(*pChild, aChildPos, aAllocation);
1341 0 : }
1342 :
1343 0 : IMPL_LINK(VclFrame, WindowEventListener, VclSimpleEvent*, pEvent)
1344 : {
1345 0 : if (pEvent && pEvent->GetId() == VCLEVENT_OBJECT_DYING)
1346 0 : designate_label(NULL);
1347 0 : return 0;
1348 : }
1349 :
1350 0 : void VclFrame::designate_label(vcl::Window *pWindow)
1351 : {
1352 : assert(!pWindow || pWindow->GetParent() == this);
1353 0 : if (m_pLabel)
1354 0 : m_pLabel->RemoveEventListener(LINK(this, VclFrame, WindowEventListener));
1355 0 : m_pLabel = pWindow;
1356 0 : if (m_pLabel)
1357 0 : m_pLabel->AddEventListener(LINK(this, VclFrame, WindowEventListener));
1358 0 : }
1359 :
1360 0 : const vcl::Window *VclFrame::get_label_widget() const
1361 : {
1362 : assert(GetChildCount() == 2);
1363 0 : if (m_pLabel)
1364 0 : return m_pLabel;
1365 : //The label widget is normally the first (of two) children
1366 0 : const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1367 0 : if (pWindowImpl->mpFirstChild == pWindowImpl->mpLastChild) //no label exists
1368 0 : return NULL;
1369 0 : return pWindowImpl->mpFirstChild;
1370 : }
1371 :
1372 0 : vcl::Window *VclFrame::get_label_widget()
1373 : {
1374 0 : return const_cast<vcl::Window*>(const_cast<const VclFrame*>(this)->get_label_widget());
1375 : }
1376 :
1377 0 : const vcl::Window *VclFrame::get_child() const
1378 : {
1379 : assert(GetChildCount() == 2);
1380 : //The child widget is the normally the last (of two) children
1381 0 : const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1382 0 : if (!m_pLabel)
1383 0 : return pWindowImpl->mpLastChild;
1384 0 : if (pWindowImpl->mpFirstChild == pWindowImpl->mpLastChild) //only label exists
1385 0 : return NULL;
1386 0 : return pWindowImpl->mpLastChild;
1387 : }
1388 :
1389 0 : vcl::Window *VclFrame::get_child()
1390 : {
1391 0 : return const_cast<vcl::Window*>(const_cast<const VclFrame*>(this)->get_child());
1392 : }
1393 :
1394 0 : void VclFrame::set_label(const OUString &rLabel)
1395 : {
1396 0 : vcl::Window *pLabel = get_label_widget();
1397 : assert(pLabel);
1398 0 : pLabel->SetText(rLabel);
1399 0 : }
1400 :
1401 0 : OUString VclFrame::get_label() const
1402 : {
1403 0 : const vcl::Window *pLabel = get_label_widget();
1404 : assert(pLabel);
1405 0 : return pLabel->GetText();
1406 : }
1407 :
1408 0 : OUString VclFrame::getDefaultAccessibleName() const
1409 : {
1410 0 : const vcl::Window *pLabel = get_label_widget();
1411 0 : if (pLabel)
1412 0 : return pLabel->GetAccessibleName();
1413 0 : return VclBin::getDefaultAccessibleName();
1414 : }
1415 :
1416 0 : Size VclAlignment::calculateRequisition() const
1417 : {
1418 0 : Size aRet(m_nLeftPadding + m_nRightPadding,
1419 0 : m_nTopPadding + m_nBottomPadding);
1420 :
1421 0 : const vcl::Window *pChild = get_child();
1422 0 : if (pChild && pChild->IsVisible())
1423 : {
1424 0 : Size aChildSize = getLayoutRequisition(*pChild);
1425 0 : aRet.Width() += aChildSize.Width();
1426 0 : aRet.Height() += aChildSize.Height();
1427 : }
1428 :
1429 0 : return aRet;
1430 : }
1431 :
1432 0 : void VclAlignment::setAllocation(const Size &rAllocation)
1433 : {
1434 0 : vcl::Window *pChild = get_child();
1435 0 : if (!pChild || !pChild->IsVisible())
1436 0 : return;
1437 :
1438 0 : Point aChildPos(m_nLeftPadding, m_nTopPadding);
1439 :
1440 0 : Size aAllocation;
1441 0 : aAllocation.Width() = rAllocation.Width() - (m_nLeftPadding + m_nRightPadding);
1442 0 : aAllocation.Height() = rAllocation.Height() - (m_nTopPadding + m_nBottomPadding);
1443 :
1444 0 : setLayoutAllocation(*pChild, aChildPos, aAllocation);
1445 : }
1446 :
1447 0 : bool VclAlignment::set_property(const OString &rKey, const OString &rValue)
1448 : {
1449 0 : if (rKey == "bottom-padding")
1450 0 : m_nBottomPadding = rValue.toInt32();
1451 0 : else if (rKey == "left-padding")
1452 0 : m_nLeftPadding = rValue.toInt32();
1453 0 : else if (rKey == "right-padding")
1454 0 : m_nRightPadding = rValue.toInt32();
1455 0 : else if (rKey == "top-padding")
1456 0 : m_nTopPadding = rValue.toInt32();
1457 0 : else if (rKey == "xalign")
1458 0 : m_fXAlign = rValue.toFloat();
1459 0 : else if (rKey == "xscale")
1460 0 : m_fXScale = rValue.toFloat();
1461 0 : else if (rKey == "yalign")
1462 0 : m_fYAlign = rValue.toFloat();
1463 0 : else if (rKey == "yscale")
1464 0 : m_fYScale = rValue.toFloat();
1465 : else
1466 0 : return VclBin::set_property(rKey, rValue);
1467 0 : return true;
1468 : }
1469 :
1470 0 : const vcl::Window *VclExpander::get_child() const
1471 : {
1472 0 : const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1473 :
1474 : assert(pWindowImpl->mpFirstChild == m_pDisclosureButton.get());
1475 :
1476 0 : return pWindowImpl->mpFirstChild->GetWindow(WINDOW_NEXT);
1477 : }
1478 :
1479 0 : vcl::Window *VclExpander::get_child()
1480 : {
1481 0 : return const_cast<vcl::Window*>(const_cast<const VclExpander*>(this)->get_child());
1482 : }
1483 :
1484 0 : Size VclExpander::calculateRequisition() const
1485 : {
1486 0 : Size aRet(0, 0);
1487 :
1488 0 : WindowImpl* pWindowImpl = ImplGetWindowImpl();
1489 :
1490 0 : const vcl::Window *pChild = get_child();
1491 0 : const vcl::Window *pLabel = pChild != pWindowImpl->mpLastChild ? pWindowImpl->mpLastChild : NULL;
1492 :
1493 0 : if (pChild && pChild->IsVisible() && m_pDisclosureButton->IsChecked())
1494 0 : aRet = getLayoutRequisition(*pChild);
1495 :
1496 0 : Size aExpanderSize = getLayoutRequisition(*m_pDisclosureButton.get());
1497 :
1498 0 : if (pLabel && pLabel->IsVisible())
1499 : {
1500 0 : Size aLabelSize = getLayoutRequisition(*pLabel);
1501 0 : aExpanderSize.Height() = std::max(aExpanderSize.Height(), aLabelSize.Height());
1502 0 : aExpanderSize.Width() += aLabelSize.Width();
1503 : }
1504 :
1505 0 : aRet.Height() += aExpanderSize.Height();
1506 0 : aRet.Width() = std::max(aExpanderSize.Width(), aRet.Width());
1507 :
1508 : const FrameStyle &rFrameStyle =
1509 0 : GetSettings().GetStyleSettings().GetFrameStyle();
1510 0 : aRet.Width() += rFrameStyle.left + rFrameStyle.right;
1511 0 : aRet.Height() += rFrameStyle.top + rFrameStyle.bottom;
1512 :
1513 0 : return aRet;
1514 : }
1515 :
1516 0 : void VclExpander::setAllocation(const Size &rAllocation)
1517 : {
1518 : const FrameStyle &rFrameStyle =
1519 0 : GetSettings().GetStyleSettings().GetFrameStyle();
1520 0 : Size aAllocation(rAllocation.Width() - rFrameStyle.left - rFrameStyle.right,
1521 0 : rAllocation.Height() - rFrameStyle.top - rFrameStyle.bottom);
1522 0 : Point aChildPos(rFrameStyle.left, rFrameStyle.top);
1523 :
1524 0 : WindowImpl* pWindowImpl = ImplGetWindowImpl();
1525 :
1526 : //The label widget is the last (of two) children
1527 0 : vcl::Window *pChild = get_child();
1528 0 : vcl::Window *pLabel = pChild != pWindowImpl->mpLastChild ? pWindowImpl->mpLastChild : NULL;
1529 :
1530 0 : Size aButtonSize = getLayoutRequisition(*m_pDisclosureButton.get());
1531 0 : Size aLabelSize;
1532 0 : Size aExpanderSize = aButtonSize;
1533 0 : if (pLabel && pLabel->IsVisible())
1534 : {
1535 0 : aLabelSize = getLayoutRequisition(*pLabel);
1536 0 : aExpanderSize.Height() = std::max(aExpanderSize.Height(), aLabelSize.Height());
1537 0 : aExpanderSize.Width() += aLabelSize.Width();
1538 : }
1539 :
1540 0 : aExpanderSize.Height() = std::min(aExpanderSize.Height(), aAllocation.Height());
1541 0 : aExpanderSize.Width() = std::min(aExpanderSize.Width(), aAllocation.Width());
1542 :
1543 0 : aButtonSize.Height() = std::min(aButtonSize.Height(), aExpanderSize.Height());
1544 0 : aButtonSize.Width() = std::min(aButtonSize.Width(), aExpanderSize.Width());
1545 :
1546 0 : long nExtraExpanderHeight = aExpanderSize.Height() - aButtonSize.Height();
1547 0 : Point aButtonPos(aChildPos.X(), aChildPos.Y() + nExtraExpanderHeight/2);
1548 0 : setLayoutAllocation(*m_pDisclosureButton.get(), aButtonPos, aButtonSize);
1549 :
1550 0 : if (pLabel && pLabel->IsVisible())
1551 : {
1552 0 : aLabelSize.Height() = std::min(aLabelSize.Height(), aExpanderSize.Height());
1553 0 : aLabelSize.Width() = std::min(aLabelSize.Width(),
1554 0 : aExpanderSize.Width() - aButtonSize.Width());
1555 :
1556 0 : long nExtraLabelHeight = aExpanderSize.Height() - aLabelSize.Height();
1557 0 : Point aLabelPos(aChildPos.X() + aButtonSize.Width(), aChildPos.Y() + nExtraLabelHeight/2);
1558 0 : setLayoutAllocation(*pLabel, aLabelPos, aLabelSize);
1559 : }
1560 :
1561 0 : aAllocation.Height() -= aExpanderSize.Height();
1562 0 : aChildPos.Y() += aExpanderSize.Height();
1563 :
1564 0 : if (pChild && pChild->IsVisible())
1565 : {
1566 0 : if (!m_pDisclosureButton->IsChecked())
1567 0 : aAllocation = Size();
1568 0 : setLayoutAllocation(*pChild, aChildPos, aAllocation);
1569 : }
1570 0 : }
1571 :
1572 0 : bool VclExpander::set_property(const OString &rKey, const OString &rValue)
1573 : {
1574 0 : if (rKey == "expanded")
1575 0 : set_expanded(toBool(rValue));
1576 0 : else if (rKey == "resize-toplevel")
1577 0 : m_bResizeTopLevel = toBool(rValue);
1578 : else
1579 0 : return VclBin::set_property(rKey, rValue);
1580 0 : return true;
1581 : }
1582 :
1583 0 : void VclExpander::StateChanged(StateChangedType nType)
1584 : {
1585 0 : VclBin::StateChanged( nType );
1586 :
1587 0 : if (nType == StateChangedType::INITSHOW)
1588 : {
1589 0 : vcl::Window *pChild = get_child();
1590 0 : if (pChild)
1591 0 : pChild->Show(m_pDisclosureButton->IsChecked());
1592 : }
1593 0 : }
1594 :
1595 0 : IMPL_LINK( VclExpander, ClickHdl, DisclosureButton*, pBtn )
1596 : {
1597 0 : vcl::Window *pChild = get_child();
1598 0 : if (pChild)
1599 : {
1600 0 : pChild->Show(pBtn->IsChecked());
1601 0 : queue_resize();
1602 0 : Dialog* pResizeDialog = m_bResizeTopLevel ? GetParentDialog() : NULL;
1603 0 : if (pResizeDialog)
1604 0 : pResizeDialog->setOptimalLayoutSize();
1605 : }
1606 0 : maExpandedHdl.Call(this);
1607 0 : return 0;
1608 : }
1609 :
1610 0 : VclScrolledWindow::VclScrolledWindow(vcl::Window *pParent, WinBits nStyle)
1611 : : VclBin(pParent, nStyle)
1612 : , m_bUserManagedScrolling(false)
1613 0 : , m_pVScroll(new ScrollBar(this, WB_HIDE | WB_VERT))
1614 0 : , m_pHScroll(new ScrollBar(this, WB_HIDE | WB_HORZ))
1615 0 : , m_aScrollBarBox(this, WB_HIDE)
1616 : {
1617 0 : SetType(WINDOW_SCROLLWINDOW);
1618 :
1619 0 : Link aLink( LINK( this, VclScrolledWindow, ScrollBarHdl ) );
1620 0 : m_pVScroll->SetScrollHdl(aLink);
1621 0 : m_pHScroll->SetScrollHdl(aLink);
1622 0 : }
1623 :
1624 0 : IMPL_LINK_NOARG(VclScrolledWindow, ScrollBarHdl)
1625 : {
1626 0 : vcl::Window *pChild = get_child();
1627 0 : if (!pChild)
1628 0 : return 1;
1629 :
1630 : assert(dynamic_cast<VclViewport*>(pChild) && "scrolledwindow child should be a Viewport");
1631 :
1632 0 : pChild = pChild->GetWindow(WINDOW_FIRSTCHILD);
1633 :
1634 0 : if (!pChild)
1635 0 : return 1;
1636 :
1637 0 : Point aWinPos;
1638 :
1639 0 : if (m_pHScroll->IsVisible())
1640 : {
1641 0 : aWinPos.X() = -m_pHScroll->GetThumbPos();
1642 : }
1643 :
1644 0 : if (m_pVScroll->IsVisible())
1645 : {
1646 0 : aWinPos.Y() = -m_pVScroll->GetThumbPos();
1647 : }
1648 :
1649 0 : pChild->SetPosPixel(aWinPos);
1650 :
1651 0 : return 1;
1652 : }
1653 :
1654 0 : const vcl::Window *VclScrolledWindow::get_child() const
1655 : {
1656 : assert(GetChildCount() == 4);
1657 0 : const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1658 0 : return pWindowImpl->mpLastChild;
1659 : }
1660 :
1661 0 : vcl::Window *VclScrolledWindow::get_child()
1662 : {
1663 0 : return const_cast<vcl::Window*>(const_cast<const VclScrolledWindow*>(this)->get_child());
1664 : }
1665 :
1666 0 : Size VclScrolledWindow::calculateRequisition() const
1667 : {
1668 0 : Size aRet(0, 0);
1669 :
1670 0 : const vcl::Window *pChild = get_child();
1671 0 : if (pChild && pChild->IsVisible())
1672 0 : aRet = getLayoutRequisition(*pChild);
1673 :
1674 0 : if (GetStyle() & WB_VSCROLL)
1675 0 : aRet.Width() += getLayoutRequisition(*m_pVScroll.get()).Width();
1676 :
1677 0 : if (GetStyle() & WB_HSCROLL)
1678 0 : aRet.Height() += getLayoutRequisition(*m_pHScroll.get()).Height();
1679 :
1680 0 : return aRet;
1681 : }
1682 :
1683 0 : void VclScrolledWindow::InitScrollBars(const Size &rRequest)
1684 : {
1685 0 : const vcl::Window *pChild = get_child();
1686 0 : if (!pChild || !pChild->IsVisible())
1687 0 : return;
1688 :
1689 0 : Size aOutSize(getVisibleChildSize());
1690 :
1691 0 : if (m_pVScroll->IsVisible())
1692 : {
1693 0 : m_pVScroll->SetRangeMax(rRequest.Height());
1694 0 : m_pVScroll->SetVisibleSize(aOutSize.Height());
1695 0 : m_pVScroll->SetPageSize(16);
1696 : }
1697 :
1698 0 : if (m_pHScroll->IsVisible())
1699 : {
1700 0 : m_pHScroll->SetRangeMax(rRequest.Width());
1701 0 : m_pHScroll->SetVisibleSize(aOutSize.Width());
1702 0 : m_pHScroll->SetPageSize(16);
1703 : }
1704 : }
1705 :
1706 0 : void VclScrolledWindow::setAllocation(const Size &rAllocation)
1707 : {
1708 0 : Size aChildAllocation(rAllocation);
1709 0 : Size aChildReq;
1710 :
1711 0 : vcl::Window *pChild = get_child();
1712 0 : if (pChild && pChild->IsVisible())
1713 0 : aChildReq = getLayoutRequisition(*pChild);
1714 :
1715 0 : long nAvailHeight = rAllocation.Height();
1716 0 : long nAvailWidth = rAllocation.Width();
1717 : // vert. ScrollBar
1718 0 : if (GetStyle() & WB_AUTOVSCROLL)
1719 : {
1720 0 : m_pVScroll->Show(nAvailHeight < aChildReq.Height());
1721 : }
1722 :
1723 0 : if (m_pVScroll->IsVisible())
1724 0 : nAvailWidth -= getLayoutRequisition(*m_pVScroll.get()).Width();
1725 :
1726 : // horz. ScrollBar
1727 0 : if (GetStyle() & WB_AUTOHSCROLL)
1728 : {
1729 0 : bool bShowHScroll = nAvailWidth < aChildReq.Width();
1730 0 : m_pHScroll->Show(bShowHScroll);
1731 :
1732 0 : if (bShowHScroll)
1733 0 : nAvailHeight -= getLayoutRequisition(*m_pHScroll.get()).Height();
1734 :
1735 0 : if (GetStyle() & WB_AUTOVSCROLL)
1736 0 : m_pVScroll->Show(nAvailHeight < aChildReq.Height());
1737 : }
1738 :
1739 0 : Size aInnerSize(aChildAllocation);
1740 0 : long nScrollBarWidth = 0, nScrollBarHeight = 0;
1741 :
1742 0 : if (m_pVScroll->IsVisible())
1743 : {
1744 0 : nScrollBarWidth = getLayoutRequisition(*m_pVScroll.get()).Width();
1745 0 : Point aScrollPos(rAllocation.Width() - nScrollBarWidth, 0);
1746 0 : Size aScrollSize(nScrollBarWidth, rAllocation.Height());
1747 0 : setLayoutAllocation(*m_pVScroll.get(), aScrollPos, aScrollSize);
1748 0 : aChildAllocation.Width() -= nScrollBarWidth;
1749 0 : aInnerSize.Width() -= nScrollBarWidth;
1750 0 : aChildAllocation.Height() = aChildReq.Height();
1751 : }
1752 :
1753 0 : if (m_pHScroll->IsVisible())
1754 : {
1755 0 : nScrollBarHeight = getLayoutRequisition(*m_pHScroll.get()).Height();
1756 0 : Point aScrollPos(0, rAllocation.Height() - nScrollBarHeight);
1757 0 : Size aScrollSize(rAllocation.Width(), nScrollBarHeight);
1758 0 : setLayoutAllocation(*m_pHScroll.get(), aScrollPos, aScrollSize);
1759 0 : aChildAllocation.Height() -= nScrollBarHeight;
1760 0 : aInnerSize.Height() -= nScrollBarHeight;
1761 0 : aChildAllocation.Width() = aChildReq.Width();
1762 : }
1763 :
1764 0 : if (m_pVScroll->IsVisible() && m_pHScroll->IsVisible())
1765 : {
1766 0 : Point aBoxPos(aInnerSize.Width(), aInnerSize.Height());
1767 0 : m_aScrollBarBox.SetPosSizePixel(aBoxPos, Size(nScrollBarWidth, nScrollBarHeight));
1768 0 : m_aScrollBarBox.Show();
1769 : }
1770 : else
1771 : {
1772 0 : m_aScrollBarBox.Hide();
1773 : }
1774 :
1775 0 : if (pChild && pChild->IsVisible())
1776 : {
1777 : assert(dynamic_cast<VclViewport*>(pChild) && "scrolledwindow child should be a Viewport");
1778 0 : setLayoutAllocation(*pChild, Point(0, 0), aInnerSize);
1779 : }
1780 :
1781 0 : if (!m_bUserManagedScrolling)
1782 0 : InitScrollBars(aChildReq);
1783 0 : }
1784 :
1785 0 : Size VclScrolledWindow::getVisibleChildSize() const
1786 : {
1787 0 : Size aRet(GetSizePixel());
1788 0 : if (m_pVScroll->IsVisible())
1789 0 : aRet.Width() -= m_pVScroll->GetSizePixel().Width();
1790 0 : if (m_pHScroll->IsVisible())
1791 0 : aRet.Height() -= m_pHScroll->GetSizePixel().Height();
1792 0 : return aRet;
1793 : }
1794 :
1795 0 : bool VclScrolledWindow::set_property(const OString &rKey, const OString &rValue)
1796 : {
1797 0 : bool bRet = VclBin::set_property(rKey, rValue);
1798 0 : m_pVScroll->Show((GetStyle() & WB_VSCROLL) != 0);
1799 0 : m_pHScroll->Show((GetStyle() & WB_HSCROLL) != 0);
1800 0 : return bRet;
1801 : }
1802 :
1803 0 : bool VclScrolledWindow::Notify(NotifyEvent& rNEvt)
1804 : {
1805 0 : bool nDone = false;
1806 0 : if ( rNEvt.GetType() == EVENT_COMMAND )
1807 : {
1808 0 : const CommandEvent& rCEvt = *rNEvt.GetCommandEvent();
1809 0 : if ( rCEvt.GetCommand() == COMMAND_WHEEL )
1810 : {
1811 0 : const CommandWheelData* pData = rCEvt.GetWheelData();
1812 0 : if( !pData->GetModifier() && ( pData->GetMode() == CommandWheelMode::SCROLL ) )
1813 : {
1814 0 : nDone = HandleScrollCommand(rCEvt, m_pHScroll.get(), m_pVScroll.get());
1815 : }
1816 : }
1817 : }
1818 :
1819 0 : return nDone || VclBin::Notify( rNEvt );
1820 : }
1821 :
1822 0 : void VclViewport::setAllocation(const Size &rAllocation)
1823 : {
1824 0 : vcl::Window *pChild = get_child();
1825 0 : if (pChild && pChild->IsVisible())
1826 : {
1827 0 : Size aReq(getLayoutRequisition(*pChild));
1828 0 : aReq.Width() = std::max(aReq.Width(), rAllocation.Width());
1829 0 : aReq.Height() = std::max(aReq.Height(), rAllocation.Height());
1830 0 : setLayoutAllocation(*pChild, Point(0, 0), aReq);
1831 : }
1832 0 : }
1833 :
1834 0 : const vcl::Window *VclEventBox::get_child() const
1835 : {
1836 0 : const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1837 :
1838 : assert(pWindowImpl->mpFirstChild == &m_aEventBoxHelper);
1839 :
1840 0 : return pWindowImpl->mpFirstChild->GetWindow(WINDOW_NEXT);
1841 : }
1842 :
1843 0 : vcl::Window *VclEventBox::get_child()
1844 : {
1845 0 : return const_cast<vcl::Window*>(const_cast<const VclEventBox*>(this)->get_child());
1846 : }
1847 :
1848 0 : void VclEventBox::setAllocation(const Size& rAllocation)
1849 : {
1850 0 : Point aChildPos(0, 0);
1851 0 : for (vcl::Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
1852 : {
1853 0 : if (!pChild->IsVisible())
1854 0 : continue;
1855 0 : setLayoutAllocation(*pChild, aChildPos, rAllocation);
1856 : }
1857 0 : }
1858 :
1859 0 : Size VclEventBox::calculateRequisition() const
1860 : {
1861 0 : Size aRet(0, 0);
1862 :
1863 0 : for (const vcl::Window* pChild = get_child(); pChild;
1864 : pChild = pChild->GetWindow(WINDOW_NEXT))
1865 : {
1866 0 : if (!pChild->IsVisible())
1867 0 : continue;
1868 0 : Size aChildSize = getLayoutRequisition(*pChild);
1869 0 : aRet.Width() = std::max(aRet.Width(), aChildSize.Width());
1870 0 : aRet.Height() = std::max(aRet.Height(), aChildSize.Height());
1871 : }
1872 :
1873 0 : return aRet;
1874 : }
1875 :
1876 0 : void VclEventBox::Command(const CommandEvent&)
1877 : {
1878 : //discard events by default to block them reaching children
1879 0 : }
1880 :
1881 738 : void VclSizeGroup::trigger_queue_resize()
1882 : {
1883 : //sufficient to trigger one widget to trigger all of them
1884 738 : if (!m_aWindows.empty())
1885 : {
1886 0 : vcl::Window *pWindow = *m_aWindows.begin();
1887 0 : pWindow->queue_resize();
1888 : }
1889 738 : }
1890 :
1891 0 : void VclSizeGroup::set_ignore_hidden(bool bIgnoreHidden)
1892 : {
1893 0 : if (bIgnoreHidden != m_bIgnoreHidden)
1894 : {
1895 0 : m_bIgnoreHidden = bIgnoreHidden;
1896 0 : trigger_queue_resize();
1897 : }
1898 0 : }
1899 :
1900 738 : void VclSizeGroup::set_mode(VclSizeGroupMode eMode)
1901 : {
1902 738 : if (eMode != m_eMode)
1903 : {
1904 738 : m_eMode = eMode;
1905 738 : trigger_queue_resize();
1906 : }
1907 :
1908 738 : }
1909 :
1910 738 : bool VclSizeGroup::set_property(const OString &rKey, const OString &rValue)
1911 : {
1912 738 : if (rKey == "ignore-hidden")
1913 0 : set_ignore_hidden(toBool(rValue));
1914 738 : else if (rKey == "mode")
1915 : {
1916 738 : VclSizeGroupMode eMode = VCL_SIZE_GROUP_HORIZONTAL;
1917 738 : if (rValue.equals("none"))
1918 0 : eMode = VCL_SIZE_GROUP_NONE;
1919 738 : else if (rValue.equals("horizontal"))
1920 0 : eMode = VCL_SIZE_GROUP_HORIZONTAL;
1921 738 : else if (rValue.equals("vertical"))
1922 738 : eMode = VCL_SIZE_GROUP_VERTICAL;
1923 0 : else if (rValue.equals("both"))
1924 0 : eMode = VCL_SIZE_GROUP_BOTH;
1925 : else
1926 : {
1927 : SAL_WARN("vcl.layout", "unknown size group mode" << rValue.getStr());
1928 : }
1929 738 : set_mode(eMode);
1930 : }
1931 : else
1932 : {
1933 : SAL_INFO("vcl.layout", "unhandled property: " << rKey.getStr());
1934 0 : return false;
1935 : }
1936 738 : return true;
1937 : }
1938 :
1939 0 : void MessageDialog::create_owned_areas()
1940 : {
1941 0 : set_border_width(12);
1942 0 : m_pOwnedContentArea = new VclVBox(this, false, 24);
1943 0 : set_content_area(m_pOwnedContentArea);
1944 0 : m_pOwnedContentArea->Show();
1945 0 : m_pOwnedActionArea = new VclHButtonBox(m_pOwnedContentArea);
1946 0 : set_action_area(m_pOwnedActionArea);
1947 0 : m_pOwnedActionArea->Show();
1948 0 : }
1949 :
1950 0 : MessageDialog::MessageDialog(vcl::Window* pParent, WinBits nStyle)
1951 : : Dialog(pParent, nStyle)
1952 : , m_eButtonsType(VCL_BUTTONS_NONE)
1953 : , m_eMessageType(VCL_MESSAGE_INFO)
1954 : , m_pOwnedContentArea(NULL)
1955 : , m_pOwnedActionArea(NULL)
1956 : , m_pGrid(NULL)
1957 : , m_pImage(NULL)
1958 : , m_pPrimaryMessage(NULL)
1959 0 : , m_pSecondaryMessage(NULL)
1960 : {
1961 0 : SetType(WINDOW_MESSBOX);
1962 0 : }
1963 :
1964 0 : MessageDialog::MessageDialog(vcl::Window* pParent,
1965 : const OUString &rMessage,
1966 : VclMessageType eMessageType,
1967 : VclButtonsType eButtonsType,
1968 : WinBits nStyle)
1969 : : Dialog(pParent, nStyle)
1970 : , m_eButtonsType(eButtonsType)
1971 : , m_eMessageType(eMessageType)
1972 : , m_pGrid(NULL)
1973 : , m_pImage(NULL)
1974 : , m_pPrimaryMessage(NULL)
1975 : , m_pSecondaryMessage(NULL)
1976 0 : , m_sPrimaryString(rMessage)
1977 : {
1978 0 : SetType(WINDOW_MESSBOX);
1979 0 : create_owned_areas();
1980 0 : }
1981 :
1982 0 : MessageDialog::MessageDialog(vcl::Window* pParent, const OString& rID, const OUString& rUIXMLDescription)
1983 : : Dialog(pParent, rID, rUIXMLDescription, WINDOW_MESSBOX)
1984 : , m_eButtonsType(VCL_BUTTONS_NONE)
1985 : , m_eMessageType(VCL_MESSAGE_INFO)
1986 : , m_pOwnedContentArea(NULL)
1987 : , m_pOwnedActionArea(NULL)
1988 : , m_pGrid(NULL)
1989 : , m_pImage(NULL)
1990 : , m_pPrimaryMessage(NULL)
1991 0 : , m_pSecondaryMessage(NULL)
1992 : {
1993 0 : }
1994 :
1995 0 : MessageDialog::~MessageDialog()
1996 : {
1997 0 : for (size_t i = 0; i < m_aOwnedButtons.size(); ++i)
1998 0 : delete m_aOwnedButtons[i];
1999 0 : delete m_pSecondaryMessage;
2000 0 : delete m_pPrimaryMessage;
2001 0 : delete m_pImage;
2002 0 : delete m_pGrid;
2003 0 : delete m_pOwnedActionArea;
2004 0 : delete m_pOwnedContentArea;
2005 0 : }
2006 :
2007 0 : void MessageDialog::response(short nResponseId)
2008 : {
2009 0 : EndDialog(nResponseId);
2010 0 : }
2011 :
2012 0 : IMPL_LINK(MessageDialog, ButtonHdl, Button *, pButton)
2013 : {
2014 0 : response(get_response(pButton));
2015 0 : return 0;
2016 : }
2017 :
2018 0 : short MessageDialog::get_response(const vcl::Window *pWindow) const
2019 : {
2020 0 : std::map<const vcl::Window*, short>::const_iterator aFind = m_aResponses.find(pWindow);
2021 0 : if (aFind != m_aResponses.end())
2022 0 : return aFind->second;
2023 0 : if (!m_pUIBuilder)
2024 0 : return RET_CANCEL;
2025 0 : return m_pUIBuilder->get_response(pWindow);
2026 : }
2027 :
2028 0 : void MessageDialog::setButtonHandlers(VclButtonBox *pButtonBox)
2029 : {
2030 : assert(pButtonBox);
2031 0 : for (vcl::Window* pChild = pButtonBox->GetWindow(WINDOW_FIRSTCHILD); pChild;
2032 : pChild = pChild->GetWindow(WINDOW_NEXT))
2033 : {
2034 0 : switch (pChild->GetType())
2035 : {
2036 : case WINDOW_PUSHBUTTON:
2037 : {
2038 0 : PushButton* pButton = static_cast<PushButton*>(pChild);
2039 0 : pButton->SetClickHdl(LINK(this, MessageDialog, ButtonHdl));
2040 0 : break;
2041 : }
2042 : //insist that the response ids match the default actions for those
2043 : //widgets, and leave their default handlers in place
2044 : case WINDOW_OKBUTTON:
2045 : assert(get_response(pChild) == RET_OK);
2046 0 : break;
2047 : case WINDOW_CANCELBUTTON:
2048 : assert(get_response(pChild) == RET_CANCEL);
2049 0 : break;
2050 : case WINDOW_HELPBUTTON:
2051 : assert(get_response(pChild) == RET_HELP);
2052 0 : break;
2053 : default:
2054 : SAL_WARN("vcl.layout", "The type of widget " <<
2055 : pChild->GetHelpId() << " is currently not handled");
2056 0 : break;
2057 : }
2058 : //The default is to stick the focus into the first widget
2059 : //that accepts it, and if that happens and it's a button
2060 : //then that becomes the new default button, so explicitly
2061 : //put the focus into the default button
2062 0 : if (pChild->GetStyle() & WB_DEFBUTTON)
2063 0 : pChild->GrabFocus();
2064 : }
2065 0 : }
2066 :
2067 0 : void MessageDialog::SetMessagesWidths(vcl::Window *pParent,
2068 : VclMultiLineEdit *pPrimaryMessage, VclMultiLineEdit *pSecondaryMessage)
2069 : {
2070 0 : if (pSecondaryMessage)
2071 : {
2072 : assert(pPrimaryMessage);
2073 0 : vcl::Font aFont = pParent->GetSettings().GetStyleSettings().GetLabelFont();
2074 0 : aFont.SetSize(Size(0, aFont.GetSize().Height() * 1.2));
2075 0 : aFont.SetWeight(WEIGHT_BOLD);
2076 0 : pPrimaryMessage->SetControlFont(aFont);
2077 0 : pPrimaryMessage->SetMaxTextWidth(pPrimaryMessage->approximate_char_width() * 44);
2078 0 : pSecondaryMessage->SetMaxTextWidth(pSecondaryMessage->approximate_char_width() * 60);
2079 : }
2080 : else
2081 0 : pPrimaryMessage->SetMaxTextWidth(pPrimaryMessage->approximate_char_width() * 60);
2082 0 : }
2083 :
2084 0 : short MessageDialog::Execute()
2085 : {
2086 0 : setDeferredProperties();
2087 :
2088 0 : if (!m_pGrid)
2089 : {
2090 0 : VclContainer *pContainer = get_content_area();
2091 : assert(pContainer);
2092 :
2093 0 : m_pGrid = new VclGrid(pContainer);
2094 0 : m_pGrid->reorderWithinParent(0);
2095 0 : m_pGrid->set_column_spacing(12);
2096 0 : m_pGrid->set_row_spacing(GetTextHeight());
2097 :
2098 0 : m_pImage = new FixedImage(m_pGrid, WB_CENTER | WB_VCENTER | WB_3DLOOK);
2099 0 : switch (m_eMessageType)
2100 : {
2101 : case VCL_MESSAGE_INFO:
2102 0 : m_pImage->SetImage(InfoBox::GetStandardImage());
2103 0 : break;
2104 : case VCL_MESSAGE_WARNING:
2105 0 : m_pImage->SetImage(WarningBox::GetStandardImage());
2106 0 : break;
2107 : case VCL_MESSAGE_QUESTION:
2108 0 : m_pImage->SetImage(QueryBox::GetStandardImage());
2109 0 : break;
2110 : case VCL_MESSAGE_ERROR:
2111 0 : m_pImage->SetImage(ErrorBox::GetStandardImage());
2112 0 : break;
2113 : }
2114 0 : m_pImage->set_grid_left_attach(0);
2115 0 : m_pImage->set_grid_top_attach(0);
2116 0 : m_pImage->set_valign(VCL_ALIGN_START);
2117 0 : m_pImage->Show();
2118 :
2119 0 : WinBits nWinStyle = WB_CLIPCHILDREN | WB_LEFT | WB_VCENTER | WB_NOLABEL | WB_NOTABSTOP;
2120 :
2121 0 : bool bHasSecondaryText = !m_sSecondaryString.isEmpty();
2122 :
2123 0 : m_pPrimaryMessage = new VclMultiLineEdit(m_pGrid, nWinStyle);
2124 0 : m_pPrimaryMessage->SetPaintTransparent(true);
2125 0 : m_pPrimaryMessage->EnableCursor(false);
2126 :
2127 0 : m_pPrimaryMessage->set_grid_left_attach(1);
2128 0 : m_pPrimaryMessage->set_grid_top_attach(0);
2129 0 : m_pPrimaryMessage->set_hexpand(true);
2130 0 : m_pPrimaryMessage->SetText(m_sPrimaryString);
2131 0 : m_pPrimaryMessage->Show(!m_sPrimaryString.isEmpty());
2132 :
2133 0 : m_pSecondaryMessage = new VclMultiLineEdit(m_pGrid, nWinStyle);
2134 0 : m_pSecondaryMessage->SetPaintTransparent(true);
2135 0 : m_pSecondaryMessage->EnableCursor(false);
2136 0 : m_pSecondaryMessage->set_grid_left_attach(1);
2137 0 : m_pSecondaryMessage->set_grid_top_attach(1);
2138 0 : m_pSecondaryMessage->set_hexpand(true);
2139 0 : m_pSecondaryMessage->SetText(m_sSecondaryString);
2140 0 : m_pSecondaryMessage->Show(bHasSecondaryText);
2141 :
2142 0 : MessageDialog::SetMessagesWidths(this, m_pPrimaryMessage, bHasSecondaryText ? m_pSecondaryMessage : NULL);
2143 :
2144 0 : VclButtonBox *pButtonBox = get_action_area();
2145 : assert(pButtonBox);
2146 :
2147 : PushButton *pBtn;
2148 0 : switch (m_eButtonsType)
2149 : {
2150 : case VCL_BUTTONS_NONE:
2151 0 : break;
2152 : case VCL_BUTTONS_OK:
2153 0 : pBtn = new OKButton(pButtonBox);
2154 0 : pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON);
2155 0 : pBtn->Show();
2156 0 : m_aOwnedButtons.push_back(pBtn);
2157 0 : m_aResponses[pBtn] = RET_OK;
2158 0 : break;
2159 : case VCL_BUTTONS_CLOSE:
2160 0 : pBtn = new CloseButton(pButtonBox);
2161 0 : pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON);
2162 0 : pBtn->Show();
2163 0 : m_aOwnedButtons.push_back(pBtn);
2164 0 : m_aResponses[pBtn] = RET_CLOSE;
2165 0 : break;
2166 : case VCL_BUTTONS_CANCEL:
2167 0 : pBtn = new CancelButton(pButtonBox);
2168 0 : pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON);
2169 0 : m_aOwnedButtons.push_back(pBtn);
2170 0 : m_aResponses[pBtn] = RET_CANCEL;
2171 0 : break;
2172 : case VCL_BUTTONS_YES_NO:
2173 0 : pBtn = new PushButton(pButtonBox);
2174 0 : pBtn->SetText(Button::GetStandardText(BUTTON_YES));
2175 0 : pBtn->Show();
2176 0 : m_aOwnedButtons.push_back(pBtn);
2177 0 : m_aResponses[pBtn] = RET_YES;
2178 :
2179 0 : pBtn = new PushButton(pButtonBox);
2180 0 : pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON);
2181 0 : pBtn->SetText(Button::GetStandardText(BUTTON_NO));
2182 0 : pBtn->Show();
2183 0 : m_aOwnedButtons.push_back(pBtn);
2184 0 : m_aResponses[pBtn] = RET_NO;
2185 0 : break;
2186 : case VCL_BUTTONS_OK_CANCEL:
2187 0 : pBtn = new OKButton(pButtonBox);
2188 0 : pBtn->Show();
2189 0 : m_aOwnedButtons.push_back(pBtn);
2190 0 : m_aResponses[pBtn] = RET_OK;
2191 :
2192 0 : pBtn = new CancelButton(pButtonBox);
2193 0 : pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON);
2194 0 : pBtn->Show();
2195 0 : m_aOwnedButtons.push_back(pBtn);
2196 0 : m_aResponses[pBtn] = RET_CANCEL;
2197 0 : break;
2198 : }
2199 0 : setButtonHandlers(pButtonBox);
2200 0 : pButtonBox->sort_native_button_order();
2201 0 : m_pGrid->Show();
2202 : }
2203 0 : return Dialog::Execute();
2204 : }
2205 :
2206 0 : OUString MessageDialog::get_primary_text() const
2207 : {
2208 0 : const_cast<MessageDialog*>(this)->setDeferredProperties();
2209 :
2210 0 : return m_sPrimaryString;
2211 : }
2212 :
2213 0 : OUString MessageDialog::get_secondary_text() const
2214 : {
2215 0 : const_cast<MessageDialog*>(this)->setDeferredProperties();
2216 :
2217 0 : return m_sSecondaryString;
2218 : }
2219 :
2220 0 : bool MessageDialog::set_property(const OString &rKey, const OString &rValue)
2221 : {
2222 0 : if (rKey == "text")
2223 0 : set_primary_text(OStringToOUString(rValue, RTL_TEXTENCODING_UTF8));
2224 0 : else if (rKey == "secondary-text")
2225 0 : set_secondary_text(OStringToOUString(rValue, RTL_TEXTENCODING_UTF8));
2226 0 : else if (rKey == "message-type")
2227 : {
2228 0 : VclMessageType eMode = VCL_MESSAGE_INFO;
2229 0 : if (rValue.equals("info"))
2230 0 : eMode = VCL_MESSAGE_INFO;
2231 0 : else if (rValue.equals("warning"))
2232 0 : eMode = VCL_MESSAGE_WARNING;
2233 0 : else if (rValue.equals("question"))
2234 0 : eMode = VCL_MESSAGE_QUESTION;
2235 0 : else if (rValue.equals("error"))
2236 0 : eMode = VCL_MESSAGE_ERROR;
2237 : else
2238 : {
2239 : SAL_WARN("vcl.layout", "unknown message type mode" << rValue.getStr());
2240 : }
2241 0 : m_eMessageType = eMode;
2242 : }
2243 0 : else if (rKey == "buttons")
2244 : {
2245 0 : VclButtonsType eMode = VCL_BUTTONS_NONE;
2246 0 : if (rValue.equals("none"))
2247 0 : eMode = VCL_BUTTONS_NONE;
2248 0 : else if (rValue.equals("ok"))
2249 0 : eMode = VCL_BUTTONS_OK;
2250 0 : else if (rValue.equals("cancel"))
2251 0 : eMode = VCL_BUTTONS_CANCEL;
2252 0 : else if (rValue.equals("close"))
2253 0 : eMode = VCL_BUTTONS_CLOSE;
2254 0 : else if (rValue.equals("yes-no"))
2255 0 : eMode = VCL_BUTTONS_YES_NO;
2256 0 : else if (rValue.equals("ok-cancel"))
2257 0 : eMode = VCL_BUTTONS_OK_CANCEL;
2258 : else
2259 : {
2260 : SAL_WARN("vcl.layout", "unknown buttons type mode" << rValue.getStr());
2261 : }
2262 0 : m_eButtonsType = eMode;
2263 : }
2264 : else
2265 0 : return Dialog::set_property(rKey, rValue);
2266 0 : return true;
2267 : }
2268 :
2269 0 : void MessageDialog::set_primary_text(const OUString &rPrimaryString)
2270 : {
2271 0 : m_sPrimaryString = rPrimaryString;
2272 0 : if (m_pPrimaryMessage)
2273 : {
2274 0 : m_pPrimaryMessage->SetText(m_sPrimaryString);
2275 0 : m_pPrimaryMessage->Show(!m_sPrimaryString.isEmpty());
2276 : }
2277 0 : }
2278 :
2279 0 : void MessageDialog::set_secondary_text(const OUString &rSecondaryString)
2280 : {
2281 0 : m_sSecondaryString = rSecondaryString;
2282 0 : if (m_pSecondaryMessage)
2283 : {
2284 0 : m_pSecondaryMessage->SetText(OUString("\n") + m_sSecondaryString);
2285 0 : m_pSecondaryMessage->Show(!m_sSecondaryString.isEmpty());
2286 : }
2287 0 : }
2288 :
2289 0 : Size getLegacyBestSizeForChildren(const vcl::Window &rWindow)
2290 : {
2291 0 : Rectangle aBounds;
2292 :
2293 0 : for (const vcl::Window* pChild = rWindow.GetWindow(WINDOW_FIRSTCHILD); pChild;
2294 : pChild = pChild->GetWindow(WINDOW_NEXT))
2295 : {
2296 0 : if (!pChild->IsVisible())
2297 0 : continue;
2298 :
2299 0 : Rectangle aChildBounds(pChild->GetPosPixel(), pChild->GetSizePixel());
2300 0 : aBounds.Union(aChildBounds);
2301 : }
2302 :
2303 0 : if (aBounds.IsEmpty())
2304 0 : return rWindow.GetSizePixel();
2305 :
2306 0 : Size aRet(aBounds.GetSize());
2307 0 : Point aTopLeft(aBounds.TopLeft());
2308 0 : aRet.Width() += aTopLeft.X()*2;
2309 0 : aRet.Height() += aTopLeft.Y()*2;
2310 :
2311 0 : return aRet;
2312 : }
2313 :
2314 118993 : vcl::Window* getNonLayoutParent(vcl::Window *pWindow)
2315 : {
2316 241500 : while (pWindow)
2317 : {
2318 122507 : pWindow = pWindow->GetParent();
2319 122507 : if (!pWindow || !isContainerWindow(*pWindow))
2320 118993 : break;
2321 : }
2322 118993 : return pWindow;
2323 : }
2324 :
2325 0 : vcl::Window* getNonLayoutRealParent(vcl::Window *pWindow)
2326 : {
2327 0 : while (pWindow)
2328 : {
2329 0 : pWindow = pWindow->ImplGetParent();
2330 0 : if (!pWindow || !isContainerWindow(*pWindow))
2331 0 : break;
2332 : }
2333 0 : return pWindow;
2334 : }
2335 :
2336 315369 : bool isVisibleInLayout(const vcl::Window *pWindow)
2337 : {
2338 315369 : bool bVisible = true;
2339 638800 : while (bVisible)
2340 : {
2341 323313 : bVisible = pWindow->IsVisible();
2342 323313 : pWindow = pWindow->GetParent();
2343 323313 : if (!pWindow || !isContainerWindow(*pWindow))
2344 315251 : break;
2345 : }
2346 315369 : return bVisible;
2347 : }
2348 :
2349 1340 : bool isEnabledInLayout(const vcl::Window *pWindow)
2350 : {
2351 1340 : bool bEnabled = true;
2352 2692 : while (bEnabled)
2353 : {
2354 1352 : bEnabled = pWindow->IsEnabled();
2355 1352 : pWindow = pWindow->GetParent();
2356 1352 : if (!pWindow || !isContainerWindow(*pWindow))
2357 1340 : break;
2358 : }
2359 1340 : return bEnabled;
2360 : }
2361 :
2362 719023 : bool isLayoutEnabled(const vcl::Window *pWindow)
2363 : {
2364 : //Child is a container => we're layout enabled
2365 719023 : const vcl::Window *pChild = pWindow ? pWindow->GetWindow(WINDOW_FIRSTCHILD) : NULL;
2366 719023 : return pChild && isContainerWindow(*pChild) && !pChild->GetWindow(WINDOW_NEXT);
2367 : }
2368 :
2369 0 : bool isInitialLayout(const vcl::Window *pWindow)
2370 : {
2371 0 : Dialog *pParentDialog = pWindow ? pWindow->GetParentDialog() : NULL;
2372 0 : return pParentDialog && pParentDialog->isCalculatingInitialLayoutSize();
2373 1233 : }
2374 :
2375 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|