Back to index

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