nux-1.16.0
Layout.cpp
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 "Layout.h"
00025 #include "View.h"
00026 
00027 namespace nux
00028 {
00029   NUX_IMPLEMENT_OBJECT_TYPE(Layout);
00030   NUX_IMPLEMENT_OBJECT_TYPE(SpaceLayout);
00031 
00032   Layout::Layout (NUX_FILE_LINE_DECL)
00033     :   Area (NUX_FILE_LINE_PARAM)
00034   {
00035     m_h_in_margin       = 0;
00036     m_h_out_margin      = 0;
00037     m_v_in_margin       = 0;
00038     m_v_out_margin      = 0;
00039     m_contentWidth      = 0;
00040     m_contentHeight     = 0;
00041     m_ContentStacking   = eStackExpand;
00042     _has_focus_control  = false;
00043     _queued_draw        = false;
00044     _ignore_focus       = false;
00045 
00046     SetMinimumSize(1, 1);
00047   }
00048 
00049   Layout::~Layout()
00050   {
00051     // It is possible that this layout object is in the refresh list. Remove
00052     // it here before it is deleted.
00053     WindowThread* wt = GetWindowThread();
00054     if (wt)
00055       wt->RemoveObjectFromLayoutQueue(this);
00056 
00057     std::list<Area *>::iterator it;
00058 
00059     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00060     {
00061       (*it)->UnParentObject();
00062     }
00063 
00064     _layout_element_list.clear();
00065   }
00066 
00067 
00068   void Layout::RemoveChildObject (Area *bo)
00069   {
00070     std::list<Area *>::iterator it;
00071     it = std::find (_layout_element_list.begin(), _layout_element_list.end(), bo);
00072 
00073     if (it != _layout_element_list.end())
00074     {
00075       /* we need to emit the signal before the unparent, just in case
00076          one of the callbacks wanted to use this object */
00077       ViewRemoved.emit (this, bo);
00078       bo->UnParentObject();
00079       _layout_element_list.erase (it);
00080     }
00081   }
00082 
00083   bool Layout::FindWidget (Area *WidgetObject) const
00084   {
00085     std::list<Area *>::const_iterator it;
00086 
00087     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00088     {
00089       if ( (*it) == WidgetObject)
00090       {
00091         return true;
00092       }
00093     }
00094 
00095     return false;
00096   }
00097 
00098   bool Layout::IsEmpty() const
00099   {
00100     return (_layout_element_list.size() == 0);
00101   }
00102 
00103   bool Layout::HasFocusableEntries ()
00104   {
00105     std::list<Area *>::const_iterator it;
00106 
00107     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00108     {
00109       bool can_focus = false;
00110       if ( (*it)->IsArea() )
00111       {
00112         CoreArea *area = NUX_STATIC_CAST (CoreArea *, (*it) );
00113         can_focus = area->CanFocus ();
00114       }
00115       else if ( (*it)->IsView() )
00116       {
00117         View *ic = NUX_STATIC_CAST (View *, (*it) );
00118         can_focus = ic->CanFocus ();
00119       }
00120       else if ( (*it)->IsLayout() )
00121       {
00122         Layout *layout = NUX_STATIC_CAST (Layout *, (*it) );
00123         can_focus = layout->CanFocus ();
00124       }
00125 
00126       if (can_focus == true)
00127         return true;
00128     }
00129 
00130     return false;
00131   }
00132 
00133   void Layout::OnChildFocusChanged (/*Area *parent,*/ Area *child)
00134   {
00135     ChildFocusChanged.emit (/*parent,*/ child);
00136   }
00137 
00138 // If(stretchfactor == 0): the WidgetLayout geometry will be set to SetGeometry(0,0,1,1);
00139 // and the children will take their natural size by expending WidgetLayout.
00140 // If the parent of WidgetLayout offers more space, it won't be used by WidgetLayout.
00141   void Layout::AddLayout (Layout *layout, unsigned int stretchFactor, MinorDimensionPosition minor_position, MinorDimensionSize minor_size, float percentage, LayoutPosition index)
00142   {
00143     nuxAssertMsg (layout != 0, TEXT ("[Layout::AddView] Invalid parameter.") );
00144     NUX_RETURN_IF_TRUE (layout == 0);
00145     //  Should never happen
00146     nuxAssertMsg (layout != this, TEXT ("[Layout::AddLayout] Error: Trying to add a layout to itself.") );
00147     NUX_RETURN_IF_FALSE (layout != 0);
00148 
00149     Area *parent = layout->GetParentObject();
00150     nuxAssertMsg (parent == 0, TEXT ("[Layout::AddLayout] Trying to add an object that already has a parent.") );
00151     NUX_RETURN_IF_TRUE (parent != 0);
00152 
00153     nuxAssertMsg (index >= 0, TEXT ("[Layout::AddLayout] Invalid index position. Adding at the beginning of the list..") );
00154 
00155     layout->SetStretchFactor (stretchFactor);
00156     layout->SetPositioning (minor_position);
00157     layout->SetExtend (minor_size);
00158 
00159     if (percentage < 1.0f)
00160     {
00161       layout->SetPercentage (1.0f);
00162     }
00163     else if (percentage > 100.0f)
00164     {
00165       layout->SetPercentage (100.0f);
00166     }
00167     else
00168     {
00169       layout->SetPercentage (percentage);
00170     }
00171 
00172     layout->SetParentObject (this);
00173 
00174     layout->OnChildQueueDraw.connect (sigc::mem_fun (this, &Layout::ChildLayoutChildQueuedDraw));
00175     layout->OnQueueDraw.connect (sigc::mem_fun (this, &Layout::ChildLayoutQueuedDraw));
00176 
00177     if (HasFocusControl () && HasFocusableEntries () == false)
00178     {
00179       //layout->SetFocused (true);
00180       //ChildFocusChanged (this, layout);
00181     }
00182 
00183     if (index < 0)
00184       index = NUX_LAYOUT_BEGIN;
00185 
00186     if (index == NUX_LAYOUT_END || index >= _layout_element_list.size())
00187     {
00188       _layout_element_list.push_back (layout);
00189     }
00190     else
00191     {
00192 #if defined(NUX_OS_WINDOWS) && !defined(NUX_VISUAL_STUDIO_2010)
00193       std::list<Area *>::iterator pos = _layout_element_list.begin();
00194 #else
00195       auto pos = _layout_element_list.begin();
00196 #endif
00197       int idx = index;
00198       while (pos != _layout_element_list.end() && idx > 0)
00199       {
00200         idx--;
00201         pos++;
00202       }
00203       _layout_element_list.insert(pos, layout);
00204     }
00205 
00206     _connection_map[layout] = layout->ChildFocusChanged.connect (sigc::mem_fun (this, &Layout::OnChildFocusChanged));
00207 
00208     //--->> Removed because it cause problem with The splitter widget: ComputeLayout2();
00209   }
00210 
00212 
00236   void Layout::AddView (Area *bo, unsigned int stretchFactor, MinorDimensionPosition minor_position, MinorDimensionSize minor_size, float percentage, LayoutPosition index)
00237   {
00238     nuxAssertMsg (bo != 0, TEXT ("[Layout::AddView] Invalid parameter.") );
00239     NUX_RETURN_IF_TRUE (bo == 0);
00240 
00241     Area *parent = bo->GetParentObject();
00242     nuxAssertMsg (parent == 0, TEXT ("[Layout::AddView] Trying to add an object that already has a parent.") );
00243     NUX_RETURN_IF_TRUE (parent != 0);
00244 
00245     nuxAssertMsg (index >= 0, TEXT ("[Layout::AddView] Invalid index position. Adding at the beginning of the list..") );
00246 
00247     bo->SetStretchFactor (stretchFactor);
00248     bo->SetPositioning (minor_position);
00249     bo->SetExtend (minor_size);
00250 
00251     if (percentage < 1.0f)
00252     {
00253       bo->SetPercentage (1.0f);
00254     }
00255     else if (percentage > 100.0f)
00256     {
00257       bo->SetPercentage (100.0f);
00258     }
00259     else
00260     {
00261       bo->SetPercentage (percentage);
00262     }
00263 
00264     bo->SetParentObject (this);
00265 
00266     if (bo->IsView ())
00267       static_cast<View *> (bo)->OnQueueDraw.connect (sigc::mem_fun (this, &Layout::ChildViewQueuedDraw));
00268 
00269     //if (HasFocusControl () && HasFocusableEntries () == false)
00270     //{
00271       //bo->SetFocused (true);
00272       //ChildFocusChanged (this, bo);
00273     //}
00274 
00275     if (index < 0)
00276       index = NUX_LAYOUT_BEGIN;
00277 
00278     if (index == NUX_LAYOUT_END || index >= _layout_element_list.size())
00279     {
00280       _layout_element_list.push_back (bo);
00281     }
00282     else
00283     {
00284 #if defined(NUX_OS_WINDOWS) && !defined(NUX_VISUAL_STUDIO_2010)
00285       std::list<Area *>::iterator pos = _layout_element_list.begin();
00286 #else
00287       auto pos = _layout_element_list.begin();
00288 #endif
00289       int idx = index;
00290       while (pos != _layout_element_list.end() && idx > 0)
00291       {
00292         idx--;
00293         pos++;
00294       }
00295       _layout_element_list.insert(pos, bo);
00296     }
00297 
00298     _connection_map[bo] = bo->ChildFocusChanged.connect (sigc::mem_fun (this, &Layout::OnChildFocusChanged));
00299 
00300     ViewAdded.emit (this, bo);
00301     //--->> Removed because it cause problem with The splitter widget: ComputeLayout2();
00302   }
00303 
00304   void Layout::AddSpace (unsigned int width, unsigned int stretchFactor, LayoutPosition index)
00305   {
00306     AddLayout (new SpaceLayout(), stretchFactor);
00307   }
00308 
00309   void Layout::Clear()
00310   {
00311     std::list<Area *>::iterator it;
00312 
00313     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00314     {
00315       (*it)->UnParentObject();
00316     }
00317 
00318     _layout_element_list.clear();
00319   }
00320 
00321   bool Layout::SearchInAllSubNodes (Area *bo)
00322   {
00323     std::list<Area *>::iterator it;
00324 
00325     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00326     {
00327       if ( (*it) == bo)
00328       {
00329         return true;
00330       }
00331       else if ( (*it)->IsLayout() )
00332       {
00333         Layout *layout = NUX_STATIC_CAST (Layout *, (*it) );
00334 
00335         if (layout->SearchInAllSubNodes (bo) )
00336         {
00337           return true;
00338         }
00339       }
00340     }
00341 
00342     return false;
00343   }
00344 
00345   bool Layout::SearchInFirstSubNodes (Area *bo)
00346   {
00347     std::list<Area *>::iterator it;
00348 
00349     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00350     {
00351       if ( (*it) == bo)
00352       {
00353         return true;
00354       }
00355     }
00356 
00357     return false;
00358   }
00359 
00360   unsigned int Layout::GetMaxStretchFactor()
00361   {
00362     unsigned int value = 0;
00363     unsigned int sf;
00364     std::list<Area *>::iterator it;
00365 
00366     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00367     {
00368       sf = (*it)->GetStretchFactor();
00369 
00370       if (sf >= value)
00371       {
00372         value = sf;
00373       }
00374     }
00375 
00376     return value;
00377   }
00378 
00379   unsigned int Layout::GetMinStretchFactor()
00380   {
00381     unsigned int value = 0xFFFFFFFF;
00382     unsigned int sf;
00383     std::list<Area *>::iterator it;
00384 
00385     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00386     {
00387       sf = (*it)->GetStretchFactor();
00388 
00389       if (sf <= value)
00390       {
00391         value = sf;
00392       }
00393     }
00394 
00395     return value;
00396   }
00397 
00398   unsigned int Layout::GetNumStretchFactor (unsigned int sf)
00399   {
00400     unsigned int count = 0;
00401     std::list<Area *>::iterator it;
00402 
00403     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00404     {
00405       if ( (*it)->GetStretchFactor() == sf)
00406       {
00407         count++;
00408       }
00409     }
00410 
00411     return count;
00412   }
00413 
00414   void Layout::DoneRedraw()
00415   {
00416     std::list<Area *>::iterator it;
00417 
00418     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00419     {
00420       if ( (*it)->IsView() )
00421       {
00422         View *ic = NUX_STATIC_CAST (View *, (*it) );
00423         ic->DoneRedraw();
00424       }
00425     }
00426   }
00427 
00428   void Layout::DoActivateFocus ()
00429   {
00430     std::list<Area *>::const_iterator it;
00431     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00432     {
00433       if ((*it)->GetFocused ())
00434       {
00435         (*it)->ActivateFocus ();
00436         break;
00437       }
00438     }
00439   }
00440 
00441   bool Layout::FocusFirstChild ()
00442   {
00443     if (_layout_element_list.empty ())
00444       return false;
00445 
00446     std::list<Area *>::const_iterator it;
00447     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00448     {
00449       if ((*it)->CanFocus ())
00450       {
00451         (*it)->SetFocused (true);
00452         ChildFocusChanged (/*this,*/ (*it));
00453         return true;
00454       }
00455     }
00456 
00457     return false;
00458   }
00459 
00460   bool Layout::FocusLastChild ()
00461   {
00462     if (_layout_element_list.empty ())
00463       return false;
00464 
00465     std::list<Area *>::reverse_iterator it;
00466     for (it = _layout_element_list.rbegin(); it != _layout_element_list.rend(); it++)
00467     {
00468       if ((*it)->CanFocus ())
00469       {
00470         (*it)->SetFocused (true);
00471         ChildFocusChanged (/*this,*/ (*it));
00472         return true;
00473       }
00474     }
00475 
00476     return false;
00477   }
00478 
00479 
00480   bool Layout::FocusNextChild (Area *child)
00481   {
00482     std::list<Area *>::const_iterator it;
00483     bool found_child = false;
00484 
00485     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00486     {
00487       if (found_child)
00488       {
00489         if ((*it)->CanFocus ())
00490         {
00491           (*it)->SetFocused (true);
00492           ChildFocusChanged (/*this,*/ (*it));
00493           return true;
00494         }
00495       }
00496 
00497       if ((*it) == child)
00498       {
00499         found_child = true;
00500       }
00501     }
00502 
00503     return false;
00504   }
00505 
00506   bool Layout::FocusPreviousChild (Area *child)
00507   {
00508     std::list<Area *>::reverse_iterator it;
00509     bool found_child = false;
00510 
00511     for (it = _layout_element_list.rbegin(); it != _layout_element_list.rend(); it++)
00512     {
00513 
00514       if (found_child)
00515       {
00516         if ((*it)->CanFocus ())
00517         {
00518           (*it)->SetFocused (true);
00519           ChildFocusChanged (/*this,*/ (*it));
00520           return true;
00521         }
00522       }
00523 
00524       if ((*it) == child)
00525       {
00526         found_child = true;
00527       }
00528     }
00529 
00530     return false;
00531   }
00532 
00533 
00534   void Layout::SetFocusControl (bool focus_control)
00535   {
00536     _has_focus_control = focus_control;
00537   }
00538 
00539   bool Layout::HasFocusControl ()
00540   {
00541     return _has_focus_control;
00542   }
00543 
00544 
00545   long Layout::SendEventToArea (Area *area, IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
00546   {
00547     // if parent is null return, thats a valid usecase so no warnings.
00548     if (area == NULL)
00549     {
00550       return 0;
00551     }
00552 
00553     long ret = 0;
00554     if ( area->IsView() )
00555     {
00556       View *ic = NUX_STATIC_CAST (View *, area );
00557       ret = ic->ProcessFocusEvent (ievent, ret, ProcessEventInfo);
00558     }
00559     else if ( area->IsLayout() )
00560     {
00561       Layout *layout = NUX_STATIC_CAST (Layout *, area );
00562       layout->SetFocusControl (true);
00563       SetFocusControl (false);
00564       ret = layout->ProcessFocusEvent (ievent, ret, ProcessEventInfo);
00565     }
00566 
00567     return ret;
00568   }
00569 
00570   Area* Layout::GetFocusedChild ()
00571   {
00572     std::list<Area *>::iterator it;
00573     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00574     {
00575       if ((*it)->GetFocused ())
00576       {
00577         return (*it);
00578       }
00579     }
00580 
00581     return NULL;
00582   }
00583 
00584   long Layout::DoFocusPrev (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
00585   {
00586     Area *focused_child = GetFocusedChild ();
00587     if (focused_child == NULL) return ProcessEventInfo;
00588     bool success = FocusPreviousChild (focused_child);
00589     //focused_child->SetFocused (false);
00590 
00591     if (success == false)
00592     {
00593       Area *parent = GetParentObject ();
00594       if (parent != NULL)
00595         return SendEventToArea (parent, ievent, TraverseInfo, ProcessEventInfo);
00596       else
00597         FocusFirstChild ();
00598     }
00599 
00600     return ProcessEventInfo;
00601   }
00602 
00603   long Layout::DoFocusNext (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
00604   {
00605     Area *focused_child = GetFocusedChild ();
00606     if (focused_child == NULL) return ProcessEventInfo;
00607     bool success = FocusNextChild(focused_child);
00608     //focused_child->SetFocused (false);
00609 
00610     if (success == false)
00611     {
00612       Area *parent = GetParentObject ();
00613       if (parent != NULL)
00614         return SendEventToArea (parent, ievent, TraverseInfo, ProcessEventInfo);
00615       else
00616         FocusFirstChild ();
00617     }
00618 
00619     return ProcessEventInfo;
00620   }
00621 
00622   long Layout::DoFocusUp (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
00623   {
00624     return DoFocusPrev (ievent, TraverseInfo, ProcessEventInfo);
00625   }
00626   long Layout::DoFocusDown (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
00627   {
00628     return DoFocusNext (ievent, TraverseInfo, ProcessEventInfo);
00629   }
00630   long Layout::DoFocusLeft (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
00631   {
00632     return DoFocusPrev (ievent, TraverseInfo, ProcessEventInfo);
00633   }
00634   long Layout::DoFocusRight (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
00635   {
00636     return DoFocusNext (ievent, TraverseInfo, ProcessEventInfo);
00637   }
00638 
00639 
00640   long Layout::ProcessFocusEvent (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
00641   {
00642     long ret = TraverseInfo;
00643 
00644 
00645     if (GetFocused () && (ievent.e_event == NUX_KEYDOWN))
00646     {
00647       Area *focused_child = NULL;
00648       Area *parent = GetParentObject ();
00649       FocusDirection direction;
00650       FocusEventType type;
00651 
00652       direction = FOCUS_DIRECTION_NONE;
00653 
00654       type = Focusable::GetFocusableEventType (ievent.e_event,
00655                                                ievent.GetKeySym(),
00656                                                ievent.GetText(),
00657                                                &direction);
00658 
00659       if ((type == FOCUS_EVENT_DIRECTION) && (direction != FOCUS_DIRECTION_NONE))
00660       {
00661         focused_child = GetFocusedChild ();
00662 
00663         /* if nothing is focused, focus the first child else send the event to the parent */
00664 
00665         if (focused_child == NULL)
00666         {
00667           bool have_focused_child = FocusFirstChild ();
00668           if (have_focused_child == false)
00669           {
00670             /* propagate up */
00671             if ((parent != NULL) && parent->IsLayout ())
00672             {
00673               ret |= SendEventToArea (parent, ievent, ret, ProcessEventInfo);
00674             }
00675             else
00676             {
00677               FocusFirstChild ();
00678             }
00679           }
00680         }
00681         else // we have a focused child
00682         {
00683           // if the focused child is the last/first handle next/prev for those
00684           if (direction == FOCUS_DIRECTION_PREV)
00685           {
00686             if (focused_child == _layout_element_list.front ())
00687             {
00688               if (parent != NULL)
00689               {
00690                 ret |= SendEventToArea (parent, ievent, ret, ProcessEventInfo);
00691               }
00692               else
00693               {
00694                 FocusLastChild ();
00695               }
00696               return ret;
00697             }
00698           }
00699           else if (direction == FOCUS_DIRECTION_NEXT)
00700           {
00701             if (focused_child == _layout_element_list.back ())
00702             {
00703               if (parent != NULL)
00704               {
00705                 ret |= SendEventToArea (parent, ievent, ret, ProcessEventInfo);
00706               }
00707               else
00708               {
00709                 FocusFirstChild ();
00710               }
00711               return ret;
00712             }
00713           }
00714 
00715           switch (direction)
00716           {
00717             case FOCUS_DIRECTION_NEXT:
00718               ret |= DoFocusNext (ievent, ret, ProcessEventInfo);
00719               break;
00720             case FOCUS_DIRECTION_PREV:
00721               ret |= DoFocusPrev (ievent, ret, ProcessEventInfo);
00722               break;
00723             case FOCUS_DIRECTION_UP:
00724               ret |= DoFocusUp (ievent, ret, ProcessEventInfo);
00725               break;
00726             case FOCUS_DIRECTION_DOWN:
00727               ret |= DoFocusDown (ievent, ret, ProcessEventInfo);
00728               break;
00729             case FOCUS_DIRECTION_LEFT:
00730               ret |= DoFocusLeft (ievent, ret, ProcessEventInfo);
00731               break;
00732             case FOCUS_DIRECTION_RIGHT:
00733               ret |= DoFocusRight (ievent, ret, ProcessEventInfo);
00734               break;
00735             default:
00736               break;
00737           }
00738 
00739           return ret;
00740         }
00741       }
00742 
00743       if (type == FOCUS_EVENT_ACTIVATE)
00744       {
00745         ActivateFocus ();
00746       }
00747     }
00748 
00749     return ret;
00750   }
00751 
00752   Area* Layout::FindAreaUnderMouse(const Point& mouse_position, NuxEventType event_type)
00753   {
00754     bool mouse_inside = TestMousePointerInclusionFilterMouseWheel(mouse_position, event_type);
00755 
00756     if(mouse_inside == false)
00757       return NULL;
00758 
00759     std::list<Area *>::iterator it;
00760     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00761     {
00762       if ((*it)->IsVisible() && (*it)->IsSensitive())
00763       {
00764         Area* hit_view = NUX_STATIC_CAST(Area*, (*it)->FindAreaUnderMouse(mouse_position, event_type));
00765         if(hit_view)
00766           return hit_view;
00767       }
00768     }
00769 
00770     return NULL;
00771   }
00772 
00773   void Layout::ProcessDraw (GraphicsEngine &GfxContext, bool force_draw)
00774   {
00775     std::list<Area *>::iterator it;
00776     GfxContext.PushModelViewMatrix (Get2DMatrix ());
00777     GfxContext.PushClippingRectangle (GetGeometry ());
00778 
00779     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00780     {
00781       if (!(*it)->IsVisible ())
00782         continue;
00783 
00784       if ((*it)->IsView ())
00785       {
00786         View *ic = NUX_STATIC_CAST (View*, (*it));
00787         ic->ProcessDraw (GfxContext, force_draw);
00788       }
00789       else if ((*it)->IsLayout ())
00790       {
00791         Layout *layout = NUX_STATIC_CAST (Layout*, (*it));
00792         layout->ProcessDraw (GfxContext, force_draw);
00793       }
00794       // InputArea should be tested last
00795       else if ((*it)->IsInputArea ())
00796       {
00797         InputArea *input_area = NUX_STATIC_CAST (InputArea*, (*it));
00798         input_area->OnDraw (GfxContext, force_draw);
00799       }
00800     }
00801 
00802     GfxContext.PopClippingRectangle ();
00803     GfxContext.PopModelViewMatrix ();
00804 
00805     //GfxContext.PopClipOffset ();
00806 
00807     _queued_draw = false;
00808   }
00809 
00810   void Layout::QueueDraw ()
00811   {
00812     if (_queued_draw)
00813     {
00814       // A draw has already been scheduled.
00815       return;
00816     }
00817 
00818     std::list<Area *>::iterator it;
00819 
00820     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00821     {
00822       if ((*it)->IsView ())
00823       {
00824         View *ic = NUX_STATIC_CAST (View *, (*it));
00825         ic->QueueDraw ();
00826       }
00827       else if ((*it)->IsLayout ())
00828       {
00829         Layout *layout = NUX_STATIC_CAST (Layout *, (*it));
00830         layout->QueueDraw ();
00831       }
00832     }
00833 
00834     _queued_draw = true;
00835     OnQueueDraw.emit (this);
00836   }
00837 
00838   bool Layout::IsQueuedForDraw ()
00839   {
00840     return _queued_draw;
00841   }
00842 
00843   void Layout::SetContentDistribution (LayoutContentDistribution stacking)
00844   {
00845     m_ContentStacking = stacking;
00846   }
00847 
00848   LayoutContentDistribution Layout::GetContentDistribution()
00849   {
00850     return m_ContentStacking;
00851   }
00852 
00853   void Layout::RequestBottomUpLayoutComputation (Area *bo_initiator)
00854   {
00855 
00856   }
00857 
00858   void Layout::ChildViewQueuedDraw (View *view)
00859   {
00860     OnChildQueueDraw.emit (view);
00861   }
00862 
00863   void Layout::ChildLayoutQueuedDraw (Layout *layout)
00864   {
00865     OnChildQueueDraw.emit (layout);
00866   }
00867 
00868   void Layout::ChildLayoutChildQueuedDraw (Area *area)
00869   {
00870     OnChildQueueDraw.emit (area);
00871   }
00872 
00873   /* Focusable Code */
00874   bool Layout::DoGetFocused ()
00875   {
00876     bool focused = false;
00877 
00878     std::list<Area *>::iterator it;
00879     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00880     {
00881       if ((*it)->GetFocused ())
00882         focused = true;
00883     }
00884 
00885     return focused;
00886   }
00887 
00888   void Layout::DoSetFocused (bool focused)
00889   {
00890     _is_focused = focused;
00891     if (focused == GetFocused ())
00892       return;
00893 
00894     if (focused == false)
00895     {
00896       std::list<Area *>::iterator it;
00897 
00898       for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00899       {
00900         if ((*it)->GetFocused ())
00901         {
00902           if ( (*it)->IsArea() )
00903           {
00904             CoreArea *area = NUX_STATIC_CAST (CoreArea *, (*it) );
00905             area->SetFocused (false);
00906           }
00907           else if ( (*it)->IsView() )
00908           {
00909             View *ic = NUX_STATIC_CAST (View *, (*it) );
00910             ic->SetFocused (false);
00911           }
00912           else if ( (*it)->IsLayout() )
00913           {
00914             Layout *layout = NUX_STATIC_CAST (Layout *, (*it) );
00915             layout->SetFocused (false);
00916           }
00917         }
00918 
00919       }
00920     }
00921     else
00922     {
00923       SetFocusControl (true);
00924 
00925       if (GetFocused () == false)
00926       {
00927         FocusFirstChild ();
00928         _ignore_focus = true;
00929       }
00930 
00931       // we need to chain up
00932       Area *_parent = GetParentObject();
00933       if (_parent == NULL)
00934       {
00935         return;
00936       }
00937 
00938       if (_parent->IsView ())
00939       {
00940         View *parent = (View*)_parent;
00941         if (parent->GetFocused () == false && parent->HasPassiveFocus () == false)
00942         {
00943           parent->SetFocused (true);
00944         }
00945         parent->SetFocusControl (false);
00946       }
00947       else if (_parent->IsLayout ())
00948       {
00949         Layout *parent = (Layout *)_parent;
00950         parent->SetFocusControl (false);
00951       }
00952 
00953     }
00954   }
00955 
00956   bool Layout::DoCanFocus ()
00957   {
00958     std::list<Area *>::iterator it;
00959     if (_layout_element_list.empty ())
00960       return false;
00961 
00962     for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
00963     {
00964       bool can_focus = false;
00965       if ( (*it)->IsArea() )
00966       {
00967         CoreArea *area = NUX_STATIC_CAST (CoreArea *, (*it) );
00968         can_focus = area->CanFocus ();
00969       }
00970       else if ( (*it)->IsView() )
00971       {
00972         View *ic = NUX_STATIC_CAST (View *, (*it) );
00973         can_focus = ic->CanFocus ();
00974       }
00975       else if ( (*it)->IsLayout() )
00976       {
00977         Layout *layout = NUX_STATIC_CAST (Layout *, (*it) );
00978         can_focus = layout->CanFocus ();
00979       }
00980 
00981       if (can_focus == true)
00982         return true;
00983     }
00984 
00985     return false;
00986   }
00987 
00988   bool Layout::AcceptKeyNavFocus()
00989   {
00990     return false;
00991   }
00992 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends