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 <vcl/dialog.hxx>
11 : #include <vcl/layout.hxx>
12 : #include "window.h"
13 :
14 0 : VclContainer::VclContainer(Window *pParent, WinBits nStyle)
15 : : Window(WINDOW_CONTAINER)
16 0 : , m_bLayoutDirty(true)
17 : {
18 0 : ImplInit(pParent, nStyle, NULL);
19 0 : EnableChildTransparentMode();
20 0 : SetPaintTransparent(sal_True);
21 0 : SetBackground();
22 0 : }
23 :
24 0 : Size VclContainer::GetOptimalSize(WindowSizeType eType) const
25 : {
26 0 : if (eType == WINDOWSIZE_MAXIMUM)
27 0 : return Window::GetOptimalSize(eType);
28 0 : return calculateRequisition();
29 : }
30 :
31 0 : void VclContainer::setLayoutPosSize(Window &rWindow, const Point &rPos, const Size &rSize)
32 : {
33 0 : sal_Int32 nBorderWidth = rWindow.get_border_width();
34 0 : sal_Int32 nLeft = rWindow.get_margin_left() + nBorderWidth;
35 0 : sal_Int32 nTop = rWindow.get_margin_top() + nBorderWidth;
36 0 : sal_Int32 nRight = rWindow.get_margin_right() + nBorderWidth;
37 0 : sal_Int32 nBottom = rWindow.get_margin_bottom() + nBorderWidth;
38 0 : Point aPos(rPos.X() + nLeft, rPos.Y() + nTop);
39 0 : Size aSize(rSize.Width() - nLeft - nRight, rSize.Height() - nTop - nBottom);
40 0 : rWindow.SetPosSizePixel(aPos, aSize);
41 0 : }
42 :
43 0 : void VclContainer::setLayoutAllocation(Window &rChild, const Point &rAllocPos, const Size &rChildAlloc)
44 : {
45 0 : VclAlign eHalign = rChild.get_halign();
46 0 : VclAlign eValign = rChild.get_valign();
47 :
48 : //typical case
49 0 : if (eHalign == VCL_ALIGN_FILL && eValign == VCL_ALIGN_FILL)
50 : {
51 0 : setLayoutPosSize(rChild, rAllocPos, rChildAlloc);
52 0 : return;
53 : }
54 :
55 0 : Point aChildPos(rAllocPos);
56 0 : Size aChildSize(rChildAlloc);
57 0 : Size aChildPreferredSize(getLayoutRequisition(rChild));
58 :
59 0 : switch (eHalign)
60 : {
61 : case VCL_ALIGN_FILL:
62 0 : break;
63 : case VCL_ALIGN_START:
64 0 : if (aChildPreferredSize.Width() < rChildAlloc.Width())
65 0 : aChildSize.Width() = aChildPreferredSize.Width();
66 0 : break;
67 : case VCL_ALIGN_END:
68 0 : if (aChildPreferredSize.Width() < rChildAlloc.Width())
69 0 : aChildSize.Width() = aChildPreferredSize.Width();
70 0 : aChildPos.X() += rChildAlloc.Width();
71 0 : aChildPos.X() -= aChildSize.Width();
72 0 : break;
73 : case VCL_ALIGN_CENTER:
74 0 : if (aChildPreferredSize.Width() < aChildSize.Width())
75 0 : aChildSize.Width() = aChildPreferredSize.Width();
76 0 : aChildPos.X() += (rChildAlloc.Width() - aChildSize.Width()) / 2;
77 0 : break;
78 : }
79 :
80 0 : switch (eValign)
81 : {
82 : case VCL_ALIGN_FILL:
83 0 : break;
84 : case VCL_ALIGN_START:
85 0 : if (aChildPreferredSize.Height() < rChildAlloc.Height())
86 0 : aChildSize.Height() = aChildPreferredSize.Height();
87 0 : break;
88 : case VCL_ALIGN_END:
89 0 : if (aChildPreferredSize.Height() < rChildAlloc.Height())
90 0 : aChildSize.Height() = aChildPreferredSize.Height();
91 0 : aChildPos.Y() += rChildAlloc.Height();
92 0 : aChildPos.Y() -= aChildSize.Height();
93 0 : break;
94 : case VCL_ALIGN_CENTER:
95 0 : if (aChildPreferredSize.Height() < aChildSize.Height())
96 0 : aChildSize.Height() = aChildPreferredSize.Height();
97 0 : aChildPos.Y() += (rChildAlloc.Height() - aChildSize.Height()) / 2;
98 0 : break;
99 : }
100 :
101 0 : setLayoutPosSize(rChild, aChildPos, aChildSize);
102 : }
103 :
104 0 : Size VclContainer::getLayoutRequisition(const Window &rWindow)
105 : {
106 0 : sal_Int32 nBorderWidth = rWindow.get_border_width();
107 0 : sal_Int32 nLeft = rWindow.get_margin_left() + nBorderWidth;
108 0 : sal_Int32 nTop = rWindow.get_margin_top() + nBorderWidth;
109 0 : sal_Int32 nRight = rWindow.get_margin_right() + nBorderWidth;
110 0 : sal_Int32 nBottom = rWindow.get_margin_bottom() + nBorderWidth;
111 0 : Size aSize(rWindow.get_preferred_size());
112 0 : return Size(aSize.Width() + nLeft + nRight, aSize.Height() + nTop + nBottom);
113 : }
114 :
115 0 : void VclContainer::SetPosSizePixel(const Point& rAllocPos, const Size& rAllocation)
116 : {
117 0 : bool bSizeChanged = rAllocation != GetOutputSizePixel();
118 0 : Window::SetPosSizePixel(rAllocPos, rAllocation);
119 0 : if (m_bLayoutDirty || bSizeChanged)
120 : {
121 0 : m_bLayoutDirty = false;
122 0 : setAllocation(rAllocation);
123 : }
124 0 : }
125 :
126 0 : void VclContainer::SetPosPixel(const Point& rAllocPos)
127 : {
128 0 : Point aAllocPos = rAllocPos;
129 0 : sal_Int32 nBorderWidth = get_border_width();
130 0 : aAllocPos.X() += nBorderWidth + get_margin_left();
131 0 : aAllocPos.Y() += nBorderWidth + get_margin_top();
132 :
133 0 : if (aAllocPos != GetPosPixel())
134 0 : Window::SetPosPixel(aAllocPos);
135 0 : }
136 :
137 0 : void VclContainer::SetSizePixel(const Size& rAllocation)
138 : {
139 0 : Size aAllocation = rAllocation;
140 0 : sal_Int32 nBorderWidth = get_border_width();
141 0 : aAllocation.Width() -= nBorderWidth*2 + get_margin_left() + get_margin_right();
142 0 : aAllocation.Height() -= nBorderWidth*2 + get_margin_top() + get_margin_bottom();
143 0 : bool bSizeChanged = aAllocation != GetSizePixel();
144 0 : if (bSizeChanged)
145 0 : Window::SetSizePixel(aAllocation);
146 0 : if (m_bLayoutDirty || bSizeChanged)
147 : {
148 0 : m_bLayoutDirty = false;
149 0 : setAllocation(aAllocation);
150 : }
151 0 : }
152 :
153 0 : void VclBox::accumulateMaxes(const Size &rChildSize, Size &rSize) const
154 : {
155 0 : long nSecondaryChildDimension = getSecondaryDimension(rChildSize);
156 0 : long nSecondaryBoxDimension = getSecondaryDimension(rSize);
157 0 : setSecondaryDimension(rSize, std::max(nSecondaryChildDimension, nSecondaryBoxDimension));
158 :
159 0 : long nPrimaryChildDimension = getPrimaryDimension(rChildSize);
160 0 : long nPrimaryBoxDimension = getPrimaryDimension(rSize);
161 0 : if (m_bHomogeneous)
162 0 : setPrimaryDimension(rSize, std::max(nPrimaryBoxDimension, nPrimaryChildDimension));
163 : else
164 0 : setPrimaryDimension(rSize, nPrimaryBoxDimension + nPrimaryChildDimension);
165 0 : }
166 :
167 0 : Size VclBox::calculateRequisition() const
168 : {
169 0 : sal_uInt16 nVisibleChildren = 0;
170 :
171 0 : Size aSize;
172 0 : for (Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
173 : {
174 0 : if (!pChild->IsVisible())
175 0 : continue;
176 0 : ++nVisibleChildren;
177 0 : Size aChildSize = getLayoutRequisition(*pChild);
178 :
179 0 : long nPrimaryDimension = getPrimaryDimension(aChildSize);
180 0 : nPrimaryDimension += pChild->get_padding() * 2;
181 0 : setPrimaryDimension(aChildSize, nPrimaryDimension);
182 :
183 0 : accumulateMaxes(aChildSize, aSize);
184 : }
185 :
186 0 : return finalizeMaxes(aSize, nVisibleChildren);
187 : }
188 :
189 0 : void VclBox::setAllocation(const Size &rAllocation)
190 : {
191 0 : sal_uInt16 nVisibleChildren = 0, nExpandChildren = 0;
192 0 : for (Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
193 : {
194 0 : if (!pChild->IsVisible())
195 0 : continue;
196 0 : ++nVisibleChildren;
197 0 : bool bExpand = getPrimaryDimensionChildExpand(*pChild);
198 0 : if (bExpand)
199 0 : ++nExpandChildren;
200 : }
201 :
202 0 : if (!nVisibleChildren)
203 0 : return;
204 :
205 0 : long nAllocPrimaryDimension = getPrimaryDimension(rAllocation);
206 :
207 0 : long nHomogeneousDimension = 0, nExtraSpace = 0;
208 0 : if (m_bHomogeneous)
209 : {
210 : nHomogeneousDimension = ((nAllocPrimaryDimension -
211 0 : (nVisibleChildren - 1) * m_nSpacing)) / nVisibleChildren;
212 : }
213 0 : else if (nExpandChildren)
214 : {
215 0 : Size aRequisition = calculateRequisition();
216 0 : nExtraSpace = (getPrimaryDimension(rAllocation) - getPrimaryDimension(aRequisition)) / nExpandChildren;
217 : }
218 :
219 0 : for (sal_Int32 ePackType = VCL_PACK_START; ePackType <= VCL_PACK_END; ++ePackType)
220 : {
221 0 : Point aPos(0, 0);
222 0 : if (ePackType == VCL_PACK_END)
223 : {
224 0 : long nPrimaryCoordinate = getPrimaryCoordinate(aPos);
225 0 : setPrimaryCoordinate(aPos, nPrimaryCoordinate + nAllocPrimaryDimension);
226 : }
227 :
228 0 : for (Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
229 : {
230 0 : if (!pChild->IsVisible())
231 0 : continue;
232 :
233 0 : sal_Int32 ePacking = pChild->get_pack_type();
234 :
235 0 : if (ePacking != ePackType)
236 0 : continue;
237 :
238 0 : long nPadding = pChild->get_padding();
239 :
240 0 : Size aBoxSize;
241 0 : if (m_bHomogeneous)
242 0 : setPrimaryDimension(aBoxSize, nHomogeneousDimension);
243 : else
244 : {
245 0 : aBoxSize = getLayoutRequisition(*pChild);
246 0 : long nPrimaryDimension = getPrimaryDimension(aBoxSize);
247 0 : nPrimaryDimension += nPadding * 2;
248 0 : if (getPrimaryDimensionChildExpand(*pChild))
249 0 : nPrimaryDimension += nExtraSpace;
250 0 : setPrimaryDimension(aBoxSize, nPrimaryDimension);
251 : }
252 0 : setSecondaryDimension(aBoxSize, getSecondaryDimension(rAllocation));
253 :
254 0 : Point aChildPos(aPos);
255 0 : Size aChildSize(aBoxSize);
256 0 : long nPrimaryCoordinate = getPrimaryCoordinate(aPos);
257 :
258 0 : bool bFill = pChild->get_fill();
259 0 : if (bFill)
260 : {
261 : setPrimaryDimension(aChildSize, std::max(static_cast<long>(1),
262 0 : getPrimaryDimension(aBoxSize) - nPadding * 2));
263 :
264 0 : setPrimaryCoordinate(aChildPos, nPrimaryCoordinate + nPadding);
265 : }
266 : else
267 : {
268 : setPrimaryDimension(aChildSize,
269 0 : getPrimaryDimension(getLayoutRequisition(*pChild)));
270 :
271 : setPrimaryCoordinate(aChildPos, nPrimaryCoordinate +
272 0 : (getPrimaryDimension(aBoxSize) - getPrimaryDimension(aChildSize)) / 2);
273 : }
274 :
275 0 : long nDiff = getPrimaryDimension(aBoxSize) + m_nSpacing;
276 0 : if (ePackType == VCL_PACK_START)
277 0 : setPrimaryCoordinate(aPos, nPrimaryCoordinate + nDiff);
278 : else
279 : {
280 0 : setPrimaryCoordinate(aPos, nPrimaryCoordinate - nDiff);
281 0 : setPrimaryCoordinate(aChildPos, getPrimaryCoordinate(aChildPos) -
282 0 : getPrimaryDimension(aBoxSize));
283 : }
284 :
285 0 : setLayoutAllocation(*pChild, aChildPos, aChildSize);
286 : }
287 : }
288 : }
289 :
290 0 : bool VclBox::set_property(const rtl::OString &rKey, const rtl::OString &rValue)
291 : {
292 0 : if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("spacing")))
293 0 : set_spacing(rValue.toInt32());
294 0 : else if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("homogeneous")))
295 0 : set_homogeneous(toBool(rValue));
296 : else
297 0 : return VclContainer::set_property(rKey, rValue);
298 0 : return true;
299 : }
300 :
301 : #define DEFAULT_CHILD_MIN_WIDTH 85
302 : #define DEFAULT_CHILD_MIN_HEIGHT 27
303 :
304 0 : Size VclBox::finalizeMaxes(const Size &rSize, sal_uInt16 nVisibleChildren) const
305 : {
306 0 : Size aRet;
307 :
308 0 : if (nVisibleChildren)
309 : {
310 0 : long nPrimaryDimension = getPrimaryDimension(rSize);
311 0 : if (m_bHomogeneous)
312 0 : nPrimaryDimension *= nVisibleChildren;
313 0 : setPrimaryDimension(aRet, nPrimaryDimension + m_nSpacing * (nVisibleChildren-1));
314 0 : setSecondaryDimension(aRet, getSecondaryDimension(rSize));
315 : }
316 :
317 0 : return aRet;
318 : }
319 :
320 0 : Size VclButtonBox::addReqGroups(const VclButtonBox::Requisition &rReq) const
321 : {
322 0 : Size aRet;
323 :
324 0 : long nMainGroupDimension = getPrimaryDimension(rReq.m_aMainGroupSize);
325 0 : long nSubGroupDimension = getPrimaryDimension(rReq.m_aSubGroupSize);
326 :
327 : assert(m_bHomogeneous);
328 :
329 0 : if (m_bHomogeneousGroups)
330 0 : setPrimaryDimension(aRet, std::max(nMainGroupDimension, nSubGroupDimension));
331 : else
332 : {
333 : setPrimaryDimension(aRet,
334 : (rReq.m_nMainGroupChildren * nMainGroupDimension
335 : + rReq.m_nSubGroupChildren * nSubGroupDimension) /
336 0 : (rReq.m_nMainGroupChildren + rReq.m_nSubGroupChildren));
337 : }
338 :
339 : setSecondaryDimension(aRet,
340 0 : std::max(getSecondaryDimension(rReq.m_aMainGroupSize),
341 0 : getSecondaryDimension(rReq.m_aSubGroupSize)));
342 :
343 0 : return aRet;
344 : }
345 :
346 0 : VclButtonBox::Requisition VclButtonBox::calculatePrimarySecondaryRequisitions() const
347 : {
348 0 : Requisition aReq;
349 :
350 0 : Size aMainGroupSize(DEFAULT_CHILD_MIN_WIDTH, DEFAULT_CHILD_MIN_HEIGHT); //to-do, pull from theme
351 0 : Size aSubGroupSize(DEFAULT_CHILD_MIN_WIDTH, DEFAULT_CHILD_MIN_HEIGHT); //to-do, pull from theme
352 :
353 0 : for (const Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
354 : {
355 0 : if (!pChild->IsVisible())
356 0 : continue;
357 0 : Size aChildSize = getLayoutRequisition(*pChild);
358 0 : if (!pChild->get_secondary())
359 : {
360 0 : ++aReq.m_nMainGroupChildren;
361 0 : accumulateMaxes(aChildSize, aMainGroupSize);
362 : }
363 : else
364 : {
365 0 : ++aReq.m_nSubGroupChildren;
366 0 : accumulateMaxes(aChildSize, aSubGroupSize);
367 : }
368 : }
369 :
370 0 : if (aReq.m_nMainGroupChildren)
371 0 : aReq.m_aMainGroupSize = aMainGroupSize;
372 0 : if (aReq.m_nSubGroupChildren)
373 0 : aReq.m_aSubGroupSize = aSubGroupSize;
374 :
375 0 : return aReq;
376 : }
377 :
378 0 : Size VclButtonBox::calculateRequisition() const
379 : {
380 0 : Requisition aReq(calculatePrimarySecondaryRequisitions());
381 0 : sal_uInt16 nVisibleChildren = aReq.m_nMainGroupChildren + aReq.m_nSubGroupChildren;
382 0 : return finalizeMaxes(addReqGroups(aReq), nVisibleChildren);
383 : }
384 :
385 0 : bool VclButtonBox::set_property(const rtl::OString &rKey, const rtl::OString &rValue)
386 : {
387 0 : if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("layout-style")))
388 : {
389 0 : VclButtonBoxStyle eStyle = VCL_BUTTONBOX_DEFAULT_STYLE;
390 0 : if (rValue.equalsL(RTL_CONSTASCII_STRINGPARAM("start")))
391 0 : eStyle = VCL_BUTTONBOX_START;
392 0 : else if (rValue.equalsL(RTL_CONSTASCII_STRINGPARAM("spread")))
393 0 : eStyle = VCL_BUTTONBOX_SPREAD;
394 0 : else if (rValue.equalsL(RTL_CONSTASCII_STRINGPARAM("edge")))
395 0 : eStyle = VCL_BUTTONBOX_EDGE;
396 0 : else if (rValue.equalsL(RTL_CONSTASCII_STRINGPARAM("start")))
397 0 : eStyle = VCL_BUTTONBOX_START;
398 0 : else if (rValue.equalsL(RTL_CONSTASCII_STRINGPARAM("end")))
399 0 : eStyle = VCL_BUTTONBOX_END;
400 0 : else if (rValue.equalsL(RTL_CONSTASCII_STRINGPARAM("center")))
401 0 : eStyle = VCL_BUTTONBOX_CENTER;
402 : else
403 : {
404 : SAL_WARN("vcl.layout", "unknown layout style " << rValue.getStr());
405 : }
406 0 : set_layout(eStyle);
407 : }
408 0 : else if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("homogeneous")))
409 0 : m_bHomogeneousGroups = toBool(rValue);
410 : else
411 0 : return VclBox::set_property(rKey, rValue);
412 0 : return true;
413 : }
414 :
415 0 : void VclButtonBox::setAllocation(const Size &rAllocation)
416 : {
417 0 : Requisition aReq(calculatePrimarySecondaryRequisitions());
418 :
419 0 : sal_uInt16 nVisibleChildren = aReq.m_nMainGroupChildren + aReq.m_nSubGroupChildren;
420 0 : if (!nVisibleChildren)
421 0 : return;
422 :
423 0 : long nAllocPrimaryDimension = getPrimaryDimension(rAllocation);
424 :
425 0 : long nMainGroupPrimaryDimension = getPrimaryDimension(aReq.m_aMainGroupSize);
426 0 : long nSubGroupPrimaryDimension = getPrimaryDimension(aReq.m_aSubGroupSize);
427 0 : if (m_bHomogeneousGroups)
428 0 : nSubGroupPrimaryDimension = nMainGroupPrimaryDimension = std::max(nSubGroupPrimaryDimension, nMainGroupPrimaryDimension);
429 :
430 0 : Point aMainGroupPos, aOtherGroupPos;
431 :
432 : //To-Do, other layout styles
433 0 : switch (m_eLayoutStyle)
434 : {
435 : case VCL_BUTTONBOX_START:
436 0 : if (aReq.m_nSubGroupChildren)
437 : {
438 : long nOtherPrimaryDimension = getPrimaryDimension(
439 0 : finalizeMaxes(aReq.m_aSubGroupSize, aReq.m_nSubGroupChildren));
440 : setPrimaryCoordinate(aOtherGroupPos,
441 0 : nAllocPrimaryDimension - nOtherPrimaryDimension);
442 : }
443 0 : break;
444 : default:
445 : SAL_WARN("vcl.layout", "todo unimplemented layout style");
446 : case VCL_BUTTONBOX_DEFAULT_STYLE:
447 : case VCL_BUTTONBOX_END:
448 0 : if (aReq.m_nMainGroupChildren)
449 : {
450 : long nMainPrimaryDimension = getPrimaryDimension(
451 0 : finalizeMaxes(aReq.m_aMainGroupSize, aReq.m_nMainGroupChildren));
452 : setPrimaryCoordinate(aMainGroupPos,
453 0 : nAllocPrimaryDimension - nMainPrimaryDimension);
454 : }
455 0 : break;
456 : }
457 :
458 0 : Size aChildSize;
459 0 : setSecondaryDimension(aChildSize, getSecondaryDimension(rAllocation));
460 :
461 0 : for (Window *pChild = GetWindow(WINDOW_FIRSTCHILD); pChild; pChild = pChild->GetWindow(WINDOW_NEXT))
462 : {
463 0 : if (!pChild->IsVisible())
464 0 : continue;
465 :
466 0 : if (pChild->get_secondary())
467 : {
468 0 : setPrimaryDimension(aChildSize, nSubGroupPrimaryDimension);
469 0 : setLayoutAllocation(*pChild, aOtherGroupPos, aChildSize);
470 0 : long nPrimaryCoordinate = getPrimaryCoordinate(aOtherGroupPos);
471 0 : setPrimaryCoordinate(aOtherGroupPos, nPrimaryCoordinate + nSubGroupPrimaryDimension + m_nSpacing);
472 : }
473 : else
474 : {
475 0 : setPrimaryDimension(aChildSize, nMainGroupPrimaryDimension);
476 0 : setLayoutAllocation(*pChild, aMainGroupPos, aChildSize);
477 0 : long nPrimaryCoordinate = getPrimaryCoordinate(aMainGroupPos);
478 0 : setPrimaryCoordinate(aMainGroupPos, nPrimaryCoordinate + nMainGroupPrimaryDimension + m_nSpacing);
479 : }
480 : }
481 : }
482 :
483 0 : VclGrid::array_type VclGrid::assembleGrid() const
484 : {
485 0 : ext_array_type A;
486 :
487 0 : for (Window* pChild = GetWindow(WINDOW_FIRSTCHILD); pChild;
488 : pChild = pChild->GetWindow(WINDOW_NEXT))
489 : {
490 0 : sal_Int32 nLeftAttach = pChild->get_grid_left_attach();
491 0 : sal_Int32 nWidth = pChild->get_grid_width();
492 0 : sal_Int32 nMaxXPos = nLeftAttach+nWidth-1;
493 :
494 0 : sal_Int32 nTopAttach = pChild->get_grid_top_attach();
495 0 : sal_Int32 nHeight = pChild->get_grid_height();
496 0 : sal_Int32 nMaxYPos = nTopAttach+nHeight-1;
497 :
498 0 : sal_Int32 nCurrentMaxXPos = A.shape()[0]-1;
499 0 : sal_Int32 nCurrentMaxYPos = A.shape()[1]-1;
500 0 : if (nMaxXPos > nCurrentMaxXPos || nMaxYPos > nCurrentMaxYPos)
501 : {
502 0 : nCurrentMaxXPos = std::max(nMaxXPos, nCurrentMaxXPos);
503 0 : nCurrentMaxYPos = std::max(nMaxYPos, nCurrentMaxYPos);
504 0 : A.resize(boost::extents[nCurrentMaxXPos+1][nCurrentMaxYPos+1]);
505 : }
506 :
507 0 : ExtendedGridEntry &rEntry = A[nLeftAttach][nTopAttach];
508 0 : rEntry.pChild = pChild;
509 0 : rEntry.nSpanWidth = nWidth;
510 0 : rEntry.nSpanHeight = nHeight;
511 0 : rEntry.x = nLeftAttach;
512 0 : rEntry.y = nTopAttach;
513 :
514 0 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
515 : {
516 0 : for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
517 : {
518 0 : ExtendedGridEntry &rSpan = A[nLeftAttach+nSpanX][nTopAttach+nSpanY];
519 0 : rSpan.x = nLeftAttach;
520 0 : rSpan.y = nTopAttach;
521 : }
522 : }
523 : }
524 :
525 : //see if we have any empty rows/cols
526 0 : sal_Int32 nMaxX = A.shape()[0];
527 0 : sal_Int32 nMaxY = A.shape()[1];
528 :
529 0 : std::vector<bool> aNonEmptyCols(nMaxX);
530 0 : std::vector<bool> aNonEmptyRows(nMaxY);
531 :
532 0 : for (sal_Int32 x = 0; x < nMaxX; ++x)
533 : {
534 0 : for (sal_Int32 y = 0; y < nMaxY; ++y)
535 : {
536 0 : const GridEntry &rEntry = A[x][y];
537 0 : const Window *pChild = rEntry.pChild;
538 0 : if (pChild && pChild->IsVisible())
539 : {
540 0 : aNonEmptyCols[x] = true;
541 0 : aNonEmptyRows[y] = true;
542 : }
543 : }
544 : }
545 :
546 : //reduce the spans of elements that span empty rows or columns
547 0 : for (sal_Int32 x = 0; x < nMaxX; ++x)
548 : {
549 0 : for (sal_Int32 y = 0; y < nMaxY; ++y)
550 : {
551 0 : ExtendedGridEntry &rSpan = A[x][y];
552 : //cell x/y is spanned by the widget at cell rSpan.x/rSpan.y,
553 : //just points back to itself if there's no cell spanning
554 0 : if ((rSpan.x == -1) || (rSpan.y == -1))
555 : {
556 : //there is no entry for this cell, i.e. this is a cell
557 : //with no widget in it, or spanned by any other widget
558 0 : continue;
559 : }
560 0 : ExtendedGridEntry &rEntry = A[rSpan.x][rSpan.y];
561 0 : if (aNonEmptyCols[x] == false)
562 0 : --rEntry.nSpanWidth;
563 0 : if (aNonEmptyRows[y] == false)
564 0 : --rEntry.nSpanHeight;
565 : }
566 : }
567 :
568 0 : sal_Int32 nNonEmptyCols = std::count(aNonEmptyCols.begin(), aNonEmptyCols.end(), true);
569 0 : sal_Int32 nNonEmptyRows = std::count(aNonEmptyRows.begin(), aNonEmptyRows.end(), true);
570 :
571 : //make new grid without empty rows and columns
572 0 : array_type B(boost::extents[nNonEmptyCols][nNonEmptyRows]);
573 0 : for (sal_Int32 x = 0, x2 = 0; x < nMaxX; ++x)
574 : {
575 0 : if (aNonEmptyCols[x] == false)
576 0 : continue;
577 0 : for (sal_Int32 y = 0, y2 = 0; y < nMaxY; ++y)
578 : {
579 0 : if (aNonEmptyRows[y] == false)
580 0 : continue;
581 0 : GridEntry &rEntry = A[x][y];
582 0 : B[x2][y2++] = rEntry;
583 : }
584 0 : ++x2;
585 : }
586 :
587 0 : return B;
588 : }
589 :
590 0 : bool VclGrid::isNullGrid(const array_type &A) const
591 : {
592 0 : sal_Int32 nMaxX = A.shape()[0];
593 0 : sal_Int32 nMaxY = A.shape()[1];
594 :
595 0 : if (!nMaxX || !nMaxY)
596 0 : return true;
597 0 : return false;
598 : }
599 :
600 0 : void VclGrid::calcMaxs(const array_type &A, std::vector<Value> &rWidths, std::vector<Value> &rHeights) const
601 : {
602 0 : sal_Int32 nMaxX = A.shape()[0];
603 0 : sal_Int32 nMaxY = A.shape()[1];
604 :
605 0 : rWidths.resize(nMaxX);
606 0 : rHeights.resize(nMaxY);
607 :
608 : //first use the non spanning entries to set default width/heights
609 0 : for (sal_Int32 x = 0; x < nMaxX; ++x)
610 : {
611 0 : for (sal_Int32 y = 0; y < nMaxY; ++y)
612 : {
613 0 : const GridEntry &rEntry = A[x][y];
614 0 : const Window *pChild = rEntry.pChild;
615 0 : if (!pChild)
616 0 : continue;
617 :
618 0 : sal_Int32 nWidth = rEntry.nSpanWidth;
619 0 : sal_Int32 nHeight = rEntry.nSpanHeight;
620 :
621 0 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
622 0 : rWidths[x+nSpanX].m_bExpand = rWidths[x+nSpanX].m_bExpand | pChild->get_hexpand();
623 :
624 0 : for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
625 0 : rHeights[y+nSpanY].m_bExpand = rHeights[y+nSpanY].m_bExpand | pChild->get_vexpand();
626 :
627 0 : if (nWidth == 1 || nHeight == 1)
628 : {
629 0 : Size aChildSize = getLayoutRequisition(*pChild);
630 0 : if (nWidth == 1)
631 0 : rWidths[x].m_nValue = std::max(rWidths[x].m_nValue, aChildSize.Width());
632 0 : if (nHeight == 1)
633 0 : rHeights[y].m_nValue = std::max(rHeights[y].m_nValue, aChildSize.Height());
634 : }
635 : }
636 : }
637 :
638 : //now use the spanning entries and split any extra sizes across expanding rows/cols
639 : //where possible
640 0 : for (sal_Int32 x = 0; x < nMaxX; ++x)
641 : {
642 0 : for (sal_Int32 y = 0; y < nMaxY; ++y)
643 : {
644 0 : const GridEntry &rEntry = A[x][y];
645 0 : const Window *pChild = rEntry.pChild;
646 0 : if (!pChild)
647 0 : continue;
648 :
649 0 : sal_Int32 nWidth = rEntry.nSpanWidth;
650 0 : sal_Int32 nHeight = rEntry.nSpanHeight;
651 :
652 0 : if (nWidth == 1 && nHeight == 1)
653 0 : continue;
654 :
655 0 : Size aChildSize = getLayoutRequisition(*pChild);
656 :
657 0 : if (nWidth > 1)
658 : {
659 0 : sal_Int32 nExistingWidth = 0;
660 0 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
661 0 : nExistingWidth += rWidths[x+nSpanX].m_nValue;
662 :
663 0 : sal_Int32 nExtraWidth = aChildSize.Width() - nExistingWidth;
664 :
665 0 : if (nExtraWidth > 0)
666 : {
667 0 : bool bForceExpandAll = false;
668 0 : sal_Int32 nExpandables = 0;
669 0 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
670 0 : if (rWidths[x+nSpanX].m_bExpand)
671 0 : ++nExpandables;
672 0 : if (nExpandables == 0)
673 : {
674 0 : nExpandables = nWidth;
675 0 : bForceExpandAll = true;
676 : }
677 :
678 0 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
679 : {
680 0 : if (rWidths[x+nSpanX].m_bExpand || bForceExpandAll)
681 0 : rWidths[x+nSpanX].m_nValue += nExtraWidth/nExpandables;
682 : }
683 : }
684 : }
685 :
686 0 : if (nHeight > 1)
687 : {
688 0 : sal_Int32 nExistingHeight = 0;
689 0 : for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
690 0 : nExistingHeight += rHeights[y+nSpanY].m_nValue;
691 :
692 0 : sal_Int32 nExtraHeight = aChildSize.Height() - nExistingHeight;
693 :
694 0 : if (nExtraHeight > 0)
695 : {
696 0 : bool bForceExpandAll = false;
697 0 : sal_Int32 nExpandables = 0;
698 0 : for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
699 0 : if (rHeights[y+nSpanY].m_bExpand)
700 0 : ++nExpandables;
701 0 : if (nExpandables == 0)
702 : {
703 0 : nExpandables = nHeight;
704 0 : bForceExpandAll = true;
705 : }
706 :
707 0 : for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
708 : {
709 0 : if (rHeights[y+nSpanY].m_bExpand || bForceExpandAll)
710 0 : rHeights[y+nSpanY].m_nValue += nExtraHeight/nExpandables;
711 : }
712 : }
713 : }
714 : }
715 : }
716 0 : }
717 :
718 0 : bool compareValues(const VclGrid::Value &i, const VclGrid::Value &j)
719 : {
720 0 : return i.m_nValue < j.m_nValue;
721 : }
722 :
723 0 : VclGrid::Value accumulateValues(const VclGrid::Value &i, const VclGrid::Value &j)
724 : {
725 0 : VclGrid::Value aRet;
726 0 : aRet.m_nValue = i.m_nValue + j.m_nValue;
727 0 : aRet.m_bExpand = i.m_bExpand | j.m_bExpand;
728 0 : return aRet;
729 : }
730 :
731 0 : Size VclGrid::calculateRequisition() const
732 : {
733 0 : array_type A = assembleGrid();
734 :
735 0 : if (isNullGrid(A))
736 0 : return Size();
737 :
738 0 : std::vector<Value> aWidths;
739 0 : std::vector<Value> aHeights;
740 0 : calcMaxs(A, aWidths, aHeights);
741 :
742 0 : long nTotalWidth = 0;
743 0 : if (get_column_homogeneous())
744 : {
745 0 : nTotalWidth = std::max_element(aWidths.begin(), aWidths.end(), compareValues)->m_nValue;
746 0 : nTotalWidth *= aWidths.size();
747 : }
748 : else
749 : {
750 0 : nTotalWidth = std::accumulate(aWidths.begin(), aWidths.end(), Value(), accumulateValues).m_nValue;
751 : }
752 :
753 0 : nTotalWidth += get_column_spacing() * (aWidths.size()-1);
754 :
755 0 : long nTotalHeight = 0;
756 0 : if (get_row_homogeneous())
757 : {
758 0 : nTotalHeight = std::max_element(aHeights.begin(), aHeights.end(), compareValues)->m_nValue;
759 0 : nTotalHeight *= aHeights.size();
760 : }
761 : else
762 : {
763 0 : nTotalHeight = std::accumulate(aHeights.begin(), aHeights.end(), Value(), accumulateValues).m_nValue;
764 : }
765 :
766 0 : nTotalHeight += get_row_spacing() * (aHeights.size()-1);
767 :
768 0 : return Size(nTotalWidth, nTotalHeight);
769 : }
770 :
771 0 : void VclGrid::setAllocation(const Size& rAllocation)
772 : {
773 0 : array_type A = assembleGrid();
774 :
775 0 : if (isNullGrid(A))
776 0 : return;
777 :
778 0 : sal_Int32 nMaxX = A.shape()[0];
779 0 : sal_Int32 nMaxY = A.shape()[1];
780 :
781 0 : Size aRequisition;
782 0 : std::vector<Value> aWidths(nMaxX);
783 0 : std::vector<Value> aHeights(nMaxY);
784 0 : if (!get_column_homogeneous() || !get_row_homogeneous())
785 : {
786 0 : aRequisition = calculateRequisition();
787 0 : calcMaxs(A, aWidths, aHeights);
788 : }
789 :
790 0 : long nAvailableWidth = rAllocation.Width() - (get_column_spacing() * nMaxX);
791 0 : if (get_column_homogeneous())
792 : {
793 0 : for (sal_Int32 x = 0; x < nMaxX; ++x)
794 0 : aWidths[x].m_nValue = nAvailableWidth/nMaxX;
795 : }
796 0 : else if (rAllocation.Width() != aRequisition.Width())
797 : {
798 0 : sal_Int32 nExpandables = 0;
799 0 : for (sal_Int32 x = 0; x < nMaxX; ++x)
800 0 : if (aWidths[x].m_bExpand)
801 0 : ++nExpandables;
802 0 : long nExtraWidthForExpanders = nExpandables ? (rAllocation.Width() - aRequisition.Width()) / nExpandables : 0;
803 :
804 0 : if (rAllocation.Width() < aRequisition.Width())
805 : {
806 0 : long nExtraWidth = (rAllocation.Width() - aRequisition.Width() - nExtraWidthForExpanders * nExpandables) / nMaxX;
807 :
808 0 : for (sal_Int32 x = 0; x < nMaxX; ++x)
809 0 : aWidths[x].m_nValue += nExtraWidth;
810 : }
811 :
812 0 : if (nExtraWidthForExpanders)
813 : {
814 0 : for (sal_Int32 x = 0; x < nMaxX; ++x)
815 0 : if (aWidths[x].m_bExpand)
816 0 : aWidths[x].m_nValue += nExtraWidthForExpanders;
817 : }
818 : }
819 :
820 0 : long nAvailableHeight = rAllocation.Height() - (get_row_spacing() * nMaxY);
821 0 : if (get_row_homogeneous())
822 : {
823 0 : for (sal_Int32 y = 0; y < nMaxY; ++y)
824 0 : aHeights[y].m_nValue = nAvailableHeight/nMaxY;
825 : }
826 0 : else if (rAllocation.Height() != aRequisition.Height())
827 : {
828 0 : sal_Int32 nExpandables = 0;
829 0 : for (sal_Int32 y = 0; y < nMaxY; ++y)
830 0 : if (aHeights[y].m_bExpand)
831 0 : ++nExpandables;
832 0 : long nExtraHeightForExpanders = nExpandables ? (rAllocation.Height() - aRequisition.Height()) / nExpandables : 0;
833 :
834 0 : if (rAllocation.Height() < aRequisition.Height())
835 : {
836 0 : long nExtraHeight = (rAllocation.Height() - aRequisition.Height() - nExtraHeightForExpanders * nExpandables) / nMaxY;
837 :
838 0 : for (sal_Int32 y = 0; y < nMaxY; ++y)
839 0 : aHeights[y].m_nValue += nExtraHeight;
840 : }
841 :
842 0 : if (nExtraHeightForExpanders)
843 : {
844 0 : for (sal_Int32 y = 0; y < nMaxY; ++y)
845 0 : if (aHeights[y].m_bExpand)
846 0 : aHeights[y].m_nValue += nExtraHeightForExpanders;
847 : }
848 : }
849 :
850 0 : Point aAllocPos(0, 0);
851 0 : for (sal_Int32 x = 0; x < nMaxX; ++x)
852 : {
853 0 : for (sal_Int32 y = 0; y < nMaxY; ++y)
854 : {
855 0 : GridEntry &rEntry = A[x][y];
856 0 : Window *pChild = rEntry.pChild;
857 0 : if (pChild)
858 : {
859 0 : Size aChildAlloc(0, 0);
860 :
861 0 : sal_Int32 nWidth = rEntry.nSpanWidth;
862 0 : for (sal_Int32 nSpanX = 0; nSpanX < nWidth; ++nSpanX)
863 0 : aChildAlloc.Width() += aWidths[x+nSpanX].m_nValue;
864 0 : aChildAlloc.Width() += get_column_spacing()*(nWidth-1);
865 :
866 0 : sal_Int32 nHeight = rEntry.nSpanHeight;
867 0 : for (sal_Int32 nSpanY = 0; nSpanY < nHeight; ++nSpanY)
868 0 : aChildAlloc.Height() += aHeights[y+nSpanY].m_nValue;
869 0 : aChildAlloc.Height() += get_row_spacing()*(nHeight-1);
870 :
871 0 : setLayoutAllocation(*pChild, aAllocPos, aChildAlloc);
872 : }
873 0 : aAllocPos.Y() += aHeights[y].m_nValue + get_row_spacing();
874 : }
875 0 : aAllocPos.X() += aWidths[x].m_nValue + get_column_spacing();
876 0 : aAllocPos.Y() = 0;
877 0 : }
878 : }
879 :
880 0 : bool toBool(const rtl::OString &rValue)
881 : {
882 0 : return (rValue[0] == 't' || rValue[0] == 'T' || rValue[0] == '1');
883 : }
884 :
885 0 : bool VclGrid::set_property(const rtl::OString &rKey, const rtl::OString &rValue)
886 : {
887 0 : if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("row-spacing")))
888 0 : set_row_spacing(rValue.toInt32());
889 0 : else if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("column-spacing")))
890 0 : set_column_spacing(rValue.toInt32());
891 0 : else if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("row-homogeneous")))
892 0 : set_row_homogeneous(toBool(rValue));
893 0 : else if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("column-homogeneous")))
894 0 : set_column_homogeneous(toBool(rValue));
895 0 : else if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("n-rows")))
896 : /*nothing to do*/;
897 : else
898 0 : return VclContainer::set_property(rKey, rValue);
899 0 : return true;
900 : }
901 :
902 0 : void setGridAttach(Window &rWidget, sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nWidth, sal_Int32 nHeight)
903 : {
904 0 : rWidget.set_grid_left_attach(nLeft);
905 0 : rWidget.set_grid_top_attach(nTop);
906 0 : rWidget.set_grid_width(nWidth);
907 0 : rWidget.set_grid_height(nHeight);
908 0 : }
909 :
910 0 : const Window *VclBin::get_child() const
911 : {
912 0 : const WindowImpl* pWindowImpl = ImplGetWindowImpl();
913 :
914 0 : return pWindowImpl->mpFirstChild;
915 : }
916 :
917 0 : Window *VclBin::get_child()
918 : {
919 0 : return const_cast<Window*>(const_cast<const VclBin*>(this)->get_child());
920 : }
921 :
922 0 : Size VclBin::calculateRequisition() const
923 : {
924 0 : const Window *pChild = get_child();
925 0 : if (pChild && pChild->IsVisible())
926 0 : return getLayoutRequisition(*pChild);
927 0 : return Size(0, 0);
928 : }
929 :
930 0 : void VclBin::setAllocation(const Size &rAllocation)
931 : {
932 0 : Window *pChild = get_child();
933 0 : if (pChild && pChild->IsVisible())
934 0 : setLayoutAllocation(*pChild, Point(0, 0), rAllocation);
935 0 : }
936 :
937 : //To-Do, hook a DecorationView into VclFrame ?
938 :
939 0 : Size VclFrame::calculateRequisition() const
940 : {
941 0 : Size aRet(0, 0);
942 :
943 0 : WindowImpl* pWindowImpl = ImplGetWindowImpl();
944 :
945 0 : const Window *pChild = get_child();
946 0 : const Window *pLabel = pChild != pWindowImpl->mpLastChild ? pWindowImpl->mpLastChild : NULL;
947 :
948 0 : if (pChild && pChild->IsVisible())
949 0 : aRet = getLayoutRequisition(*pChild);
950 :
951 0 : if (pLabel && pLabel->IsVisible())
952 : {
953 0 : Size aLabelSize = getLayoutRequisition(*pLabel);
954 0 : aRet.Height() += aLabelSize.Height();
955 0 : aRet.Width() = std::max(aLabelSize.Width(), aRet.Width());
956 : }
957 :
958 : const FrameStyle &rFrameStyle =
959 0 : GetSettings().GetStyleSettings().GetFrameStyle();
960 0 : aRet.Width() += rFrameStyle.left + rFrameStyle.right;
961 0 : aRet.Height() += rFrameStyle.top + rFrameStyle.bottom;
962 :
963 0 : return aRet;
964 : }
965 :
966 0 : void VclFrame::setAllocation(const Size &rAllocation)
967 : {
968 : //SetBackground( Color(0xFF, 0x00, 0xFF) );
969 :
970 : const FrameStyle &rFrameStyle =
971 0 : GetSettings().GetStyleSettings().GetFrameStyle();
972 0 : Size aAllocation(rAllocation.Width() - rFrameStyle.left - rFrameStyle.right,
973 0 : rAllocation.Height() - rFrameStyle.top - rFrameStyle.bottom);
974 0 : Point aChildPos(rFrameStyle.left, rFrameStyle.top);
975 :
976 0 : WindowImpl* pWindowImpl = ImplGetWindowImpl();
977 :
978 : //The label widget is the last (of two) children
979 0 : Window *pChild = get_child();
980 0 : Window *pLabel = pChild != pWindowImpl->mpLastChild ? pWindowImpl->mpLastChild : NULL;
981 :
982 0 : if (pLabel && pLabel->IsVisible())
983 : {
984 0 : Size aLabelSize = getLayoutRequisition(*pLabel);
985 0 : aLabelSize.Height() = std::min(aLabelSize.Height(), aAllocation.Height());
986 0 : aLabelSize.Width() = std::min(aLabelSize.Width(), aAllocation.Width());
987 0 : setLayoutAllocation(*pLabel, aChildPos, aLabelSize);
988 0 : aAllocation.Height() -= aLabelSize.Height();
989 0 : aChildPos.Y() += aLabelSize.Height();
990 : }
991 :
992 0 : if (pChild && pChild->IsVisible())
993 0 : setLayoutAllocation(*pChild, aChildPos, aAllocation);
994 0 : }
995 :
996 0 : const Window *VclFrame::get_label_widget() const
997 : {
998 : //The label widget is the last (of two) children
999 0 : const Window *pChild = get_child();
1000 0 : const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1001 0 : return pChild != pWindowImpl->mpLastChild ? pWindowImpl->mpLastChild : NULL;
1002 : }
1003 :
1004 0 : Window *VclFrame::get_label_widget()
1005 : {
1006 0 : return const_cast<Window*>(const_cast<const VclFrame*>(this)->get_label_widget());
1007 : }
1008 :
1009 0 : void VclFrame::set_label(const rtl::OUString &rLabel)
1010 : {
1011 : //The label widget is the last (of two) children
1012 0 : Window *pLabel = get_label_widget();
1013 : assert(pLabel);
1014 0 : pLabel->SetText(rLabel);
1015 0 : }
1016 :
1017 0 : Size VclAlignment::calculateRequisition() const
1018 : {
1019 : Size aRet(m_nLeftPadding + m_nRightPadding,
1020 0 : m_nTopPadding + m_nBottomPadding);
1021 :
1022 0 : const Window *pChild = get_child();
1023 0 : if (pChild && pChild->IsVisible())
1024 : {
1025 0 : Size aChildSize = getLayoutRequisition(*pChild);
1026 0 : aRet.Width() += aChildSize.Width();
1027 0 : aRet.Height() += aChildSize.Height();
1028 : }
1029 :
1030 0 : return aRet;
1031 : }
1032 :
1033 0 : void VclAlignment::setAllocation(const Size &rAllocation)
1034 : {
1035 0 : Window *pChild = get_child();
1036 0 : if (!pChild || !pChild->IsVisible())
1037 0 : return;
1038 :
1039 0 : Point aChildPos(m_nLeftPadding, m_nTopPadding);
1040 :
1041 0 : Size aAllocation;
1042 0 : aAllocation.Width() = rAllocation.Width() - (m_nLeftPadding + m_nRightPadding);
1043 0 : aAllocation.Height() = rAllocation.Height() - (m_nTopPadding + m_nBottomPadding);
1044 :
1045 0 : setLayoutAllocation(*pChild, aChildPos, aAllocation);
1046 : }
1047 :
1048 0 : bool VclAlignment::set_property(const rtl::OString &rKey, const rtl::OString &rValue)
1049 : {
1050 0 : if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("bottom-padding")))
1051 0 : m_nBottomPadding = rValue.toInt32();
1052 0 : else if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("left-padding")))
1053 0 : m_nLeftPadding = rValue.toInt32();
1054 0 : else if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("right-padding")))
1055 0 : m_nRightPadding = rValue.toInt32();
1056 0 : else if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("top-padding")))
1057 0 : m_nTopPadding = rValue.toInt32();
1058 0 : else if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("xalign")))
1059 0 : m_fXAlign = rValue.toFloat();
1060 0 : else if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("xscale")))
1061 0 : m_fXScale = rValue.toFloat();
1062 0 : else if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("yalign")))
1063 0 : m_fYAlign = rValue.toFloat();
1064 0 : else if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("yscale")))
1065 0 : m_fYScale = rValue.toFloat();
1066 : else
1067 0 : return VclBin::set_property(rKey, rValue);
1068 0 : return true;
1069 : }
1070 :
1071 0 : const Window *VclExpander::get_child() const
1072 : {
1073 0 : const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1074 :
1075 : assert(pWindowImpl->mpFirstChild == &m_aDisclosureButton);
1076 :
1077 0 : return pWindowImpl->mpFirstChild->GetWindow(WINDOW_NEXT);
1078 : }
1079 :
1080 0 : Window *VclExpander::get_child()
1081 : {
1082 0 : return const_cast<Window*>(const_cast<const VclExpander*>(this)->get_child());
1083 : }
1084 :
1085 0 : Size VclExpander::calculateRequisition() const
1086 : {
1087 0 : Size aRet(0, 0);
1088 :
1089 0 : WindowImpl* pWindowImpl = ImplGetWindowImpl();
1090 :
1091 0 : const Window *pChild = get_child();
1092 0 : const Window *pLabel = pChild != pWindowImpl->mpLastChild ? pWindowImpl->mpLastChild : NULL;
1093 :
1094 0 : if (pChild && pChild->IsVisible() && m_aDisclosureButton.IsChecked())
1095 0 : aRet = getLayoutRequisition(*pChild);
1096 :
1097 0 : Size aExpanderSize = getLayoutRequisition(m_aDisclosureButton);
1098 :
1099 0 : if (pLabel && pLabel->IsVisible())
1100 : {
1101 0 : Size aLabelSize = getLayoutRequisition(*pLabel);
1102 0 : aExpanderSize.Height() = std::max(aExpanderSize.Height(), aLabelSize.Height());
1103 0 : aExpanderSize.Width() += aLabelSize.Width();
1104 : }
1105 :
1106 0 : aRet.Height() += aExpanderSize.Height();
1107 0 : aRet.Width() = std::max(aExpanderSize.Width(), aRet.Width());
1108 :
1109 : const FrameStyle &rFrameStyle =
1110 0 : GetSettings().GetStyleSettings().GetFrameStyle();
1111 0 : aRet.Width() += rFrameStyle.left + rFrameStyle.right;
1112 0 : aRet.Height() += rFrameStyle.top + rFrameStyle.bottom;
1113 :
1114 0 : return aRet;
1115 : }
1116 :
1117 0 : void VclExpander::setAllocation(const Size &rAllocation)
1118 : {
1119 : const FrameStyle &rFrameStyle =
1120 0 : GetSettings().GetStyleSettings().GetFrameStyle();
1121 0 : Size aAllocation(rAllocation.Width() - rFrameStyle.left - rFrameStyle.right,
1122 0 : rAllocation.Height() - rFrameStyle.top - rFrameStyle.bottom);
1123 0 : Point aChildPos(rFrameStyle.left, rFrameStyle.top);
1124 :
1125 0 : WindowImpl* pWindowImpl = ImplGetWindowImpl();
1126 :
1127 : //The label widget is the last (of two) children
1128 0 : Window *pChild = get_child();
1129 0 : Window *pLabel = pChild != pWindowImpl->mpLastChild ? pWindowImpl->mpLastChild : NULL;
1130 :
1131 0 : Size aButtonSize = getLayoutRequisition(m_aDisclosureButton);
1132 0 : Size aLabelSize;
1133 0 : Size aExpanderSize = aButtonSize;
1134 0 : if (pLabel && pLabel->IsVisible())
1135 : {
1136 0 : aLabelSize = getLayoutRequisition(*pLabel);
1137 0 : aExpanderSize.Height() = std::max(aExpanderSize.Height(), aLabelSize.Height());
1138 0 : aExpanderSize.Width() += aLabelSize.Width();
1139 : }
1140 :
1141 0 : aExpanderSize.Height() = std::min(aExpanderSize.Height(), aAllocation.Height());
1142 0 : aExpanderSize.Width() = std::min(aExpanderSize.Width(), aAllocation.Width());
1143 :
1144 0 : aButtonSize.Height() = std::min(aButtonSize.Height(), aExpanderSize.Height());
1145 0 : aButtonSize.Width() = std::min(aButtonSize.Width(), aExpanderSize.Width());
1146 :
1147 0 : long nExtraExpanderHeight = aExpanderSize.Height() - aButtonSize.Height();
1148 0 : Point aButtonPos(aChildPos.X(), aChildPos.Y() + nExtraExpanderHeight/2);
1149 0 : setLayoutAllocation(m_aDisclosureButton, aButtonPos, aButtonSize);
1150 :
1151 0 : if (pLabel && pLabel->IsVisible())
1152 : {
1153 0 : aLabelSize.Height() = std::min(aLabelSize.Height(), aExpanderSize.Height());
1154 0 : aLabelSize.Width() = std::min(aLabelSize.Width(),
1155 0 : aExpanderSize.Width() - aButtonSize.Width());
1156 :
1157 0 : long nExtraLabelHeight = aExpanderSize.Height() - aLabelSize.Height();
1158 0 : Point aLabelPos(aChildPos.X() + aButtonSize.Width(), aChildPos.Y() + nExtraLabelHeight/2);
1159 0 : setLayoutAllocation(*pLabel, aLabelPos, aLabelSize);
1160 : }
1161 :
1162 0 : aAllocation.Height() -= aExpanderSize.Height();
1163 0 : aChildPos.Y() += aExpanderSize.Height();
1164 :
1165 0 : if (pChild && pChild->IsVisible())
1166 : {
1167 0 : if (!m_aDisclosureButton.IsChecked())
1168 0 : aAllocation = Size();
1169 0 : setLayoutAllocation(*pChild, aChildPos, aAllocation);
1170 : }
1171 0 : }
1172 :
1173 0 : bool VclExpander::set_property(const rtl::OString &rKey, const rtl::OString &rValue)
1174 : {
1175 0 : if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("expanded")))
1176 0 : m_aDisclosureButton.Check(toBool(rValue));
1177 0 : else if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("resize-toplevel")))
1178 0 : m_bResizeTopLevel = toBool(rValue);
1179 : else
1180 0 : return VclBin::set_property(rKey, rValue);
1181 0 : return true;
1182 : }
1183 :
1184 0 : IMPL_LINK( VclExpander, ClickHdl, DisclosureButton*, pBtn )
1185 : {
1186 0 : Window *pChild = get_child();
1187 0 : if (pChild)
1188 : {
1189 0 : pChild->Show(pBtn->IsChecked());
1190 0 : queue_resize();
1191 0 : Dialog* pResizeDialog = m_bResizeTopLevel ? GetParentDialog() : NULL;
1192 0 : if (pResizeDialog)
1193 0 : pResizeDialog->setInitialLayoutSize();
1194 : }
1195 0 : return 0;
1196 : }
1197 :
1198 0 : const Window *VclScrolledWindow::get_child() const
1199 : {
1200 : assert(GetChildCount() == 3);
1201 0 : const WindowImpl* pWindowImpl = ImplGetWindowImpl();
1202 0 : return pWindowImpl->mpLastChild;
1203 : }
1204 :
1205 0 : Window *VclScrolledWindow::get_child()
1206 : {
1207 0 : return const_cast<Window*>(const_cast<const VclScrolledWindow*>(this)->get_child());
1208 : }
1209 :
1210 0 : Size VclScrolledWindow::calculateRequisition() const
1211 : {
1212 0 : Size aRet(0, 0);
1213 :
1214 0 : const Window *pChild = get_child();
1215 0 : if (pChild && pChild->IsVisible())
1216 0 : aRet = getLayoutRequisition(*pChild);
1217 :
1218 0 : if (m_aVScroll.IsVisible())
1219 0 : aRet.Width() += getLayoutRequisition(m_aVScroll).Width();
1220 :
1221 0 : if (m_aHScroll.IsVisible())
1222 0 : aRet.Height() += getLayoutRequisition(m_aVScroll).Height();
1223 :
1224 0 : return aRet;
1225 : }
1226 :
1227 0 : void VclScrolledWindow::setAllocation(const Size &rAllocation)
1228 : {
1229 0 : Size aChildAllocation(rAllocation);
1230 0 : Size aChildReq;
1231 :
1232 0 : Window *pChild = get_child();
1233 0 : if (pChild && pChild->IsVisible())
1234 0 : aChildReq = getLayoutRequisition(*pChild);
1235 :
1236 0 : if (m_aVScroll.IsVisible())
1237 : {
1238 0 : long nScrollBarWidth = getLayoutRequisition(m_aVScroll).Width();
1239 0 : Point aScrollPos(rAllocation.Width() - nScrollBarWidth, 0);
1240 0 : Size aScrollSize(nScrollBarWidth, rAllocation.Height());
1241 0 : setLayoutAllocation(m_aVScroll, aScrollPos, aScrollSize);
1242 0 : aChildAllocation.Width() -= nScrollBarWidth;
1243 0 : aChildAllocation.Height() = aChildReq.Height();
1244 : }
1245 :
1246 0 : if (m_aHScroll.IsVisible())
1247 : {
1248 0 : long nScrollBarHeight = getLayoutRequisition(m_aHScroll).Height();
1249 0 : Point aScrollPos(0, rAllocation.Height() - nScrollBarHeight);
1250 0 : Size aScrollSize(rAllocation.Width(), nScrollBarHeight);
1251 0 : setLayoutAllocation(m_aHScroll, aScrollPos, aScrollSize);
1252 0 : aChildAllocation.Height() -= nScrollBarHeight;
1253 0 : aChildAllocation.Width() = aChildReq.Width();
1254 : }
1255 :
1256 0 : if (pChild && pChild->IsVisible())
1257 : {
1258 0 : Point aChildPos(pChild->GetPosPixel());
1259 0 : if (!m_aHScroll.IsVisible())
1260 0 : aChildPos.X() = 0;
1261 0 : if (!m_aVScroll.IsVisible())
1262 0 : aChildPos.Y() = 0;
1263 0 : setLayoutAllocation(*pChild, aChildPos, aChildAllocation);
1264 : }
1265 0 : }
1266 :
1267 0 : Size VclScrolledWindow::getVisibleChildSize() const
1268 : {
1269 0 : Size aRet(GetSizePixel());
1270 0 : if (m_aVScroll.IsVisible())
1271 0 : aRet.Width() -= m_aVScroll.GetSizePixel().Width();
1272 0 : if (m_aHScroll.IsVisible())
1273 0 : aRet.Height() -= m_aHScroll.GetSizePixel().Height();
1274 0 : return aRet;
1275 : }
1276 :
1277 0 : bool VclScrolledWindow::set_property(const rtl::OString &rKey, const rtl::OString &rValue)
1278 : {
1279 0 : bool bRet = VclBin::set_property(rKey, rValue);
1280 0 : m_aVScroll.Show(GetStyle() & WB_VERT);
1281 0 : m_aHScroll.Show(GetStyle() & WB_HORZ);
1282 0 : return bRet;
1283 : }
1284 :
1285 0 : Size getLegacyBestSizeForChildren(const Window &rWindow)
1286 : {
1287 0 : Rectangle aBounds;
1288 :
1289 0 : for (const Window* pChild = rWindow.GetWindow(WINDOW_FIRSTCHILD); pChild;
1290 : pChild = pChild->GetWindow(WINDOW_NEXT))
1291 : {
1292 0 : if (!pChild->IsVisible())
1293 0 : continue;
1294 :
1295 0 : Rectangle aChildBounds(pChild->GetPosPixel(), pChild->GetSizePixel());
1296 0 : aBounds.Union(aChildBounds);
1297 : }
1298 :
1299 0 : if (aBounds.IsEmpty())
1300 0 : return rWindow.GetSizePixel();
1301 :
1302 0 : Size aRet(aBounds.GetSize());
1303 0 : Point aTopLeft(aBounds.TopLeft());
1304 0 : aRet.Width() += aTopLeft.X()*2;
1305 0 : aRet.Height() += aTopLeft.Y()*2;
1306 :
1307 0 : return aRet;
1308 : }
1309 :
1310 680 : Window* getNonLayoutParent(Window *pWindow)
1311 : {
1312 1360 : while (pWindow)
1313 : {
1314 680 : pWindow = pWindow->GetParent();
1315 680 : if (!pWindow || !isContainerWindow(*pWindow))
1316 680 : break;
1317 : }
1318 680 : return pWindow;
1319 : }
1320 :
1321 0 : Window* getNonLayoutRealParent(Window *pWindow)
1322 : {
1323 0 : while (pWindow)
1324 : {
1325 0 : pWindow = pWindow->ImplGetParent();
1326 0 : if (!pWindow || !isContainerWindow(*pWindow))
1327 0 : break;
1328 : }
1329 0 : return pWindow;
1330 : }
1331 :
1332 408 : bool isVisibleInLayout(const Window *pWindow)
1333 : {
1334 408 : bool bVisible = true;
1335 816 : while (bVisible)
1336 : {
1337 408 : bVisible = pWindow->IsVisible();
1338 408 : pWindow = pWindow->GetParent();
1339 408 : if (!pWindow || !isContainerWindow(*pWindow))
1340 408 : break;
1341 : }
1342 408 : return bVisible;
1343 : }
1344 :
1345 0 : bool isEnabledInLayout(const Window *pWindow)
1346 : {
1347 0 : bool bEnabled = true;
1348 0 : while (bEnabled)
1349 : {
1350 0 : bEnabled = pWindow->IsEnabled();
1351 0 : pWindow = pWindow->GetParent();
1352 0 : if (!pWindow || !isContainerWindow(*pWindow))
1353 0 : break;
1354 : }
1355 0 : return bEnabled;
1356 108 : }
1357 :
1358 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|