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 8148 : VclContainer::VclContainer(vcl::Window *pParent, WinBits nStyle)
19 : : Window(WINDOW_CONTAINER)
20 8148 : , m_bLayoutDirty(true)
21 : {
22 8148 : ImplInit(pParent, nStyle, NULL);
23 8148 : EnableChildTransparentMode();
24 8148 : SetPaintTransparent(true);
25 8148 : SetBackground();
26 8148 : }
27 :
28 6 : sal_uInt16 VclContainer::getDefaultAccessibleRole() const
29 : {
30 6 : return com::sun::star::accessibility::AccessibleRole::PANEL;
31 : }
32 :
33 8069 : Size VclContainer::GetOptimalSize() const
34 : {
35 8069 : return calculateRequisition();
36 : }
37 :
38 36084 : void VclContainer::setLayoutPosSize(vcl::Window &rWindow, const Point &rPos, const Size &rSize)
39 : {
40 36084 : sal_Int32 nBorderWidth = rWindow.get_border_width();
41 36084 : sal_Int32 nLeft = rWindow.get_margin_left() + nBorderWidth;
42 36084 : sal_Int32 nTop = rWindow.get_margin_top() + nBorderWidth;
43 36084 : sal_Int32 nRight = rWindow.get_margin_right() + nBorderWidth;
44 36084 : sal_Int32 nBottom = rWindow.get_margin_bottom() + nBorderWidth;
45 36084 : Point aPos(rPos.X() + nLeft, rPos.Y() + nTop);
46 36084 : Size aSize(rSize.Width() - nLeft - nRight, rSize.Height() - nTop - nBottom);
47 36084 : rWindow.SetPosSizePixel(aPos, aSize);
48 36084 : }
49 :
50 36084 : void VclContainer::setLayoutAllocation(vcl::Window &rChild, const Point &rAllocPos, const Size &rChildAlloc)
51 : {
52 36084 : VclAlign eHalign = rChild.get_halign();
53 36084 : VclAlign eValign = rChild.get_valign();
54 :
55 : //typical case
56 36084 : if (eHalign == VCL_ALIGN_FILL && eValign == VCL_ALIGN_FILL)
57 : {
58 30806 : setLayoutPosSize(rChild, rAllocPos, rChildAlloc);
59 66890 : return;
60 : }
61 :
62 5278 : Point aChildPos(rAllocPos);
63 5278 : Size aChildSize(rChildAlloc);
64 5278 : Size aChildPreferredSize(getLayoutRequisition(rChild));
65 :
66 5278 : switch (eHalign)
67 : {
68 : case VCL_ALIGN_FILL:
69 264 : break;
70 : case VCL_ALIGN_START:
71 936 : if (aChildPreferredSize.Width() < rChildAlloc.Width())
72 150 : aChildSize.Width() = aChildPreferredSize.Width();
73 936 : break;
74 : case VCL_ALIGN_END:
75 974 : if (aChildPreferredSize.Width() < rChildAlloc.Width())
76 0 : aChildSize.Width() = aChildPreferredSize.Width();
77 974 : aChildPos.X() += rChildAlloc.Width();
78 974 : aChildPos.X() -= aChildSize.Width();
79 974 : break;
80 : case VCL_ALIGN_CENTER:
81 3104 : if (aChildPreferredSize.Width() < aChildSize.Width())
82 0 : aChildSize.Width() = aChildPreferredSize.Width();
83 3104 : aChildPos.X() += (rChildAlloc.Width() - aChildSize.Width()) / 2;
84 3104 : break;
85 : }
86 :
87 5278 : switch (eValign)
88 : {
89 : case VCL_ALIGN_FILL:
90 2584 : 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 2694 : if (aChildPreferredSize.Height() < aChildSize.Height())
103 2430 : aChildSize.Height() = aChildPreferredSize.Height();
104 2694 : aChildPos.Y() += (rChildAlloc.Height() - aChildSize.Height()) / 2;
105 2694 : break;
106 : }
107 :
108 5278 : setLayoutPosSize(rChild, aChildPos, aChildSize);
109 : }
110 :
111 80155 : Size VclContainer::getLayoutRequisition(const vcl::Window &rWindow)
112 : {
113 80155 : sal_Int32 nBorderWidth = rWindow.get_border_width();
114 80155 : sal_Int32 nLeft = rWindow.get_margin_left() + nBorderWidth;
115 80155 : sal_Int32 nTop = rWindow.get_margin_top() + nBorderWidth;
116 80155 : sal_Int32 nRight = rWindow.get_margin_right() + nBorderWidth;
117 80155 : sal_Int32 nBottom = rWindow.get_margin_bottom() + nBorderWidth;
118 80155 : Size aSize(rWindow.get_preferred_size());
119 80155 : return Size(aSize.Width() + nLeft + nRight, aSize.Height() + nTop + nBottom);
120 : }
121 :
122 14022 : void VclContainer::SetPosSizePixel(const Point& rAllocPos, const Size& rAllocation)
123 : {
124 14022 : bool bSizeChanged = rAllocation != GetOutputSizePixel();
125 14022 : Window::SetPosSizePixel(rAllocPos, rAllocation);
126 14022 : if (m_bLayoutDirty || bSizeChanged)
127 : {
128 12661 : m_bLayoutDirty = false;
129 12661 : setAllocation(rAllocation);
130 : }
131 14022 : }
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 278183 : void VclContainer::queue_resize(StateChangedType eReason)
161 : {
162 278183 : markLayoutDirty();
163 278183 : Window::queue_resize(eReason);
164 278183 : }
165 :
166 25240 : void VclBox::accumulateMaxes(const Size &rChildSize, Size &rSize) const
167 : {
168 25240 : long nSecondaryChildDimension = getSecondaryDimension(rChildSize);
169 25240 : long nSecondaryBoxDimension = getSecondaryDimension(rSize);
170 25240 : setSecondaryDimension(rSize, std::max(nSecondaryChildDimension, nSecondaryBoxDimension));
171 :
172 25240 : long nPrimaryChildDimension = getPrimaryDimension(rChildSize);
173 25240 : long nPrimaryBoxDimension = getPrimaryDimension(rSize);
174 25240 : if (m_bHomogeneous)
175 4 : setPrimaryDimension(rSize, std::max(nPrimaryBoxDimension, nPrimaryChildDimension));
176 : else
177 25236 : setPrimaryDimension(rSize, nPrimaryBoxDimension + nPrimaryChildDimension);
178 25240 : }
179 :
180 11197 : Size VclBox::calculateRequisition() const
181 : {
182 11197 : sal_uInt16 nVisibleChildren = 0;
183 :
184 11197 : Size aSize;
185 38265 : for (vcl::Window *pChild = GetWindow(GetWindowType::FirstChild); pChild; pChild = pChild->GetWindow(GetWindowType::Next))
186 : {
187 27068 : if (!pChild->IsVisible())
188 1828 : continue;
189 25240 : ++nVisibleChildren;
190 25240 : Size aChildSize = getLayoutRequisition(*pChild);
191 :
192 25240 : long nPrimaryDimension = getPrimaryDimension(aChildSize);
193 25240 : nPrimaryDimension += pChild->get_padding() * 2;
194 25240 : setPrimaryDimension(aChildSize, nPrimaryDimension);
195 :
196 25240 : accumulateMaxes(aChildSize, aSize);
197 : }
198 :
199 11197 : return finalizeMaxes(aSize, nVisibleChildren);
200 : }
201 :
202 11236 : void VclBox::setAllocation(const Size &rAllocation)
203 : {
204 11236 : sal_uInt16 nVisibleChildren = 0, nExpandChildren = 0;
205 41813 : for (vcl::Window *pChild = GetWindow(GetWindowType::FirstChild); pChild; pChild = pChild->GetWindow(GetWindowType::Next))
206 : {
207 30577 : if (!pChild->IsVisible())
208 3255 : continue;
209 27322 : ++nVisibleChildren;
210 27322 : bool bExpand = getPrimaryDimensionChildExpand(*pChild);
211 27322 : if (bExpand)
212 3604 : ++nExpandChildren;
213 : }
214 :
215 11236 : if (!nVisibleChildren)
216 11236 : return;
217 :
218 11236 : long nAllocPrimaryDimension = getPrimaryDimension(rAllocation);
219 :
220 11236 : long nHomogeneousDimension = 0, nExtraSpace = 0;
221 11236 : if (m_bHomogeneous)
222 : {
223 3 : nHomogeneousDimension = ((nAllocPrimaryDimension -
224 6 : (nVisibleChildren - 1) * m_nSpacing)) / nVisibleChildren;
225 : }
226 11233 : else if (nExpandChildren)
227 : {
228 3599 : Size aRequisition = calculateRequisition();
229 3599 : 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 33708 : std::vector<vcl::Window*> aWindows[2];
234 41813 : for (vcl::Window *pChild = GetWindow(GetWindowType::FirstChild); pChild; pChild = pChild->GetWindow(GetWindowType::Next))
235 : {
236 30577 : if (!pChild->IsVisible())
237 3255 : continue;
238 :
239 27322 : sal_Int32 ePacking = pChild->get_pack_type();
240 27322 : 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 11236 : std::reverse(aWindows[VCL_PACK_END].begin(),aWindows[VCL_PACK_END].end());
247 :
248 33708 : for (sal_Int32 ePackType = VCL_PACK_START; ePackType <= VCL_PACK_END; ++ePackType)
249 : {
250 22472 : Point aPos(0, 0);
251 22472 : if (ePackType == VCL_PACK_END)
252 : {
253 11236 : long nPrimaryCoordinate = getPrimaryCoordinate(aPos);
254 11236 : setPrimaryCoordinate(aPos, nPrimaryCoordinate + nAllocPrimaryDimension);
255 : }
256 :
257 49794 : for (std::vector<vcl::Window*>::iterator aI = aWindows[ePackType].begin(), aEnd = aWindows[ePackType].end(); aI != aEnd; ++aI)
258 : {
259 27322 : vcl::Window *pChild = *aI;
260 :
261 27322 : long nPadding = pChild->get_padding();
262 :
263 27322 : Size aBoxSize;
264 27322 : if (m_bHomogeneous)
265 6 : setPrimaryDimension(aBoxSize, nHomogeneousDimension);
266 : else
267 : {
268 27316 : aBoxSize = getLayoutRequisition(*pChild);
269 27316 : long nPrimaryDimension = getPrimaryDimension(aBoxSize);
270 27316 : nPrimaryDimension += nPadding * 2;
271 27316 : if (getPrimaryDimensionChildExpand(*pChild))
272 3603 : nPrimaryDimension += nExtraSpace;
273 27316 : setPrimaryDimension(aBoxSize, nPrimaryDimension);
274 : }
275 27322 : setSecondaryDimension(aBoxSize, getSecondaryDimension(rAllocation));
276 :
277 27322 : Point aChildPos(aPos);
278 27322 : Size aChildSize(aBoxSize);
279 27322 : long nPrimaryCoordinate = getPrimaryCoordinate(aPos);
280 :
281 27322 : bool bFill = pChild->get_fill();
282 27322 : if (bFill)
283 : {
284 : setPrimaryDimension(aChildSize, std::max(static_cast<long>(1),
285 27322 : getPrimaryDimension(aBoxSize) - nPadding * 2));
286 :
287 27322 : 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 27322 : long nDiff = getPrimaryDimension(aBoxSize) + m_nSpacing;
299 27322 : if (ePackType == VCL_PACK_START)
300 21947 : setPrimaryCoordinate(aPos, nPrimaryCoordinate + nDiff);
301 : else
302 : {
303 5375 : setPrimaryCoordinate(aPos, nPrimaryCoordinate - nDiff);
304 5375 : setPrimaryCoordinate(aChildPos, getPrimaryCoordinate(aChildPos) -
305 10750 : getPrimaryDimension(aBoxSize));
306 : }
307 :
308 27322 : setLayoutAllocation(*pChild, aChildPos, aChildSize);
309 : }
310 33708 : }
311 : }
312 :
313 21928 : bool VclBox::set_property(const OString &rKey, const OString &rValue)
314 : {
315 21928 : if (rKey == "spacing")
316 6632 : set_spacing(rValue.toInt32());
317 15296 : else if (rKey == "homogeneous")
318 2 : set_homogeneous(toBool(rValue));
319 : else
320 15294 : return VclContainer::set_property(rKey, rValue);
321 6634 : return true;
322 : }
323 :
324 6 : 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 6 : 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 11197 : Size VclBox::finalizeMaxes(const Size &rSize, sal_uInt16 nVisibleChildren) const
339 : {
340 11197 : Size aRet;
341 :
342 11197 : if (nVisibleChildren)
343 : {
344 11197 : long nPrimaryDimension = getPrimaryDimension(rSize);
345 11197 : if (m_bHomogeneous)
346 2 : nPrimaryDimension *= nVisibleChildren;
347 11197 : setPrimaryDimension(aRet, nPrimaryDimension + m_nSpacing * (nVisibleChildren-1));
348 11197 : setSecondaryDimension(aRet, getSecondaryDimension(rSize));
349 : }
350 :
351 11197 : return aRet;
352 : }
353 :
354 1 : Size VclButtonBox::addReqGroups(const VclButtonBox::Requisition &rReq) const
355 : {
356 1 : Size aRet;
357 :
358 1 : long nMainGroupDimension = getPrimaryDimension(rReq.m_aMainGroupSize);
359 1 : long nSubGroupDimension = getPrimaryDimension(rReq.m_aSubGroupSize);
360 :
361 1 : setPrimaryDimension(aRet, nMainGroupDimension + nSubGroupDimension);
362 :
363 : setSecondaryDimension(aRet,
364 1 : std::max(getSecondaryDimension(rReq.m_aMainGroupSize),
365 2 : getSecondaryDimension(rReq.m_aSubGroupSize)));
366 :
367 1 : return aRet;
368 : }
369 :
370 4 : static long getMaxNonOutlier(const std::vector<long> &rG, long nAvgDimension)
371 : {
372 4 : long nMaxDimensionNonOutlier = 0;
373 8 : for (std::vector<long>::const_iterator aI = rG.begin(),
374 4 : 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 4 : return nMaxDimensionNonOutlier;
384 : }
385 :
386 4 : 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 4 : std::vector<long> aVec;
391 : //set everything < 1.5 times the average to the same width, leave the
392 : //outliers un-touched
393 4 : std::vector<bool>::const_iterator aJ = rNonHomogeneous.begin();
394 4 : 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 4 : return aVec;
409 : }
410 :
411 2 : VclButtonBox::Requisition VclButtonBox::calculatePrimarySecondaryRequisitions() const
412 : {
413 2 : Requisition aReq;
414 :
415 2 : Size aMainGroupSize(DEFAULT_CHILD_MIN_WIDTH, DEFAULT_CHILD_MIN_HEIGHT); //to-do, pull from theme
416 2 : Size aSubGroupSize(DEFAULT_CHILD_MIN_WIDTH, DEFAULT_CHILD_MIN_HEIGHT); //to-do, pull from theme
417 :
418 2 : long nMinMainGroupPrimary = getPrimaryDimension(aMainGroupSize);
419 2 : long nMinSubGroupPrimary = getPrimaryDimension(aSubGroupSize);
420 2 : long nMainGroupSecondary = getSecondaryDimension(aMainGroupSize);
421 2 : long nSubGroupSecondary = getSecondaryDimension(aSubGroupSize);
422 :
423 2 : bool bIgnoreSecondaryPacking = (m_eLayoutStyle == VCL_BUTTONBOX_SPREAD || m_eLayoutStyle == VCL_BUTTONBOX_CENTER);
424 :
425 4 : std::vector<long> aMainGroupSizes;
426 4 : std::vector<bool> aMainGroupNonHomogeneous;
427 4 : std::vector<long> aSubGroupSizes;
428 4 : std::vector<bool> aSubGroupNonHomogeneous;
429 :
430 2 : for (const vcl::Window *pChild = GetWindow(GetWindowType::FirstChild); pChild; pChild = pChild->GetWindow(GetWindowType::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 2 : 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 2 : aMainGroupSizes.end(), 0);
471 : nAccDimension = std::accumulate(aSubGroupSizes.begin(),
472 2 : aSubGroupSizes.end(), nAccDimension);
473 :
474 2 : size_t nTotalSize = aMainGroupSizes.size() + aSubGroupSizes.size();
475 :
476 2 : long nAvgDimension = nTotalSize ? nAccDimension / nTotalSize : 0;
477 :
478 : long nMaxMainNonOutlier = getMaxNonOutlier(aMainGroupSizes,
479 2 : nAvgDimension);
480 : long nMaxSubNonOutlier = getMaxNonOutlier(aSubGroupSizes,
481 2 : nAvgDimension);
482 2 : long nMaxNonOutlier = std::max(nMaxMainNonOutlier, nMaxSubNonOutlier);
483 :
484 4 : aReq.m_aMainGroupDimensions = setButtonSizes(aMainGroupSizes,
485 : aMainGroupNonHomogeneous,
486 2 : nAvgDimension, nMaxNonOutlier, nMinMainGroupPrimary);
487 4 : aReq.m_aSubGroupDimensions = setButtonSizes(aSubGroupSizes,
488 : aSubGroupNonHomogeneous,
489 2 : nAvgDimension, nMaxNonOutlier, nMinSubGroupPrimary);
490 : }
491 :
492 2 : 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 2 : 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 4 : return aReq;
508 : }
509 :
510 1 : Size VclButtonBox::addSpacing(const Size &rSize, sal_uInt16 nVisibleChildren) const
511 : {
512 1 : Size aRet;
513 :
514 1 : 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 1 : return aRet;
523 : }
524 :
525 1 : Size VclButtonBox::calculateRequisition() const
526 : {
527 1 : Requisition aReq(calculatePrimarySecondaryRequisitions());
528 1 : sal_uInt16 nVisibleChildren = aReq.m_aMainGroupDimensions.size() +
529 1 : aReq.m_aSubGroupDimensions.size();
530 1 : 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 1 : void VclButtonBox::setAllocation(const Size &rAllocation)
560 : {
561 1 : Requisition aReq(calculatePrimarySecondaryRequisitions());
562 :
563 1 : if (aReq.m_aMainGroupDimensions.empty() && aReq.m_aSubGroupDimensions.empty())
564 2 : 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(GetWindowType::FirstChild); pChild; pChild = pChild->GetWindow(GetWindowType::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 : explicit 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(GetWindowType::FirstChild); pChild;
740 0 : pChild = pChild->GetWindow(GetWindowType::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 4905 : VclGrid::array_type VclGrid::assembleGrid() const
752 : {
753 4905 : ext_array_type A;
754 :
755 23223 : for (vcl::Window* pChild = GetWindow(GetWindowType::FirstChild); pChild;
756 : pChild = pChild->GetWindow(GetWindowType::Next))
757 : {
758 18318 : sal_Int32 nLeftAttach = std::max<sal_Int32>(pChild->get_grid_left_attach(), 0);
759 18318 : sal_Int32 nWidth = pChild->get_grid_width();
760 18318 : sal_Int32 nMaxXPos = nLeftAttach+nWidth-1;
761 :
762 18318 : sal_Int32 nTopAttach = std::max<sal_Int32>(pChild->get_grid_top_attach(), 0);
763 18318 : sal_Int32 nHeight = pChild->get_grid_height();
764 18318 : sal_Int32 nMaxYPos = nTopAttach+nHeight-1;
765 :
766 18318 : sal_Int32 nCurrentMaxXPos = A.shape()[0]-1;
767 18318 : sal_Int32 nCurrentMaxYPos = A.shape()[1]-1;
768 18318 : if (nMaxXPos > nCurrentMaxXPos || nMaxYPos > nCurrentMaxYPos)
769 : {
770 14905 : nCurrentMaxXPos = std::max(nMaxXPos, nCurrentMaxXPos);
771 14905 : nCurrentMaxYPos = std::max(nMaxYPos, nCurrentMaxYPos);
772 14905 : A.resize(boost::extents[nCurrentMaxXPos+1][nCurrentMaxYPos+1]);
773 : }
774 :
775 18318 : ExtendedGridEntry &rEntry = A[nLeftAttach][nTopAttach];
776 18318 : rEntry.pChild = pChild;
777 18318 : rEntry.nSpanWidth = nWidth;
778 18318 : rEntry.nSpanHeight = nHeight;
779 18318 : rEntry.x = nLeftAttach;
780 18318 : rEntry.y = nTopAttach;
781 :
782 38331 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
783 : {
784 40026 : for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
785 : {
786 20013 : ExtendedGridEntry &rSpan = A[nLeftAttach+nSpanX][nTopAttach+nSpanY];
787 20013 : rSpan.x = nLeftAttach;
788 20013 : rSpan.y = nTopAttach;
789 : }
790 : }
791 : }
792 :
793 : //see if we have any empty rows/cols
794 4905 : sal_Int32 nMaxX = A.shape()[0];
795 4905 : sal_Int32 nMaxY = A.shape()[1];
796 :
797 9810 : std::vector<bool> aNonEmptyCols(nMaxX);
798 9810 : std::vector<bool> aNonEmptyRows(nMaxY);
799 :
800 17729 : for (sal_Int32 x = 0; x < nMaxX; ++x)
801 : {
802 32847 : for (sal_Int32 y = 0; y < nMaxY; ++y)
803 : {
804 20023 : const GridEntry &rEntry = A[x][y];
805 20023 : const vcl::Window *pChild = rEntry.pChild;
806 20023 : if (pChild && pChild->IsVisible())
807 : {
808 18318 : aNonEmptyCols[x] = true;
809 18318 : if (get_column_homogeneous())
810 : {
811 16922 : for (sal_Int32 nSpanX = 1; nSpanX < rEntry.nSpanWidth; ++nSpanX)
812 1695 : aNonEmptyCols[x+nSpanX] = true;
813 : }
814 18318 : aNonEmptyRows[y] = true;
815 18318 : 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 4905 : if (!get_column_homogeneous())
825 : {
826 : //reduce the spans of elements that span empty columns
827 4210 : for (sal_Int32 x = 0; x < nMaxX; ++x)
828 : {
829 2688 : std::set<ExtendedGridEntry*> candidates;
830 5789 : for (sal_Int32 y = 0; y < nMaxY; ++y)
831 : {
832 3101 : if (aNonEmptyCols[x])
833 3101 : 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 2688 : 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 2688 : }
853 : }
854 :
855 4905 : if (!get_row_homogeneous())
856 : {
857 : //reduce the spans of elements that span empty rows
858 13586 : for (sal_Int32 y = 0; y < nMaxY; ++y)
859 : {
860 8681 : std::set<ExtendedGridEntry*> candidates;
861 28704 : for (sal_Int32 x = 0; x < nMaxX; ++x)
862 : {
863 20023 : if (aNonEmptyRows[y])
864 20023 : 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 8681 : 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 8681 : }
884 : }
885 :
886 4905 : sal_Int32 nNonEmptyCols = std::count(aNonEmptyCols.begin(), aNonEmptyCols.end(), true);
887 4905 : sal_Int32 nNonEmptyRows = std::count(aNonEmptyRows.begin(), aNonEmptyRows.end(), true);
888 :
889 : //make new grid without empty rows and columns
890 4905 : array_type B(boost::extents[nNonEmptyCols][nNonEmptyRows]);
891 17729 : for (sal_Int32 x = 0, x2 = 0; x < nMaxX; ++x)
892 : {
893 12824 : if (!aNonEmptyCols[x])
894 0 : continue;
895 32847 : for (sal_Int32 y = 0, y2 = 0; y < nMaxY; ++y)
896 : {
897 20023 : if (!aNonEmptyRows[y])
898 0 : continue;
899 20023 : GridEntry &rEntry = A[x][y];
900 20023 : B[x2][y2++] = rEntry;
901 : }
902 12824 : ++x2;
903 : }
904 :
905 9810 : return B;
906 : }
907 :
908 4905 : bool VclGrid::isNullGrid(const array_type &A)
909 : {
910 4905 : sal_Int32 nMaxX = A.shape()[0];
911 4905 : sal_Int32 nMaxY = A.shape()[1];
912 :
913 4905 : if (!nMaxX || !nMaxY)
914 0 : return true;
915 4905 : return false;
916 : }
917 :
918 4905 : void VclGrid::calcMaxs(const array_type &A, std::vector<Value> &rWidths, std::vector<Value> &rHeights)
919 : {
920 4905 : sal_Int32 nMaxX = A.shape()[0];
921 4905 : sal_Int32 nMaxY = A.shape()[1];
922 :
923 4905 : rWidths.resize(nMaxX);
924 4905 : rHeights.resize(nMaxY);
925 :
926 : //first use the non spanning entries to set default width/heights
927 17729 : for (sal_Int32 x = 0; x < nMaxX; ++x)
928 : {
929 32847 : for (sal_Int32 y = 0; y < nMaxY; ++y)
930 : {
931 20023 : const GridEntry &rEntry = A[x][y];
932 20023 : const vcl::Window *pChild = rEntry.pChild;
933 20023 : if (!pChild || !pChild->IsVisible())
934 1705 : continue;
935 :
936 18318 : sal_Int32 nWidth = rEntry.nSpanWidth;
937 18318 : sal_Int32 nHeight = rEntry.nSpanHeight;
938 :
939 38331 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
940 20013 : rWidths[x+nSpanX].m_bExpand |= pChild->get_hexpand();
941 :
942 36636 : for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
943 18318 : rHeights[y+nSpanY].m_bExpand |= pChild->get_vexpand();
944 :
945 18318 : if (nWidth == 1 || nHeight == 1)
946 : {
947 18318 : Size aChildSize = getLayoutRequisition(*pChild);
948 18318 : if (nWidth == 1)
949 16623 : rWidths[x].m_nValue = std::max(rWidths[x].m_nValue, aChildSize.Width());
950 18318 : if (nHeight == 1)
951 18318 : 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 17729 : for (sal_Int32 x = 0; x < nMaxX; ++x)
959 : {
960 32847 : for (sal_Int32 y = 0; y < nMaxY; ++y)
961 : {
962 20023 : const GridEntry &rEntry = A[x][y];
963 20023 : const vcl::Window *pChild = rEntry.pChild;
964 20023 : if (!pChild || !pChild->IsVisible())
965 20033 : continue;
966 :
967 18318 : sal_Int32 nWidth = rEntry.nSpanWidth;
968 18318 : sal_Int32 nHeight = rEntry.nSpanHeight;
969 :
970 18318 : if (nWidth == 1 && nHeight == 1)
971 16623 : continue;
972 :
973 1695 : Size aChildSize = getLayoutRequisition(*pChild);
974 :
975 1695 : if (nWidth > 1)
976 : {
977 1695 : sal_Int32 nExistingWidth = 0;
978 5085 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
979 3390 : nExistingWidth += rWidths[x+nSpanX].m_nValue;
980 :
981 1695 : sal_Int32 nExtraWidth = aChildSize.Width() - nExistingWidth;
982 :
983 1695 : if (nExtraWidth > 0)
984 : {
985 5 : bool bForceExpandAll = false;
986 5 : sal_Int32 nExpandables = 0;
987 15 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
988 10 : if (rWidths[x+nSpanX].m_bExpand)
989 0 : ++nExpandables;
990 5 : if (nExpandables == 0)
991 : {
992 5 : nExpandables = nWidth;
993 5 : bForceExpandAll = true;
994 : }
995 :
996 15 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
997 : {
998 10 : if (rWidths[x+nSpanX].m_bExpand || bForceExpandAll)
999 10 : rWidths[x+nSpanX].m_nValue += nExtraWidth/nExpandables;
1000 : }
1001 : }
1002 : }
1003 :
1004 1695 : 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 4905 : }
1035 :
1036 5255 : bool compareValues(const VclGrid::Value &i, const VclGrid::Value &j)
1037 : {
1038 5255 : return i.m_nValue < j.m_nValue;
1039 : }
1040 :
1041 7762 : VclGrid::Value accumulateValues(const VclGrid::Value &i, const VclGrid::Value &j)
1042 : {
1043 7762 : VclGrid::Value aRet;
1044 7762 : aRet.m_nValue = i.m_nValue + j.m_nValue;
1045 7762 : aRet.m_bExpand = i.m_bExpand || j.m_bExpand;
1046 7762 : return aRet;
1047 : }
1048 :
1049 1894 : Size VclGrid::calculateRequisition() const
1050 : {
1051 1894 : return calculateRequisitionForSpacings(get_row_spacing(), get_column_spacing());
1052 : }
1053 :
1054 3481 : Size VclGrid::calculateRequisitionForSpacings(sal_Int32 nRowSpacing, sal_Int32 nColSpacing) const
1055 : {
1056 3481 : array_type A = assembleGrid();
1057 :
1058 3481 : if (isNullGrid(A))
1059 0 : return Size();
1060 :
1061 6962 : std::vector<Value> aWidths;
1062 6962 : std::vector<Value> aHeights;
1063 3481 : calcMaxs(A, aWidths, aHeights);
1064 :
1065 3481 : long nTotalWidth = 0;
1066 3481 : if (get_column_homogeneous())
1067 : {
1068 2559 : nTotalWidth = std::max_element(aWidths.begin(), aWidths.end(), compareValues)->m_nValue;
1069 2559 : nTotalWidth *= aWidths.size();
1070 : }
1071 : else
1072 : {
1073 922 : nTotalWidth = std::accumulate(aWidths.begin(), aWidths.end(), Value(), accumulateValues).m_nValue;
1074 : }
1075 :
1076 3481 : nTotalWidth += nColSpacing * (aWidths.size()-1);
1077 :
1078 3481 : long nTotalHeight = 0;
1079 3481 : 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 3481 : nTotalHeight = std::accumulate(aHeights.begin(), aHeights.end(), Value(), accumulateValues).m_nValue;
1087 : }
1088 :
1089 3481 : nTotalHeight += nRowSpacing * (aHeights.size()-1);
1090 :
1091 6962 : return Size(nTotalWidth, nTotalHeight);
1092 : }
1093 :
1094 1424 : void VclGrid::setAllocation(const Size& rAllocation)
1095 : {
1096 1424 : array_type A = assembleGrid();
1097 :
1098 1424 : if (isNullGrid(A))
1099 1424 : return;
1100 :
1101 1424 : sal_Int32 nMaxX = A.shape()[0];
1102 1424 : sal_Int32 nMaxY = A.shape()[1];
1103 :
1104 1424 : Size aRequisition;
1105 2848 : std::vector<Value> aWidths(nMaxX);
1106 2848 : std::vector<Value> aHeights(nMaxY);
1107 1424 : if (!get_column_homogeneous() || !get_row_homogeneous())
1108 : {
1109 1424 : aRequisition = calculateRequisition();
1110 1424 : calcMaxs(A, aWidths, aHeights);
1111 : }
1112 :
1113 1424 : sal_Int32 nColSpacing(get_column_spacing());
1114 1424 : sal_Int32 nRowSpacing(get_row_spacing());
1115 :
1116 1424 : long nAvailableWidth = rAllocation.Width();
1117 1424 : if (nMaxX)
1118 1424 : nAvailableWidth -= nColSpacing * (nMaxX - 1);
1119 1424 : if (get_column_homogeneous())
1120 : {
1121 3146 : for (sal_Int32 x = 0; x < nMaxX; ++x)
1122 2322 : aWidths[x].m_nValue = nAvailableWidth/nMaxX;
1123 : }
1124 600 : else if (rAllocation.Width() != aRequisition.Width())
1125 : {
1126 430 : sal_Int32 nExpandables = 0;
1127 1140 : for (sal_Int32 x = 0; x < nMaxX; ++x)
1128 710 : if (aWidths[x].m_bExpand)
1129 431 : ++nExpandables;
1130 430 : long nExtraWidthForExpanders = nExpandables ? (rAllocation.Width() - aRequisition.Width()) / nExpandables : 0;
1131 :
1132 : //We don't fit and there is no volunteer to be shrunk
1133 430 : 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 430 : if (nExtraWidthForExpanders)
1152 : {
1153 1140 : for (sal_Int32 x = 0; x < nMaxX; ++x)
1154 710 : if (aWidths[x].m_bExpand)
1155 431 : aWidths[x].m_nValue += nExtraWidthForExpanders;
1156 : }
1157 : }
1158 :
1159 1424 : long nAvailableHeight = rAllocation.Height();
1160 1424 : if (nMaxY)
1161 1424 : nAvailableHeight -= nRowSpacing * (nMaxY - 1);
1162 1424 : 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 1424 : else if (rAllocation.Height() != aRequisition.Height())
1168 : {
1169 643 : sal_Int32 nExpandables = 0;
1170 1784 : for (sal_Int32 y = 0; y < nMaxY; ++y)
1171 1141 : if (aHeights[y].m_bExpand)
1172 114 : ++nExpandables;
1173 643 : long nExtraHeightForExpanders = nExpandables ? (rAllocation.Height() - aRequisition.Height()) / nExpandables : 0;
1174 :
1175 : //We don't fit and there is no volunteer to be shrunk
1176 643 : if (!nExpandables && rAllocation.Height() < aRequisition.Height())
1177 : {
1178 : //first reduce spacing
1179 2645 : while (nRowSpacing)
1180 : {
1181 1587 : nRowSpacing /= 2;
1182 1587 : aRequisition = calculateRequisitionForSpacings(nRowSpacing, nColSpacing);
1183 1587 : if (aRequisition.Height() <= rAllocation.Height())
1184 0 : break;
1185 : }
1186 :
1187 : //share out the remaining pain to everyone
1188 529 : long nExtraHeight = (rAllocation.Height() - aRequisition.Height()) / nMaxY;
1189 :
1190 1442 : for (sal_Int32 y = 0; y < nMaxY; ++y)
1191 913 : aHeights[y].m_nValue += nExtraHeight;
1192 : }
1193 :
1194 643 : if (nExtraHeightForExpanders)
1195 : {
1196 342 : for (sal_Int32 y = 0; y < nMaxY; ++y)
1197 228 : if (aHeights[y].m_bExpand)
1198 114 : aHeights[y].m_nValue += nExtraHeightForExpanders;
1199 : }
1200 : }
1201 :
1202 1424 : Point aAllocPos(0, 0);
1203 4777 : for (sal_Int32 x = 0; x < nMaxX; ++x)
1204 : {
1205 8842 : for (sal_Int32 y = 0; y < nMaxY; ++y)
1206 : {
1207 5489 : GridEntry &rEntry = A[x][y];
1208 5489 : vcl::Window *pChild = rEntry.pChild;
1209 5489 : if (pChild)
1210 : {
1211 4999 : Size aChildAlloc(0, 0);
1212 :
1213 4999 : sal_Int32 nWidth = rEntry.nSpanWidth;
1214 10484 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
1215 5485 : aChildAlloc.Width() += aWidths[x+nSpanX].m_nValue;
1216 4999 : aChildAlloc.Width() += nColSpacing*(nWidth-1);
1217 :
1218 4999 : sal_Int32 nHeight = rEntry.nSpanHeight;
1219 9998 : for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
1220 4999 : aChildAlloc.Height() += aHeights[y+nSpanY].m_nValue;
1221 4999 : aChildAlloc.Height() += nRowSpacing*(nHeight-1);
1222 :
1223 4999 : setLayoutAllocation(*pChild, aAllocPos, aChildAlloc);
1224 : }
1225 5489 : aAllocPos.Y() += aHeights[y].m_nValue + nRowSpacing;
1226 : }
1227 3353 : aAllocPos.X() += aWidths[x].m_nValue + nColSpacing;
1228 3353 : aAllocPos.Y() = 0;
1229 1424 : }
1230 : }
1231 :
1232 49857 : bool toBool(const OString &rValue)
1233 : {
1234 49857 : return (!rValue.isEmpty() && (rValue[0] == 't' || rValue[0] == 'T' || rValue[0] == '1'));
1235 : }
1236 :
1237 5252 : bool VclGrid::set_property(const OString &rKey, const OString &rValue)
1238 : {
1239 5252 : if (rKey == "row-spacing")
1240 696 : set_row_spacing(rValue.toInt32());
1241 4556 : else if (rKey == "column-spacing")
1242 830 : set_column_spacing(rValue.toInt32());
1243 3726 : else if (rKey == "row-homogeneous")
1244 0 : set_row_homogeneous(toBool(rValue));
1245 3726 : else if (rKey == "column-homogeneous")
1246 676 : set_column_homogeneous(toBool(rValue));
1247 3050 : else if (rKey == "n-rows")
1248 : /*nothing to do*/;
1249 : else
1250 3050 : return VclContainer::set_property(rKey, rValue);
1251 2202 : 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 0 : VclFrame::~VclFrame()
1290 : {
1291 0 : disposeOnce();
1292 0 : }
1293 :
1294 0 : void VclFrame::dispose()
1295 : {
1296 0 : m_pLabel.clear();
1297 0 : VclBin::dispose();
1298 0 : }
1299 :
1300 : //To-Do, hook a DecorationView into VclFrame ?
1301 :
1302 0 : Size VclFrame::calculateRequisition() const
1303 : {
1304 0 : Size aRet(0, 0);
1305 :
1306 0 : const vcl::Window *pChild = get_child();
1307 0 : const vcl::Window *pLabel = get_label_widget();
1308 :
1309 0 : if (pChild && pChild->IsVisible())
1310 0 : aRet = getLayoutRequisition(*pChild);
1311 :
1312 0 : if (pLabel && pLabel->IsVisible())
1313 : {
1314 0 : Size aLabelSize = getLayoutRequisition(*pLabel);
1315 0 : aRet.Height() += aLabelSize.Height();
1316 0 : aRet.Width() = std::max(aLabelSize.Width(), aRet.Width());
1317 : }
1318 :
1319 : const FrameStyle &rFrameStyle =
1320 0 : GetSettings().GetStyleSettings().GetFrameStyle();
1321 0 : aRet.Width() += rFrameStyle.left + rFrameStyle.right;
1322 0 : aRet.Height() += rFrameStyle.top + rFrameStyle.bottom;
1323 :
1324 0 : return aRet;
1325 : }
1326 :
1327 0 : void VclFrame::setAllocation(const Size &rAllocation)
1328 : {
1329 : //SetBackground( Color(0xFF, 0x00, 0xFF) );
1330 :
1331 : const FrameStyle &rFrameStyle =
1332 0 : GetSettings().GetStyleSettings().GetFrameStyle();
1333 0 : Size aAllocation(rAllocation.Width() - rFrameStyle.left - rFrameStyle.right,
1334 0 : rAllocation.Height() - rFrameStyle.top - rFrameStyle.bottom);
1335 0 : Point aChildPos(rFrameStyle.left, rFrameStyle.top);
1336 :
1337 0 : vcl::Window *pChild = get_child();
1338 0 : vcl::Window *pLabel = get_label_widget();
1339 :
1340 0 : if (pLabel && pLabel->IsVisible())
1341 : {
1342 0 : Size aLabelSize = getLayoutRequisition(*pLabel);
1343 0 : aLabelSize.Height() = std::min(aLabelSize.Height(), aAllocation.Height());
1344 0 : aLabelSize.Width() = std::min(aLabelSize.Width(), aAllocation.Width());
1345 0 : setLayoutAllocation(*pLabel, aChildPos, aLabelSize);
1346 0 : aAllocation.Height() -= aLabelSize.Height();
1347 0 : aChildPos.Y() += aLabelSize.Height();
1348 : }
1349 :
1350 0 : if (pChild && pChild->IsVisible())
1351 0 : setLayoutAllocation(*pChild, aChildPos, aAllocation);
1352 0 : }
1353 :
1354 0 : IMPL_LINK(VclFrame, WindowEventListener, VclSimpleEvent*, pEvent)
1355 : {
1356 0 : if (pEvent && pEvent->GetId() == VCLEVENT_OBJECT_DYING)
1357 0 : designate_label(NULL);
1358 0 : return 0;
1359 : }
1360 :
1361 0 : void VclFrame::designate_label(vcl::Window *pWindow)
1362 : {
1363 : assert(!pWindow || pWindow->GetParent() == this);
1364 0 : if (m_pLabel)
1365 0 : m_pLabel->RemoveEventListener(LINK(this, VclFrame, WindowEventListener));
1366 0 : m_pLabel = pWindow;
1367 0 : if (m_pLabel)
1368 0 : m_pLabel->AddEventListener(LINK(this, VclFrame, WindowEventListener));
1369 0 : }
1370 :
1371 0 : const vcl::Window *VclFrame::get_label_widget() const
1372 : {
1373 : assert(GetChildCount() == 2);
1374 0 : if (m_pLabel)
1375 0 : return m_pLabel;
1376 : //The label widget is normally the first (of two) children
1377 0 : const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1378 0 : if (pWindowImpl->mpFirstChild == pWindowImpl->mpLastChild) //no label exists
1379 0 : return NULL;
1380 0 : return pWindowImpl->mpFirstChild;
1381 : }
1382 :
1383 0 : vcl::Window *VclFrame::get_label_widget()
1384 : {
1385 0 : return const_cast<vcl::Window*>(const_cast<const VclFrame*>(this)->get_label_widget());
1386 : }
1387 :
1388 0 : const vcl::Window *VclFrame::get_child() const
1389 : {
1390 : assert(GetChildCount() == 2);
1391 : //The child widget is the normally the last (of two) children
1392 0 : const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1393 0 : if (!m_pLabel)
1394 0 : return pWindowImpl->mpLastChild;
1395 0 : if (pWindowImpl->mpFirstChild == pWindowImpl->mpLastChild) //only label exists
1396 0 : return NULL;
1397 0 : return pWindowImpl->mpLastChild;
1398 : }
1399 :
1400 0 : vcl::Window *VclFrame::get_child()
1401 : {
1402 0 : return const_cast<vcl::Window*>(const_cast<const VclFrame*>(this)->get_child());
1403 : }
1404 :
1405 0 : void VclFrame::set_label(const OUString &rLabel)
1406 : {
1407 0 : vcl::Window *pLabel = get_label_widget();
1408 : assert(pLabel);
1409 0 : pLabel->SetText(rLabel);
1410 0 : }
1411 :
1412 0 : OUString VclFrame::get_label() const
1413 : {
1414 0 : const vcl::Window *pLabel = get_label_widget();
1415 : assert(pLabel);
1416 0 : return pLabel->GetText();
1417 : }
1418 :
1419 0 : OUString VclFrame::getDefaultAccessibleName() const
1420 : {
1421 0 : const vcl::Window *pLabel = get_label_widget();
1422 0 : if (pLabel)
1423 0 : return pLabel->GetAccessibleName();
1424 0 : return VclBin::getDefaultAccessibleName();
1425 : }
1426 :
1427 0 : Size VclAlignment::calculateRequisition() const
1428 : {
1429 0 : Size aRet(m_nLeftPadding + m_nRightPadding,
1430 0 : m_nTopPadding + m_nBottomPadding);
1431 :
1432 0 : const vcl::Window *pChild = get_child();
1433 0 : if (pChild && pChild->IsVisible())
1434 : {
1435 0 : Size aChildSize = getLayoutRequisition(*pChild);
1436 0 : aRet.Width() += aChildSize.Width();
1437 0 : aRet.Height() += aChildSize.Height();
1438 : }
1439 :
1440 0 : return aRet;
1441 : }
1442 :
1443 0 : void VclAlignment::setAllocation(const Size &rAllocation)
1444 : {
1445 0 : vcl::Window *pChild = get_child();
1446 0 : if (!pChild || !pChild->IsVisible())
1447 0 : return;
1448 :
1449 0 : Point aChildPos(m_nLeftPadding, m_nTopPadding);
1450 :
1451 0 : Size aAllocation;
1452 0 : aAllocation.Width() = rAllocation.Width() - (m_nLeftPadding + m_nRightPadding);
1453 0 : aAllocation.Height() = rAllocation.Height() - (m_nTopPadding + m_nBottomPadding);
1454 :
1455 0 : setLayoutAllocation(*pChild, aChildPos, aAllocation);
1456 : }
1457 :
1458 0 : bool VclAlignment::set_property(const OString &rKey, const OString &rValue)
1459 : {
1460 0 : if (rKey == "bottom-padding")
1461 0 : m_nBottomPadding = rValue.toInt32();
1462 0 : else if (rKey == "left-padding")
1463 0 : m_nLeftPadding = rValue.toInt32();
1464 0 : else if (rKey == "right-padding")
1465 0 : m_nRightPadding = rValue.toInt32();
1466 0 : else if (rKey == "top-padding")
1467 0 : m_nTopPadding = rValue.toInt32();
1468 0 : else if (rKey == "xalign")
1469 0 : m_fXAlign = rValue.toFloat();
1470 0 : else if (rKey == "xscale")
1471 0 : m_fXScale = rValue.toFloat();
1472 0 : else if (rKey == "yalign")
1473 0 : m_fYAlign = rValue.toFloat();
1474 0 : else if (rKey == "yscale")
1475 0 : m_fYScale = rValue.toFloat();
1476 : else
1477 0 : return VclBin::set_property(rKey, rValue);
1478 0 : return true;
1479 : }
1480 :
1481 0 : void VclExpander::dispose()
1482 : {
1483 0 : m_pDisclosureButton.disposeAndClear();
1484 0 : VclBin::dispose();
1485 0 : }
1486 :
1487 0 : const vcl::Window *VclExpander::get_child() const
1488 : {
1489 0 : const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1490 :
1491 : assert(pWindowImpl->mpFirstChild == m_pDisclosureButton);
1492 :
1493 0 : return pWindowImpl->mpFirstChild->GetWindow(GetWindowType::Next);
1494 : }
1495 :
1496 0 : vcl::Window *VclExpander::get_child()
1497 : {
1498 0 : return const_cast<vcl::Window*>(const_cast<const VclExpander*>(this)->get_child());
1499 : }
1500 :
1501 0 : Size VclExpander::calculateRequisition() const
1502 : {
1503 0 : Size aRet(0, 0);
1504 :
1505 0 : WindowImpl* pWindowImpl = ImplGetWindowImpl();
1506 :
1507 0 : const vcl::Window *pChild = get_child();
1508 0 : const vcl::Window *pLabel = pChild != pWindowImpl->mpLastChild ? pWindowImpl->mpLastChild.get() : NULL;
1509 :
1510 0 : if (pChild && pChild->IsVisible() && m_pDisclosureButton->IsChecked())
1511 0 : aRet = getLayoutRequisition(*pChild);
1512 :
1513 0 : Size aExpanderSize = getLayoutRequisition(*m_pDisclosureButton);
1514 :
1515 0 : if (pLabel && pLabel->IsVisible())
1516 : {
1517 0 : Size aLabelSize = getLayoutRequisition(*pLabel);
1518 0 : aExpanderSize.Height() = std::max(aExpanderSize.Height(), aLabelSize.Height());
1519 0 : aExpanderSize.Width() += aLabelSize.Width();
1520 : }
1521 :
1522 0 : aRet.Height() += aExpanderSize.Height();
1523 0 : aRet.Width() = std::max(aExpanderSize.Width(), aRet.Width());
1524 :
1525 : const FrameStyle &rFrameStyle =
1526 0 : GetSettings().GetStyleSettings().GetFrameStyle();
1527 0 : aRet.Width() += rFrameStyle.left + rFrameStyle.right;
1528 0 : aRet.Height() += rFrameStyle.top + rFrameStyle.bottom;
1529 :
1530 0 : return aRet;
1531 : }
1532 :
1533 0 : void VclExpander::setAllocation(const Size &rAllocation)
1534 : {
1535 : const FrameStyle &rFrameStyle =
1536 0 : GetSettings().GetStyleSettings().GetFrameStyle();
1537 0 : Size aAllocation(rAllocation.Width() - rFrameStyle.left - rFrameStyle.right,
1538 0 : rAllocation.Height() - rFrameStyle.top - rFrameStyle.bottom);
1539 0 : Point aChildPos(rFrameStyle.left, rFrameStyle.top);
1540 :
1541 0 : WindowImpl* pWindowImpl = ImplGetWindowImpl();
1542 :
1543 : //The label widget is the last (of two) children
1544 0 : vcl::Window *pChild = get_child();
1545 0 : vcl::Window *pLabel = pChild != pWindowImpl->mpLastChild.get() ? pWindowImpl->mpLastChild.get() : NULL;
1546 :
1547 0 : Size aButtonSize = getLayoutRequisition(*m_pDisclosureButton);
1548 0 : Size aLabelSize;
1549 0 : Size aExpanderSize = aButtonSize;
1550 0 : if (pLabel && pLabel->IsVisible())
1551 : {
1552 0 : aLabelSize = getLayoutRequisition(*pLabel);
1553 0 : aExpanderSize.Height() = std::max(aExpanderSize.Height(), aLabelSize.Height());
1554 0 : aExpanderSize.Width() += aLabelSize.Width();
1555 : }
1556 :
1557 0 : aExpanderSize.Height() = std::min(aExpanderSize.Height(), aAllocation.Height());
1558 0 : aExpanderSize.Width() = std::min(aExpanderSize.Width(), aAllocation.Width());
1559 :
1560 0 : aButtonSize.Height() = std::min(aButtonSize.Height(), aExpanderSize.Height());
1561 0 : aButtonSize.Width() = std::min(aButtonSize.Width(), aExpanderSize.Width());
1562 :
1563 0 : long nExtraExpanderHeight = aExpanderSize.Height() - aButtonSize.Height();
1564 0 : Point aButtonPos(aChildPos.X(), aChildPos.Y() + nExtraExpanderHeight/2);
1565 0 : setLayoutAllocation(*m_pDisclosureButton, aButtonPos, aButtonSize);
1566 :
1567 0 : if (pLabel && pLabel->IsVisible())
1568 : {
1569 0 : aLabelSize.Height() = std::min(aLabelSize.Height(), aExpanderSize.Height());
1570 0 : aLabelSize.Width() = std::min(aLabelSize.Width(),
1571 0 : aExpanderSize.Width() - aButtonSize.Width());
1572 :
1573 0 : long nExtraLabelHeight = aExpanderSize.Height() - aLabelSize.Height();
1574 0 : Point aLabelPos(aChildPos.X() + aButtonSize.Width(), aChildPos.Y() + nExtraLabelHeight/2);
1575 0 : setLayoutAllocation(*pLabel, aLabelPos, aLabelSize);
1576 : }
1577 :
1578 0 : aAllocation.Height() -= aExpanderSize.Height();
1579 0 : aChildPos.Y() += aExpanderSize.Height();
1580 :
1581 0 : if (pChild && pChild->IsVisible())
1582 : {
1583 0 : if (!m_pDisclosureButton->IsChecked())
1584 0 : aAllocation = Size();
1585 0 : setLayoutAllocation(*pChild, aChildPos, aAllocation);
1586 : }
1587 0 : }
1588 :
1589 0 : bool VclExpander::set_property(const OString &rKey, const OString &rValue)
1590 : {
1591 0 : if (rKey == "expanded")
1592 0 : set_expanded(toBool(rValue));
1593 0 : else if (rKey == "resize-toplevel")
1594 0 : m_bResizeTopLevel = toBool(rValue);
1595 : else
1596 0 : return VclBin::set_property(rKey, rValue);
1597 0 : return true;
1598 : }
1599 :
1600 0 : void VclExpander::StateChanged(StateChangedType nType)
1601 : {
1602 0 : VclBin::StateChanged( nType );
1603 :
1604 0 : if (nType == StateChangedType::InitShow)
1605 : {
1606 0 : vcl::Window *pChild = get_child();
1607 0 : if (pChild)
1608 0 : pChild->Show(m_pDisclosureButton->IsChecked());
1609 : }
1610 0 : }
1611 :
1612 0 : IMPL_LINK( VclExpander, ClickHdl, DisclosureButton*, pBtn )
1613 : {
1614 0 : vcl::Window *pChild = get_child();
1615 0 : if (pChild)
1616 : {
1617 0 : pChild->Show(pBtn->IsChecked());
1618 0 : queue_resize();
1619 0 : Dialog* pResizeDialog = m_bResizeTopLevel ? GetParentDialog() : NULL;
1620 0 : if (pResizeDialog)
1621 0 : pResizeDialog->setOptimalLayoutSize();
1622 : }
1623 0 : maExpandedHdl.Call(this);
1624 0 : return 0;
1625 : }
1626 :
1627 0 : VclScrolledWindow::VclScrolledWindow(vcl::Window *pParent, WinBits nStyle)
1628 : : VclBin(pParent, nStyle)
1629 : , m_bUserManagedScrolling(false)
1630 : , m_pVScroll(VclPtr<ScrollBar>::Create(this, WB_HIDE | WB_VERT))
1631 : , m_pHScroll(VclPtr<ScrollBar>::Create(this, WB_HIDE | WB_HORZ))
1632 0 : , m_aScrollBarBox(VclPtr<ScrollBarBox>::Create(this, WB_HIDE))
1633 : {
1634 0 : SetType(WINDOW_SCROLLWINDOW);
1635 :
1636 0 : Link<> aLink( LINK( this, VclScrolledWindow, ScrollBarHdl ) );
1637 0 : m_pVScroll->SetScrollHdl(aLink);
1638 0 : m_pHScroll->SetScrollHdl(aLink);
1639 0 : }
1640 :
1641 0 : void VclScrolledWindow::dispose()
1642 : {
1643 0 : m_pVScroll.disposeAndClear();
1644 0 : m_pHScroll.disposeAndClear();
1645 0 : m_aScrollBarBox.disposeAndClear();
1646 0 : VclBin::dispose();
1647 0 : }
1648 :
1649 0 : IMPL_LINK_NOARG(VclScrolledWindow, ScrollBarHdl)
1650 : {
1651 0 : vcl::Window *pChild = get_child();
1652 0 : if (!pChild)
1653 0 : return 1;
1654 :
1655 : assert(dynamic_cast<VclViewport*>(pChild) && "scrolledwindow child should be a Viewport");
1656 :
1657 0 : pChild = pChild->GetWindow(GetWindowType::FirstChild);
1658 :
1659 0 : if (!pChild)
1660 0 : return 1;
1661 :
1662 0 : Point aWinPos;
1663 :
1664 0 : if (m_pHScroll->IsVisible())
1665 : {
1666 0 : aWinPos.X() = -m_pHScroll->GetThumbPos();
1667 : }
1668 :
1669 0 : if (m_pVScroll->IsVisible())
1670 : {
1671 0 : aWinPos.Y() = -m_pVScroll->GetThumbPos();
1672 : }
1673 :
1674 0 : pChild->SetPosPixel(aWinPos);
1675 :
1676 0 : return 1;
1677 : }
1678 :
1679 0 : const vcl::Window *VclScrolledWindow::get_child() const
1680 : {
1681 : assert(GetChildCount() == 4);
1682 0 : const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1683 0 : return pWindowImpl->mpLastChild;
1684 : }
1685 :
1686 0 : vcl::Window *VclScrolledWindow::get_child()
1687 : {
1688 0 : return const_cast<vcl::Window*>(const_cast<const VclScrolledWindow*>(this)->get_child());
1689 : }
1690 :
1691 0 : Size VclScrolledWindow::calculateRequisition() const
1692 : {
1693 0 : Size aRet(0, 0);
1694 :
1695 0 : const vcl::Window *pChild = get_child();
1696 0 : if (pChild && pChild->IsVisible())
1697 0 : aRet = getLayoutRequisition(*pChild);
1698 :
1699 0 : if (GetStyle() & WB_VSCROLL)
1700 0 : aRet.Width() += getLayoutRequisition(*m_pVScroll).Width();
1701 :
1702 0 : if (GetStyle() & WB_HSCROLL)
1703 0 : aRet.Height() += getLayoutRequisition(*m_pHScroll).Height();
1704 :
1705 0 : return aRet;
1706 : }
1707 :
1708 0 : void VclScrolledWindow::InitScrollBars(const Size &rRequest)
1709 : {
1710 0 : const vcl::Window *pChild = get_child();
1711 0 : if (!pChild || !pChild->IsVisible())
1712 0 : return;
1713 :
1714 0 : Size aOutSize(getVisibleChildSize());
1715 :
1716 0 : if (m_pVScroll->IsVisible())
1717 : {
1718 0 : m_pVScroll->SetRangeMax(rRequest.Height());
1719 0 : m_pVScroll->SetVisibleSize(aOutSize.Height());
1720 0 : m_pVScroll->SetPageSize(16);
1721 : }
1722 :
1723 0 : if (m_pHScroll->IsVisible())
1724 : {
1725 0 : m_pHScroll->SetRangeMax(rRequest.Width());
1726 0 : m_pHScroll->SetVisibleSize(aOutSize.Width());
1727 0 : m_pHScroll->SetPageSize(16);
1728 : }
1729 : }
1730 :
1731 0 : void VclScrolledWindow::setAllocation(const Size &rAllocation)
1732 : {
1733 0 : Size aChildAllocation(rAllocation);
1734 0 : Size aChildReq;
1735 :
1736 0 : vcl::Window *pChild = get_child();
1737 0 : if (pChild && pChild->IsVisible())
1738 0 : aChildReq = getLayoutRequisition(*pChild);
1739 :
1740 0 : long nAvailHeight = rAllocation.Height();
1741 0 : long nAvailWidth = rAllocation.Width();
1742 : // vert. ScrollBar
1743 0 : if (GetStyle() & WB_AUTOVSCROLL)
1744 : {
1745 0 : m_pVScroll->Show(nAvailHeight < aChildReq.Height());
1746 : }
1747 :
1748 0 : if (m_pVScroll->IsVisible())
1749 0 : nAvailWidth -= getLayoutRequisition(*m_pVScroll).Width();
1750 :
1751 : // horz. ScrollBar
1752 0 : if (GetStyle() & WB_AUTOHSCROLL)
1753 : {
1754 0 : bool bShowHScroll = nAvailWidth < aChildReq.Width();
1755 0 : m_pHScroll->Show(bShowHScroll);
1756 :
1757 0 : if (bShowHScroll)
1758 0 : nAvailHeight -= getLayoutRequisition(*m_pHScroll).Height();
1759 :
1760 0 : if (GetStyle() & WB_AUTOVSCROLL)
1761 0 : m_pVScroll->Show(nAvailHeight < aChildReq.Height());
1762 : }
1763 :
1764 0 : Size aInnerSize(aChildAllocation);
1765 0 : long nScrollBarWidth = 0, nScrollBarHeight = 0;
1766 :
1767 0 : if (m_pVScroll->IsVisible())
1768 : {
1769 0 : nScrollBarWidth = getLayoutRequisition(*m_pVScroll).Width();
1770 0 : Point aScrollPos(rAllocation.Width() - nScrollBarWidth, 0);
1771 0 : Size aScrollSize(nScrollBarWidth, rAllocation.Height());
1772 0 : setLayoutAllocation(*m_pVScroll, aScrollPos, aScrollSize);
1773 0 : aChildAllocation.Width() -= nScrollBarWidth;
1774 0 : aInnerSize.Width() -= nScrollBarWidth;
1775 0 : aChildAllocation.Height() = aChildReq.Height();
1776 : }
1777 :
1778 0 : if (m_pHScroll->IsVisible())
1779 : {
1780 0 : nScrollBarHeight = getLayoutRequisition(*m_pHScroll).Height();
1781 0 : Point aScrollPos(0, rAllocation.Height() - nScrollBarHeight);
1782 0 : Size aScrollSize(rAllocation.Width(), nScrollBarHeight);
1783 0 : setLayoutAllocation(*m_pHScroll, aScrollPos, aScrollSize);
1784 0 : aChildAllocation.Height() -= nScrollBarHeight;
1785 0 : aInnerSize.Height() -= nScrollBarHeight;
1786 0 : aChildAllocation.Width() = aChildReq.Width();
1787 : }
1788 :
1789 0 : if (m_pVScroll->IsVisible() && m_pHScroll->IsVisible())
1790 : {
1791 0 : Point aBoxPos(aInnerSize.Width(), aInnerSize.Height());
1792 0 : m_aScrollBarBox->SetPosSizePixel(aBoxPos, Size(nScrollBarWidth, nScrollBarHeight));
1793 0 : m_aScrollBarBox->Show();
1794 : }
1795 : else
1796 : {
1797 0 : m_aScrollBarBox->Hide();
1798 : }
1799 :
1800 0 : if (pChild && pChild->IsVisible())
1801 : {
1802 : assert(dynamic_cast<VclViewport*>(pChild) && "scrolledwindow child should be a Viewport");
1803 0 : setLayoutAllocation(*pChild, Point(0, 0), aInnerSize);
1804 : }
1805 :
1806 0 : if (!m_bUserManagedScrolling)
1807 0 : InitScrollBars(aChildReq);
1808 0 : }
1809 :
1810 0 : Size VclScrolledWindow::getVisibleChildSize() const
1811 : {
1812 0 : Size aRet(GetSizePixel());
1813 0 : if (m_pVScroll->IsVisible())
1814 0 : aRet.Width() -= m_pVScroll->GetSizePixel().Width();
1815 0 : if (m_pHScroll->IsVisible())
1816 0 : aRet.Height() -= m_pHScroll->GetSizePixel().Height();
1817 0 : return aRet;
1818 : }
1819 :
1820 0 : bool VclScrolledWindow::set_property(const OString &rKey, const OString &rValue)
1821 : {
1822 0 : bool bRet = VclBin::set_property(rKey, rValue);
1823 0 : m_pVScroll->Show((GetStyle() & WB_VSCROLL) != 0);
1824 0 : m_pHScroll->Show((GetStyle() & WB_HSCROLL) != 0);
1825 0 : return bRet;
1826 : }
1827 :
1828 0 : bool VclScrolledWindow::Notify(NotifyEvent& rNEvt)
1829 : {
1830 0 : bool nDone = false;
1831 0 : if ( rNEvt.GetType() == MouseNotifyEvent::COMMAND )
1832 : {
1833 0 : const CommandEvent& rCEvt = *rNEvt.GetCommandEvent();
1834 0 : if ( rCEvt.GetCommand() == CommandEventId::Wheel )
1835 : {
1836 0 : const CommandWheelData* pData = rCEvt.GetWheelData();
1837 0 : if( !pData->GetModifier() && ( pData->GetMode() == CommandWheelMode::SCROLL ) )
1838 : {
1839 0 : nDone = HandleScrollCommand(rCEvt, m_pHScroll, m_pVScroll);
1840 : }
1841 : }
1842 : }
1843 :
1844 0 : return nDone || VclBin::Notify( rNEvt );
1845 : }
1846 :
1847 0 : void VclViewport::setAllocation(const Size &rAllocation)
1848 : {
1849 0 : vcl::Window *pChild = get_child();
1850 0 : if (pChild && pChild->IsVisible())
1851 : {
1852 0 : Size aReq(getLayoutRequisition(*pChild));
1853 0 : aReq.Width() = std::max(aReq.Width(), rAllocation.Width());
1854 0 : aReq.Height() = std::max(aReq.Height(), rAllocation.Height());
1855 0 : setLayoutAllocation(*pChild, Point(0, 0), aReq);
1856 : }
1857 0 : }
1858 :
1859 0 : const vcl::Window *VclEventBox::get_child() const
1860 : {
1861 0 : const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1862 :
1863 : assert(pWindowImpl->mpFirstChild.get() == m_aEventBoxHelper.get());
1864 :
1865 0 : return pWindowImpl->mpFirstChild->GetWindow(GetWindowType::Next);
1866 : }
1867 :
1868 0 : vcl::Window *VclEventBox::get_child()
1869 : {
1870 0 : return const_cast<vcl::Window*>(const_cast<const VclEventBox*>(this)->get_child());
1871 : }
1872 :
1873 0 : void VclEventBox::setAllocation(const Size& rAllocation)
1874 : {
1875 0 : Point aChildPos(0, 0);
1876 0 : for (vcl::Window *pChild = GetWindow(GetWindowType::FirstChild); pChild; pChild = pChild->GetWindow(GetWindowType::Next))
1877 : {
1878 0 : if (!pChild->IsVisible())
1879 0 : continue;
1880 0 : setLayoutAllocation(*pChild, aChildPos, rAllocation);
1881 : }
1882 0 : }
1883 :
1884 0 : Size VclEventBox::calculateRequisition() const
1885 : {
1886 0 : Size aRet(0, 0);
1887 :
1888 0 : for (const vcl::Window* pChild = get_child(); pChild;
1889 : pChild = pChild->GetWindow(GetWindowType::Next))
1890 : {
1891 0 : if (!pChild->IsVisible())
1892 0 : continue;
1893 0 : Size aChildSize = getLayoutRequisition(*pChild);
1894 0 : aRet.Width() = std::max(aRet.Width(), aChildSize.Width());
1895 0 : aRet.Height() = std::max(aRet.Height(), aChildSize.Height());
1896 : }
1897 :
1898 0 : return aRet;
1899 : }
1900 :
1901 0 : void VclEventBox::Command(const CommandEvent&)
1902 : {
1903 : //discard events by default to block them reaching children
1904 0 : }
1905 :
1906 0 : VclEventBox::~VclEventBox()
1907 : {
1908 0 : disposeOnce();
1909 0 : }
1910 :
1911 0 : void VclEventBox::dispose()
1912 : {
1913 0 : m_aEventBoxHelper.disposeAndClear();
1914 0 : VclBin::dispose();
1915 0 : }
1916 :
1917 339 : void VclSizeGroup::trigger_queue_resize()
1918 : {
1919 : //sufficient to trigger one widget to trigger all of them
1920 339 : if (!m_aWindows.empty())
1921 : {
1922 0 : vcl::Window *pWindow = *m_aWindows.begin();
1923 0 : pWindow->queue_resize();
1924 : }
1925 339 : }
1926 :
1927 0 : void VclSizeGroup::set_ignore_hidden(bool bIgnoreHidden)
1928 : {
1929 0 : if (bIgnoreHidden != m_bIgnoreHidden)
1930 : {
1931 0 : m_bIgnoreHidden = bIgnoreHidden;
1932 0 : trigger_queue_resize();
1933 : }
1934 0 : }
1935 :
1936 339 : void VclSizeGroup::set_mode(VclSizeGroupMode eMode)
1937 : {
1938 339 : if (eMode != m_eMode)
1939 : {
1940 339 : m_eMode = eMode;
1941 339 : trigger_queue_resize();
1942 : }
1943 :
1944 339 : }
1945 :
1946 339 : bool VclSizeGroup::set_property(const OString &rKey, const OString &rValue)
1947 : {
1948 339 : if (rKey == "ignore-hidden")
1949 0 : set_ignore_hidden(toBool(rValue));
1950 339 : else if (rKey == "mode")
1951 : {
1952 339 : VclSizeGroupMode eMode = VCL_SIZE_GROUP_HORIZONTAL;
1953 339 : if (rValue.equals("none"))
1954 0 : eMode = VCL_SIZE_GROUP_NONE;
1955 339 : else if (rValue.equals("horizontal"))
1956 0 : eMode = VCL_SIZE_GROUP_HORIZONTAL;
1957 339 : else if (rValue.equals("vertical"))
1958 338 : eMode = VCL_SIZE_GROUP_VERTICAL;
1959 1 : else if (rValue.equals("both"))
1960 1 : eMode = VCL_SIZE_GROUP_BOTH;
1961 : else
1962 : {
1963 : SAL_WARN("vcl.layout", "unknown size group mode" << rValue.getStr());
1964 : }
1965 339 : set_mode(eMode);
1966 : }
1967 : else
1968 : {
1969 : SAL_INFO("vcl.layout", "unhandled property: " << rKey.getStr());
1970 0 : return false;
1971 : }
1972 339 : return true;
1973 : }
1974 :
1975 0 : void MessageDialog::create_owned_areas()
1976 : {
1977 0 : set_border_width(12);
1978 0 : m_pOwnedContentArea.set(VclPtr<VclVBox>::Create(this, false, 24));
1979 0 : set_content_area(m_pOwnedContentArea);
1980 0 : m_pOwnedContentArea->Show();
1981 0 : m_pOwnedActionArea.set( VclPtr<VclHButtonBox>::Create(m_pOwnedContentArea) );
1982 0 : set_action_area(m_pOwnedActionArea);
1983 0 : m_pOwnedActionArea->Show();
1984 0 : }
1985 :
1986 0 : MessageDialog::MessageDialog(vcl::Window* pParent, WinBits nStyle)
1987 : : Dialog(pParent, nStyle)
1988 : , m_eButtonsType(VCL_BUTTONS_NONE)
1989 : , m_eMessageType(VCL_MESSAGE_INFO)
1990 : , m_pOwnedContentArea(NULL)
1991 : , m_pOwnedActionArea(NULL)
1992 : , m_pGrid(NULL)
1993 : , m_pImage(NULL)
1994 : , m_pPrimaryMessage(NULL)
1995 0 : , m_pSecondaryMessage(NULL)
1996 : {
1997 0 : SetType(WINDOW_MESSBOX);
1998 0 : }
1999 :
2000 0 : MessageDialog::MessageDialog(vcl::Window* pParent,
2001 : const OUString &rMessage,
2002 : VclMessageType eMessageType,
2003 : VclButtonsType eButtonsType,
2004 : WinBits nStyle)
2005 : : Dialog(pParent, nStyle)
2006 : , m_eButtonsType(eButtonsType)
2007 : , m_eMessageType(eMessageType)
2008 : , m_pGrid(NULL)
2009 : , m_pImage(NULL)
2010 : , m_pPrimaryMessage(NULL)
2011 : , m_pSecondaryMessage(NULL)
2012 0 : , m_sPrimaryString(rMessage)
2013 : {
2014 0 : SetType(WINDOW_MESSBOX);
2015 0 : create_owned_areas();
2016 0 : }
2017 :
2018 0 : MessageDialog::MessageDialog(vcl::Window* pParent, const OString& rID, const OUString& rUIXMLDescription)
2019 : : Dialog(pParent, OStringToOUString(rID, RTL_TEXTENCODING_UTF8), rUIXMLDescription, WINDOW_MESSBOX)
2020 : , m_eButtonsType(VCL_BUTTONS_NONE)
2021 : , m_eMessageType(VCL_MESSAGE_INFO)
2022 : , m_pOwnedContentArea(NULL)
2023 : , m_pOwnedActionArea(NULL)
2024 : , m_pGrid(NULL)
2025 : , m_pImage(NULL)
2026 : , m_pPrimaryMessage(NULL)
2027 0 : , m_pSecondaryMessage(NULL)
2028 : {
2029 0 : }
2030 :
2031 0 : void MessageDialog::dispose()
2032 : {
2033 0 : for (size_t i = 0; i < m_aOwnedButtons.size(); ++i)
2034 0 : m_aOwnedButtons[i].disposeAndClear();
2035 0 : m_aOwnedButtons.clear();
2036 :
2037 0 : m_pPrimaryMessage.disposeAndClear();
2038 0 : m_pSecondaryMessage.disposeAndClear();
2039 0 : m_pImage.disposeAndClear();
2040 0 : m_pGrid.disposeAndClear();
2041 0 : m_pOwnedActionArea.disposeAndClear();
2042 0 : m_pOwnedContentArea.disposeAndClear();
2043 0 : Dialog::dispose();
2044 0 : }
2045 :
2046 0 : MessageDialog::~MessageDialog()
2047 : {
2048 0 : disposeOnce();
2049 0 : }
2050 :
2051 0 : void MessageDialog::response(short nResponseId)
2052 : {
2053 0 : EndDialog(nResponseId);
2054 0 : }
2055 :
2056 0 : IMPL_LINK(MessageDialog, ButtonHdl, Button *, pButton)
2057 : {
2058 0 : response(get_response(pButton));
2059 0 : return 0;
2060 : }
2061 :
2062 0 : short MessageDialog::get_response(const vcl::Window *pWindow) const
2063 : {
2064 0 : auto aFind = m_aResponses.find(pWindow);
2065 0 : if (aFind != m_aResponses.end())
2066 0 : return aFind->second;
2067 0 : if (!m_pUIBuilder)
2068 0 : return RET_CANCEL;
2069 0 : return m_pUIBuilder->get_response(pWindow);
2070 : }
2071 :
2072 0 : void MessageDialog::setButtonHandlers(VclButtonBox *pButtonBox)
2073 : {
2074 : assert(pButtonBox);
2075 0 : for (vcl::Window* pChild = pButtonBox->GetWindow(GetWindowType::FirstChild); pChild;
2076 : pChild = pChild->GetWindow(GetWindowType::Next))
2077 : {
2078 0 : switch (pChild->GetType())
2079 : {
2080 : case WINDOW_PUSHBUTTON:
2081 : {
2082 0 : PushButton* pButton = static_cast<PushButton*>(pChild);
2083 0 : pButton->SetClickHdl(LINK(this, MessageDialog, ButtonHdl));
2084 0 : break;
2085 : }
2086 : //insist that the response ids match the default actions for those
2087 : //widgets, and leave their default handlers in place
2088 : case WINDOW_OKBUTTON:
2089 : assert(get_response(pChild) == RET_OK);
2090 0 : break;
2091 : case WINDOW_CANCELBUTTON:
2092 : assert(get_response(pChild) == RET_CANCEL);
2093 0 : break;
2094 : case WINDOW_HELPBUTTON:
2095 : assert(get_response(pChild) == RET_HELP);
2096 0 : break;
2097 : default:
2098 : SAL_WARN("vcl.layout", "The type of widget " <<
2099 : pChild->GetHelpId() << " is currently not handled");
2100 0 : break;
2101 : }
2102 : //The default is to stick the focus into the first widget
2103 : //that accepts it, and if that happens and it's a button
2104 : //then that becomes the new default button, so explicitly
2105 : //put the focus into the default button
2106 0 : if (pChild->GetStyle() & WB_DEFBUTTON)
2107 0 : pChild->GrabFocus();
2108 : }
2109 0 : }
2110 :
2111 0 : void MessageDialog::SetMessagesWidths(vcl::Window *pParent,
2112 : VclMultiLineEdit *pPrimaryMessage, VclMultiLineEdit *pSecondaryMessage)
2113 : {
2114 0 : if (pSecondaryMessage)
2115 : {
2116 : assert(pPrimaryMessage);
2117 0 : vcl::Font aFont = pParent->GetSettings().GetStyleSettings().GetLabelFont();
2118 0 : aFont.SetSize(Size(0, aFont.GetSize().Height() * 1.2));
2119 0 : aFont.SetWeight(WEIGHT_BOLD);
2120 0 : pPrimaryMessage->SetControlFont(aFont);
2121 0 : pPrimaryMessage->SetMaxTextWidth(pPrimaryMessage->approximate_char_width() * 44);
2122 0 : pSecondaryMessage->SetMaxTextWidth(pSecondaryMessage->approximate_char_width() * 60);
2123 : }
2124 : else
2125 0 : pPrimaryMessage->SetMaxTextWidth(pPrimaryMessage->approximate_char_width() * 60);
2126 0 : }
2127 :
2128 0 : short MessageDialog::Execute()
2129 : {
2130 0 : setDeferredProperties();
2131 :
2132 0 : if (!m_pGrid)
2133 : {
2134 0 : VclContainer *pContainer = get_content_area();
2135 : assert(pContainer);
2136 :
2137 0 : m_pGrid.set( VclPtr<VclGrid>::Create(pContainer) );
2138 0 : m_pGrid->reorderWithinParent(0);
2139 0 : m_pGrid->set_column_spacing(12);
2140 0 : m_pGrid->set_row_spacing(GetTextHeight());
2141 :
2142 0 : m_pImage = VclPtr<FixedImage>::Create(m_pGrid, WB_CENTER | WB_VCENTER | WB_3DLOOK);
2143 0 : switch (m_eMessageType)
2144 : {
2145 : case VCL_MESSAGE_INFO:
2146 0 : m_pImage->SetImage(InfoBox::GetStandardImage());
2147 0 : break;
2148 : case VCL_MESSAGE_WARNING:
2149 0 : m_pImage->SetImage(WarningBox::GetStandardImage());
2150 0 : break;
2151 : case VCL_MESSAGE_QUESTION:
2152 0 : m_pImage->SetImage(QueryBox::GetStandardImage());
2153 0 : break;
2154 : case VCL_MESSAGE_ERROR:
2155 0 : m_pImage->SetImage(ErrorBox::GetStandardImage());
2156 0 : break;
2157 : }
2158 0 : m_pImage->set_grid_left_attach(0);
2159 0 : m_pImage->set_grid_top_attach(0);
2160 0 : m_pImage->set_valign(VCL_ALIGN_START);
2161 0 : m_pImage->Show();
2162 :
2163 0 : WinBits nWinStyle = WB_CLIPCHILDREN | WB_LEFT | WB_VCENTER | WB_NOLABEL | WB_NOTABSTOP;
2164 :
2165 0 : bool bHasSecondaryText = !m_sSecondaryString.isEmpty();
2166 :
2167 0 : m_pPrimaryMessage = VclPtr<VclMultiLineEdit>::Create(m_pGrid, nWinStyle);
2168 0 : m_pPrimaryMessage->SetPaintTransparent(true);
2169 0 : m_pPrimaryMessage->EnableCursor(false);
2170 :
2171 0 : m_pPrimaryMessage->set_grid_left_attach(1);
2172 0 : m_pPrimaryMessage->set_grid_top_attach(0);
2173 0 : m_pPrimaryMessage->set_hexpand(true);
2174 0 : m_pPrimaryMessage->SetText(m_sPrimaryString);
2175 0 : m_pPrimaryMessage->Show(!m_sPrimaryString.isEmpty());
2176 :
2177 0 : m_pSecondaryMessage = VclPtr<VclMultiLineEdit>::Create(m_pGrid, nWinStyle);
2178 0 : m_pSecondaryMessage->SetPaintTransparent(true);
2179 0 : m_pSecondaryMessage->EnableCursor(false);
2180 0 : m_pSecondaryMessage->set_grid_left_attach(1);
2181 0 : m_pSecondaryMessage->set_grid_top_attach(1);
2182 0 : m_pSecondaryMessage->set_hexpand(true);
2183 0 : m_pSecondaryMessage->SetText(m_sSecondaryString);
2184 0 : m_pSecondaryMessage->Show(bHasSecondaryText);
2185 :
2186 0 : MessageDialog::SetMessagesWidths(this, m_pPrimaryMessage, bHasSecondaryText ? m_pSecondaryMessage.get() : NULL);
2187 :
2188 0 : VclButtonBox *pButtonBox = get_action_area();
2189 : assert(pButtonBox);
2190 :
2191 0 : VclPtr<PushButton> pBtn;
2192 0 : switch (m_eButtonsType)
2193 : {
2194 : case VCL_BUTTONS_NONE:
2195 0 : break;
2196 : case VCL_BUTTONS_OK:
2197 0 : pBtn.set( VclPtr<OKButton>::Create(pButtonBox) );
2198 0 : pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON);
2199 0 : pBtn->Show();
2200 0 : m_aOwnedButtons.push_back(pBtn);
2201 0 : m_aResponses[pBtn] = RET_OK;
2202 0 : break;
2203 : case VCL_BUTTONS_CLOSE:
2204 0 : pBtn.set( VclPtr<CloseButton>::Create(pButtonBox) );
2205 0 : pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON);
2206 0 : pBtn->Show();
2207 0 : m_aOwnedButtons.push_back(pBtn);
2208 0 : m_aResponses[pBtn] = RET_CLOSE;
2209 0 : break;
2210 : case VCL_BUTTONS_CANCEL:
2211 0 : pBtn.set( VclPtr<CancelButton>::Create(pButtonBox) );
2212 0 : pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON);
2213 0 : m_aOwnedButtons.push_back(pBtn);
2214 0 : m_aResponses[pBtn] = RET_CANCEL;
2215 0 : break;
2216 : case VCL_BUTTONS_YES_NO:
2217 0 : pBtn = VclPtr<PushButton>::Create(pButtonBox);
2218 0 : pBtn->SetText(Button::GetStandardText(StandardButtonType::Yes));
2219 0 : pBtn->Show();
2220 0 : m_aOwnedButtons.push_back(pBtn);
2221 0 : m_aResponses[pBtn] = RET_YES;
2222 :
2223 0 : pBtn.set( VclPtr<PushButton>::Create(pButtonBox) );
2224 0 : pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON);
2225 0 : pBtn->SetText(Button::GetStandardText(StandardButtonType::No));
2226 0 : pBtn->Show();
2227 0 : m_aOwnedButtons.push_back(pBtn);
2228 0 : m_aResponses[pBtn] = RET_NO;
2229 0 : break;
2230 : case VCL_BUTTONS_OK_CANCEL:
2231 0 : pBtn.set( VclPtr<OKButton>::Create(pButtonBox) );
2232 0 : pBtn->Show();
2233 0 : m_aOwnedButtons.push_back(pBtn);
2234 0 : m_aResponses[pBtn] = RET_OK;
2235 :
2236 0 : pBtn.set( VclPtr<CancelButton>::Create(pButtonBox) );
2237 0 : pBtn->SetStyle(pBtn->GetStyle() & WB_DEFBUTTON);
2238 0 : pBtn->Show();
2239 0 : m_aOwnedButtons.push_back(pBtn);
2240 0 : m_aResponses[pBtn] = RET_CANCEL;
2241 0 : break;
2242 : }
2243 0 : setButtonHandlers(pButtonBox);
2244 0 : pButtonBox->sort_native_button_order();
2245 0 : m_pGrid->Show();
2246 : }
2247 0 : return Dialog::Execute();
2248 : }
2249 :
2250 0 : OUString MessageDialog::get_primary_text() const
2251 : {
2252 0 : const_cast<MessageDialog*>(this)->setDeferredProperties();
2253 :
2254 0 : return m_sPrimaryString;
2255 : }
2256 :
2257 0 : OUString MessageDialog::get_secondary_text() const
2258 : {
2259 0 : const_cast<MessageDialog*>(this)->setDeferredProperties();
2260 :
2261 0 : return m_sSecondaryString;
2262 : }
2263 :
2264 0 : bool MessageDialog::set_property(const OString &rKey, const OString &rValue)
2265 : {
2266 0 : if (rKey == "text")
2267 0 : set_primary_text(OStringToOUString(rValue, RTL_TEXTENCODING_UTF8));
2268 0 : else if (rKey == "secondary-text")
2269 0 : set_secondary_text(OStringToOUString(rValue, RTL_TEXTENCODING_UTF8));
2270 0 : else if (rKey == "message-type")
2271 : {
2272 0 : VclMessageType eMode = VCL_MESSAGE_INFO;
2273 0 : if (rValue.equals("info"))
2274 0 : eMode = VCL_MESSAGE_INFO;
2275 0 : else if (rValue.equals("warning"))
2276 0 : eMode = VCL_MESSAGE_WARNING;
2277 0 : else if (rValue.equals("question"))
2278 0 : eMode = VCL_MESSAGE_QUESTION;
2279 0 : else if (rValue.equals("error"))
2280 0 : eMode = VCL_MESSAGE_ERROR;
2281 : else
2282 : {
2283 : SAL_WARN("vcl.layout", "unknown message type mode" << rValue.getStr());
2284 : }
2285 0 : m_eMessageType = eMode;
2286 : }
2287 0 : else if (rKey == "buttons")
2288 : {
2289 0 : VclButtonsType eMode = VCL_BUTTONS_NONE;
2290 0 : if (rValue.equals("none"))
2291 0 : eMode = VCL_BUTTONS_NONE;
2292 0 : else if (rValue.equals("ok"))
2293 0 : eMode = VCL_BUTTONS_OK;
2294 0 : else if (rValue.equals("cancel"))
2295 0 : eMode = VCL_BUTTONS_CANCEL;
2296 0 : else if (rValue.equals("close"))
2297 0 : eMode = VCL_BUTTONS_CLOSE;
2298 0 : else if (rValue.equals("yes-no"))
2299 0 : eMode = VCL_BUTTONS_YES_NO;
2300 0 : else if (rValue.equals("ok-cancel"))
2301 0 : eMode = VCL_BUTTONS_OK_CANCEL;
2302 : else
2303 : {
2304 : SAL_WARN("vcl.layout", "unknown buttons type mode" << rValue.getStr());
2305 : }
2306 0 : m_eButtonsType = eMode;
2307 : }
2308 : else
2309 0 : return Dialog::set_property(rKey, rValue);
2310 0 : return true;
2311 : }
2312 :
2313 0 : void MessageDialog::set_primary_text(const OUString &rPrimaryString)
2314 : {
2315 0 : m_sPrimaryString = rPrimaryString;
2316 0 : if (m_pPrimaryMessage)
2317 : {
2318 0 : m_pPrimaryMessage->SetText(m_sPrimaryString);
2319 0 : m_pPrimaryMessage->Show(!m_sPrimaryString.isEmpty());
2320 : }
2321 0 : }
2322 :
2323 0 : void MessageDialog::set_secondary_text(const OUString &rSecondaryString)
2324 : {
2325 0 : m_sSecondaryString = rSecondaryString;
2326 0 : if (m_pSecondaryMessage)
2327 : {
2328 0 : m_pSecondaryMessage->SetText("\n" + m_sSecondaryString);
2329 0 : m_pSecondaryMessage->Show(!m_sSecondaryString.isEmpty());
2330 : }
2331 0 : }
2332 :
2333 0 : Size getLegacyBestSizeForChildren(const vcl::Window &rWindow)
2334 : {
2335 0 : Rectangle aBounds;
2336 :
2337 0 : for (const vcl::Window* pChild = rWindow.GetWindow(GetWindowType::FirstChild); pChild;
2338 : pChild = pChild->GetWindow(GetWindowType::Next))
2339 : {
2340 0 : if (!pChild->IsVisible())
2341 0 : continue;
2342 :
2343 0 : Rectangle aChildBounds(pChild->GetPosPixel(), pChild->GetSizePixel());
2344 0 : aBounds.Union(aChildBounds);
2345 : }
2346 :
2347 0 : if (aBounds.IsEmpty())
2348 0 : return rWindow.GetSizePixel();
2349 :
2350 0 : Size aRet(aBounds.GetSize());
2351 0 : Point aTopLeft(aBounds.TopLeft());
2352 0 : aRet.Width() += aTopLeft.X()*2;
2353 0 : aRet.Height() += aTopLeft.Y()*2;
2354 :
2355 0 : return aRet;
2356 : }
2357 :
2358 50525 : vcl::Window* getNonLayoutParent(vcl::Window *pWindow)
2359 : {
2360 103194 : while (pWindow)
2361 : {
2362 52669 : pWindow = pWindow->GetParent();
2363 52669 : if (!pWindow || !isContainerWindow(*pWindow))
2364 50525 : break;
2365 : }
2366 50525 : return pWindow;
2367 : }
2368 :
2369 3 : vcl::Window* getNonLayoutRealParent(vcl::Window *pWindow)
2370 : {
2371 6 : while (pWindow)
2372 : {
2373 3 : pWindow = pWindow->ImplGetParent();
2374 3 : if (!pWindow || !isContainerWindow(*pWindow))
2375 3 : break;
2376 : }
2377 3 : return pWindow;
2378 : }
2379 :
2380 120842 : bool isVisibleInLayout(const vcl::Window *pWindow)
2381 : {
2382 120842 : bool bVisible = true;
2383 244709 : while (bVisible)
2384 : {
2385 123792 : bVisible = pWindow->IsVisible();
2386 123792 : pWindow = pWindow->GetParent();
2387 123792 : if (!pWindow || !isContainerWindow(*pWindow))
2388 120767 : break;
2389 : }
2390 120842 : return bVisible;
2391 : }
2392 :
2393 619 : bool isEnabledInLayout(const vcl::Window *pWindow)
2394 : {
2395 619 : bool bEnabled = true;
2396 1244 : while (bEnabled)
2397 : {
2398 625 : bEnabled = pWindow->IsEnabled();
2399 625 : pWindow = pWindow->GetParent();
2400 625 : if (!pWindow || !isContainerWindow(*pWindow))
2401 619 : break;
2402 : }
2403 619 : return bEnabled;
2404 : }
2405 :
2406 1024887 : bool isLayoutEnabled(const vcl::Window *pWindow)
2407 : {
2408 : //Child is a container => we're layout enabled
2409 1024887 : const vcl::Window *pChild = pWindow ? pWindow->GetWindow(GetWindowType::FirstChild) : NULL;
2410 1024887 : return pChild && isContainerWindow(*pChild) && !pChild->GetWindow(GetWindowType::Next);
2411 : }
2412 :
2413 0 : bool isInitialLayout(const vcl::Window *pWindow)
2414 : {
2415 0 : Dialog *pParentDialog = pWindow ? pWindow->GetParentDialog() : NULL;
2416 0 : return pParentDialog && pParentDialog->isCalculatingInitialLayoutSize();
2417 801 : }
2418 :
2419 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|