Back to index

nux  3.0.0
HSplitter.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 "HSplitter.h"
00025 
00026 #include "NuxGraphics/GLTextureResourceManager.h"
00027 
00028 #include "WindowCompositor.h"
00029 #include "Layout.h"
00030 #include "HLayout.h"
00031 #include "VLayout.h"
00032 
00033 namespace nux
00034 {
00035 
00036   NUX_IMPLEMENT_OBJECT_TYPE(HSplitter);
00037   static const int HSPLITTERHEIGHT = 5;
00038   static const int HSTICK_SIZE = 5;
00039 
00040   HSplitter::HSplitter(NUX_FILE_LINE_DECL)
00041     :   View(NUX_FILE_LINE_PARAM)
00042   {
00043     new_addition                = false;
00044     m_initial_config            = true;
00045     m_focus_splitter_index      = -1;
00046     m_ResizeOnSplitterRelease   = true;
00047 
00048     mvt_dx = 0;
00049     mvt_dy = 0;
00050     m_current_x = 0;
00051     m_current_y = 0;
00052     m_current_width = 200;
00053     m_current_height = 200;
00054 
00055     //SetMinimumSize(200,200);
00056     SetGeometry(Geometry(m_current_x, m_current_y, m_current_width, m_current_height));
00057   }
00058 
00059   HSplitter::~HSplitter()
00060   {
00061     std::vector< Area* >::iterator it0;
00062     for (it0 = m_InterfaceObject.begin(); it0 != m_InterfaceObject.end(); it0++)
00063     {
00064       (*it0)->UnParentObject();
00065     }
00066     m_InterfaceObject.clear();
00067 
00068     std::vector< MySplitter* >::iterator it2;
00069     for (it2 = m_SplitterObject.begin(); it2 != m_SplitterObject.end(); it2++)
00070     {
00071       (*it2)->UnParentObject();
00072     }
00073     m_SplitterObject.clear();
00074 
00075     m_SplitConfig.clear();
00076   }
00077 
00078   void HSplitter::Draw(GraphicsEngine &graphics_engine, bool force_draw)
00079   {
00080     graphics_engine.PushClippingRectangle(GetGeometry());
00081     Geometry base = GetGeometry();
00082 //    std::vector<View*>::iterator it;
00083 //    for (it = m_InterfaceObject.begin(); it != m_InterfaceObject.end(); it++)
00084 //    {
00085 //        (*it)->ProcessDraw(force_draw);
00086 //    }
00087 
00088     GetPainter().PaintBackground(graphics_engine, base);
00089     std::vector<MySplitter *>::iterator it_splitter;
00090 
00091     for (it_splitter = m_SplitterObject.begin(); it_splitter != m_SplitterObject.end(); it_splitter++)
00092     {
00093       Geometry geo = (*it_splitter)->GetGeometry();
00094       Geometry grip_geo;
00095       int w = 20;
00096 
00097       if (geo.GetWidth() > w)
00098       {
00099         grip_geo.SetX(geo.x + (geo.GetWidth() - w) / 2);
00100         grip_geo.SetY(geo.y);
00101         grip_geo.SetWidth(w);
00102         grip_geo.SetHeight(geo.GetHeight());
00103       }
00104       else
00105       {
00106         grip_geo.SetX(geo.x - (w - geo.GetWidth()) / 2);
00107         grip_geo.SetY(geo.y);
00108         grip_geo.SetWidth(w);
00109         grip_geo.SetHeight(geo.GetHeight());
00110       }
00111 
00112       GetPainter().Draw2DLine(graphics_engine, grip_geo.x, grip_geo.y + 1, grip_geo.x + grip_geo.GetWidth(), grip_geo.y + 1, Color(0xFF111111));
00113       GetPainter().Draw2DLine(graphics_engine, grip_geo.x, grip_geo.y + 3, grip_geo.x + grip_geo.GetWidth(), grip_geo.y + 3, Color(0xFF111111));
00114     }
00115 
00116     graphics_engine.PopClippingRectangle();
00117   }
00118 
00119   void HSplitter::DrawContent(GraphicsEngine &graphics_engine, bool force_draw)
00120   {
00121     Geometry base = GetGeometry();
00122     graphics_engine.PushClippingRectangle(base);
00123     bool need_redraw = IsRedrawNeeded();
00124 
00125     std::vector<MySplitter *>::iterator it_splitter;
00126     std::vector<Area *>::iterator it;
00127 
00128     //for(it = m_InterfaceObject.begin(); it != m_InterfaceObject.end(); it++)
00129     for (it = m_InterfaceObject.begin(), it_splitter = m_SplitterObject.begin();
00130          it != m_InterfaceObject.end();
00131          it++, it_splitter++)
00132     {
00133       Geometry sgeo = (*it_splitter)->GetGeometry();
00134       graphics_engine.PushClippingRectangle(Rect(
00135                                           base.x, base.y, base.GetWidth(), sgeo.y - base.y));
00136 
00137       base.SetY(sgeo.y + sgeo.GetHeight());
00138 
00139       if (force_draw || need_redraw)
00140       {
00141         if ((*it)->Type().IsDerivedFromType(View::StaticObjectType))
00142         {
00143           View *ic = static_cast<View *>(*it);
00144           ic->ProcessDraw(graphics_engine, true);
00145         }
00146         else if ((*it)->Type().IsObjectType(InputArea::StaticObjectType))
00147         {
00148           InputArea *base_area = static_cast<InputArea *>(*it);
00149           base_area->OnDraw(graphics_engine, true);
00150         }
00151         else if ((*it)->Type().IsObjectType(HLayout::StaticObjectType))
00152         {
00153           HLayout *layout = static_cast<HLayout *>(*it);
00154           layout->ProcessDraw(graphics_engine, true);
00155         }
00156         else if ((*it)->Type().IsObjectType(VLayout::StaticObjectType))
00157         {
00158           VLayout *layout = static_cast<VLayout *>(*it);
00159           layout->ProcessDraw(graphics_engine, true);
00160         }
00161       }
00162       else
00163       {
00164         if ((*it)->Type().IsDerivedFromType(View::StaticObjectType))
00165         {
00166           View *ic = static_cast<View *>(*it);
00167           ic->ProcessDraw(graphics_engine, false);
00168         }
00169         else if ((*it)->Type().IsObjectType(InputArea::StaticObjectType))
00170         {
00171           InputArea *base_area = static_cast<InputArea *>(*it);
00172           base_area->OnDraw(graphics_engine, false);
00173         }
00174         else if ((*it)->Type().IsObjectType(HLayout::StaticObjectType))
00175         {
00176           HLayout *layout = static_cast<HLayout *>(*it);
00177           layout->ProcessDraw(graphics_engine, false);
00178         }
00179         else if ((*it)->Type().IsObjectType(VLayout::StaticObjectType))
00180         {
00181           VLayout *layout = static_cast<VLayout *>(*it);
00182           layout->ProcessDraw(graphics_engine, false);
00183         }
00184       }
00185 
00186       graphics_engine.PopClippingRectangle();
00187     }
00188 
00189     graphics_engine.PopClippingRectangle();
00190   }
00191 
00192   void HSplitter::PostDraw(GraphicsEngine &graphics_engine, bool force_draw)
00193   {
00194 
00195   }
00196 
00197   void HSplitter::OverlayDrawing(GraphicsEngine &graphics_engine)
00198   {
00199     unsigned int num_element = (unsigned int) m_SplitterObject.size();
00200 
00201     Geometry base = GetGeometry();
00202 
00203     if (m_focus_splitter_index >= 0)
00204     {
00205       Geometry geo = m_SplitterObject[m_focus_splitter_index]->GetGeometry();
00206       geo.OffsetPosition(mvt_dx, mvt_dy);
00207 
00208       if (m_focus_splitter_index == 0 && num_element > 1)
00209       {
00210         if (geo.y < base.y)
00211         {
00212           geo.SetY(base.y);
00213         }
00214 
00215         if (geo.y  + HSPLITTERHEIGHT > m_SplitterObject[m_focus_splitter_index + 1]->GetGeometry().y)
00216         {
00217           geo.SetY(m_SplitterObject[m_focus_splitter_index+1]->GetGeometry().y - HSPLITTERHEIGHT);
00218         }
00219       }
00220 
00221       if ((m_focus_splitter_index > 0) && (m_focus_splitter_index < (int) num_element - 1))
00222       {
00223         if (geo.y < m_SplitterObject[m_focus_splitter_index - 1]->GetGeometry().y + HSPLITTERHEIGHT)
00224         {
00225           geo.SetY(m_SplitterObject[m_focus_splitter_index - 1]->GetGeometry().y + HSPLITTERHEIGHT);
00226         }
00227 
00228         if (geo.y + HSPLITTERHEIGHT > m_SplitterObject[m_focus_splitter_index + 1]->GetGeometry().y)
00229         {
00230           geo.SetY(m_SplitterObject[m_focus_splitter_index + 1]->GetGeometry().y - HSPLITTERHEIGHT);
00231         }
00232       }
00233 
00234       graphics_engine.GetRenderStates().SetBlend(true, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00235       {
00236         GetPainter().Paint2DQuadColor(graphics_engine, geo, Color(0xBB868686));
00237       }
00238       graphics_engine.GetRenderStates().SetBlend(false);
00239     }
00240   }
00241 
00242   void HSplitter::AddWidget(Area *ic, float stretchfactor)
00243   {
00244     if (ic)
00245     {
00246       MySplitter *splitter = new MySplitter;
00247       splitter->SetParentObject(this);
00248       //splitter->SinkReference();
00249 
00250       unsigned int no = (unsigned int) m_InterfaceObject.size();
00251       splitter->mouse_down.connect(sigc::bind(sigc::mem_fun(this, &HSplitter::OnSplitterMouseDown), no));
00252       splitter->mouse_drag.connect(sigc::bind(sigc::mem_fun(this, &HSplitter::OnSplitterMouseDrag), no));
00253       splitter->mouse_up.connect(sigc::bind(sigc::mem_fun(this, &HSplitter::OnSplitterMouseUp), no));
00254 
00255       ic->SetParentObject(this);
00256       m_InterfaceObject.push_back(ic);
00257       m_SplitterObject.push_back(splitter);
00258       m_SplitConfig.push_back(stretchfactor);
00259 
00260       new_addition = true;
00261       ComputeContentSize();
00262     }
00263   }
00264 
00265   void HSplitter::clearContent()
00266   {
00267     m_InterfaceObject.clear();
00268   }
00269 
00270   long HSplitter::ComputeContentSize()
00271   {
00272     unsigned int num_element = (unsigned int) m_InterfaceObject.size();
00273     int x = GetBaseX();
00274     int y = GetBaseY();
00275     int w = GetBaseWidth();
00276     int h = GetBaseHeight();
00277 
00278     if ((w == 0) || (h == 0))
00279     {
00280       return eCompliantHeight | eCompliantWidth;
00281     }
00282 
00283     if (num_element < 1)
00284     {
00285       m_current_height = h;
00286       m_current_width = w;
00287       m_current_x = x;
00288       m_current_y = y;
00289 
00290       new_addition = false;
00291       return eCompliantHeight | eCompliantWidth;
00292     }
00293 
00294     std::vector<Area *>::iterator it;
00295     std::vector<MySplitter *>::iterator it_splitter;
00296 
00297     if (new_addition)
00298     {
00299       ResetSplitConfig();
00300       new_addition = false;
00301     }
00302 
00303     if (m_current_width != w)
00304     {
00305       for (unsigned int i = 0; i < num_element; i++)
00306       {
00307         Geometry splitter_geo = m_SplitterObject[i]->GetGeometry();
00308         splitter_geo.SetWidth(w);
00309         splitter_geo.SetX(x);
00310 
00311         m_SplitterObject[i]->SetGeometry(splitter_geo);
00312       }
00313     }
00314 
00315     if (m_current_height != h)
00316     {
00317       int size_to_distribute = h - num_element * HSPLITTERHEIGHT;
00318       int previous_spliter_end = m_current_y;
00319       int new_spliter_end = y;
00320 
00321       for (unsigned int i = 0; i < num_element; i++)
00322       {
00323         Geometry splitter_geo = m_SplitterObject[i]->GetGeometry();
00324         // compute percentage of space occupied by the element i;
00325         // width of element i = m_SplitterObject[i]->GetY() - previous_splliter_end
00326         int splitter_start = m_SplitterObject[i]->GetBaseY();
00327         float percent = float(splitter_start - previous_spliter_end) / float(m_current_height - num_element * HSPLITTERHEIGHT);
00328 
00329         if (percent > 1.0f)
00330           percent = 1.0f;
00331 
00332         splitter_geo.SetY(new_spliter_end + size_to_distribute * percent);
00333         previous_spliter_end = splitter_start + HSPLITTERHEIGHT;
00334         new_spliter_end = new_spliter_end + size_to_distribute * percent + HSPLITTERHEIGHT;
00335         m_SplitterObject[i]->SetGeometry(splitter_geo);
00336       }
00337 
00338       if (m_SplitterObject[0]->GetBaseY() < y)
00339       {
00340         m_SplitterObject[0]->SetBaseY(y);
00341       }
00342 
00343       m_SplitterObject[num_element-1]->SetBaseY(y + h - HSPLITTERHEIGHT);
00344     }
00345 
00346     int accheight = y;
00347 
00348     for (unsigned int i = 0; i < num_element; i++)
00349     {
00350       Geometry splitter_geo = m_SplitterObject[i]->GetGeometry();
00351 
00352       //m_InterfaceObject[i]->SetGeometry(Geometry(x, accheight, w, splitter_geo.y - accheight));
00353 
00354       if (m_InterfaceObject[i]->Type().IsDerivedFromType(View::StaticObjectType))
00355       {
00356         View *ic = static_cast<View *>(m_InterfaceObject[i]);
00357         ic->SetGeometry(Geometry(x, accheight, w, splitter_geo.y - accheight));
00358         // if we are already computing the layout from the main window down, we need to call
00359         // ComputeElementLayout to force the computing of this element layout.
00360         GetWindowThread()->ComputeElementLayout(ic);
00361       }
00362       else if (m_InterfaceObject[i]->Type().IsObjectType(InputArea::StaticObjectType))
00363       {
00364         InputArea *base_area = static_cast<InputArea *>(m_InterfaceObject[i]);
00365         base_area->SetGeometry(Geometry(x, accheight, w, splitter_geo.y - accheight));
00366       }
00367       else if (m_InterfaceObject[i]->Type().IsDerivedFromType(Layout::StaticObjectType))
00368       {
00369         Layout *layout = static_cast<Layout *>(m_InterfaceObject[i]);
00370         layout->SetGeometry(Geometry(x, accheight, w, splitter_geo.y - accheight));
00371         // if we are already computing the layout from the main window down, we need to call
00372         // ComputeElementLayout to force the computing of this element layout.
00373         GetWindowThread()->ComputeElementLayout(layout);
00374       }
00375 
00376       accheight += splitter_geo.y - accheight + HSPLITTERHEIGHT;
00377     }
00378 
00379     m_current_height = h;
00380     m_current_width = w;
00381     m_current_x = x;
00382     m_current_y = y;
00383 
00384     return eCompliantHeight | eCompliantWidth;
00385   }
00386 
00387   void HSplitter::ResetSplitConfig()
00388   {
00389 
00390     int x = GetBaseX();
00391     int y = GetBaseY();
00392     int w = GetBaseWidth();
00393     int h = GetBaseHeight();
00394     unsigned int num_element = (unsigned int) m_InterfaceObject.size();
00395 
00396     if (num_element < 1)
00397     {
00398       return;
00399     }
00400 
00401     float max_stretch = 0.0f;
00402     float stretchfactor;
00403 
00404     for (unsigned int i = 0; i < (unsigned int) m_SplitConfig.size(); i++)
00405     {
00406       stretchfactor = m_SplitConfig[i];
00407 
00408       if (max_stretch < stretchfactor)
00409       {
00410         max_stretch = stretchfactor;
00411       }
00412     }
00413 
00414     float total = 0;
00415 
00416     for (unsigned int i = 0; i < (unsigned int) m_SplitConfig.size(); i++)
00417     {
00418       stretchfactor = m_SplitConfig[i];
00419       total += stretchfactor / max_stretch;
00420     }
00421 
00422     int availableheight = (h - num_element * HSPLITTERHEIGHT);
00423     float max_size = float(availableheight) / total;
00424 
00425     for (unsigned int i = 0; i < (unsigned int) m_SplitConfig.size(); i++)
00426     {
00427       stretchfactor = m_SplitConfig[i];
00428       y += stretchfactor * max_size / max_stretch;
00429       Geometry geo(x, y, w, HSPLITTERHEIGHT);
00430       m_SplitterObject[i]->SetGeometry(geo);
00431     }
00432 
00433     m_SplitterObject[num_element-1]->SetBaseX(y + h - HSPLITTERHEIGHT);
00434 
00435     m_initial_config = true;
00436   }
00437 
00438   void HSplitter::OnSplitterMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags, int header_pos)
00439   {
00440     m_point = Point(x, y);
00441 
00442     m_focus_splitter_index = header_pos;
00443     GetWindowThread()->GetWindowCompositor().SetWidgetDrawingOverlay(this, GetWindowThread()->GetWindowCompositor().GetProcessingTopView());
00444 
00445 
00446     // Hint for the window to initiate a redraw
00447     GetWindowThread()->RequestRedraw();
00448   }
00449 
00450   void HSplitter::OnSplitterMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags, int header_pos)
00451   {
00452     if (mvt_dy)
00453     {
00454       Geometry geo = m_SplitterObject[header_pos]->GetGeometry();
00455       geo.OffsetPosition(0, mvt_dy);
00456 
00457       unsigned int num_element = (unsigned int) m_SplitterObject.size();
00458 
00459       if (header_pos < (int) num_element - 1)
00460       {
00461         // Make the splitter bar stick to the next one if the distance between them is less than HSTICK_SIZE.
00462         if (m_SplitterObject[header_pos + 1]->GetGeometry().y - geo.y - HSPLITTERHEIGHT < HSTICK_SIZE)
00463           geo.SetY( m_SplitterObject[header_pos + 1]->GetGeometry().y - HSPLITTERHEIGHT );
00464       }
00465 
00466       m_SplitterObject[header_pos]->SetGeometry(geo);
00467       ResizeSplitter(header_pos);
00468     }
00469 
00470     m_focus_splitter_index = -1;
00471     mvt_dx = 0;
00472     mvt_dy = 0;
00473 
00474     // End overlay drawing;
00475     GetWindowThread()->GetWindowCompositor().SetWidgetDrawingOverlay(0, GetWindowThread()->GetWindowCompositor().GetProcessingTopView());
00476     // Hint for the window to initiate a redraw
00477     GetWindowThread()->RequestRedraw();
00478   }
00479 
00480   void HSplitter::OnSplitterMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags, int header_pos)
00481   {
00482     Geometry geo = m_SplitterObject[header_pos]->GetGeometry();
00483     int num_element = (int) m_SplitterObject.size();
00484 
00485     if (header_pos == num_element - 1)
00486     {
00487       // The last splitter cannot be moved
00488       return;
00489     }
00490 
00491     mvt_dx = 0;
00492     mvt_dy = (y - m_point.y);
00493 
00494     if (m_ResizeOnSplitterRelease == false)
00495     {
00496       // Continuously redraw resize and redraw the 2 parts of the widget.
00497       // This is slow.
00498       geo.OffsetPosition(mvt_dx, mvt_dy);
00499       m_SplitterObject[header_pos]->SetGeometry(geo);
00500       ResizeSplitter(header_pos);
00501 
00502       mvt_dx = 0;
00503       mvt_dy = 0;
00504     }
00505 
00506     // Hint for the window to initiate a redraw
00507     GetWindowThread()->RequestRedraw();
00508   }
00509 
00510   void HSplitter::ResizeSplitter(int header_pos)
00511   {
00512     Geometry geo = m_SplitterObject[header_pos]->GetGeometry();
00513     int num_element = (int) m_SplitterObject.size();
00514 
00515     if ((header_pos == 0) && (m_SplitterObject[header_pos]->GetBaseY() < GetBaseY()))
00516     {
00517       m_SplitterObject[header_pos]->SetBaseY(GetBaseY());
00518     }
00519 
00520     if ((header_pos == num_element - 1) && (m_SplitterObject[header_pos]->GetBaseY() > GetBaseY() + GetBaseHeight() - HSPLITTERHEIGHT))
00521     {
00522       m_SplitterObject[header_pos]->SetBaseY(GetBaseY() + GetBaseHeight() - HSPLITTERHEIGHT);
00523     }
00524 
00525     if (header_pos < (int) num_element - 1)
00526     {
00527       int posy0, posy1;
00528       posy0 = m_SplitterObject[header_pos]->GetBaseY();
00529       posy1 = m_SplitterObject[header_pos + 1]->GetBaseY();
00530 
00531       if (posy0 > posy1 - HSPLITTERHEIGHT)
00532       {
00533         posy0 = posy1 - HSPLITTERHEIGHT;
00534         m_SplitterObject[header_pos]->SetBaseY(posy0);
00535       }
00536     }
00537 
00538     if (0 < header_pos)
00539     {
00540       int posy0, posy1;
00541       posy0 = m_SplitterObject[header_pos]->GetBaseY();
00542       posy1 = m_SplitterObject[header_pos - 1]->GetBaseY();
00543 
00544       if (posy0 < posy1 + HSPLITTERHEIGHT)
00545       {
00546         posy0 = posy1 + HSPLITTERHEIGHT;
00547         m_SplitterObject[header_pos]->SetBaseY(posy0);
00548       }
00549     }
00550 
00551     ComputeContentSize();
00552     QueueDraw();
00553   }
00554 
00555 // HSplitter need to re implement DoneRedraw because it does not
00556 // have a m_compositionlayout where its child are located;
00557   void HSplitter::DoneRedraw()
00558   {
00559     std::vector<Area *>::iterator it;
00560 
00561     for (it = m_InterfaceObject.begin(); it != m_InterfaceObject.end(); it++)
00562     {
00563       //(*it)->DoneRedraw();
00564       if ((*it)->Type().IsDerivedFromType(View::StaticObjectType))
00565       {
00566         View *ic = static_cast<View *>(*it);
00567         ic->DoneRedraw();
00568       }
00569 
00570       else if ((*it)->Type().IsObjectType(InputArea::StaticObjectType))
00571       {
00572         //InputArea* base_area = NUX_STATIC_CAST(InputArea*, (*it));
00573       }
00574     }
00575   }
00576 
00577   Area* HSplitter::FindAreaUnderMouse(const Point& mouse_position, NuxEventType event_type)
00578   {
00579     bool mouse_inside = TestMousePointerInclusionFilterMouseWheel(mouse_position, event_type);
00580 
00581     if (mouse_inside == false)
00582       return NULL;
00583 
00584     std::vector<MySplitter*>::iterator splitter_it;
00585     for (splitter_it = m_SplitterObject.begin(); splitter_it != m_SplitterObject.end(); splitter_it++)
00586     {
00587       Area* found_area = (*splitter_it)->FindAreaUnderMouse(mouse_position, event_type);
00588       if (found_area)
00589         return found_area;
00590     }
00591 
00592     std::vector<Area *>::iterator it;
00593     for (it = m_InterfaceObject.begin(); it != m_InterfaceObject.end(); it++)
00594     {
00595       Area* found_area = (*it)->FindAreaUnderMouse(mouse_position, event_type);
00596 
00597       if (found_area)
00598         return found_area;
00599     }
00600 
00601     if ((event_type == NUX_MOUSE_WHEEL) && (!AcceptMouseWheelEvent()))
00602       return NULL;
00603     return this;
00604   }
00605 
00606   bool HSplitter::AcceptKeyNavFocus()
00607   {
00608     return false;
00609   }
00610 
00611   Area* HSplitter::KeyNavIteration(KeyNavDirection direction)
00612   {
00613     if (m_InterfaceObject.size() == 0)
00614       return NULL;
00615 
00616     if (next_object_to_key_focus_area_)
00617     {
00618       if ((direction == KEY_NAV_LEFT) || (direction == KEY_NAV_RIGHT))
00619       {
00620         // Don't know what to do with this
00621         return NULL;
00622       }
00623       std::vector<Area*>::iterator it;
00624       std::vector<Area*>::iterator it_next;
00625       it = std::find(m_InterfaceObject.begin(), m_InterfaceObject.end(), next_object_to_key_focus_area_);
00626 
00627       if (it == m_InterfaceObject.end())
00628       {
00629         // Should never happen
00630         nuxAssert(0);
00631         return NULL;
00632       }
00633 
00634       it_next = it;
00635       ++it_next;
00636 
00637       if ((direction == KEY_NAV_UP) && (it == m_InterfaceObject.begin()))
00638       {
00639         // can't go further
00640         return NULL;
00641       }
00642 
00643       if ((direction == KEY_NAV_DOWN) && (it_next == m_InterfaceObject.end()))
00644       {
00645         // can't go further
00646         return NULL;
00647       }
00648 
00649       if ((direction == KEY_NAV_UP))
00650       {
00651         --it;
00652         Area* key_nav_focus = (*it)->KeyNavIteration(direction);
00653 
00654         while (key_nav_focus == NULL)
00655         {
00656           if (it == m_InterfaceObject.begin())
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_DOWN))
00667       {
00668         ++it;
00669         Area* key_nav_focus = (*it)->KeyNavIteration(direction);
00670 
00671         while (key_nav_focus == NULL)
00672         {
00673           ++it;
00674           if (it == m_InterfaceObject.end())
00675             break;
00676 
00677           key_nav_focus = (*it)->KeyNavIteration(direction);
00678         }
00679 
00680         return key_nav_focus;
00681       }
00682     }
00683     else
00684     {
00685       Area* key_nav_focus = NULL;
00686       if (direction == KEY_NAV_UP)
00687       {
00688         std::vector<Area*>::reverse_iterator it = m_InterfaceObject.rbegin();
00689         key_nav_focus = (*it)->KeyNavIteration(direction);
00690 
00691         while (key_nav_focus == NULL)
00692         {
00693           ++it;
00694           if (it == m_InterfaceObject.rend())
00695             break;
00696 
00697           key_nav_focus = (*it)->KeyNavIteration(direction);
00698         }
00699       }
00700       else
00701       {
00702         std::vector<Area*>::iterator it = m_InterfaceObject.begin();
00703         key_nav_focus = (*it)->KeyNavIteration(direction);
00704 
00705         while (key_nav_focus == NULL)
00706         {
00707           ++it;
00708           if (it == m_InterfaceObject.end())
00709             break;
00710 
00711           key_nav_focus = (*it)->KeyNavIteration(direction);
00712         }
00713       }
00714       return key_nav_focus;
00715     }
00716 
00717     return NULL;
00718   }
00719 }