HaikuDepot: notify work status from main window
[haiku.git] / src / libs / alm / Area.cpp
blobcd80cd2c83f67930c4e599a6682330017dfb202c
1 /*
2 * Copyright 2007-2008, Christof Lutteroth, lutteroth@cs.auckland.ac.nz
3 * Copyright 2007-2008, James Kim, jkim202@ec.auckland.ac.nz
4 * Copyright 2010, Clemens Zeidler <haiku@clemens-zeidler.de>
5 * Distributed under the terms of the MIT License.
6 */
9 #include "Area.h"
11 #include <Alignment.h>
12 #include <ControlLook.h>
13 #include <View.h>
15 #include "ALMLayout.h"
16 #include "RowColumnManager.h"
17 #include "Row.h"
18 #include "Column.h"
21 using namespace LinearProgramming;
24 BLayoutItem*
25 Area::Item()
27 return fLayoutItem;
31 /**
32 * Gets the left tab of the area.
34 * @return the left tab of the area
36 XTab*
37 Area::Left() const
39 return fLeft;
43 /**
44 * Gets the right tab of the area.
46 * @return the right tab of the area
48 XTab*
49 Area::Right() const
51 return fRight;
55 /**
56 * Gets the top tab of the area.
58 YTab*
59 Area::Top() const
61 return fTop;
65 /**
66 * Gets the bottom tab of the area.
68 YTab*
69 Area::Bottom() const
71 return fBottom;
75 /**
76 * Sets the left tab of the area.
78 * @param left the left tab of the area
80 void
81 Area::SetLeft(BReference<XTab> left)
83 fLeft = left;
85 fMinContentWidth->SetLeftSide(-1.0, fLeft, 1.0, fRight);
86 if (fMaxContentWidth != NULL)
87 fMaxContentWidth->SetLeftSide(-1.0, fLeft, 1.0, fRight);
88 fRowColumnManager->TabsChanged(this);
90 fLayoutItem->Layout()->InvalidateLayout();
94 /**
95 * Sets the right tab of the area.
97 * @param right the right tab of the area
99 void
100 Area::SetRight(BReference<XTab> right)
102 fRight = right;
104 fMinContentWidth->SetLeftSide(-1.0, fLeft, 1.0, fRight);
105 if (fMaxContentWidth != NULL)
106 fMaxContentWidth->SetLeftSide(-1.0, fLeft, 1.0, fRight);
107 fRowColumnManager->TabsChanged(this);
109 fLayoutItem->Layout()->InvalidateLayout();
114 * Sets the top tab of the area.
116 void
117 Area::SetTop(BReference<YTab> top)
119 fTop = top;
121 fMinContentHeight->SetLeftSide(-1.0, fTop, 1.0, fBottom);
122 if (fMaxContentHeight != NULL)
123 fMaxContentHeight->SetLeftSide(-1.0, fTop, 1.0, fBottom);
124 fRowColumnManager->TabsChanged(this);
126 fLayoutItem->Layout()->InvalidateLayout();
131 * Sets the bottom tab of the area.
133 void
134 Area::SetBottom(BReference<YTab> bottom)
136 fBottom = bottom;
138 fMinContentHeight->SetLeftSide(-1.0, fTop, 1.0, fBottom);
139 if (fMaxContentHeight != NULL)
140 fMaxContentHeight->SetLeftSide(-1.0, fTop, 1.0, fBottom);
141 fRowColumnManager->TabsChanged(this);
143 fLayoutItem->Layout()->InvalidateLayout();
148 * Gets the row that defines the top and bottom tabs.
150 Row*
151 Area::GetRow() const
153 return fRow;
158 * Gets the column that defines the left and right tabs.
160 Column*
161 Area::GetColumn() const
163 return fColumn;
168 * The reluctance with which the area's content shrinks below its preferred size.
169 * The bigger the less likely is such shrinking.
171 BSize
172 Area::ShrinkPenalties() const
174 return fShrinkPenalties;
179 * The reluctance with which the area's content grows over its preferred size.
180 * The bigger the less likely is such growth.
182 BSize
183 Area::GrowPenalties() const
185 return fGrowPenalties;
189 void
190 Area::SetShrinkPenalties(BSize shrink) {
191 fShrinkPenalties = shrink;
193 fLayoutItem->Layout()->InvalidateLayout();
197 void
198 Area::SetGrowPenalties(BSize grow)
200 fGrowPenalties = grow;
202 fLayoutItem->Layout()->InvalidateLayout();
207 * Gets aspect ratio of the area's content.
209 double
210 Area::ContentAspectRatio() const
212 return fContentAspectRatio;
217 * Sets aspect ratio of the area's content.
218 * May be different from the aspect ratio of the area.
220 void
221 Area::SetContentAspectRatio(double ratio)
223 fContentAspectRatio = ratio;
224 if (fContentAspectRatio <= 0) {
225 delete fContentAspectRatioC;
226 fContentAspectRatioC = NULL;
227 } else if (fContentAspectRatioC == NULL) {
228 fContentAspectRatioC = fLS->AddConstraint(-1.0, fLeft, 1.0, fRight,
229 ratio, fTop, -ratio, fBottom, kEQ, 0.0);
230 } else {
231 fContentAspectRatioC->SetLeftSide(-1.0, fLeft, 1.0, fRight, ratio,
232 fTop, -ratio, fBottom);
234 /* called during BALMLayout::ItemUnarchived */
235 if (BLayout* layout = fLayoutItem->Layout())
236 layout->InvalidateLayout();
240 void
241 Area::GetInsets(float* left, float* top, float* right, float* bottom) const
243 if (left)
244 *left = fLeftTopInset.Width();
245 if (top)
246 *top = fLeftTopInset.Height();
247 if (right)
248 *right = fRightBottomInset.Width();
249 if (bottom)
250 *bottom = fRightBottomInset.Height();
255 * Gets left inset between area and its content.
257 float
258 Area::LeftInset() const
260 if (fLeftTopInset.IsWidthSet())
261 return fLeftTopInset.Width();
263 BALMLayout* layout = static_cast<BALMLayout*>(fLayoutItem->Layout());
264 return layout->InsetForTab(fLeft.Get());
269 * Gets top inset between area and its content.
271 float
272 Area::TopInset() const
274 if (fLeftTopInset.IsHeightSet())
275 return fLeftTopInset.Height();
277 BALMLayout* layout = static_cast<BALMLayout*>(fLayoutItem->Layout());
278 return layout->InsetForTab(fTop.Get());
283 * Gets right inset between area and its content.
285 float
286 Area::RightInset() const
288 if (fRightBottomInset.IsWidthSet())
289 return fRightBottomInset.Width();
291 BALMLayout* layout = static_cast<BALMLayout*>(fLayoutItem->Layout());
292 return layout->InsetForTab(fRight.Get());
297 * Gets bottom inset between area and its content.
299 float
300 Area::BottomInset() const
302 if (fRightBottomInset.IsHeightSet())
303 return fRightBottomInset.Height();
305 BALMLayout* layout = static_cast<BALMLayout*>(fLayoutItem->Layout());
306 return layout->InsetForTab(fBottom.Get());
310 void
311 Area::SetInsets(float insets)
313 if (insets != B_SIZE_UNSET)
314 insets = BControlLook::ComposeSpacing(insets);
316 fLeftTopInset.Set(insets, insets);
317 fRightBottomInset.Set(insets, insets);
318 fLayoutItem->Layout()->InvalidateLayout();
322 void
323 Area::SetInsets(float horizontal, float vertical)
325 if (horizontal != B_SIZE_UNSET)
326 horizontal = BControlLook::ComposeSpacing(horizontal);
327 if (vertical != B_SIZE_UNSET)
328 vertical = BControlLook::ComposeSpacing(vertical);
330 fLeftTopInset.Set(horizontal, horizontal);
331 fRightBottomInset.Set(vertical, vertical);
332 fLayoutItem->Layout()->InvalidateLayout();
336 void
337 Area::SetInsets(float left, float top, float right, float bottom)
339 if (left != B_SIZE_UNSET)
340 left = BControlLook::ComposeSpacing(left);
341 if (right != B_SIZE_UNSET)
342 right = BControlLook::ComposeSpacing(right);
343 if (top != B_SIZE_UNSET)
344 top = BControlLook::ComposeSpacing(top);
345 if (bottom != B_SIZE_UNSET)
346 bottom = BControlLook::ComposeSpacing(bottom);
348 fLeftTopInset.Set(left, top);
349 fRightBottomInset.Set(right, bottom);
350 fLayoutItem->Layout()->InvalidateLayout();
355 * Sets left inset between area and its content.
357 void
358 Area::SetLeftInset(float left)
360 fLeftTopInset.width = left;
361 fLayoutItem->Layout()->InvalidateLayout();
366 * Sets top inset between area and its content.
368 void
369 Area::SetTopInset(float top)
371 fLeftTopInset.height = top;
372 fLayoutItem->Layout()->InvalidateLayout();
377 * Sets right inset between area and its content.
379 void
380 Area::SetRightInset(float right)
382 fRightBottomInset.width = right;
383 fLayoutItem->Layout()->InvalidateLayout();
388 * Sets bottom inset between area and its content.
390 void
391 Area::SetBottomInset(float bottom)
393 fRightBottomInset.height = bottom;
394 fLayoutItem->Layout()->InvalidateLayout();
398 BString
399 Area::ToString() const
401 BString string = "Area(";
402 string += fLeft->ToString();
403 string << ", ";
404 string += fTop->ToString();
405 string << ", ";
406 string += fRight->ToString();
407 string << ", ";
408 string += fBottom->ToString();
409 string << ")";
410 return string;
415 * Sets the width of the area to be the same as the width of the given area
416 * times factor.
418 * @param area the area that should have the same width
419 * @return the same-width constraint
421 Constraint*
422 Area::SetWidthAs(Area* area, float factor)
424 return fLS->AddConstraint(-1.0, fLeft, 1.0, fRight, factor, area->Left(),
425 -factor, area->Right(), kEQ, 0.0);
430 * Sets the height of the area to be the same as the height of the given area
431 * times factor.
433 * @param area the area that should have the same height
434 * @return the same-height constraint
436 Constraint*
437 Area::SetHeightAs(Area* area, float factor)
439 return fLS->AddConstraint(-1.0, fTop, 1.0, fBottom, factor, area->Top(),
440 -factor, area->Bottom(), kEQ, 0.0);
444 void
445 Area::InvalidateSizeConstraints()
447 // check if if we are initialized
448 if (!fLeft)
449 return;
451 BSize minSize = fLayoutItem->MinSize();
452 BSize maxSize = fLayoutItem->MaxSize();
454 _UpdateMinSizeConstraint(minSize);
455 _UpdateMaxSizeConstraint(maxSize);
459 BRect
460 Area::Frame() const
462 return BRect(round(fLeft->Value()), round(fTop->Value()),
463 round(fRight->Value()), round(fBottom->Value()));
468 * Destructor.
469 * Removes the area from its specification.
471 Area::~Area()
473 delete fMinContentWidth;
474 delete fMaxContentWidth;
475 delete fMinContentHeight;
476 delete fMaxContentHeight;
477 delete fContentAspectRatioC;
481 static int32 sAreaID = 0;
483 static int32
484 new_area_id()
486 return sAreaID++;
491 * Constructor.
492 * Uses XTabs and YTabs.
494 Area::Area(BLayoutItem* item)
496 fLayoutItem(item),
497 fLS(NULL),
498 fLeft(NULL),
499 fRight(NULL),
500 fTop(NULL),
501 fBottom(NULL),
502 fRow(NULL),
503 fColumn(NULL),
504 fShrinkPenalties(5, 5),
505 fGrowPenalties(5, 5),
506 fContentAspectRatio(-1),
507 fRowColumnManager(NULL),
508 fMinContentWidth(NULL),
509 fMaxContentWidth(NULL),
510 fMinContentHeight(NULL),
511 fMaxContentHeight(NULL),
512 fContentAspectRatioC(NULL)
514 fID = new_area_id();
518 int32
519 Area::ID() const
521 return fID;
525 void
526 Area::SetID(int32 id)
528 fID = id;
533 * Initialize variables.
535 void
536 Area::_Init(LinearSpec* ls, XTab* left, YTab* top, XTab* right, YTab* bottom,
537 RowColumnManager* manager)
539 fLS = ls;
540 fLeft = left;
541 fRight = right;
542 fTop = top;
543 fBottom = bottom;
545 fRowColumnManager = manager;
547 // adds the two essential constraints of the area that make sure that the
548 // left x-tab is really to the left of the right x-tab, and the top y-tab
549 // really above the bottom y-tab
550 fMinContentWidth = ls->AddConstraint(-1.0, fLeft, 1.0, fRight, kGE, 0);
551 fMinContentHeight = ls->AddConstraint(-1.0, fTop, 1.0, fBottom, kGE, 0);
553 InvalidateSizeConstraints();
557 void
558 Area::_Init(LinearSpec* ls, Row* row, Column* column, RowColumnManager* manager)
560 _Init(ls, column->Left(), row->Top(), column->Right(),
561 row->Bottom(), manager);
563 fRow = row;
564 fColumn = column;
569 * Perform layout on the area.
571 void
572 Area::_DoLayout(const BPoint& offset)
574 // check if if we are initialized
575 if (!fLeft)
576 return;
578 if (!fLayoutItem->IsVisible())
579 fLayoutItem->AlignInFrame(BRect(0, 0, -1, -1));
581 BRect areaFrame(Frame());
582 areaFrame.left += LeftInset();
583 areaFrame.right -= RightInset();
584 areaFrame.top += TopInset();
585 areaFrame.bottom -= BottomInset();
587 fLayoutItem->AlignInFrame(areaFrame.OffsetBySelf(offset));
591 void
592 Area::_UpdateMinSizeConstraint(BSize min)
594 if (!fLayoutItem->IsVisible()) {
595 fMinContentHeight->SetRightSide(-1);
596 fMinContentWidth->SetRightSide(-1);
597 return;
600 float width = 0.;
601 float height = 0.;
602 if (min.width > 0)
603 width = min.Width() + LeftInset() + RightInset();
604 if (min.height > 0)
605 height = min.Height() + TopInset() + BottomInset();
607 fMinContentWidth->SetRightSide(width);
608 fMinContentHeight->SetRightSide(height);
612 void
613 Area::_UpdateMaxSizeConstraint(BSize max)
615 if (!fLayoutItem->IsVisible()) {
616 if (fMaxContentHeight != NULL)
617 fMaxContentHeight->SetRightSide(B_SIZE_UNLIMITED);
618 if (fMaxContentWidth != NULL)
619 fMaxContentWidth->SetRightSide(B_SIZE_UNLIMITED);
620 return;
623 max.width += LeftInset() + RightInset();
624 max.height += TopInset() + BottomInset();
626 const double kPriority = 100;
627 // we only need max constraints if the alignment is full height/width
628 // otherwise we can just align the item in the free space
629 BAlignment alignment = fLayoutItem->Alignment();
630 double priority = kPriority;
631 if (alignment.Vertical() == B_ALIGN_USE_FULL_HEIGHT)
632 priority = -1;
634 if (max.Height() < 20000) {
635 if (fMaxContentHeight == NULL) {
636 fMaxContentHeight = fLS->AddConstraint(-1.0, fTop, 1.0, fBottom,
637 kLE, max.Height(), priority, priority);
638 } else {
639 fMaxContentHeight->SetRightSide(max.Height());
640 fMaxContentHeight->SetPenaltyNeg(priority);
641 fMaxContentHeight->SetPenaltyPos(priority);
643 } else {
644 delete fMaxContentHeight;
645 fMaxContentHeight = NULL;
648 priority = kPriority;
649 if (alignment.Horizontal() == B_ALIGN_USE_FULL_WIDTH)
650 priority = -1;
652 if (max.Width() < 20000) {
653 if (fMaxContentWidth == NULL) {
654 fMaxContentWidth = fLS->AddConstraint(-1.0, fLeft, 1.0, fRight, kLE,
655 max.Width(), priority, priority);
656 } else {
657 fMaxContentWidth->SetRightSide(max.Width());
658 fMaxContentWidth->SetPenaltyNeg(priority);
659 fMaxContentWidth->SetPenaltyPos(priority);
661 } else {
662 delete fMaxContentWidth;
663 fMaxContentWidth = NULL;