00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "xrb_layout.hpp"
00012
00013 #include "xrb_screen.hpp"
00014
00015 namespace Xrb
00016 {
00017
00018 Layout::Layout (
00019 LineDirection const major_direction,
00020 Uint32 const major_count,
00021 ContainerWidget *const parent,
00022 std::string const &name)
00023 :
00024 ContainerWidget(parent, name)
00025 {
00026 Initialize(major_direction, major_count);
00027 }
00028
00029 Layout::Layout (
00030 Orientation const orientation,
00031 ContainerWidget *const parent,
00032 std::string const &name)
00033 :
00034 ContainerWidget(parent, name)
00035 {
00036 LineDirection major_direction;
00037 Uint32 major_count = 1;
00038 major_direction = (orientation == HORIZONTAL) ? COLUMN : ROW;
00039
00040 Initialize(major_direction, major_count);
00041 }
00042
00043 Layout::~Layout ()
00044 {
00045 DeleteColumnSizePropertyArrays();
00046 DeleteRowSizePropertyArrays();
00047 }
00048
00049 Widget *Layout::GridChild (
00050 Uint32 const major_index,
00051 Uint32 const minor_index) const
00052 {
00053 ASSERT1(major_index < MinorCount());
00054 ASSERT1(minor_index < MajorCount());
00055 Uint32 linear_index = major_index * MajorCount() + minor_index;
00056 if (linear_index < m_child_vector.size())
00057 return m_child_vector[linear_index];
00058 else
00059 return 0;
00060 }
00061
00062 Widget *Layout::GridChildByColumnAndRow (
00063 Uint32 const column_index,
00064 Uint32 const row_index) const
00065 {
00066 ASSERT1(column_index < ColumnCount());
00067 ASSERT1(row_index < RowCount());
00068 Uint32 linear_index = (m_major_direction == ROW) ?
00069 row_index * ColumnCount() + column_index :
00070 column_index * RowCount() + row_index;
00071 if (linear_index < m_child_vector.size())
00072 return m_child_vector[linear_index];
00073 else
00074 return 0;
00075 }
00076
00077 ScreenCoordVector2 const &Layout::TotalSpacing () const
00078 {
00079 UpdateTotalSpacing();
00080 return m_total_spacing;
00081 }
00082
00083 Uint32 Layout::ColumnCount () const
00084 {
00085 UpdateColumnSizeProperties();
00086 return m_column_count;
00087 }
00088
00089 Bool2 const &Layout::ColumnMinSizeEnabled (Uint32 const index) const
00090 {
00091 UpdateColumnSizeProperties();
00092 ASSERT1(index < m_column_count);
00093 return m_column_size_properties[index].m_min_size_enabled;
00094 }
00095
00096 ScreenCoordVector2 const &Layout::ColumnMinSize (Uint32 const index) const
00097 {
00098 UpdateColumnSizeProperties();
00099 ASSERT1(index < m_column_count);
00100 return m_column_size_properties[index].m_min_size;
00101 }
00102
00103 Bool2 const &Layout::ColumnMaxSizeEnabled (Uint32 const index) const
00104 {
00105 UpdateColumnSizeProperties();
00106 ASSERT1(index < m_column_count);
00107 return m_column_size_properties[index].m_max_size_enabled;
00108 }
00109
00110 ScreenCoordVector2 const &Layout::ColumnMaxSize (Uint32 const index) const
00111 {
00112 UpdateColumnSizeProperties();
00113 ASSERT1(index < m_column_count);
00114 return m_column_size_properties[index].m_max_size;
00115 }
00116
00117 ScreenCoord Layout::ColumnWidth (Uint32 const index) const
00118 {
00119 UpdateColumnSizeProperties();
00120 ASSERT1(index < m_column_count);
00121 return m_column_width[index];
00122 }
00123
00124 Uint32 Layout::HiddenColumnCount () const
00125 {
00126 UpdateColumnSizeProperties();
00127 return m_hidden_column_count;
00128 }
00129
00130 Uint32 Layout::RowCount () const
00131 {
00132 UpdateRowSizeProperties();
00133 return m_row_count;
00134 }
00135
00136 Bool2 const &Layout::RowMinSizeEnabled (Uint32 const index) const
00137 {
00138 UpdateRowSizeProperties();
00139 ASSERT1(index < m_row_count);
00140 return m_row_size_properties[index].m_min_size_enabled;
00141 }
00142
00143 ScreenCoordVector2 const &Layout::RowMinSize (Uint32 const index) const
00144 {
00145 UpdateRowSizeProperties();
00146 ASSERT1(index < m_row_count);
00147 return m_row_size_properties[index].m_min_size;
00148 }
00149
00150 Bool2 const &Layout::RowMaxSizeEnabled (Uint32 const index) const
00151 {
00152 UpdateRowSizeProperties();
00153 ASSERT1(index < m_row_count);
00154 return m_row_size_properties[index].m_max_size_enabled;
00155 }
00156
00157 ScreenCoordVector2 const &Layout::RowMaxSize (Uint32 const index) const
00158 {
00159 UpdateRowSizeProperties();
00160 ASSERT1(index < m_row_count);
00161 return m_row_size_properties[index].m_max_size;
00162 }
00163
00164 ScreenCoord Layout::RowHeight (Uint32 const index) const
00165 {
00166 UpdateRowSizeProperties();
00167 ASSERT1(index < m_row_count);
00168 return m_row_height[index];
00169 }
00170
00171 Uint32 Layout::HiddenRowCount () const
00172 {
00173 UpdateRowSizeProperties();
00174 return m_hidden_row_count;
00175 }
00176
00177 Bool2 Layout::ContentsMinSizeEnabled () const
00178 {
00179 UpdateContentsSizeProperties();
00180 return m_contents_size_properties.m_min_size_enabled;
00181 }
00182
00183 ScreenCoordVector2 Layout::ContentsMinSize () const
00184 {
00185 UpdateContentsSizeProperties();
00186 return m_contents_size_properties.m_min_size;
00187 }
00188
00189 Bool2 Layout::ContentsMaxSizeEnabled () const
00190 {
00191 UpdateContentsSizeProperties();
00192 return m_contents_size_properties.m_max_size_enabled;
00193 }
00194
00195 ScreenCoordVector2 Layout::ContentsMaxSize () const
00196 {
00197 UpdateContentsSizeProperties();
00198 return m_contents_size_properties.m_max_size;
00199 }
00200
00201 void Layout::SetMajorDirection (LineDirection const major_direction)
00202 {
00203 if (m_major_direction != major_direction)
00204 {
00205 m_major_direction = major_direction;
00206
00207
00208 DirtyColumnSizePropertyAllocations();
00209 DirtyRowSizePropertyAllocations();
00210 }
00211 }
00212
00213 void Layout::SetMajorCount (Uint32 const major_count)
00214 {
00215 ASSERT1(major_count > 0);
00216
00217 if (m_major_count != major_count)
00218 {
00219 m_major_count = major_count;
00220
00221
00222 DirtyColumnSizePropertyAllocations();
00223 DirtyRowSizePropertyAllocations();
00224 }
00225 }
00226
00227 void Layout::SetIsUsingZeroedFrameMargins (
00228 bool const is_using_zeroed_frame_margins)
00229 {
00230 if (m_is_using_zeroed_frame_margins != is_using_zeroed_frame_margins)
00231 {
00232 m_is_using_zeroed_frame_margins = is_using_zeroed_frame_margins;
00233 HandleChangedLayoutFrameMargins();
00234 }
00235 }
00236
00237 void Layout::SetIsUsingZeroedLayoutSpacingMargins (
00238 bool const is_using_zeroed_layout_spacing_margins)
00239 {
00240 if (m_is_using_zeroed_layout_spacing_margins !=
00241 is_using_zeroed_layout_spacing_margins)
00242 {
00243 m_is_using_zeroed_layout_spacing_margins =
00244 is_using_zeroed_layout_spacing_margins;
00245 HandleChangedLayoutSpacingMargins();
00246 }
00247 }
00248
00249 void Layout::SetSizePropertyEnabled (
00250 SizeProperties::Property const property,
00251 Uint32 const component,
00252 bool const value)
00253 {
00254 ASSERT1(component <= 1);
00255 if (property == SizeProperties::MIN)
00256 m_preferred_size_properties.m_min_size_enabled[component] = value;
00257 else
00258 m_preferred_size_properties.m_max_size_enabled[component] = value;
00259 ConstrainPreferredSizeProperties();
00260 ContainerWidget::SetSizePropertyEnabled(property, component, value, true);
00261 CalculateMinAndMaxSizePropertiesFromContents();
00262
00263 }
00264
00265 void Layout::SetSizePropertyEnabled (
00266 SizeProperties::Property const property,
00267 Bool2 const &value)
00268 {
00269 if (property == SizeProperties::MIN)
00270 m_preferred_size_properties.m_min_size_enabled = value;
00271 else
00272 m_preferred_size_properties.m_max_size_enabled = value;
00273 ConstrainPreferredSizeProperties();
00274 ContainerWidget::SetSizePropertyEnabled(property, value, true);
00275 CalculateMinAndMaxSizePropertiesFromContents();
00276
00277 }
00278
00279 void Layout::SetSizeProperty (
00280 SizeProperties::Property const property,
00281 Uint32 const component,
00282 ScreenCoord const value)
00283 {
00284 ASSERT1(component <= 1);
00285 ASSERT1(value >= 0);
00286 if (property == SizeProperties::MIN)
00287 m_preferred_size_properties.m_min_size[component] = value;
00288 else
00289 m_preferred_size_properties.m_max_size[component] = value;
00290 ConstrainPreferredSizeProperties();
00291 ContainerWidget::SetSizeProperty(property, component, value, true);
00292 CalculateMinAndMaxSizePropertiesFromContents();
00293
00294 }
00295
00296 void Layout::SetSizeProperty (
00297 SizeProperties::Property const property,
00298 ScreenCoordVector2 const &value)
00299 {
00300 ASSERT1(value[Dim::X] >= 0);
00301 ASSERT1(value[Dim::Y] >= 0);
00302 if (property == SizeProperties::MIN)
00303 m_preferred_size_properties.m_min_size = value;
00304 else
00305 m_preferred_size_properties.m_max_size = value;
00306 ConstrainPreferredSizeProperties();
00307 ContainerWidget::SetSizeProperty(property, value, true);
00308 CalculateMinAndMaxSizePropertiesFromContents();
00309
00310 }
00311
00312 ScreenCoordVector2 Layout::Resize (ScreenCoordVector2 const &size)
00313 {
00314 ContainerWidget::Resize(size);
00315
00316
00317 if (ChildResizeBlockerCount() == 0)
00318 {
00319 DelegateWidthsToColumns();
00320 DelegateHeightsToRows();
00321 ResizeAndRepositionChildWidgets();
00322 }
00323 else
00324 IndicateChildResizeWasBlocked();
00325
00326 return Size();
00327 }
00328
00329 void Layout::AttachChild (Widget *const child)
00330 {
00331
00332 ContainerWidget::AttachChild(child);
00333
00334
00335 DirtyTotalSpacing();
00336 DirtyColumnSizePropertyAllocations();
00337 DirtyRowSizePropertyAllocations();
00338
00339 if (ChildResizeBlockerCount() == 0)
00340 {
00341
00342 CalculateMinAndMaxSizePropertiesFromContents();
00343
00344 Resize(Size());
00345
00346
00347 }
00348 else
00349 IndicateChildResizeWasBlocked();
00350 }
00351
00352 void Layout::DetachChild (Widget *const child)
00353 {
00354
00355 ContainerWidget::DetachChild(child);
00356
00357
00358 DirtyTotalSpacing();
00359 DirtyColumnSizePropertyAllocations();
00360 DirtyRowSizePropertyAllocations();
00361
00362 if (ChildResizeBlockerCount() == 0)
00363 {
00364
00365 CalculateMinAndMaxSizePropertiesFromContents();
00366
00367 Resize(Size());
00368
00369
00370 }
00371 else
00372 IndicateChildResizeWasBlocked();
00373 }
00374
00375 void Layout::MoveChildDown (Widget *const child)
00376 {
00377
00378 ContainerWidget::MoveChildDown(child);
00379
00380
00381
00382 DirtyTotalSpacing();
00383 DirtyColumnSizeProperties();
00384 DirtyRowSizeProperties();
00385
00386 if (ChildResizeBlockerCount() == 0)
00387 {
00388
00389 CalculateMinAndMaxSizePropertiesFromContents();
00390
00391 Resize(Size());
00392
00393
00394 }
00395 else
00396 IndicateChildResizeWasBlocked();
00397 }
00398
00399 void Layout::MoveChildUp (Widget *const child)
00400 {
00401
00402 ContainerWidget::MoveChildUp(child);
00403
00404
00405
00406 DirtyTotalSpacing();
00407 DirtyColumnSizeProperties();
00408 DirtyRowSizeProperties();
00409
00410 if (ChildResizeBlockerCount() == 0)
00411 {
00412
00413 CalculateMinAndMaxSizePropertiesFromContents();
00414
00415 Resize(Size());
00416
00417
00418 }
00419 else
00420 IndicateChildResizeWasBlocked();
00421 }
00422
00423 void Layout::MoveChildToBottom (Widget *const child)
00424 {
00425
00426 ContainerWidget::MoveChildToBottom(child);
00427
00428
00429
00430 DirtyTotalSpacing();
00431 DirtyColumnSizeProperties();
00432 DirtyRowSizeProperties();
00433
00434 if (ChildResizeBlockerCount() == 0)
00435 {
00436
00437 CalculateMinAndMaxSizePropertiesFromContents();
00438
00439 Resize(Size());
00440
00441
00442 }
00443 else
00444 IndicateChildResizeWasBlocked();
00445 }
00446
00447 void Layout::MoveChildToTop (Widget *const child)
00448 {
00449
00450 ContainerWidget::MoveChildToTop(child);
00451
00452
00453
00454 DirtyTotalSpacing();
00455 DirtyColumnSizeProperties();
00456 DirtyRowSizeProperties();
00457
00458 if (ChildResizeBlockerCount() == 0)
00459 {
00460
00461 CalculateMinAndMaxSizePropertiesFromContents();
00462
00463 Resize(Size());
00464
00465
00466 }
00467 else
00468 IndicateChildResizeWasBlocked();
00469 }
00470
00471 void Layout::HandleChangedWidgetSkinMargins (
00472 WidgetSkin::MarginsType const margins_type)
00473 {
00474 if (margins_type == WidgetSkin::LAYOUT_FRAME_MARGINS)
00475 HandleChangedLayoutFrameMargins();
00476 else if (margins_type == WidgetSkin::LAYOUT_SPACING_MARGINS)
00477 HandleChangedLayoutSpacingMargins();
00478 }
00479
00480 void Layout::HandleChangedLayoutFrameMargins ()
00481 {
00482 DirtyTotalSpacing();
00483 DirtyContentsSizeProperties();
00484 ConstrainPreferredSizeProperties();
00485
00486 if (ChildResizeBlockerCount() == 0)
00487 {
00488 CalculateMinAndMaxSizePropertiesFromContents();
00489
00490 }
00491 else
00492 IndicateChildResizeWasBlocked();
00493 }
00494
00495 void Layout::HandleChangedLayoutSpacingMargins ()
00496 {
00497 DirtyTotalSpacing();
00498 DirtyContentsSizeProperties();
00499 ConstrainPreferredSizeProperties();
00500
00501 if (ChildResizeBlockerCount() == 0)
00502 {
00503 CalculateMinAndMaxSizePropertiesFromContents();
00504
00505 }
00506 else
00507 IndicateChildResizeWasBlocked();
00508 }
00509
00510 void Layout::ChildSizePropertiesChanged (Widget *const child)
00511 {
00512
00513
00514 DirtyTotalSpacing();
00515 DirtyColumnSizeProperties();
00516 DirtyRowSizeProperties();
00517
00518 if (ChildResizeBlockerCount() == 0)
00519 {
00520
00521 CalculateMinAndMaxSizePropertiesFromContents();
00522
00523 Resize(Size());
00524
00525
00526 }
00527 else
00528 IndicateChildResizeWasBlocked();
00529 }
00530
00531 void Layout::ChildStackPriorityChanged (
00532 Widget *const child,
00533 StackPriority const previous_stack_priority)
00534 {
00535 ContainerWidget::ChildStackPriorityChanged(child, previous_stack_priority);
00536
00537
00538
00539 DirtyTotalSpacing();
00540 DirtyColumnSizeProperties();
00541 DirtyRowSizeProperties();
00542
00543 if (ChildResizeBlockerCount() == 0)
00544 {
00545
00546 CalculateMinAndMaxSizePropertiesFromContents();
00547
00548 Resize(Size());
00549
00550
00551 }
00552 else
00553 IndicateChildResizeWasBlocked();
00554 }
00555
00556 int Layout::SizePropertiesSortingFunction (
00557 SizeProperties const *const properties_a,
00558 SizeProperties const *const properties_b,
00559 Uint32 const index)
00560 {
00561 ASSERT1(index <= 1);
00562 ASSERT1(properties_a != NULL);
00563 ASSERT1(properties_b != NULL);
00564 ASSERT1(properties_a->m_data != NULL);
00565 ASSERT1(properties_b->m_data != NULL);
00566 ASSERT1(properties_a->m_data == properties_b->m_data);
00567 ScreenCoord size_allotment = *properties_a->m_data;
00568
00569 if (properties_a->m_max_size_enabled[index] && properties_a->m_max_size[index] < size_allotment)
00570 {
00571 if (properties_b->m_max_size_enabled[index] && properties_b->m_max_size[index] < size_allotment)
00572
00573 return properties_a->m_max_size[index] - properties_b->m_max_size[index];
00574 else
00575
00576 return -1;
00577 }
00578 else
00579 {
00580 if (properties_b->m_max_size_enabled[index] && properties_b->m_max_size[index] < size_allotment)
00581
00582 return 1;
00583 }
00584
00585 if (properties_a->m_min_size_enabled[index] && properties_a->m_min_size[index] > size_allotment)
00586 {
00587 if (properties_b->m_min_size_enabled[index] && properties_b->m_min_size[index] > size_allotment)
00588
00589 return properties_b->m_min_size[index] - properties_a->m_min_size[index];
00590 else
00591
00592 return -1;
00593 }
00594 else
00595 {
00596 if (properties_b->m_min_size_enabled[index] && properties_b->m_min_size[index] > size_allotment)
00597
00598 return 1;
00599 }
00600
00601
00602 return 0;
00603 }
00604
00605 int Layout::ColumnCompareConstraints (void const *a, void const *b)
00606 {
00607 SizeProperties const *column_a =
00608 *(static_cast<SizeProperties *const *>(a));
00609 SizeProperties const *column_b =
00610 *(static_cast<SizeProperties *const *>(b));
00611 ASSERT1(dynamic_cast<SizeProperties const *>(column_a) != NULL);
00612 ASSERT1(dynamic_cast<SizeProperties const *>(column_b) != NULL);
00613
00614 return SizePropertiesSortingFunction(column_a, column_b, Dim::X);
00615 }
00616
00617 int Layout::RowCompareConstraints (void const *a, void const *b)
00618 {
00619 SizeProperties const *row_a =
00620 *(static_cast<SizeProperties const *const *>(a));
00621 SizeProperties const *row_b =
00622 *(static_cast<SizeProperties const *const *>(b));
00623 ASSERT1(dynamic_cast<SizeProperties const *>(row_a) != NULL);
00624 ASSERT1(dynamic_cast<SizeProperties const *>(row_b) != NULL);
00625
00626 return SizePropertiesSortingFunction(row_a, row_b, Dim::Y);
00627 }
00628
00629 void Layout::DelegateWidthsToColumns ()
00630 {
00631
00632 if (ColumnCount() == 0 || RowCount() == 0)
00633 return;
00634
00635
00636 Uint32 unhidden_column_count = 0;
00637
00638 SizeProperties const **column_order = new SizeProperties const *[m_column_count];
00639
00640 for (Uint32 i = 0; i < m_column_count; ++i)
00641 if (!m_column_is_hidden[i])
00642 column_order[unhidden_column_count++] = &m_column_size_properties[i];
00643
00644
00645 for (Uint32 i = 0; i < m_column_count; ++i)
00646 m_column_width[i] = 0;
00647
00648
00649 ASSERT1(m_hidden_column_count == ColumnCount() - unhidden_column_count);
00650 ScreenCoord total_width_left = Width() - TotalSpacing()[Dim::X];
00651 ASSERT1(total_width_left >= 0);
00652
00653
00654 for (Uint32 i = 0; i < unhidden_column_count; ++i)
00655 {
00656 m_line_share_of_size[Dim::X] = total_width_left / (unhidden_column_count - i);
00657
00658 qsort(column_order + i,
00659 unhidden_column_count - i,
00660 sizeof(SizeProperties const *),
00661 Layout::ColumnCompareConstraints);
00662
00663
00664 Uint32 column_index = column_order[i] - m_column_size_properties;
00665 m_column_width[column_index] =
00666 column_order[i]->AdjustedSizeComponent(Dim::X, m_line_share_of_size[Dim::X]);
00667
00668
00669 total_width_left -= m_column_width[column_index];
00670 ASSERT1(total_width_left >= 0);
00671 }
00672
00673 Delete(column_order);
00674 }
00675
00676 void Layout::DelegateHeightsToRows ()
00677 {
00678
00679 if (ColumnCount() == 0 || RowCount() == 0)
00680 return;
00681
00682
00683 Uint32 unhidden_row_count = 0;
00684
00685 SizeProperties const **row_order = new SizeProperties const *[m_row_count];
00686
00687 for (Uint32 i = 0; i < m_row_count; ++i)
00688 if (!m_row_is_hidden[i])
00689 row_order[unhidden_row_count++] = &m_row_size_properties[i];
00690
00691
00692 for (Uint32 i = 0; i < m_row_count; ++i)
00693 m_row_height[i] = 0;
00694
00695
00696 ASSERT1(m_hidden_row_count == RowCount() - unhidden_row_count);
00697 ScreenCoord total_height_left = Height() - TotalSpacing()[Dim::Y];
00698 ASSERT1(total_height_left >= 0);
00699
00700
00701 for (Uint32 i = 0; i < unhidden_row_count; ++i)
00702 {
00703 m_line_share_of_size[Dim::Y] = total_height_left / (unhidden_row_count - i);
00704 ASSERT1(m_line_share_of_size[Dim::Y] >= 0);
00705
00706 qsort(row_order + i,
00707 unhidden_row_count - i,
00708 sizeof(SizeProperties const *),
00709 Layout::RowCompareConstraints);
00710
00711
00712 Uint32 row_index = row_order[i] - m_row_size_properties;
00713 m_row_height[row_index] =
00714 row_order[i]->AdjustedSizeComponent(Dim::Y, m_line_share_of_size[Dim::Y]);
00715
00716
00717 total_height_left -= m_row_height[row_index];
00718 ASSERT1(total_height_left >= 0);
00719 }
00720
00721 Delete(row_order);
00722 }
00723
00724 void Layout::ResizeAndRepositionChildWidgets ()
00725 {
00726 ScreenCoordVector2 positional_offset;
00727 ScreenCoordVector2 layout_frame_margins(CalculateLayoutFrameMargins());
00728 ScreenCoordVector2 layout_spacing_margins(CalculateLayoutSpacingMargins());
00729
00730 positional_offset[Dim::Y] = Position()[Dim::Y] + layout_frame_margins[Dim::Y];
00731 for (Uint32 row = m_row_count - 1; row < m_row_count; --row)
00732 {
00733 if (m_row_is_hidden[row])
00734 continue;
00735
00736 positional_offset[Dim::X] = Position()[Dim::X] + layout_frame_margins[Dim::X];
00737 for (Uint32 column = 0; column < m_column_count; ++column)
00738 {
00739 if (m_column_is_hidden[column])
00740 continue;
00741
00742 Widget *child = GridChildByColumnAndRow(column, row);
00743
00744
00745 if (child != NULL &&
00746 !child->IsHidden() &&
00747 !child->IsModal())
00748 {
00749 ScreenCoordVector2 requested_size(
00750 m_column_width[column],
00751 m_row_height[row]);
00752
00753
00754 child->Resize(requested_size);
00755
00756
00757
00758 ScreenCoordVector2 extra_space(requested_size - child->Size());
00759
00760
00761
00762
00763
00764
00765 child->MoveTo(positional_offset + extra_space / 2);
00766 }
00767
00768 positional_offset[Dim::X] += m_column_width[column] + layout_spacing_margins[Dim::X];
00769 }
00770
00771 positional_offset[Dim::Y] += m_row_height[row] + layout_spacing_margins[Dim::Y];
00772 }
00773 }
00774
00775 void Layout::ConstrainPreferredSizeProperties ()
00776 {
00777 for (Uint8 i = 0; i < 2; ++i)
00778 {
00779 if (m_preferred_size_properties.m_min_size[i] < TotalSpacing()[i])
00780 m_preferred_size_properties.m_min_size[i] = TotalSpacing()[i];
00781
00782 if (m_preferred_size_properties.m_max_size[i] < TotalSpacing()[i])
00783 m_preferred_size_properties.m_max_size[i] = TotalSpacing()[i];
00784 }
00785 }
00786
00787 void Layout::CalculateLineSizeProperties (
00788 LineDirection const line_direction,
00789 Uint32 const line_index,
00790 SizeProperties *const size_properties,
00791 bool *const line_is_hidden) const
00792 {
00793 if (line_direction == MajorDirection())
00794 ASSERT1(line_index < MinorCount());
00795 else
00796 ASSERT1(line_index < MajorCount());
00797 ASSERT1(size_properties != NULL);
00798 ASSERT1(line_is_hidden != NULL);
00799
00800 size_properties->m_min_size_enabled = Bool2(false, false);
00801 size_properties->m_min_size =
00802 ScreenCoordVector2(
00803 SizeProperties::DefaultMinSizeComponent(),
00804 SizeProperties::DefaultMinSizeComponent());
00805
00806 Uint32 is_horizontal = (line_direction == ROW) ? 1 : 0;
00807
00808 Uint32 along = 1 - is_horizontal;
00809
00810 Uint32 across = 1 - along;
00811
00812
00813 size_properties->m_max_size_enabled[along] = m_child_vector.size() > 0;
00814 size_properties->m_max_size_enabled[across] = false;
00815
00816
00817 size_properties->m_max_size[along] = 0;
00818 size_properties->m_max_size[across] =
00819 SizeProperties::DefaultMaxSizeComponent();
00820
00821
00822 Uint32 line_widget_count =
00823 (line_direction == MajorDirection()) ?
00824 MajorCount() :
00825 MinorCount();
00826
00827 Uint32 hidden_child_widget_count = 0;
00828 for (Uint32 i = 0; i < line_widget_count; ++i)
00829 {
00830 Widget const *child;
00831 if (line_direction == MajorDirection())
00832 child = GridChild(line_index, i);
00833 else
00834 child = GridChild(i, line_index);
00835
00836
00837 if (child == NULL ||
00838 child->IsHidden() ||
00839 child->IsModal())
00840 {
00841 ++hidden_child_widget_count;
00842 continue;
00843 }
00844
00845
00846
00847 size_properties->m_min_size_enabled[along] =
00848 size_properties->m_min_size_enabled[along] ||
00849 child->MinSizeEnabled()[along];
00850
00851
00852 size_properties->m_min_size_enabled[across] =
00853 size_properties->m_min_size_enabled[across] ||
00854 child->MinSizeEnabled()[across];
00855
00856
00857 if (child->MinSizeEnabled()[along])
00858
00859 size_properties->m_min_size[along] += child->MinSize()[along];
00860
00861
00862 if (child->MinSizeEnabled()[across])
00863
00864 if (size_properties->m_min_size[across] <
00865 child->MinSize()[across])
00866
00867 size_properties->m_min_size[across] =
00868 child->MinSize()[across];
00869
00870
00871
00872 size_properties->m_max_size_enabled[along] =
00873 size_properties->m_max_size_enabled[along] &&
00874 child->MaxSizeEnabled()[along];
00875
00876
00877 size_properties->m_max_size_enabled[across] =
00878 size_properties->m_max_size_enabled[across] ||
00879 child->MaxSizeEnabled()[across];
00880
00881
00882 if (child->MaxSizeEnabled()[along])
00883
00884 size_properties->m_max_size[along] += child->MaxSize()[along];
00885
00886
00887 if (child->MaxSizeEnabled()[across])
00888
00889 if (size_properties->m_max_size[across] >
00890 child->MaxSize()[across])
00891
00892 size_properties->m_max_size[across] =
00893 child->MaxSize()[across];
00894 }
00895
00896
00897
00898 size_properties->m_max_size =
00899 size_properties->AdjustedSize(size_properties->m_max_size);
00900
00901
00902 *line_is_hidden = (hidden_child_widget_count == line_widget_count);
00903 }
00904
00905 void Layout::DirtyTotalSpacing ()
00906 {
00907 m_total_spacing_needs_update = true;
00908 }
00909
00910 void Layout::DirtyColumnSizePropertyAllocations ()
00911 {
00912 m_column_size_property_arrays_need_reallocation = true;
00913 m_total_spacing_needs_update = true;
00914 DirtyColumnSizeProperties();
00915 }
00916
00917 void Layout::DirtyColumnSizeProperties ()
00918 {
00919 m_column_size_properties_need_update = true;
00920 DirtyContentsSizeProperties();
00921 }
00922
00923 void Layout::DirtyRowSizePropertyAllocations ()
00924 {
00925 m_row_size_property_arrays_need_reallocation = true;
00926 m_total_spacing_needs_update = true;
00927 DirtyRowSizeProperties();
00928 }
00929
00930 void Layout::DirtyRowSizeProperties ()
00931 {
00932 m_row_size_properties_need_update = true;
00933 DirtyContentsSizeProperties();
00934 }
00935
00936 void Layout::DirtyContentsSizeProperties ()
00937 {
00938 m_contents_size_properties_need_update = true;
00939 }
00940
00941 void Layout::UpdateTotalSpacing () const
00942 {
00943
00944 if (!m_total_spacing_needs_update)
00945 return;
00946
00947 m_total_spacing_needs_update = false;
00948
00949 Uint32 column_spaces;
00950 Uint32 row_spaces;
00951
00952 if (ColumnCount() == 0 || ColumnCount() == HiddenColumnCount())
00953 column_spaces = 0;
00954 else
00955 {
00956 ASSERT1(ColumnCount() > HiddenColumnCount());
00957 column_spaces = ColumnCount() - 1 - HiddenColumnCount();
00958 }
00959
00960 if (RowCount() == 0 || RowCount() == HiddenRowCount())
00961 row_spaces = 0;
00962 else
00963 {
00964 ASSERT1(RowCount() > HiddenRowCount());
00965 row_spaces = RowCount() - 1 - HiddenRowCount();
00966 }
00967
00968 m_total_spacing =
00969 CalculateLayoutFrameMargins() * 2 +
00970 ScreenCoordVector2(
00971 CalculateLayoutSpacingMargins()[Dim::X] * column_spaces,
00972 CalculateLayoutSpacingMargins()[Dim::Y] * row_spaces);
00973 }
00974
00975 void Layout::UpdateColumnSizePropertyAllocation () const
00976 {
00977
00978 if (!m_column_size_property_arrays_need_reallocation)
00979 return;
00980
00981 m_column_size_property_arrays_need_reallocation = false;
00982 ASSERT1(m_column_size_properties_need_update);
00983
00984
00985 Uint32 column_count =
00986 (MajorDirection() == COLUMN) ?
00987 MinorCount() :
00988 MajorCount();
00989
00990 if (m_column_count > 0)
00991 {
00992 ASSERT1(m_column_size_properties != NULL);
00993 ASSERT1(m_column_width != NULL);
00994 ASSERT1(m_column_is_hidden != NULL);
00995 }
00996
00997
00998 if (m_column_count == column_count)
00999 return;
01000
01001 DeleteColumnSizePropertyArrays();
01002
01003 ASSERT1(m_column_size_properties == NULL);
01004 ASSERT1(m_column_width == NULL);
01005 ASSERT1(m_column_is_hidden == NULL);
01006
01007 m_column_count = column_count;
01008 if (m_column_count > 0)
01009 {
01010 m_column_size_properties = new SizeProperties[m_column_count];
01011 for (Uint32 i = 0; i < m_column_count; ++i)
01012 m_column_size_properties[i].m_data = &m_line_share_of_size[Dim::X];
01013 m_column_width = new ScreenCoord[m_column_count];
01014 m_column_is_hidden = new bool[m_column_count];
01015 }
01016 }
01017
01018 void Layout::UpdateColumnSizeProperties () const
01019 {
01020 UpdateColumnSizePropertyAllocation();
01021
01022
01023 if (!m_column_size_properties_need_update)
01024 return;
01025
01026 m_column_size_properties_need_update = false;
01027
01028 m_hidden_column_count = 0;
01029 for (Uint32 i = 0; i < m_column_count; ++i)
01030 {
01031 CalculateLineSizeProperties(
01032 COLUMN,
01033 i,
01034 m_column_size_properties + i,
01035 m_column_is_hidden + i);
01036 if (m_column_is_hidden[i])
01037 ++m_hidden_column_count;
01038 }
01039 }
01040
01041 void Layout::UpdateRowSizePropertyAllocation () const
01042 {
01043
01044 if (!m_row_size_property_arrays_need_reallocation)
01045 return;
01046
01047 m_row_size_property_arrays_need_reallocation = false;
01048 ASSERT1(m_row_size_properties_need_update);
01049
01050
01051 Uint32 row_count = (MajorDirection() == ROW) ?
01052 MinorCount() :
01053 MajorCount();
01054
01055 if (m_row_count > 0)
01056 {
01057 ASSERT1(m_row_size_properties != NULL);
01058 ASSERT1(m_row_height != NULL);
01059 ASSERT1(m_row_is_hidden != NULL);
01060 }
01061
01062
01063 if (m_row_count == row_count)
01064 return;
01065
01066 DeleteRowSizePropertyArrays();
01067
01068 ASSERT1(m_row_size_properties == NULL);
01069 ASSERT1(m_row_height == NULL);
01070 ASSERT1(m_row_is_hidden == NULL);
01071
01072 m_row_count = row_count;
01073 if (m_row_count > 0)
01074 {
01075 m_row_size_properties = new SizeProperties[m_row_count];
01076 for (Uint32 i = 0; i < m_row_count; ++i)
01077 m_row_size_properties[i].m_data = &m_line_share_of_size[Dim::Y];
01078 m_row_height = new ScreenCoord[m_row_count];
01079 m_row_is_hidden = new bool[m_row_count];
01080 }
01081 }
01082
01083 void Layout::UpdateRowSizeProperties () const
01084 {
01085 UpdateRowSizePropertyAllocation();
01086
01087
01088 if (!m_row_size_properties_need_update)
01089 return;
01090
01091 m_row_size_properties_need_update = false;
01092
01093 m_hidden_row_count = 0;
01094 for (Uint32 i = 0; i < m_row_count; ++i)
01095 {
01096 CalculateLineSizeProperties(
01097 ROW,
01098 i,
01099 m_row_size_properties + i,
01100 m_row_is_hidden + i);
01101 if (m_row_is_hidden[i])
01102 ++m_hidden_row_count;
01103 }
01104 }
01105
01106 void Layout::UpdateContentsSizeProperties () const
01107 {
01108
01109 if (!m_contents_size_properties_need_update)
01110 return;
01111
01112 m_contents_size_properties_need_update = false;
01113
01114
01115 m_contents_size_properties.m_min_size_enabled =
01116 Bool2(TotalSpacing()[Dim::X] > 0,
01117 TotalSpacing()[Dim::Y] > 0);
01118 m_contents_size_properties.m_min_size = TotalSpacing();
01119
01120
01121 m_contents_size_properties.m_max_size_enabled =
01122 Bool2(ColumnCount() - m_hidden_column_count > 0,
01123 RowCount() - m_hidden_row_count > 0);
01124 m_contents_size_properties.m_max_size = TotalSpacing();
01125
01126
01127 for (Uint32 i = 0; i < ColumnCount(); ++i)
01128 {
01129
01130 if (m_column_is_hidden[i])
01131 continue;
01132
01133
01134
01135 m_contents_size_properties.m_min_size_enabled[Dim::X] =
01136 m_contents_size_properties.m_min_size_enabled[Dim::X] ||
01137 ColumnMinSizeEnabled(i)[Dim::X];
01138
01139 if (ColumnMinSizeEnabled(i)[Dim::X])
01140 m_contents_size_properties.m_min_size[Dim::X] +=
01141 ColumnMinSize(i)[Dim::X];
01142
01143
01144
01145 m_contents_size_properties.m_max_size_enabled[Dim::X] =
01146 m_contents_size_properties.m_max_size_enabled[Dim::X] &&
01147 ColumnMaxSizeEnabled(i)[Dim::X];
01148
01149 if (ColumnMaxSizeEnabled(i)[Dim::X])
01150 m_contents_size_properties.m_max_size[Dim::X] +=
01151 ColumnMaxSize(i)[Dim::X];
01152 }
01153
01154
01155 for (Uint32 i = 0; i < RowCount(); ++i)
01156 {
01157
01158 if (m_row_is_hidden[i])
01159 continue;
01160
01161
01162
01163 m_contents_size_properties.m_min_size_enabled[Dim::Y] =
01164 m_contents_size_properties.m_min_size_enabled[Dim::Y] ||
01165 RowMinSizeEnabled(i)[Dim::Y];
01166
01167 if (RowMinSizeEnabled(i)[Dim::Y])
01168 m_contents_size_properties.m_min_size[Dim::Y] +=
01169 RowMinSize(i)[Dim::Y];
01170
01171
01172
01173 m_contents_size_properties.m_max_size_enabled[Dim::Y] =
01174 m_contents_size_properties.m_max_size_enabled[Dim::Y] &&
01175 RowMaxSizeEnabled(i)[Dim::Y];
01176
01177 if (RowMaxSizeEnabled(i)[Dim::Y])
01178 m_contents_size_properties.m_max_size[Dim::Y] +=
01179 RowMaxSize(i)[Dim::Y];
01180 }
01181 }
01182
01183 void Layout::DeleteColumnSizePropertyArrays () const
01184 {
01185 if (m_column_size_properties != NULL)
01186 {
01187 DeleteArrayAndNullify(m_column_size_properties);
01188 DeleteArrayAndNullify(m_column_width);
01189 DeleteArrayAndNullify(m_column_is_hidden);
01190 }
01191 else
01192 {
01193 ASSERT1(m_column_width == NULL);
01194 ASSERT1(m_column_is_hidden == NULL);
01195 }
01196 }
01197
01198 void Layout::DeleteRowSizePropertyArrays () const
01199 {
01200 if (m_row_size_properties != NULL)
01201 {
01202 DeleteArrayAndNullify(m_row_size_properties);
01203 DeleteArrayAndNullify(m_row_height);
01204 DeleteArrayAndNullify(m_row_is_hidden);
01205 }
01206 else
01207 {
01208 ASSERT1(m_row_height == NULL);
01209 ASSERT1(m_row_is_hidden == NULL);
01210 }
01211 }
01212
01213 void Layout::Initialize (
01214 LineDirection const major_direction,
01215 Uint32 const major_count)
01216 {
01217
01218 m_accepts_focus = false;
01219
01220 ASSERT1(major_count > 0);
01221
01222 DirtyTotalSpacing();
01223
01224 DirtyColumnSizePropertyAllocations();
01225 m_column_count = 0;
01226 m_column_size_properties = NULL;
01227 m_column_width = NULL;
01228 m_column_is_hidden = NULL;
01229
01230 DirtyRowSizePropertyAllocations();
01231 m_row_count = 0;
01232 m_row_size_properties = NULL;
01233 m_row_height = NULL;
01234 m_row_is_hidden = NULL;
01235
01236 m_major_count = major_count;
01237 m_major_direction = major_direction;
01238
01239 m_is_using_zeroed_frame_margins = true;
01240 m_is_using_zeroed_layout_spacing_margins = false;
01241
01242 SetBackground(NULL);
01243 }
01244
01245 }