nux-1.16.0
VSplitter.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 "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 t_s32 VSPLITTERWIDTH = 5;
00037   static const t_s32 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 &GfxContext, bool force_draw)
00080   {
00081     Geometry base = GetGeometry();
00082     GfxContext.PushClippingRectangle (base);
00083     std::vector<Area *>::iterator it;
00084 
00085     GetPainter().PaintBackground (GfxContext, 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       t_s32 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 (GfxContext, grip_geo.x + 1, grip_geo.y, grip_geo.x + 1, grip_geo.y + grip_geo.GetHeight(), Color (0xFF111111) );
00110       GetPainter().Draw2DLine (GfxContext, grip_geo.x + 3, grip_geo.y, grip_geo.x + 3, grip_geo.y + grip_geo.GetHeight(), Color (0xFF111111) );
00111     }
00112 
00113     GfxContext.PopClippingRectangle();
00114   }
00115 
00116   void VSplitter::DrawContent (GraphicsEngine &GfxContext, bool force_draw)
00117   {
00118     GfxContext.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       GfxContext.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 (GfxContext, true);
00141         }
00142         else if ( (*it)->Type().IsObjectType (InputArea::StaticObjectType) )
00143         {
00144           InputArea *base_area = NUX_STATIC_CAST (InputArea *, (*it) );
00145           base_area->OnDraw (GfxContext, true);
00146         }
00147         else if ( (*it)->Type().IsObjectType (HLayout::StaticObjectType) )
00148         {
00149           HLayout *layout = NUX_STATIC_CAST (HLayout *, (*it) );
00150           layout->ProcessDraw (GfxContext, true);
00151         }
00152         else if ( (*it)->Type().IsObjectType (VLayout::StaticObjectType) )
00153         {
00154           VLayout *layout = NUX_STATIC_CAST (VLayout *, (*it) );
00155           layout->ProcessDraw (GfxContext, 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 (GfxContext, false);
00164         }
00165         else if ( (*it)->Type().IsObjectType (InputArea::StaticObjectType) )
00166         {
00167           InputArea *base_area = NUX_STATIC_CAST (InputArea *, (*it) );
00168           base_area->OnDraw (GfxContext, false);
00169         }
00170         else if ( (*it)->Type().IsObjectType (HLayout::StaticObjectType) )
00171         {
00172           HLayout *layout = NUX_STATIC_CAST (HLayout *, (*it) );
00173           layout->ProcessDraw (GfxContext, false);
00174         }
00175         else if ( (*it)->Type().IsObjectType (VLayout::StaticObjectType) )
00176         {
00177           VLayout *layout = NUX_STATIC_CAST (VLayout *, (*it) );
00178           layout->ProcessDraw (GfxContext, false);
00179         }
00180       }
00181 
00182       GfxContext.PopClippingRectangle();
00183     }
00184 
00185     GfxContext.PopClippingRectangle();
00186   }
00187 
00188   void VSplitter::PostDraw (GraphicsEngine &GfxContext, bool force_draw)
00189   {
00190 
00191   }
00192 
00193   void VSplitter::OverlayDrawing (GraphicsEngine &GfxContext)
00194   {
00195     t_u32 num_element = (t_u32) 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 < (t_s32) 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       GfxContext.GetRenderStates().SetBlend (true, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00231       {
00232         GetPainter().Paint2DQuadColor (GfxContext, geo, Color (0xBB868686) );
00233       }
00234       GfxContext.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       t_u32 no = (t_u32) 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       ComputeChildLayout();
00258     }
00259   }
00260 
00261   void VSplitter::clearContent()
00262   {
00263     m_InterfaceObject.clear();
00264   }
00265 
00266   long VSplitter::ComputeChildLayout()
00267   {
00268     t_u32 num_element = (t_u32) m_InterfaceObject.size();
00269     t_s32 x = GetBaseX();
00270     t_s32 y = GetBaseY();
00271     t_s32 w = GetBaseWidth();
00272     t_s32 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 (t_u32 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       t_s32 size_to_distribute = w - num_element * VSPLITTERWIDTH;
00314       t_s32 previous_spliter_end = m_current_x;
00315       t_s32 new_spliter_end = x;
00316 
00317       for (t_u32 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         t_s32 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     t_s32 accwidth = x;
00343 
00344     for (t_u32 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     t_s32 x = GetBaseX();
00386     t_s32 y = GetBaseY();
00387     t_s32 w = GetBaseWidth();
00388     t_s32 h = GetBaseHeight();
00389     t_u32 num_element = (t_u32) 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 (t_u32 i = 0; i < (t_u32) 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 (t_u32 i = 0; i < (t_u32) m_SplitConfig.size(); i++)
00412     {
00413       stretchfactor = m_SplitConfig[i];
00414       total += stretchfactor / max_stretch;
00415     }
00416 
00417     t_s32 availableheight = (w - num_element * VSPLITTERWIDTH);
00418     float max_size = float (availableheight) / total;
00419 
00420     for (t_u32 i = 0; i < (t_u32) 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 (t_s32 x, t_s32 y, unsigned long button_flags, unsigned long key_flags, t_s32 header_pos)
00434   {
00435     m_point = Point(x, y);
00436 
00437     m_focus_splitter_index = header_pos;
00438     GetWindowCompositor().SetWidgetDrawingOverlay (this, GetWindowCompositor().GetProcessingTopView() );
00439 
00440     // Hint for the window to initiate a redraw
00441     GetWindowThread ()->RequestRedraw();
00442   }
00443 
00444   void VSplitter::OnSplitterMouseUp (t_s32 x, t_s32 y, unsigned long button_flags, unsigned long key_flags, t_s32 header_pos)
00445   {
00446     if (mvt_dx)
00447     {
00448       Geometry geo = m_SplitterObject[header_pos]->GetGeometry();
00449       geo.OffsetPosition (mvt_dx, 0);
00450 
00451       t_u32 num_element = (t_u32) m_SplitterObject.size();
00452 
00453       if (header_pos < (t_s32) 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     GetWindowCompositor().SetWidgetDrawingOverlay (0, GetWindowCompositor().GetProcessingTopView() );
00470     // Hint for the window to initiate a redraw
00471     GetWindowThread ()->RequestRedraw();
00472   }
00473 
00474   void VSplitter::OnSplitterMouseDrag (t_s32 x, t_s32 y, t_s32 dx, t_s32 dy, unsigned long button_flags, unsigned long key_flags, t_s32 header_pos)
00475   {
00476     Geometry geo = m_SplitterObject[header_pos]->GetGeometry();
00477     t_s32 num_element = (t_s32) 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 (t_s32 header_pos)
00505   {
00506     Geometry geo = m_SplitterObject[header_pos]->GetGeometry();
00507     t_s32 num_element = (t_s32) 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 < (t_s32) num_element - 1)
00520     {
00521       t_s32 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       t_s32 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     ComputeChildLayout();
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 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends