Back to index

nux  3.0.0
GridHLayout.cpp
Go to the documentation of this file.
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 "GridHLayout.h"
00026 #include "HLayout.h"
00027 #include "VLayout.h"
00028 
00029 namespace nux
00030 {
00031   NUX_IMPLEMENT_OBJECT_TYPE(GridHLayout);
00032 
00033   GridHLayout::GridHLayout(NUX_FILE_LINE_DECL)
00034     :   Layout(NUX_FILE_LINE_PARAM)
00035   {
00036 #if DEBUG_LAYOUT
00037     m_h_in_margin = 10;
00038     left_padding_ = 10;
00039     right_padding_ = 10;
00040     m_v_in_margin = 10;
00041     top_padding_ = 10;
00042     bottom_padding_ = 10;
00043 #endif
00044 
00045     m_h_in_margin = 10;
00046     m_v_in_margin = 10;
00047 
00048     filling_order_ = FILL_HORIZONTAL;
00049     _children_size = Size(64, 64);
00050     _force_children_size = true;
00051     _partial_visibility = true;
00052     _num_row = 1;
00053     _num_column = 1;
00054     _dynamic_column = true;
00055     match_content_size_ = true;
00056 
00057     // Start packing the elements from the top. Is the layout has more space than the elements can use,
00058     // leave that space at the bottom of the GridHLayout.
00059     m_ContentStacking = MAJOR_POSITION_LEFT;
00060 
00061     SetMinimumSize(32, 32);
00062   }
00063 
00064   GridHLayout::~GridHLayout()
00065   {
00066 
00067   }
00068 
00069   void GridHLayout::SetSpaceBetweenChildren(int horizontal_space, int vertical_space)
00070   {
00071     m_h_in_margin = horizontal_space;
00072     m_v_in_margin = vertical_space;
00073   }
00074 
00075   int GridHLayout::GetChildPos(Area *child)
00076   {
00077     int position = 0;
00078     std::list<Area *>::const_iterator it;
00079     for (it = GetChildren().begin(); it != GetChildren().end(); it++)
00080     {
00081       if ((*it) == child)
00082         break;
00083       ++position;
00084     }
00085 
00086     return position;
00087   }
00088 
00089   Area* GridHLayout::GetChildAtPosition(int pos)
00090   {
00091     int position = 0;
00092     std::list<Area *>::const_iterator it;
00093     for (it = GetChildren().begin(); it != GetChildren().end(); it++)
00094     {
00095       if (position == pos)
00096         return (*it);
00097 
00098       ++position;
00099     }
00100 
00101     return NULL;
00102   }
00103 
00104   void GridHLayout::EnablePartialVisibility(bool partial_visibility)
00105   {
00106     _partial_visibility = partial_visibility;
00107   }
00108 
00109   void GridHLayout::SetChildrenSize(int width, int height)
00110   {
00111     _children_size = Size(width, height);
00112   }
00113 
00114   Size GridHLayout::GetChildrenSize() const
00115   {
00116     return _children_size;
00117   }
00118 
00119   void GridHLayout::ForceChildrenSize(bool force)
00120   {
00121     _force_children_size = force;
00122   }
00123 
00124   int GridHLayout::GetNumColumn() const
00125   {
00126     return _num_column;
00127   }
00128 
00129   int GridHLayout::GetNumRow() const
00130   {
00131     return _num_row;
00132   }
00133 
00134   void GridHLayout::MatchContentSize(bool match_content)
00135   {
00136     match_content_size_ = match_content;
00137   }
00138 
00139   bool GridHLayout::IsMatchingContentSize() const
00140   {
00141     return match_content_size_;
00142   }
00143 
00144   void GridHLayout::GetCompositeList(std::list<Area *> *ViewList)
00145   {
00146     std::list<Area *>::iterator it;
00147 
00148     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00149     {
00150       if ((*it)->IsView())
00151       {
00152         View *ic = static_cast<View *>(*it);
00153         ViewList->push_back(ic);
00154       }
00155       else if ((*it)->IsLayout())
00156       {
00157         Layout *layout = static_cast<Layout *>(*it);
00158         layout->GetCompositeList(ViewList);
00159       }
00160     }
00161   }
00162 
00163   long GridHLayout::ComputeLayoutRowOrder()
00164   {
00165     std::list<Area *> elements;
00166 
00167     if (GetScaleFactor() == 0)
00168     {
00169       ApplyMinWidth();
00170     }
00171 
00172     if (_layout_element_list.size() == 0)
00173     {
00174       return eCompliantHeight | eCompliantWidth;
00175     }
00176 
00177     int num_elements = 0;
00178 
00179     std::list<Area *>::iterator it;
00180     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00181     {
00182       if ((*it)->IsVisible())
00183       {
00184         (*it)->SetLayoutDone(false);
00185         elements.push_back(*it);
00186         num_elements++;
00187       }
00188       (*it)->SetLayoutDone(false);
00189     }
00190 
00191     int original_height = GetBaseHeight();
00192 
00193     // The grid layout goes through the child elements and assign them a size and position. Children are filled in the grid like this:
00194     //  0   1   2   3   4   5
00195     //  6   7   8   9   10  11
00196     //  12  13  ..  ..  ..  ..
00197     // This is a left to right fill going down. An option can be added the fill the grid from top to bottom and going toward the right.
00198 
00199     nux::Geometry base = GetGeometry();
00200     it = elements.begin();
00201     int num_row = 0;
00202     int num_column = 0;
00203 
00204     if (num_elements > 0)
00205       ++num_row;
00206 
00207     if (_dynamic_column)
00208     {
00209       int X = base.x + left_padding_;
00210       int Y = base.y + top_padding_;
00211 
00212       bool first_element_of_row = true;
00213 
00214       for (int i = 0; i < num_elements; i++)
00215       {
00216         if (num_row == 1)
00217           num_column++;
00218 
00219         if (first_element_of_row)
00220         {
00221           first_element_of_row = false;
00222         }
00223 
00224         if (_force_children_size)
00225         {
00226           (*it)->SetMinimumSize(_children_size.width, _children_size.height);
00227         }
00228 
00229         (*it)->SetGeometry(nux::Geometry(X, Y, _children_size.width, _children_size.height));
00230 
00231         (*it)->ComputeContentSize();
00232 
00233         X += _children_size.width + m_h_in_margin;
00234 
00235         it++;
00236 
00237         if ((!_partial_visibility) && (X + _children_size.width > base.x + base.width))
00238         {
00239           X = base.x + left_padding_;
00240           Y += _children_size.height + m_v_in_margin;
00241 
00242           first_element_of_row = true;
00243           if (i < num_elements - 1)
00244             ++num_row;
00245         }
00246         else if (X >= base.x + base.width)
00247         {
00248           X = base.x + left_padding_;
00249           Y += _children_size.height + m_v_in_margin;
00250 
00251           first_element_of_row = true;
00252           if (i < num_elements - 1)
00253             ++num_row;
00254         }
00255       }
00256     }
00257 
00258     _num_row = num_row;
00259     _num_column = num_column;
00260 
00261     if ((GetScaleFactor() == 0) || match_content_size_)
00262     {
00263       int h = num_row * _children_size.height + (top_padding_ + bottom_padding_) + (num_row - 1) * m_v_in_margin;
00264       SetMinimumHeight(h);
00265       SetBaseHeight(h);
00266     }
00267 
00268     long size_compliance = 0L;
00269     {
00270 #if DEBUG_LAYOUT_COMPUTATION
00271       // The layout and its content resized together without trouble.
00272       std::cout << "ComputeContentSize: GridHLayout Width compliant = " << m_fittingWidth << std::endl;
00273 #endif
00274       size_compliance |= eCompliantWidth;
00275     }
00276 
00277     // The layout has been resized to tightly pack its content
00278     if (GetBaseHeight() > original_height)
00279     {
00280 #if DEBUG_LAYOUT_COMPUTATION
00281       // The layout has been resized larger in height to tightly pack its content.
00282       // Or you can say that the layout refuse to be smaller than total HEIGHT of its elements.
00283       std::cout << "ComputeContentSize: GridHLayout Height block at " << GetBaseHeight() << std::endl;
00284 #endif
00285       size_compliance |= eLargerHeight; // need scrollbar
00286     }
00287     else if (GetBaseHeight() < original_height)
00288     {
00289 #if DEBUG_LAYOUT_COMPUTATION
00290       // The layout is smaller.
00291       std::cout << "ComputeContentSize: GridHLayout Height is smaller = " << GetBaseHeight() << std::endl;
00292 #endif
00293       size_compliance |= eSmallerHeight;
00294     }
00295     else
00296     {
00297 #if DEBUG_LAYOUT_COMPUTATION
00298       // The layout and its content resized together without trouble.
00299       std::cout << "ComputeContentSize: GridHLayout Height compliant = " << GetBaseHeight() << std::endl;
00300 #endif
00301       size_compliance |= eCompliantHeight;
00302     }
00303 
00304     //    if (GetScaleFactor() == 0)
00305     //    {
00306     //        return size_compliance | eForceComply;
00307     //    }
00308 
00309     //SetDirty(false);
00310     return size_compliance;
00311   }
00312 
00313   long GridHLayout::ComputeLayoutColumnOrder()
00314   {
00315     std::list<Area *> elements;
00316 
00317     if (GetScaleFactor() == 0)
00318     {
00319       ApplyMinHeight();
00320     }
00321 
00322     if (_layout_element_list.size() == 0)
00323     {
00324       return eCompliantHeight | eCompliantWidth;
00325     }
00326 
00327     int num_elements = 0;
00328 
00329     std::list<Area *>::iterator it;
00330     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00331     {
00332       if ((*it)->IsVisible())
00333       {
00334         (*it)->SetLayoutDone(false);
00335         elements.push_back(*it);
00336         num_elements++;
00337       }
00338       (*it)->SetLayoutDone(false);
00339     }
00340 
00341     int original_width = GetBaseWidth();
00342 
00343     nux::Geometry base = GetGeometry();
00344     it = elements.begin();
00345     int num_row = 0;
00346     int num_column = 0;
00347 
00348     if (num_elements > 0)
00349       ++num_column;
00350 
00351     if (_dynamic_column)
00352     {
00353       int X = base.x + left_padding_;
00354       int Y = base.y + top_padding_;
00355 
00356       bool first_element_of_column = true;
00357 
00358       for (int i = 0; i < num_elements; i++)
00359       {
00360         if (num_column == 1)
00361           num_row++;
00362 
00363         if (first_element_of_column)
00364         {
00365           first_element_of_column = false;
00366         }
00367 
00368         if (_force_children_size)
00369         {
00370           (*it)->SetMinimumSize(_children_size.width, _children_size.height);
00371         }
00372 
00373         (*it)->SetGeometry(nux::Geometry(X, Y, _children_size.width, _children_size.height));
00374 
00375         (*it)->ComputeContentSize();
00376 
00377         Y += _children_size.height + m_v_in_margin;
00378 
00379         it++;
00380 
00381         if ((!_partial_visibility) && (Y + _children_size.height > base.y + base.height - top_padding_))
00382         {
00383           X += _children_size.width + m_h_in_margin;
00384           Y = base.y + top_padding_;
00385 
00386           first_element_of_column = true;
00387           if (i < num_elements - 1)
00388             ++num_column;
00389         }
00390         else if (Y >= base.y + base.height)
00391         {
00392           X += _children_size.width + m_h_in_margin;
00393           Y = base.y + top_padding_;
00394 
00395           first_element_of_column = true;
00396           if (i < num_elements - 1)
00397             ++num_column;
00398         }
00399       }
00400     }
00401 
00402     _num_row = num_row;
00403     _num_column = num_column;
00404 
00405     if ((GetScaleFactor() == 0) || match_content_size_)
00406     {
00407       int w = num_column * _children_size.width + (left_padding_ + right_padding_) + (num_column - 1) * m_h_in_margin;
00408       SetMinimumWidth(w);
00409       SetBaseWidth(w);
00410     }
00411 
00412     long size_compliance = 0L;
00413 
00414     if (GetBaseWidth() > original_width)
00415     {
00416 #if DEBUG_LAYOUT_COMPUTATION
00417       // The layout has been resized larger in WIDTH to tightly pack its content.
00418       // Or you can say that the layout refuse to be smaller than total WIDTH of its elements.
00419       std::cout << "ComputeContentSize: VLayout Width block at " << GetWidth() << std::endl;
00420 #endif
00421       size_compliance |= eLargerWidth; // need scrollbar
00422     }
00423     else if (GetBaseWidth() < original_width)
00424     {
00425 #if DEBUG_LAYOUT_COMPUTATION
00426       // The layout is smaller.
00427       std::cout << "ComputeContentSize: VLayout Width smaller = " << GetWidth() << std::endl;
00428 #endif
00429       size_compliance |= eSmallerWidth;
00430     }
00431     else
00432     {
00433 #if DEBUG_LAYOUT_COMPUTATION
00434       // The layout and its content resized together without trouble.
00435       std::cout << "ComputeContentSize: VLayout Width compliant = " << GetWidth() << std::endl;
00436 #endif
00437       size_compliance |= eCompliantWidth;
00438     }
00439 
00440     {
00441 #if DEBUG_LAYOUT_COMPUTATION
00442       // The layout and its content resized together without trouble.
00443       std::cout << "ComputeContentSize: VLayout Height compliant = " << m_fittingHeight << std::endl;
00444 #endif
00445       size_compliance |= eCompliantHeight;
00446     }
00447 
00448     return size_compliance;
00449   }
00450 
00451   long GridHLayout::ComputeContentSize()
00452   {
00453     if (filling_order_ == FILL_HORIZONTAL)
00454     {
00455       return ComputeLayoutRowOrder();
00456     }
00457     else
00458     {
00459       return ComputeLayoutColumnOrder();
00460     }
00461   }
00462 
00463   void GridHLayout::ProcessDraw(GraphicsEngine &graphics_engine, bool force_draw)
00464   {
00465     if (_layout_element_list.size() == 0)
00466       return;
00467 
00468     std::list<Area *> elements;
00469     std::list<Area *>::iterator it = _layout_element_list.begin();
00470 
00471     graphics_engine.PushModelViewMatrix(Get2DMatrix());
00472 
00473     Geometry base = GetGeometry();
00474     Geometry absolute_geometry = GetAbsoluteGeometry();
00475     Geometry parent_geometry = absolute_geometry;
00476     Geometry visibility_geometry = absolute_geometry;
00477 
00478     if (GetToplevel())
00479     {
00480       parent_geometry = GetToplevel()->GetAbsoluteGeometry();
00481     }
00482 
00483     visibility_geometry = parent_geometry.Intersect(absolute_geometry);
00484 
00485     graphics_engine.PushClippingRectangle(base);
00486 
00487     it = _layout_element_list.begin();
00488 
00489     bool first = false;
00490     bool last = false;
00491 
00492     int JJ = 0;
00493     int II = 0;
00494 
00495     if (filling_order_ == FILL_HORIZONTAL)
00496     {
00497       JJ = _num_row;
00498       II = _num_column;
00499     }
00500     else
00501     {
00502       JJ = _num_column;
00503       II = _num_row;
00504     }
00505 
00506     for (int j = 0; j < JJ; j++)
00507     {
00508       for (int i = 0; i < II; i++)
00509       {
00510         if (it == _layout_element_list.end())
00511           break;
00512 
00513         if ((*it)->IsVisible() == false)
00514         {
00515           ++it;
00516           continue;
00517         }
00518 
00519         Geometry it_geo = (*it)->GetAbsoluteGeometry();
00520         Geometry intersection = visibility_geometry.Intersect(it_geo);
00521 
00522         // Test if the element is inside the Grid before rendering.
00523         if (!intersection.IsNull())
00524         {
00525           if (first == false)
00526           {
00527             first = true; // First invisible child.
00528           }
00529 
00530           int x = 0;
00531           int y = 0;
00532           if (filling_order_ == FILL_HORIZONTAL)
00533           {
00534             x = base.x + left_padding_ + i * (_children_size.width + m_h_in_margin);
00535             y = base.y + top_padding_ + j * (_children_size.height + m_v_in_margin);
00536           }
00537           else
00538           {
00539             x = base.x + left_padding_ + j * (_children_size.width + m_h_in_margin);
00540             y = base.y + top_padding_ + i * (_children_size.height + m_v_in_margin);
00541           }
00542 
00543           graphics_engine.PushClippingRectangle(Geometry(x, y, _children_size.width, _children_size.height));
00544 
00545           if ((*it)->IsView())
00546           {
00547             View *ic = static_cast<View *>(*it);
00548             ic->ProcessDraw(graphics_engine, force_draw);
00549           }
00550           else if ((*it)->IsLayout())
00551           {
00552             Layout *layout = static_cast<Layout *>(*it);
00553             layout->ProcessDraw(graphics_engine, force_draw);
00554           }
00555 
00556           graphics_engine.PopClippingRectangle();
00557         }
00558         else
00559         {
00560           if (first)
00561           {
00562             // First invisible child. Exit!
00563             last = true;
00564           }
00565         }
00566 
00567         if (first && last)
00568         {
00569           // Early exit
00570           break;
00571         }
00572 
00573         it++;
00574       }
00575       if (first && last)
00576         break;
00577     }
00578 
00579     graphics_engine.PopClippingRectangle();
00580     graphics_engine.PopModelViewMatrix();
00581 
00582     _queued_draw = false;
00583   }
00584 
00585   Area* GridHLayout::KeyNavIterationRowOrder(KeyNavDirection direction)
00586   {
00587     if (_layout_element_list.size() == 0)
00588       return NULL;
00589 
00590     if (IsVisible() == false)
00591       return NULL;
00592 
00593     if (next_object_to_key_focus_area_)
00594     {
00595       std::list<Area*>::iterator it;
00596       std::list<Area*>::iterator it_next;
00597       it = std::find(_layout_element_list.begin(), _layout_element_list.end(), next_object_to_key_focus_area_);
00598       it_next = it;
00599       ++it_next;
00600 
00601       if (it == _layout_element_list.end())
00602       {
00603         // Should never happen
00604         nuxAssert(0);
00605         return NULL;
00606       }
00607 
00608       int position = GetChildPos(*it); // note that(*it) == next_object_to_key_focus_area_
00609       int nun_column = GetNumColumn();
00610       int nun_row = GetNumRow();
00611 
00612       if ((direction == KEY_NAV_LEFT) && (it == _layout_element_list.begin()))
00613       {
00614         // first item
00615         return NULL;
00616       }
00617 
00618       if ((direction == KEY_NAV_LEFT) && position % nun_column == 0)
00619       {
00620         return NULL;
00621       }
00622 
00623       if ((direction == KEY_NAV_RIGHT) && (it_next == _layout_element_list.end()))
00624       {
00625         // last item
00626         return NULL;
00627       }
00628 
00629       if ((direction == KEY_NAV_RIGHT) && position % nun_column == nun_column - 1)
00630       {
00631         // last item
00632         return NULL;
00633       }
00634 
00635       if ((direction == KEY_NAV_UP) && ((position / nun_column) == 0))
00636       {
00637         // top edge
00638         return NULL;
00639       }
00640 
00641       if ((direction == KEY_NAV_DOWN) && ((position / nun_column) == (nun_row - 1)))
00642       {
00643         // bottom edge
00644         return NULL;
00645       }
00646 
00648       if (direction == KEY_NAV_LEFT)
00649       {
00650         --it;
00651         Area* key_nav_focus = (*it)->KeyNavIteration(direction);
00652 
00653         while (key_nav_focus == NULL)
00654         {
00655           int pos = GetChildPos(*it);
00656           if (it == _layout_element_list.begin() || ((pos % nun_column) == 0))
00657             break;
00658 
00659           --it;
00660           key_nav_focus = (*it)->KeyNavIteration(direction);
00661         }
00662 
00663         return key_nav_focus;
00664       }
00665 
00666       if (direction == KEY_NAV_RIGHT)
00667       {
00668         ++it;
00669         Area* key_nav_focus = (*it)->KeyNavIteration(direction);
00670 
00671         while (key_nav_focus == NULL)
00672         {
00673           int pos = GetChildPos(*it);
00674 
00675           if ((it == _layout_element_list.end()) || (pos == (pos / nun_column) * nun_column + (nun_column -1)))
00676             break;
00677 
00678           ++it;
00679           key_nav_focus = (*it)->KeyNavIteration(direction);
00680         }
00681 
00682         return key_nav_focus;
00683       }
00684 
00685       if (direction == KEY_NAV_UP)
00686       {
00687         for (int i = 0; i < nun_column; ++i)
00688         {
00689           --it;
00690         }
00691 
00692         if (it != _layout_element_list.end())
00693           return (*it)->KeyNavIteration(direction);
00694       }
00695 
00696       if (direction == KEY_NAV_DOWN)
00697       {
00698         for (int i = 0; i < nun_column; ++i)
00699         {
00700           ++it;
00701         }
00702 
00703         if (it != _layout_element_list.end())
00704           return (*it)->KeyNavIteration(direction);
00705       }
00706     }
00707     else
00708     {
00709       std::list<Area*>::iterator it;
00710       it = _layout_element_list.begin();
00711       return (*it)->KeyNavIteration(direction);
00712     }
00713 
00714     return NULL;
00715   }
00716 
00717   Area* GridHLayout::KeyNavIterationColumnOrder(KeyNavDirection direction)
00718   {
00719     if (_layout_element_list.size() == 0)
00720       return NULL;
00721 
00722     if (IsVisible() == false)
00723       return NULL;
00724 
00725     if (next_object_to_key_focus_area_)
00726     {
00727       std::list<Area*>::iterator it;
00728       std::list<Area*>::iterator it_next;
00729       it = std::find(_layout_element_list.begin(), _layout_element_list.end(), next_object_to_key_focus_area_);
00730       it_next = it;
00731       ++it_next;
00732 
00733       if (it == _layout_element_list.end())
00734       {
00735         // Should never happen
00736         nuxAssert(0);
00737         return NULL;
00738       }
00739 
00740       int position = GetChildPos(*it); // note that(*it) == next_object_to_key_focus_area_
00741       int nun_column = GetNumColumn();
00742       int nun_row = GetNumRow();
00743 
00744       if ((direction == KEY_NAV_UP) && (it == _layout_element_list.begin()))
00745       {
00746         // first item
00747         return NULL;
00748       }
00749 
00750       if ((direction == KEY_NAV_DOWN) && (it_next == _layout_element_list.end()))
00751       {
00752         // last item
00753         return NULL;
00754       }
00755 
00756       if ((direction == KEY_NAV_UP) && ((position % nun_row) == 0))
00757       {
00758         // Left edge
00759         return NULL;
00760       }
00761 
00762       if ((direction == KEY_NAV_DOWN) && (position == (position / nun_row) * nun_row + (nun_row -1)))
00763       {
00764         // right edge
00765         return NULL;
00766       }
00767 
00768       if ((direction == KEY_NAV_LEFT) && ((position / nun_row) == 0))
00769       {
00770         // top edge
00771         return NULL;
00772       }
00773 
00774       if ((direction == KEY_NAV_RIGHT) && ((position / nun_row) == nun_column))
00775       {
00776         // bottom edge
00777         return NULL;
00778       }
00779 
00781       if (direction == KEY_NAV_UP)
00782       {
00783         --it;
00784         Area* key_nav_focus = (*it)->KeyNavIteration(direction);
00785 
00786         while (key_nav_focus == NULL)
00787         {
00788           int pos = GetChildPos(*it);
00789           if (it == _layout_element_list.begin() || ((pos % nun_row) == 0))
00790             break;
00791 
00792           --it;
00793           key_nav_focus = (*it)->KeyNavIteration(direction);
00794         }
00795 
00796         return key_nav_focus;
00797       }
00798 
00799       if (direction == KEY_NAV_DOWN)
00800       {
00801         ++it;
00802         Area* key_nav_focus = (*it)->KeyNavIteration(direction);
00803 
00804         while (key_nav_focus == NULL)
00805         {
00806           ++it;
00807           int pos = GetChildPos(*it);
00808 
00809           if ((it == _layout_element_list.end()) || (pos == (pos / nun_row) * nun_row + (nun_row -1)))
00810             break;
00811 
00812           key_nav_focus = (*it)->KeyNavIteration(direction);
00813         }
00814 
00815         return key_nav_focus;
00816       }
00817 
00818       if (direction == KEY_NAV_LEFT)
00819       {
00820         for (int i = 0; i < nun_row; ++i)
00821         {
00822           --it;
00823         }
00824         return (*it)->KeyNavIteration(direction);
00825       }
00826 
00827       if (direction == KEY_NAV_RIGHT)
00828       {
00829         for (int i = 0; i < nun_row; ++i)
00830         {
00831           ++it;
00832           if (it == _layout_element_list.end())
00833             return NULL;
00834         }
00835         return (*it)->KeyNavIteration(direction);
00836       }
00837     }
00838     else
00839     {
00840       std::list<Area*>::iterator it;
00841       it = _layout_element_list.begin();
00842       return (*it)->KeyNavIteration(direction);
00843     }
00844 
00845     return NULL;
00846 
00847   }
00848 
00849   Area* GridHLayout::KeyNavIteration(KeyNavDirection direction)
00850   {
00851     if (filling_order_ == FILL_HORIZONTAL)
00852     {
00853       return KeyNavIterationRowOrder(direction);
00854     }
00855     else
00856     {
00857       return KeyNavIterationColumnOrder(direction);
00858     }
00859   }
00860 
00861   void GridHLayout::SetFillingOrder(FillingOrder filling_order)
00862   {
00863     filling_order_ = filling_order;
00864   }
00865 
00866   GridHLayout::FillingOrder GridHLayout::GetFillingOrder() const
00867   {
00868     return filling_order_;
00869   }
00870 }