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