nux-1.14.0
|
00001 /* 00002 * Copyright 2010 Inalogic® Inc. 00003 * 00004 * This program is free software: you can redistribute it and/or modify it 00005 * under the terms of the GNU Lesser General Public License, as 00006 * published by the Free Software Foundation; either version 2.1 or 3.0 00007 * of the License. 00008 * 00009 * This program is distributed in the hope that it will be useful, but 00010 * WITHOUT ANY WARRANTY; without even the implied warranties of 00011 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR 00012 * PURPOSE. See the applicable version of the GNU Lesser General Public 00013 * License for more details. 00014 * 00015 * You should have received a copy of both the GNU Lesser General Public 00016 * License along with this program. If not, see <http://www.gnu.org/licenses/> 00017 * 00018 * Authored by: Jay Taoko <jaytaoko@inalogic.com> 00019 * 00020 */ 00021 00022 00023 #include "Nux.h" 00024 #include "View.h" 00025 #include "VLayout.h" 00026 #include "HLayout.h" 00027 00028 namespace nux 00029 { 00030 00031 static const int VERROR = 0; 00032 NUX_IMPLEMENT_OBJECT_TYPE (VLayout); 00033 00034 VLayout::VLayout (NUX_FILE_LINE_DECL) 00035 : Layout (NUX_FILE_LINE_PARAM) 00036 { 00037 #if DEBUG_LAYOUT 00038 m_h_in_margin = 10; 00039 m_h_out_margin = 10; 00040 m_v_in_margin = 10; 00041 m_v_out_margin = 10; 00042 #endif 00043 00044 // Start packing the elements from the left size. Is the layout has more space than the elements can use, 00045 // leave that space on the right side of the VLayout. 00046 m_ContentStacking = eStackTop; 00047 00048 } 00049 00050 VLayout::VLayout (NString name, NUX_FILE_LINE_DECL) 00051 : Layout (NUX_FILE_LINE_PARAM) 00052 { 00053 m_name = name; 00054 #if DEBUG_LAYOUT 00055 m_h_in_margin = 10; 00056 m_h_out_margin = 10; 00057 m_v_in_margin = 10; 00058 m_v_out_margin = 10; 00059 #endif 00060 00061 m_ContentStacking = eStackTop; 00062 } 00063 00064 VLayout::~VLayout() 00065 { 00066 } 00067 00068 //left and right in a vlayout should pass event to parent 00069 long VLayout::DoFocusLeft (IEvent &ievent, long TraverseInfo, long ProcessEventInfo) 00070 { 00071 Area *parent = GetParentObject (); 00072 if (parent != NULL) 00073 return SendEventToArea (parent, ievent, TraverseInfo, ProcessEventInfo); 00074 else 00075 FocusFirstChild (); 00076 00077 return TraverseInfo; 00078 } 00079 long VLayout::DoFocusRight (IEvent &ievent, long TraverseInfo, long ProcessEventInfo) 00080 { 00081 Area *parent = GetParentObject (); 00082 if (parent != NULL) 00083 return SendEventToArea (parent, ievent, TraverseInfo, ProcessEventInfo); 00084 else 00085 FocusLastChild (); 00086 return TraverseInfo; 00087 } 00088 00089 void VLayout::GetCompositeList (std::list<Area *> *ViewList) 00090 { 00091 std::list<Area *>::iterator it; 00092 00093 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) 00094 { 00095 if ( (*it)->IsView() ) 00096 { 00097 View *ic = NUX_STATIC_CAST (View *, (*it) ); 00098 ViewList->push_back (ic); 00099 } 00100 else if ( (*it)->IsLayout() ) 00101 { 00102 Layout *layout = NUX_STATIC_CAST (Layout *, (*it) ); 00103 layout->GetCompositeList (ViewList); 00104 } 00105 } 00106 } 00107 00109 00114 void VLayout::ComputeStacking (int remaining_height, int &offset_space, int &element_margin) 00115 { 00116 int per_element_space = 0; 00117 int total_used_space = 0; 00118 int n_elements = 0; 00119 00120 std::list<Area *>::iterator it; 00121 00122 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) 00123 { 00124 // gather all the space used by elements 00125 if ((*it)->IsVisible ()) 00126 { 00127 total_used_space += (*it)->GetBaseHeight(); 00128 n_elements++; 00129 } 00130 } 00131 00132 if (n_elements != 0) 00133 { 00134 // Compute the space available for each element 00135 per_element_space = (remaining_height - total_used_space) / int (n_elements); 00136 } 00137 00138 if (per_element_space < 0) 00139 { 00140 per_element_space = 0; 00141 } 00142 00143 int margin; 00144 00145 if (per_element_space > 0) 00146 { 00147 margin = (per_element_space) / 2; 00148 } 00149 else 00150 { 00151 margin = 0; 00152 } 00153 00154 LayoutContentDistribution stacking = GetContentDistribution(); 00155 00156 switch (stacking) 00157 { 00158 case eStackTop: 00159 case eStackLeft: 00160 { 00161 offset_space = 0; 00162 element_margin = 0; 00163 } 00164 break; 00165 00166 case eStackBottom: 00167 case eStackRight: 00168 { 00169 offset_space = (remaining_height - total_used_space); 00170 00171 if (offset_space < 0) 00172 offset_space = 0; 00173 00174 element_margin = 0; 00175 } 00176 break; 00177 00178 case eStackCenter: 00179 { 00180 offset_space = (remaining_height - total_used_space) / 2; 00181 00182 if (offset_space < 0) 00183 offset_space = 0; 00184 00185 element_margin = 0; 00186 } 00187 break; 00188 00189 case eStackExpand: 00190 default: 00191 { 00192 offset_space = 0; 00193 element_margin = margin; 00194 } 00195 break; 00196 } 00197 } 00198 00199 long VLayout::ComputeLayout2() 00200 { 00201 if (_layout_element_list.size() == 0) 00202 { 00203 return eCompliantHeight | eCompliantWidth; 00204 } 00205 00206 std::list<Area *>::iterator it; 00207 00208 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) 00209 { 00210 (*it)->SetLayoutDone (false); 00211 } 00212 00213 int original_width = GetBaseWidth(); 00214 00215 if (GetStretchFactor() == 0) 00216 { 00217 // The size must exactly fit the children. The parent cannot be larger or smaller 00218 // than the total height of its children (+ margins). 00219 // So set the parent size to Geometry(0,0,1,1) and let the children force it to extend. 00220 if (GetParentObject() && GetParentObject()->Type().IsObjectType (HLayout::StaticObjectType) ) 00221 { 00222 // The parent if a HLayout. Then a Stretch factor of 0 means this layout has its width set to 1. 00223 Area::SetBaseWidth (1); 00224 } 00225 else if (GetParentObject() && GetParentObject()->Type().IsObjectType (VLayout::StaticObjectType) ) 00226 { 00227 // The parent if a VLayout(same type). Then a Stretch factor of 0 means this layout has its height set to 1. 00228 Area::SetBaseHeight (1); 00229 } 00230 else 00231 { 00232 // This is for when a layout is set as a composition layout of an View and its stretch factor is explicitly set to 0. 00233 Area::SetBaseWidth (1); 00234 Area::SetBaseHeight (1); 00235 } 00236 00237 //The children will all assume their minimum size. 00238 } 00239 else 00240 { 00241 // The total size of the children (+ margins) may be smaller or equal to parent size. 00242 } 00243 00244 bool unadjusted_layout = false; 00245 t_size num_element = 0; 00246 00247 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) 00248 { 00249 if ((*it)->IsVisible ()) 00250 num_element++; 00251 } 00252 00253 do 00254 { 00255 // Get layout Width and Height 00256 int width = GetBaseWidth(); 00257 int height = GetBaseHeight(); 00258 00259 // Remove the margins. This is the real width and height available to the children. 00260 width -= 2 * m_h_out_margin; 00261 height -= (int) (num_element - 1) * m_v_in_margin + 2 * m_v_out_margin; 00262 00263 // Size the children according to their stretch factor. 00264 VLayoutManagement (width, height); 00265 00266 // Objects have been resized, now position them. 00267 int current_x = GetBaseX() + m_h_out_margin; 00268 int current_y = GetBaseY() + m_v_out_margin; 00269 00270 //int per_element_space = 0; 00271 //int total_used_space = 0; 00272 int offset_space = 0; 00273 int space_after_element = 0; 00274 ComputeStacking (height, offset_space, space_after_element); 00275 current_y += offset_space; 00276 00277 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) 00278 { 00279 if (!(*it)->IsVisible ()) 00280 continue; 00281 00282 current_y += space_after_element; 00283 00284 (*it)->SetBaseX (current_x); 00285 (*it)->SetBaseY (current_y); 00286 00287 MinorDimensionSize extend = (*it)->GetExtend(); 00288 MinorDimensionPosition positioning = (*it)->GetPositioning(); 00289 float percentage = (*it)->GetPercentage(); 00290 00291 // Compute the size of an element in the minor dimension (horizontal) 00292 switch (extend) 00293 { 00294 case ePercentage: 00295 { 00296 // The size of the element in the minor dimension is a percentage of layout minor dimension size. 00297 // Note that children of the processed element may force it to have a bigger size. 00298 int percentage_width = (width * percentage) / 100.0f; 00299 (*it)->SetBaseWidth (percentage_width); 00300 break; 00301 } 00302 00303 case eMatchContent: 00304 { 00305 // Force the element width to be the minimum has defined with SetMinimumWidth. 00306 // The children of this element can force it to get larger. 00307 (*it)->SetBaseWidth (0); 00308 break; 00309 } 00310 00311 case eFix: 00312 { 00313 //do nothing 00314 break; 00315 } 00316 00317 case eFull: 00318 default: 00319 { 00320 (*it)->SetBaseWidth (width); 00321 break; 00322 } 00323 } 00324 00325 // Compute the position of an element in the minor dimension. 00326 if ( (extend != eFull) || ( (*it)->GetBaseWidth() < width) ) 00327 { 00328 int widget_width = (*it)->GetBaseWidth(); 00329 00330 switch (positioning) 00331 { 00332 case eLeft: 00333 { 00334 // do nothing 00335 (*it)->SetBaseX (current_x); 00336 break; 00337 } 00338 case eRight: 00339 { 00340 if (widget_width < width) 00341 (*it)->SetBaseX (current_x + width - widget_width); 00342 else 00343 (*it)->SetBaseX (current_x); 00344 00345 break; 00346 } 00347 00348 case eCenter: 00349 default: 00350 { 00351 if (widget_width < width) 00352 (*it)->SetBaseX (current_x + (width - widget_width) / 2); 00353 else 00354 (*it)->SetBaseX (current_x); 00355 } 00356 } 00357 } 00358 00359 current_y += (*it)->GetBaseHeight() + space_after_element + m_v_in_margin; 00360 } 00361 00362 // Manage child layout 00363 m_contentWidth = GetBaseWidth() - 2 * m_h_out_margin; // Set to the size of the layout. 00364 00365 if (num_element == 0) 00366 m_fittingHeight = (int) 2 * m_v_out_margin; 00367 else 00368 m_fittingHeight = (int) (num_element - 1) * m_v_in_margin + 2 * m_v_out_margin; 00369 00370 int element_width; 00371 unadjusted_layout = false; 00372 00373 // This array is meant to store the sizes of some of the elements width. These elements must have eFull as extent and 00374 // they have not been not been constrained smaller after ComputeLayout2 is called. Because the layout may have a stretch factor of 0 00375 // and therefore its size has been set to 1x1 at the start of this function, there is a possibility that some of the elements don't have 00376 // the full width of the layout(these elements uses their minimum width because the layout was set to a size 1x1). 00377 // We check if that is the case and force a recompute. 00378 std::vector<int> FullSizeUnadjusted; 00379 00380 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) 00381 { 00382 bool larger_height = false; 00383 bool smaller_height = false; 00384 bool smaller_width = false; 00385 bool larger_width = false; 00386 int ret = 0; 00387 00388 if (!(*it)->IsVisible ()) 00389 continue; 00390 00391 if ( ( (*it)->IsLayout() || (*it)->IsView() ) /*&& ((*it)->IsLayoutDone() == false)*/ /*&& ((*it)->GetStretchFactor() != 0)*/) 00392 { 00393 ret = (*it)->ComputeLayout2(); 00394 00395 larger_height = (ret & eLargerHeight) ? true : false; 00396 smaller_height = (ret & eSmallerHeight) ? true : false; 00397 smaller_width = (ret & eSmallerWidth) ? true : false; 00398 larger_width = (ret & eLargerWidth) ? true : false; 00399 00400 if ( (larger_height || smaller_height) && ( (*it)->IsLayoutDone() == false) ) 00401 { 00402 // Stop computing the size of this layout. Its size was not convenient to its children. So the children size take priority 00403 // over the layout. In ComputeLayout2, the dimension of the layout has been set so it encompasses its children (and the margins). 00404 // Now the parent layout cannot be touched again: _layout_done = true. In VLayoutManagement, it is as if the stretchfactor 00405 // of this layout is now 0. 00406 // This is the only place where a layout can have _layout_done set to "true". 00407 00408 // If (smaller_height == true) the layout takes less space than anticipated. 00409 // Set unadjusted_layout = true, so another pass will allow its sibling to claim more space. 00410 { 00411 unadjusted_layout = true; 00412 (*it)->SetLayoutDone (true); 00413 } 00414 } 00415 00416 if ( (smaller_width == false) && ( (*it)->GetExtend() == eFull) && ( (*it)->GetBaseWidth() < (*it)->GetMaximumWidth() ) ) 00417 { 00418 // Catch all object whose size is possibly larger than the layout. Check their size at the end and 00419 // recompute the layout if necessary. 00420 // For layout elements, make sure that the stretch factor is not 0. If it is, it means it will not use the 00421 // size provided by the parent layout. Its size will be adjusted to the minimum size of the layout content. 00422 if (! ( (*it)->IsLayout() && (*it)->GetStretchFactor() == 0) ) 00423 FullSizeUnadjusted.push_back ( (*it)->GetBaseWidth() ); 00424 } 00425 00426 if ((smaller_width || larger_width) && ((*it)->GetExtend() == MINOR_SIZE_MATCHCONTENT)) 00427 { 00428 (*it)->SetMinimumWidth((*it)->GetBaseWidth()); 00429 unadjusted_layout = true; 00430 } 00431 00432 // Should be reactivate so that if the parent Layout does not call 00433 // ComputePosition2, at least it is done here to arrange the internal 00434 // element of the children. 00435 //(*it)->ComputePosition2(0,0); 00436 } 00437 00438 m_fittingHeight += (*it)->GetBaseHeight(); 00439 00440 element_width = (*it)->GetBaseWidth(); 00441 00442 if ( (*it)->IsSpaceLayout() == false) 00443 { 00444 if ( (GetStretchFactor() != 0) && (ret & eSmallerWidth) ) 00445 { 00446 if (m_contentWidth < element_width) 00447 { 00448 if (m_contentWidth < GetMaximumHeight() ) 00449 { 00450 // An element is larger than the layout width and the layout has not reach its maximum width yet. 00451 m_contentWidth = element_width; 00452 unadjusted_layout = true; 00453 } 00454 } 00455 } 00456 else 00457 { 00458 if (m_contentWidth <= element_width) 00459 { 00460 m_contentWidth = element_width; 00461 } 00462 00463 // else if((*it)->GetExtend() == eFull) 00464 // { 00465 // unadjusted_layout = true; 00466 // } 00467 } 00468 } 00469 } 00470 00471 // Set the width of the layout to be equal to the largest width it controls. 00472 // m_contentWidth is the largest width of an element within this layout. The layout size is then 00473 // m_contentWidth + 2 * m_h_out_margin; 00474 SetBaseWidth (m_contentWidth + 2 * m_h_out_margin); 00475 00476 int temp = m_contentWidth; 00477 std::vector<int>::iterator IntIterator = FullSizeUnadjusted.begin(); 00478 00479 for (IntIterator = FullSizeUnadjusted.begin(); IntIterator != FullSizeUnadjusted.end(); IntIterator++) 00480 { 00481 if ( (*IntIterator) < temp) 00482 { 00483 unadjusted_layout = true; 00484 } 00485 } 00486 } 00487 while (unadjusted_layout); 00488 00489 // m_fittingWidth is sum of the largest element width plus the outer margin. 00490 m_fittingWidth = m_contentWidth + 2 * m_h_out_margin; 00491 00492 // m_fittingHeight is sum of the element height plus the inner and outer margin. 00493 // If the stretch factor is 0 then, the layout height has been set to 1 and need to grow with the elements within. 00494 // If the stretch factor is not 0, then the layout height is set to m_fittingHeight only if the its height is less than m_fittingHeight; 00495 // This way, if the layout height is greater than m_fittingHeight there is space to compute the content stacking (ComputeStacking). 00496 if (GetBaseHeight() < m_fittingHeight) 00497 { 00498 SetBaseHeight (m_fittingHeight); 00499 } 00500 00501 m_contentHeight = m_fittingHeight; 00502 long size_compliance = 0L; 00503 00504 ComputePosition2 (0, 0); 00505 00506 if (GetBaseWidth() > original_width + VERROR) 00507 { 00508 #if DEBUG_LAYOUT_COMPUTATION 00509 // The layout has been resized larger in WIDTH to tightly pack its content. 00510 // Or you can say that the layout refuse to be smaller than total WIDTH of its elements. 00511 std::cout << "ComputeLayout2: VLayout Width block at " << GetWidth() << std::endl; 00512 #endif 00513 size_compliance |= eLargerWidth; // need scrollbar 00514 } 00515 else if (GetBaseWidth() + VERROR < original_width) 00516 { 00517 #if DEBUG_LAYOUT_COMPUTATION 00518 // The layout is smaller. 00519 std::cout << "ComputeLayout2: VLayout Width smaller = " << GetWidth() << std::endl; 00520 #endif 00521 size_compliance |= eSmallerWidth; 00522 } 00523 else 00524 { 00525 #if DEBUG_LAYOUT_COMPUTATION 00526 // The layout and its content resized together without trouble. 00527 std::cout << "ComputeLayout2: VLayout Width compliant = " << GetWidth() << std::endl; 00528 #endif 00529 size_compliance |= eCompliantWidth; 00530 } 00531 00532 { 00533 #if DEBUG_LAYOUT_COMPUTATION 00534 // The layout and its content resized together without trouble. 00535 std::cout << "ComputeLayout2: VLayout Height compliant = " << m_fittingHeight << std::endl; 00536 #endif 00537 size_compliance |= eCompliantHeight; 00538 } 00539 00540 return size_compliance; 00541 } 00542 00543 void VLayout::VLayoutManagement (int width, int height) 00544 { 00545 bool need_recompute = false; 00546 00547 do 00548 { 00549 int available_height = height; 00550 int max_stretchfactor = GetMaxStretchFactor(); 00551 std::list<Area *>::iterator it; 00552 00553 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) 00554 { 00555 if (!(*it)->IsVisible ()) 00556 continue; 00557 00558 if ( ( (*it)->GetStretchFactor() == 0) && ( (*it)->IsLayoutDone() != true) ) 00559 { 00560 (*it)->ApplyMinHeight(); 00561 } 00562 } 00563 00564 if (max_stretchfactor == 0) 00565 { 00566 // It means all object are fixed sized or all resizable object have been sized to there max or there min. 00567 return; 00568 } 00569 00570 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) 00571 { 00572 if (!(*it)->IsVisible ()) 00573 continue; 00574 00575 if ( (*it)->GetStretchFactor() == 0 || (*it)->IsLayoutDone() == true) 00576 { 00577 available_height -= (*it)->GetBaseHeight(); 00578 } 00579 } 00580 00581 if (available_height <= 2) 00582 { 00583 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) 00584 { 00585 if (!(*it)->IsVisible ()) 00586 continue; 00587 00588 if ( ( (*it)->GetStretchFactor() != 0) && (*it)->IsArea() ) 00589 { 00590 // If it is not an object of type eInputArea, do not set _layout_done to true, 00591 // so, the layout management function will later be called on the object. 00592 (*it)->ApplyMinHeight(); 00593 (*it)->SetLayoutDone (true); 00594 } 00595 else if ( ( (*it)->GetStretchFactor() != 0) && ( (*it)->IsLayout() ) && ( (*it)->IsLayoutDone() == false) ) 00596 { 00597 // The out of bound must be reset to false. 00598 (*it)->ApplyMinHeight(); 00599 (*it)->SetLayoutDone (false); 00600 } 00601 else if ( ( (*it)->GetStretchFactor() != 0) && ( (*it)->IsLayoutDone() == false) ) 00602 { 00603 (*it)->ApplyMinHeight(); 00604 // A layout must never have _layout_done set to true "here" because it must continue 00605 // doing the layout of its children and finally resize itself to fit them. 00606 // The same way, A layout size factor should never be set to 0. 00607 } 00608 } 00609 00610 return; 00611 } 00612 00613 float cumul = 0; 00614 Area *LastElementThatCanBeResized = 0; 00615 int total_distributed_size = 0; 00616 00617 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) 00618 { 00619 if (!(*it)->IsVisible ()) 00620 continue; 00621 00622 if ( ( (*it)->GetStretchFactor() != 0) && ( (*it)->IsLayoutDone() == false) ) 00623 { 00624 float sf = (float) (*it)->GetStretchFactor(); 00625 cumul += sf / max_stretchfactor; 00626 LastElementThatCanBeResized = (*it); 00627 } 00628 else 00629 { 00630 total_distributed_size += (*it)->GetBaseWidth(); 00631 } 00632 } 00633 00634 // -- 00635 // \ factor 00636 // Ref_Size * \ ------------ = available_height 00637 // / max_factor 00638 // / 00639 // -- 00640 // all element with stretchfactor != 0 00641 00642 int ref_height = available_height / cumul; 00643 00644 // 00645 need_recompute = false;; 00646 00647 for (it = _layout_element_list.begin(); it != _layout_element_list.end() && !need_recompute; it++) 00648 { 00649 if (!(*it)->IsVisible ()) 00650 continue; 00651 00652 if ( ( (*it)->GetStretchFactor() != 0) && ( (*it)->IsLayoutDone() == false) ) 00653 { 00654 int sf = (*it)->GetStretchFactor(); 00655 int new_height; 00656 00657 if (sf == max_stretchfactor) 00658 { 00659 new_height = ref_height; 00660 } 00661 else 00662 { 00663 new_height = ref_height * sf / max_stretchfactor; 00664 } 00665 00666 total_distributed_size += new_height; 00667 00668 if (LastElementThatCanBeResized == (*it) ) 00669 { 00670 // Redistribute the remaining size to the last element (at the bottom). 00671 // This is necessary because of imprecision. For instance if available_height = 451 and we have 2 elements 00672 // with the same stretch factor than each one will have a size of 225. With is correction, the first element will have a size of 00673 // 225 while the second one will have a size of 226. 00674 if (available_height - total_distributed_size > 0) 00675 { 00676 new_height += available_height - total_distributed_size; 00677 total_distributed_size = available_height; 00678 } 00679 } 00680 00681 int elemt_max_height = (*it)->GetMaximumSize().height; 00682 int elemt_min_height = (*it)->GetMinimumSize().height; 00683 00684 // A layout must never have _layout_done set to true "here" because it must continue 00685 // doing the layout of its children and finally resize itself to fit them. 00686 // The same way, A layout size factor should never be set to 0. 00687 // Q: How about SpaceLayout? Should we treat them the same as layout or widget in this particular case? 00688 // A: SapceLayout are treated like widgets in this case 00689 if (new_height < elemt_min_height) 00690 { 00691 // assume the minimum width 00692 (*it)->SetBaseHeight (elemt_min_height); 00693 00694 if ( ( (*it)->IsLayout() == false) || (*it)->IsSpaceLayout() ) 00695 { 00696 (*it)->SetLayoutDone (true); 00697 need_recompute = true; 00698 } 00699 } 00700 else if (new_height > elemt_max_height) 00701 { 00702 // assume the maximum width 00703 (*it)->SetBaseHeight (elemt_max_height); 00704 00705 if ( ( (*it)->IsLayout() == false) || (*it)->IsSpaceLayout() ) 00706 { 00707 (*it)->SetLayoutDone (true); 00708 need_recompute = true; 00709 } 00710 00711 // else 00712 // { 00713 // // set the extra space back in the pool 00714 // total_distributed_size -= (new_height - elemt_max_height); 00715 // } 00716 } 00717 else 00718 { 00719 (*it)->SetBaseHeight (new_height); 00720 } 00721 } 00722 else 00723 { 00724 // For fixed element, reset their size to the same so it is checked against 00725 // the min and max. This is necessary in case you have set the size of the element first then latter, 00726 // you define its MinimumSize and/or MaximumSize size. 00727 t_u32 w = (*it)->GetBaseWidth(); 00728 t_u32 h = (*it)->GetBaseHeight(); 00729 (*it)->SetBaseWidth (w); 00730 (*it)->SetBaseHeight (h); 00731 } 00732 } 00733 } 00734 while (need_recompute); 00735 } 00736 00737 t_u32 VLayout::GetMaxStretchFactor() 00738 { 00739 t_u32 value = 0; 00740 t_u32 sf; 00741 std::list<Area *>::iterator it; 00742 00743 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) 00744 { 00745 if (!(*it)->IsVisible ()) 00746 continue; 00747 00748 // In the recursive process, make sure we get always the highest stretch factor 00749 // of an element that has not been bounded. 00750 if ( (*it)->IsLayoutDone() == false) 00751 { 00752 sf = (*it)->GetStretchFactor(); 00753 00754 if (sf >= value) 00755 { 00756 value = sf; 00757 } 00758 } 00759 } 00760 00761 return value; 00762 } 00763 00764 void VLayout::ComputePosition2 (float offsetX, float offsetY) 00765 { 00766 std::list<Area *>::iterator it; 00767 { 00768 t_u32 num_element = 0; 00769 00770 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) 00771 { 00772 if ((*it)->IsVisible ()) 00773 num_element++; 00774 } 00775 // Get layout Width and Height 00776 int width = GetBaseWidth(); 00777 int height = GetBaseHeight(); 00778 // remove the margins 00779 width -= 2 * m_h_out_margin; 00780 height -= (int) (num_element - 1) * m_v_in_margin + 2 * m_v_out_margin; 00781 00782 // Objects have been resized, now position them. 00783 int current_x = GetBaseX() + m_h_out_margin + offsetX; // add base offset in X (used for scrolling) 00784 int current_y = GetBaseY() + m_v_out_margin + offsetY; // add base offset in Y (used for scrolling) 00785 00786 int offset_space = 0; 00787 int element_margin = 0; 00788 ComputeStacking (height, offset_space, element_margin); 00789 current_y += offset_space; 00790 00791 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) 00792 { 00793 if (!(*it)->IsVisible ()) 00794 continue; 00795 current_y += element_margin; 00796 00797 (*it)->SetBaseX (current_x); 00798 (*it)->SetBaseY (current_y); 00799 00800 MinorDimensionSize extend = (*it)->GetExtend(); 00801 MinorDimensionPosition positioning = (*it)->GetPositioning(); 00802 00803 if ( (extend != eFull) || ( (*it)->GetBaseWidth() < width) ) 00804 { 00805 int widget_width = (*it)->GetBaseWidth(); 00806 00807 switch (positioning) 00808 { 00809 case eLeft: 00810 { 00811 // do nothing 00812 (*it)->SetBaseX (current_x); 00813 break; 00814 } 00815 case eRight: 00816 { 00817 if (widget_width < width) 00818 (*it)->SetBaseX (current_x + width - widget_width); 00819 else 00820 (*it)->SetBaseX (current_x); 00821 00822 break; 00823 } 00824 00825 case eCenter: 00826 default: 00827 { 00828 if (widget_width < width) 00829 (*it)->SetBaseX (current_x + (width - widget_width) / 2); 00830 else 00831 (*it)->SetBaseX (current_x); 00832 } 00833 } 00834 } 00835 00836 current_y += (*it)->GetBaseHeight() + element_margin + m_v_in_margin; 00837 } 00838 } 00839 00840 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) 00841 { 00842 if (!(*it)->IsVisible ()) 00843 continue; 00844 00845 if ( (*it)->Type().IsDerivedFromType (Layout::StaticObjectType) ) 00846 { 00847 (*it)->ComputePosition2 (offsetX, offsetY); 00848 } 00849 else if ( (*it)->Type().IsDerivedFromType (View::StaticObjectType) ) 00850 { 00851 (*it)->PositionChildLayout (offsetX, offsetY); 00852 } 00853 } 00854 } 00855 00856 Area* VLayout::KeyNavIteration(KeyNavDirection direction) 00857 { 00858 if (_layout_element_list.size() == 0) 00859 return NULL; 00860 00861 if (IsVisible() == false) 00862 return NULL; 00863 00864 if (next_object_to_key_focus_area_) 00865 { 00866 if ((direction == KEY_NAV_LEFT) || (direction == KEY_NAV_RIGHT)) 00867 { 00868 // Don't know what to do with this 00869 return NULL; 00870 } 00871 std::list<Area*>::iterator it; 00872 std::list<Area*>::iterator it_next; 00873 it = std::find (_layout_element_list.begin(), _layout_element_list.end(), next_object_to_key_focus_area_); 00874 00875 if (it == _layout_element_list.end()) 00876 { 00877 // Should never happen 00878 nuxAssert (0); 00879 return NULL; 00880 } 00881 00882 it_next = it; 00883 ++it_next; 00884 00885 if ((direction == KEY_NAV_UP) && (it == _layout_element_list.begin())) 00886 { 00887 // can't go further 00888 return NULL; 00889 } 00890 00891 if ((direction == KEY_NAV_DOWN) && (it_next == _layout_element_list.end())) 00892 { 00893 // can't go further 00894 return NULL; 00895 } 00896 00897 if (direction == KEY_NAV_UP) 00898 { 00899 --it; 00900 Area* key_nav_focus = (*it)->KeyNavIteration(direction); 00901 00902 while (key_nav_focus == NULL) 00903 { 00904 if (it == _layout_element_list.begin()) 00905 break; 00906 00907 --it; 00908 key_nav_focus = (*it)->KeyNavIteration(direction); 00909 } 00910 00911 return key_nav_focus; 00912 } 00913 00914 if (direction == KEY_NAV_DOWN) 00915 { 00916 ++it; 00917 Area* key_nav_focus = (*it)->KeyNavIteration(direction); 00918 00919 while (key_nav_focus == NULL) 00920 { 00921 ++it; 00922 if (it == _layout_element_list.end()) 00923 break; 00924 00925 key_nav_focus = (*it)->KeyNavIteration(direction); 00926 } 00927 00928 return key_nav_focus; 00929 } 00930 } 00931 else 00932 { 00933 Area* key_nav_focus = NULL; 00934 00935 if (direction == KEY_NAV_UP) 00936 { 00937 std::list<Area*>::reverse_iterator it = _layout_element_list.rbegin(); 00938 key_nav_focus = (*it)->KeyNavIteration(direction); 00939 00940 while (key_nav_focus == NULL) 00941 { 00942 ++it; 00943 if (it == _layout_element_list.rend()) 00944 break; 00945 00946 key_nav_focus = (*it)->KeyNavIteration(direction); 00947 } 00948 } 00949 else 00950 { 00951 std::list<Area*>::iterator it = _layout_element_list.begin(); 00952 key_nav_focus = (*it)->KeyNavIteration(direction); 00953 00954 while (key_nav_focus == NULL) 00955 { 00956 ++it; 00957 if (it == _layout_element_list.end()) 00958 break; 00959 00960 key_nav_focus = (*it)->KeyNavIteration(direction); 00961 } 00962 } 00963 00964 return key_nav_focus; 00965 } 00966 00967 return NULL; 00968 } 00969 }