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