nux-1.16.0
ScrollView.cpp
00001 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
00002 /*
00003  * Copyright 2010-2011 Inalogic® Inc.
00004  *
00005  * This program is free software: you can redistribute it and/or modify it
00006  * under the terms of the GNU Lesser General Public License, as
00007  * published by the  Free Software Foundation; either version 2.1 or 3.0
00008  * of the License.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranties of
00012  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00013  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00014  * License for more details.
00015  *
00016  * You should have received a copy of both the GNU Lesser General Public
00017  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00018  *
00019  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00020  *
00021  */
00022 
00023 #include "Nux.h"
00024 #include "HScrollBar.h"
00025 #include "VScrollBar.h"
00026 #include "Layout.h"
00027 #include "HLayout.h"
00028 #include "VLayout.h"
00029 #include "ScrollView.h"
00030 
00031 namespace nux
00032 {
00033   NUX_IMPLEMENT_OBJECT_TYPE(ScrollView);
00034 
00035   ScrollView::ScrollView(NUX_FILE_LINE_DECL)
00036     : View(NUX_FILE_LINE_PARAM)
00037     , m_MouseWheelScrollSize(32)
00038       // TODO: these should really be Rects.
00039     , m_ViewContentX(0)
00040     , m_ViewContentY(0)
00041     , m_ViewContentWidth(0)
00042     , m_ViewContentHeight(0)
00043     , m_ViewX(0)
00044     , m_ViewY(0)
00045     , m_ViewWidth(0)
00046     , m_ViewHeight(0)
00047     , m_TextureIndex(0)
00048     , m_ReformatTexture(true)
00049     , m_horizontal_scrollbar_enable(true)
00050     , m_vertical_scrollbar_enable(true)
00051     , m_top_border(0)
00052     , m_border(0)
00053     , _delta_x(0)
00054     , _delta_y(0)
00055     , m_bSizeMatchContent(false)
00056     , m_ViewContentLeftMargin(0)
00057     , m_ViewContentRightMargin(0)
00058     , m_ViewContentTopMargin(0)
00059     , m_ViewContentBottomMargin(0)
00060   {
00061 
00062     //GetPainter().CreateBackgroundTexture(m_BackgroundTexture);
00063     _hscrollbar = new HScrollBar (NUX_TRACKER_LOCATION);
00064     _vscrollbar = new VScrollBar (NUX_TRACKER_LOCATION);
00065     // _hscrollbar and _vscrollbar have to be parented so they are correctly
00066     // rendered and so that GetRootGeometry/GetAbsoluteGeometry returns the
00067     // correct Geometry. This is necessary in embedded mode.
00068     _hscrollbar->SetParentObject (this);
00069     _vscrollbar->SetParentObject (this);
00070 
00071     _hscrollbar->SetReconfigureParentLayoutOnGeometryChange(false);
00072     _vscrollbar->SetReconfigureParentLayoutOnGeometryChange(false);
00073 
00074     SetMinimumSize (30, 30);
00075     SetGeometry (Geometry (0, 0, 400, 200) );
00076 
00077     _hscrollbar->OnScrollLeft.connect ( sigc::mem_fun (this, &ScrollView::ScrollLeft) );
00078     _hscrollbar->OnScrollRight.connect ( sigc::mem_fun (this, &ScrollView::ScrollRight) );
00079     _vscrollbar->OnScrollUp.connect ( sigc::mem_fun (this, &ScrollView::ScrollUp) );
00080     _vscrollbar->OnScrollDown.connect ( sigc::mem_fun (this, &ScrollView::ScrollDown) );
00081 
00082     mouse_wheel.connect(sigc::mem_fun(this, &ScrollView::RecvMouseWheel));
00083     _vscrollbar->mouse_wheel.connect(sigc::mem_fun(this, &ScrollView::RecvMouseWheel));
00084 
00085     FormatContent();
00086 
00087     //FIXME disabling until we have better API for this
00088     //ChildFocusChanged.connect (sigc::mem_fun (this, &ScrollView::OnChildFocusChanged));
00089 
00090     SetAcceptMouseWheelEvent(true);
00091   }
00092 
00093   // customization for Unity
00094   void ScrollView::SetVScrollBar (VScrollBar* newVScrollBar)
00095   {
00096     if(_vscrollbar)
00097     {
00098       // disconnect old _vscrollbar
00099       _vscrollbar->OnScrollUp.connect (sigc::mem_fun (this,
00100                                                      &ScrollView::ScrollUp));
00101       _vscrollbar->OnScrollDown.connect (sigc::mem_fun (this,
00102                                                        &ScrollView::ScrollDown));
00103       _vscrollbar->UnReference ();
00104     }
00105 
00106     _vscrollbar = newVScrollBar;
00107 
00108     _vscrollbar->SetParentObject (this);
00109     _vscrollbar->SetReconfigureParentLayoutOnGeometryChange(false);
00110 
00111     // connect new _vscrollbar
00112     _vscrollbar->OnScrollUp.connect (sigc::mem_fun (this,
00113                                                    &ScrollView::ScrollUp));
00114     _vscrollbar->OnScrollDown.connect (sigc::mem_fun (this,
00115                                                      &ScrollView::ScrollDown));
00116   }
00117 
00118   ScrollView::~ScrollView()
00119   {
00120     // Delete all the interface object: This is a problem... The widget should be destroy by there associated parameters
00121     _hscrollbar->UnReference ();
00122     _vscrollbar->UnReference ();
00123   }
00124 
00125   void ScrollView::OnChildFocusChanged (/*Area *parent,*/ Area *child)
00126   {
00127     if (child->IsView ())
00128     {
00129       View *view = (View*)child;
00130       if (view->HasPassiveFocus ())
00131       {
00132         return;
00133       }
00134     }
00135     if (child->IsLayout ())
00136       return;
00137 
00138     int child_y = child->GetGeometry ().y - GetGeometry ().y;
00139     int child_y_diff = child_y - abs (_delta_y);
00140 
00141 
00142     if (child_y_diff + child->GetGeometry ().height < GetGeometry ().height && child_y_diff >= 0)
00143     {
00144       return;
00145     }
00146 
00147     if (child_y_diff < 0)
00148     {
00149       ScrollUp (1, abs (child_y_diff));
00150     }
00151     else
00152     {
00153       int size = child_y_diff - GetGeometry ().height;
00154 
00155       // always keeps the top of a view on the screen
00156       size += (child->GetGeometry ().height, GetGeometry ().height) ? child->GetGeometry ().height : GetGeometry ().height;
00157 
00158       ScrollDown (1, size);
00159     }
00160 
00161   }
00162 
00163   long ScrollView::ProcessEvent (Event &event, long TraverseInfo, long ProcessEventInfo)
00164   {
00165     long ret = TraverseInfo;
00166     long ProcEvInfo = 0;
00167 
00168     if (event.e_event == NUX_MOUSE_PRESSED)
00169     {
00170       // Verify that the mouse down event falls inside the of the ScrollView.
00171       if (!GetGeometry ().IsPointInside (event.e_x - event.e_x_root, event.e_y - event.e_y_root))
00172       {
00173         ProcEvInfo = eDoNotProcess;
00174       }
00175     }
00176 
00177     if (event.e_event == NUX_MOUSE_WHEEL)
00178     {
00179       // nux can't tell the difference between horizontal and vertical mouse wheel events
00180       // so we are only going to support vertical
00181       if (event.e_wheeldelta > 0)
00182       {
00183         ScrollDown (abs (event.e_wheeldelta / NUX_MOUSEWHEEL_DELTA), m_MouseWheelScrollSize);
00184       }
00185       else
00186       {
00187         ScrollUp (abs (event.e_wheeldelta / NUX_MOUSEWHEEL_DELTA), m_MouseWheelScrollSize);
00188       }
00189     }
00190 
00191     if (m_vertical_scrollbar_enable)
00192       ret = _vscrollbar->ProcessEvent (event, ret, ProcEvInfo);
00193 
00194     if (m_horizontal_scrollbar_enable)
00195       ret = _hscrollbar->ProcessEvent (event, ret, ProcEvInfo);
00196 
00197     // The child layout get the Mouse down button only if the MouseDown happened inside the client view Area
00198     Geometry viewGeometry = Geometry (m_ViewX, m_ViewY, m_ViewWidth, m_ViewHeight);
00199 
00200     if ((event.e_event == NUX_MOUSE_PRESSED) ||
00201      (event.e_event == NUX_MOUSE_RELEASED) ||
00202      (event.e_event == NUX_MOUSE_MOVE))
00203     {
00204       if (!viewGeometry.IsPointInside (event.e_x - event.e_x_root, event.e_y - event.e_y_root) )
00205       {
00206         ProcEvInfo = eDoNotProcess;
00207       }
00208     }
00209 
00210     if (m_CompositionLayout)
00211     {
00212       // The ScrollView layout position is fixed. The ScrollView keeps track of the delta offset in x and y of the layout it manages.
00213       // Modify the event to account for this offset;
00214       Event mod_event = event;
00215       ret = m_CompositionLayout->ProcessEvent (mod_event, ret, ProcEvInfo);
00216     }
00217 
00218     ret = PostProcessEvent2 (event, ret, 0);
00219     return ret;
00220   }
00221 
00222   Area* ScrollView::FindAreaUnderMouse(const Point& mouse_position, NuxEventType event_type)
00223   {
00224     // Test if the mouse is inside the ScrollView.
00225     // The last parameter of TestMousePointerInclusion is a boolean used to test if the case
00226     // of mouse wheel events. If that boolean value is true, then TestMousePointerInclusion
00227     // returns true only if the mouse pointer is over this area and the the area accepts
00228     // mouse wheel events (see Area::SetAcceptMouseWheelEvent)
00229     bool mouse_inside = TestMousePointerInclusionFilterMouseWheel(mouse_position, event_type);
00230 
00231     if(mouse_inside == false)
00232     {
00233       // The mouse pointer is not over this Area. return NULL.
00234       return NULL;
00235     }
00236 
00237     Area* found_area;
00238 
00239     // Recursively go over the ui element that are managed by this ScrollView and look
00240     // for the area that is below the mouse.
00241 
00242     // Test the vertical scrollbar
00243     found_area = _vscrollbar->FindAreaUnderMouse(mouse_position, event_type);
00244     NUX_RETURN_VALUE_IF_NOTNULL(found_area, found_area);
00245 
00246     // Test the horizontal scrollbar
00247     found_area = _hscrollbar->FindAreaUnderMouse(mouse_position, event_type);
00248     NUX_RETURN_VALUE_IF_NOTNULL(found_area, found_area);
00249 
00250     // If the code gets here, it means that no area has been found yet.
00251     // Test the layout of the ScrollView
00252     return View::FindAreaUnderMouse(mouse_position, event_type);
00253   }
00254 
00255   bool ScrollView::SetLayout (Layout *layout)
00256   {
00257     if(View::SetLayout(layout) == false)
00258     {
00259       return false;
00260     }
00261 
00262     FormatContent();
00263 
00264     return true;
00265   }
00266 
00267   void ScrollView::Draw (GraphicsEngine &GfxContext, bool force_draw)
00268   {
00269     GfxContext.PushClippingRectangle (GetGeometry ());
00270 
00271     Geometry base = GetGeometry ();
00272 
00273     if (m_CompositionLayout)
00274       m_CompositionLayout->QueueDraw();
00275 
00276     GetPainter().PaintBackground (GfxContext, base);
00277 
00278     if (m_vertical_scrollbar_enable)
00279     {
00280       _vscrollbar->QueueDraw();
00281     }
00282 
00283     if (m_horizontal_scrollbar_enable)
00284     {
00285       _hscrollbar->QueueDraw();
00286     }
00287 
00288     GfxContext.PopClippingRectangle();
00289   }
00290 
00291   void ScrollView::DrawContent (GraphicsEngine &GfxContext, bool force_draw)
00292   {
00293     if (IsFullRedraw())
00294       GetPainter().PushBackgroundStack();
00295       
00296     GfxContext.PushClippingRectangle (GetGeometry ());
00297 
00298     GfxContext.PushClippingRectangle (Rect (m_ViewX, m_ViewY, m_ViewWidth, m_ViewHeight));
00299 
00300     if (m_CompositionLayout)
00301     {
00302 //       GfxContext.PushClipOffset (_delta_x, _delta_y);
00303 //       GfxContext.PushClippingRectangle (m_CompositionLayout->GetGeometry ());
00304 //       GfxContext.Push2DTranslationModelViewMatrix (_delta_x, _delta_y, 0.0f);
00305       m_CompositionLayout->ProcessDraw (GfxContext, force_draw);
00306 //       GfxContext.PopModelViewMatrix ();
00307 //       GfxContext.PopClippingRectangle ();
00308 //       GfxContext.PopClipOffset ();
00309     }
00310 
00311     GfxContext.PopClippingRectangle();
00312 
00313     if (m_vertical_scrollbar_enable)
00314     {
00315       _vscrollbar->ProcessDraw (GfxContext, force_draw);
00316     }
00317 
00318     if (m_horizontal_scrollbar_enable)
00319     {
00320       _hscrollbar->ProcessDraw (GfxContext, force_draw);
00321     }
00322 
00323     GfxContext.PopClippingRectangle();
00324 
00325     if (IsFullRedraw())
00326       GetPainter().PopBackgroundStack();
00327   }
00328 
00329   void ScrollView::PostDraw (GraphicsEngine &GfxContext, bool force_draw)
00330   {
00331 
00332   }
00333 
00335 // API //
00337   void ScrollView::EnableVerticalScrollBar (bool b)
00338   {
00339     m_vertical_scrollbar_enable = b;
00340     _delta_y = 0;
00341     ComputeChildLayout();
00342   }
00343 
00344   void ScrollView::EnableHorizontalScrollBar (bool b)
00345   {
00346     m_horizontal_scrollbar_enable = b;
00347     _delta_x = 0;
00348     ComputeChildLayout();
00349   }
00350 
00352 // Internal function //
00354 
00355   void ScrollView::SetGeometry (const Geometry &geo)
00356   {
00357     Area::SetGeometry (geo);
00358     //ComputeChildLayout();
00359   }
00360 
00361   void ScrollView::FormatContent()
00362   {
00363     Geometry geo;
00364     geo = GetGeometry();
00365 
00366     ComputeChildLayout();
00367   }
00368 
00369   void ScrollView::PreLayoutManagement()
00370   {
00371     // Give the managed layout the same size and position as the Control.
00372 
00373     Geometry geo = GetGeometry();
00374     int ScrollBarWidth = _vscrollbar->GetBaseWidth();
00375     int ScrollBarHeight = _hscrollbar->GetBaseHeight();
00376 
00377     nuxAssertMsg (ScrollBarWidth > 0, TEXT ("[ScrollView::PreLayoutManagement] Invalid scrollbar width: %d"), ScrollBarWidth);
00378     nuxAssertMsg (ScrollBarHeight > 0, TEXT ("[ScrollView::PreLayoutManagement] Invalid scrollbar height: %d"), ScrollBarHeight);
00379 
00380     m_ViewX = GetBaseX() + m_border + m_ViewContentLeftMargin;
00381     m_ViewY = GetBaseY() + m_top_border + m_ViewContentTopMargin;
00382 
00383     if (m_vertical_scrollbar_enable == false)
00384       m_ViewWidth = GetBaseWidth() - 2 * m_border - m_ViewContentRightMargin - m_ViewContentLeftMargin;
00385     else
00386       m_ViewWidth = GetBaseWidth() - ScrollBarWidth - 2 * m_border - m_ViewContentRightMargin - m_ViewContentLeftMargin;
00387 
00388     nuxAssertMsg (m_ViewWidth > 0, TEXT ("[ScrollView::PreLayoutManagement] Invalid view width: %d"), m_ViewWidth);
00389 
00390     if (m_horizontal_scrollbar_enable == false)
00391       m_ViewHeight = GetBaseHeight() - m_top_border - m_border - m_ViewContentBottomMargin - m_ViewContentTopMargin;
00392     else
00393       m_ViewHeight = GetBaseHeight() - ScrollBarHeight - m_top_border - m_border - m_ViewContentBottomMargin - m_ViewContentTopMargin;
00394 
00395     nuxAssertMsg (m_ViewHeight > 0, TEXT ("[ScrollView::PreLayoutManagement] Invalid view height: %d"), m_ViewHeight);
00396 
00397     if (m_ViewX + _delta_x +  m_ViewContentWidth < m_ViewX + m_ViewWidth)
00398     {
00399       // The position of the end of the content is smaller than the view right border position
00400       // Compute _delta_x so the end of the content match exactly the view right border position
00401       _delta_x = - (m_ViewContentWidth > m_ViewWidth ? m_ViewContentWidth - m_ViewWidth : 0);
00402       nuxAssert (_delta_x <= 0);
00403     }
00404 
00405     if (m_ViewY + _delta_y + m_ViewContentHeight < m_ViewY + m_ViewHeight)
00406     {
00407       // The position of the end of the content is smaller than the view right border position
00408       // Compute _delta_y so the end of the content match exactly the view right border position
00409       _delta_y = - (m_ViewContentHeight > m_ViewHeight ? m_ViewContentHeight - m_ViewHeight : 0);
00410       nuxAssert (_delta_y <= 0);
00411     }
00412 
00413     if (m_CompositionLayout)
00414     {
00415       // Set the composition layout to the size of the view area and offset it by (_delta_x, _delta_y)
00416 
00417       if (m_CompositionLayout->GetStretchFactor () != 0)
00418       {
00419         m_CompositionLayout->SetGeometry (
00420                 m_ViewX,
00421                 m_ViewY,
00422                 m_ViewWidth,
00423                 m_ViewHeight);
00424       }
00425 
00426       m_CompositionLayout->Set2DTranslation (_delta_x, _delta_y, 0);
00427     }
00428 
00429     // Horizontal scrollbar Geometry
00430     if (m_horizontal_scrollbar_enable)
00431     {
00432       if (m_vertical_scrollbar_enable == false)
00433       {
00434         // If there is no vertical scrollbar, take all the width available.
00435         _hscrollbar->SetBaseWidth (GetBaseWidth() - 2 * m_border);
00436       }
00437       else
00438         _hscrollbar->SetBaseWidth (GetBaseWidth() - ScrollBarWidth - 2 * m_border);
00439 
00440       _hscrollbar->SetBaseX (geo.x + m_border);
00441       _hscrollbar->SetBaseY (geo.y + geo.GetHeight() - _hscrollbar->GetBaseHeight() - m_border);
00442       _hscrollbar->ComputeChildLayout();
00443     }
00444     else
00445     {
00446       // The horizontal scrollbar won't be visible but give it a proper size anyway.
00447       _hscrollbar->SetBaseWidth (GetBaseWidth() - ScrollBarWidth - 2 * m_border);
00448       _hscrollbar->SetBaseX (geo.x + m_border);
00449       _hscrollbar->SetBaseY (geo.y + geo.GetHeight() - _hscrollbar->GetBaseHeight() - m_border);
00450       _hscrollbar->ComputeChildLayout();
00451     }
00452 
00453 
00454     // Vertical scrollbar Geometry
00455     if (m_vertical_scrollbar_enable)
00456     {
00457       if (m_horizontal_scrollbar_enable == false)
00458       {
00459         // If there is no horizontal scrollbar, take all the width available.
00460         _vscrollbar->SetBaseHeight (GetBaseHeight() - m_top_border - m_border);
00461       }
00462       else
00463         _vscrollbar->SetBaseHeight (GetBaseHeight() - ScrollBarHeight - m_top_border - m_border);
00464 
00465       _vscrollbar->SetBaseX (geo.x + geo.GetWidth() - ScrollBarWidth - m_border);
00466       _vscrollbar->SetBaseY (geo.y + m_top_border);
00467       _vscrollbar->ComputeChildLayout();
00468     }
00469     else
00470     {
00471       // The vertical scrollbar won't be visible but give it a proper size anyway.
00472       _vscrollbar->SetBaseHeight (GetBaseHeight() - ScrollBarHeight - m_top_border - m_border);
00473       _vscrollbar->SetBaseX (geo.x + geo.GetWidth() - ScrollBarWidth - m_border);
00474       _vscrollbar->SetBaseY (geo.y + m_top_border);
00475       _vscrollbar->ComputeChildLayout();
00476     }
00477   }
00478 
00479   long ScrollView::PostLayoutManagement (long LayoutResult)
00480   {
00481     if (IsSizeMatchContent ())
00482       return PostLayoutManagement2 (LayoutResult);
00483 
00484     int ScrollBarWidth = 0;
00485     int ScrollBarHeight = 0;
00486 
00487     if (m_CompositionLayout)
00488     {
00489       m_ViewContentX = m_CompositionLayout->GetBaseX();
00490       m_ViewContentY = m_CompositionLayout->GetBaseY();
00491       m_ViewContentWidth = m_CompositionLayout->GetBaseWidth();
00492       m_ViewContentHeight = m_CompositionLayout->GetBaseHeight();
00493     }
00494 
00495     if (m_horizontal_scrollbar_enable)
00496       ScrollBarHeight = _hscrollbar->GetBaseHeight();
00497 
00498     if (m_vertical_scrollbar_enable)
00499       ScrollBarWidth = _vscrollbar->GetBaseWidth();
00500 
00501     _hscrollbar->SetContainerSize (GetBaseX() + m_border + m_ViewContentLeftMargin,
00502                                   GetBaseY() + m_top_border + m_ViewContentTopMargin,
00503                                   GetBaseWidth() - ScrollBarWidth - 2 * m_border - m_ViewContentRightMargin - m_ViewContentLeftMargin,
00504                                   GetBaseHeight() - ScrollBarHeight - m_top_border - m_border - m_ViewContentBottomMargin - m_ViewContentTopMargin);
00505 
00506     if (m_horizontal_scrollbar_enable)
00507     {
00508       if (m_CompositionLayout)
00509       {
00510         _hscrollbar->SetContentSize (m_CompositionLayout->GetBaseX(), m_CompositionLayout->GetBaseY(),
00511                                     m_CompositionLayout->GetBaseWidth(), m_CompositionLayout->GetBaseHeight() );
00512       }
00513       else
00514       {
00515         _hscrollbar->SetContentSize (GetBaseX() + m_border + m_ViewContentLeftMargin,
00516                                     GetBaseY() + m_top_border + m_ViewContentTopMargin, 0, 0);
00517       }
00518 
00519       _hscrollbar->SetContentOffset (_delta_x, _delta_y);
00520     }
00521     else
00522     {
00523       _hscrollbar->SetContentSize (GetBaseX() + m_border + m_ViewContentLeftMargin,
00524                                   GetBaseY() + m_top_border + m_ViewContentTopMargin, 0, 0);
00525       _hscrollbar->SetContentOffset (0, 0);
00526     }
00527 
00528     _vscrollbar->SetContainerSize (GetBaseX() + m_border + m_ViewContentLeftMargin,
00529                                   GetBaseY() + m_top_border + m_ViewContentTopMargin,
00530                                   GetBaseWidth() - ScrollBarWidth - 2 * m_border - m_ViewContentRightMargin - m_ViewContentLeftMargin,
00531                                   GetBaseHeight() - ScrollBarHeight - m_top_border - m_border - m_ViewContentBottomMargin - m_ViewContentTopMargin);
00532 
00533     if (m_vertical_scrollbar_enable)
00534     {
00535       if (m_CompositionLayout)
00536       {
00537         _vscrollbar->SetContentSize (m_CompositionLayout->GetBaseX(), m_CompositionLayout->GetBaseY(),
00538                                     m_CompositionLayout->GetBaseWidth(), m_CompositionLayout->GetBaseHeight() );
00539       }
00540       else
00541       {
00542         _vscrollbar->SetContentSize (GetBaseX() + m_border + m_ViewContentLeftMargin,
00543                                     GetBaseY() + m_top_border + m_ViewContentTopMargin, 0, 0);
00544       }
00545 
00546       _vscrollbar->SetContentOffset (_delta_x, _delta_y);
00547     }
00548     else
00549     {
00550       _vscrollbar->SetContentSize (GetBaseX() + m_border + m_ViewContentLeftMargin,
00551                                   GetBaseY() + m_top_border + m_ViewContentTopMargin, 0, 0);
00552       _vscrollbar->SetContentOffset (0, 0);
00553     }
00554 
00555     // I may not be necessary to call this function here since ComputePosition2 was called on ComputePosition2
00556     // during the layout process.
00557     if (m_CompositionLayout)
00558       m_CompositionLayout->ComputePosition2 (0, 0);
00559 
00560     // The ScrollView always returns complient width and height to its parent layout.
00561     return (eCompliantHeight | eCompliantWidth);
00562   }
00563 
00564   long ScrollView::PostLayoutManagement2 (long LayoutResult)
00565   {
00566     // In case IsSizeMatchContent returns True, The scroll view is resized to match its content.
00567     int ScrollbarWidth = 0;
00568     int ScrollbarHeight = 0;
00569 
00570     if (m_horizontal_scrollbar_enable)
00571       ScrollbarHeight = _hscrollbar->GetBaseHeight();
00572 
00573     if (m_vertical_scrollbar_enable)
00574       ScrollbarWidth = _vscrollbar->GetBaseWidth();
00575 
00576     // We want the controller to match the size of the content as defined in:
00577     //      m_ViewContentX
00578     //      m_ViewContentY
00579     //      m_ViewContentWidth
00580     //      m_ViewContentHeight
00581     // So we make the composition layout the same size as the content
00582     // Note that classes that inherits from ScrollView are responsible for setting the dimension of the ViewContent
00583 
00584     if (m_CompositionLayout)
00585     {
00586       m_CompositionLayout->SetBaseX (m_ViewContentX);
00587       m_CompositionLayout->SetBaseY (m_ViewContentY);
00588       m_CompositionLayout->SetBaseWidth (m_ViewContentWidth);
00589       m_CompositionLayout->SetBaseHeight (m_ViewContentHeight);
00590     }
00591 
00592     Geometry base;
00593     // Given the (m_ViewContentWidth, m_ViewContentHeight) compute the size of the ScrollView.
00594     // It is possible that the ScrollView size be limited by its min/Max dimension. If this happens, then the scrollbar will reflect that.
00595     base.SetX (m_ViewContentX - m_border - m_ViewContentLeftMargin);
00596     base.SetY (m_ViewContentY - m_top_border - m_ViewContentTopMargin);
00597 
00598     if (m_horizontal_scrollbar_enable)
00599       base.SetHeight (m_top_border + m_ViewContentTopMargin + m_ViewContentHeight + m_ViewContentBottomMargin + ScrollbarHeight + m_border);
00600     else
00601       base.SetHeight (m_top_border + m_ViewContentTopMargin + m_ViewContentHeight + m_ViewContentBottomMargin + m_border);
00602 
00603     if (m_vertical_scrollbar_enable)
00604       base.SetWidth (m_border + m_ViewContentLeftMargin + m_ViewContentWidth + m_ViewContentRightMargin + ScrollbarWidth + m_border);
00605     else
00606       base.SetWidth (m_border + m_ViewContentLeftMargin + m_ViewContentWidth + m_ViewContentRightMargin + m_border);
00607 
00608     // Set the size so that is is equal to the visible content.
00609     Area::SetBaseWidth (base.GetWidth() );
00610     Area::SetBaseHeight (base.GetHeight() );
00611     Geometry geo = GetGeometry();
00612 
00613     // Horizontal scrollbar Geometry
00614     if (m_horizontal_scrollbar_enable)
00615     {
00616       if (m_vertical_scrollbar_enable == false)
00617         _hscrollbar->SetBaseWidth (GetBaseWidth() - 2 * m_border);
00618       else
00619         _hscrollbar->SetBaseWidth (GetBaseWidth() - ScrollbarWidth - 2 * m_border);
00620 
00621       _hscrollbar->SetBaseX (geo.x + m_border);
00622       _hscrollbar->SetBaseY (geo.y + geo.GetHeight() - _hscrollbar->GetBaseHeight() - m_border);
00623       _hscrollbar->ComputeChildLayout();
00624 
00625       //---
00626       _hscrollbar->SetContainerSize (GetBaseX() + m_border + m_ViewContentLeftMargin,
00627                                     GetBaseY() + m_top_border + m_ViewContentTopMargin,
00628                                     GetBaseWidth() - ScrollbarWidth - 2 * m_border - m_ViewContentRightMargin - m_ViewContentLeftMargin,
00629                                     GetBaseHeight() - ScrollbarHeight - m_top_border - m_border - m_ViewContentBottomMargin - m_ViewContentTopMargin);
00630 
00631       if (m_CompositionLayout)
00632       {
00633         _hscrollbar->SetContentSize (m_CompositionLayout->GetBaseX(), m_CompositionLayout->GetBaseY(),
00634                                     m_CompositionLayout->GetBaseWidth(), m_CompositionLayout->GetBaseHeight() );
00635       }
00636       else
00637       {
00638         _hscrollbar->SetContentSize (GetBaseX() + m_border + m_ViewContentLeftMargin,
00639                                     GetBaseY() + m_top_border + m_ViewContentTopMargin, 0, 0);
00640       }
00641 
00642       _hscrollbar->SetContentOffset (_delta_x, _delta_y);
00643     }
00644     else
00645     {
00646       _hscrollbar->SetBaseWidth (GetBaseWidth() - ScrollbarWidth - 2 * m_border);
00647       _hscrollbar->SetBaseX (geo.x + m_border);
00648       _hscrollbar->SetBaseY (geo.y + geo.GetHeight() - _hscrollbar->GetBaseHeight() - m_border);
00649       _hscrollbar->ComputeChildLayout();
00650 
00651       //---
00652       _hscrollbar->SetContainerSize (GetBaseX() + m_border + m_ViewContentLeftMargin,
00653                                     GetBaseY() + m_top_border + m_ViewContentTopMargin,
00654                                     GetBaseWidth() - ScrollbarWidth - 2 * m_border - m_ViewContentRightMargin - m_ViewContentLeftMargin,
00655                                     GetBaseHeight() - ScrollbarHeight - m_top_border - m_border - m_ViewContentBottomMargin - m_ViewContentTopMargin);
00656       _hscrollbar->SetContentSize (GetBaseX() + m_border + m_ViewContentLeftMargin,
00657                                   GetBaseY() + m_top_border + m_ViewContentTopMargin, 0, 0);
00658       _hscrollbar->SetContentOffset (0, 0);
00659     }
00660 
00661 
00662     // Vertical scrollbar Geometry
00663     if (m_vertical_scrollbar_enable)
00664     {
00665       if (m_horizontal_scrollbar_enable == false)
00666         _vscrollbar->SetBaseHeight (GetBaseHeight() - m_top_border - m_border);
00667       else
00668         _vscrollbar->SetBaseHeight (GetBaseHeight() - ScrollbarHeight - m_top_border - m_border);
00669 
00670       _vscrollbar->SetBaseX (geo.x + geo.GetWidth() - ScrollbarWidth - m_border);
00671       _vscrollbar->SetBaseY (geo.y + m_top_border);
00672       _vscrollbar->ComputeChildLayout();
00673 
00674       //---
00675       _vscrollbar->SetContainerSize (GetBaseX() + m_border + m_ViewContentLeftMargin,
00676                                     GetBaseY() + m_top_border + m_ViewContentTopMargin,
00677                                     GetBaseWidth() - ScrollbarWidth - 2 * m_border - m_ViewContentRightMargin - m_ViewContentLeftMargin,
00678                                     GetBaseHeight() - ScrollbarHeight - m_top_border - m_border - m_ViewContentBottomMargin - m_ViewContentTopMargin);
00679 
00680       if (m_CompositionLayout)
00681       {
00682         _vscrollbar->SetContentSize (m_CompositionLayout->GetBaseX(), m_CompositionLayout->GetBaseY(),
00683                                     m_CompositionLayout->GetBaseWidth(), m_CompositionLayout->GetBaseHeight() );
00684       }
00685       else
00686       {
00687         _vscrollbar->SetContentSize (GetBaseX() + m_border + m_ViewContentLeftMargin,
00688                                     GetBaseY() + m_top_border + m_ViewContentTopMargin, 0, 0);
00689       }
00690 
00691       _vscrollbar->SetContentOffset (_delta_x, _delta_y);
00692     }
00693     else
00694     {
00695       _vscrollbar->SetBaseHeight (GetBaseHeight() - ScrollbarHeight - m_top_border - m_border);
00696       _vscrollbar->SetBaseX (geo.x + geo.GetWidth() - ScrollbarWidth - m_border);
00697       _vscrollbar->SetBaseY (geo.y + m_top_border);
00698       _vscrollbar->ComputeChildLayout();
00699 
00700       //---
00701       _vscrollbar->SetContainerSize (GetBaseX() + m_border + m_ViewContentLeftMargin,
00702                                     GetBaseY() + m_top_border + m_ViewContentTopMargin,
00703                                     GetBaseWidth() - ScrollbarWidth - 2 * m_border - m_ViewContentRightMargin - m_ViewContentLeftMargin,
00704                                     GetBaseHeight() - ScrollbarHeight - m_top_border - m_border - m_ViewContentBottomMargin - m_ViewContentTopMargin);
00705       _vscrollbar->SetContentSize (GetBaseX() + m_border + m_ViewContentLeftMargin,
00706                                   GetBaseY() + m_top_border + m_ViewContentTopMargin, 0, 0);
00707       _vscrollbar->SetContentOffset (0, 0);
00708     }
00709 
00710     if (m_CompositionLayout)
00711       m_CompositionLayout->ComputePosition2 (0, 0);
00712 
00713     return (eCompliantHeight | eCompliantWidth);
00714   }
00715 
00716 // When the ScrollView is in a Layout object, and that layout call View::PositionChildLayout
00717 // the ScrollView must call its own PositionChildLayout so it can properly do the positioning of the inner object.
00718 // Otherwise, m_CompositionLayout->ComputePosition2 is called but it doesn't know that it may not contain all the
00719 // object of the ScrollView. Which result in incorrect positioning.
00720 // Here we touch only the position. Do not touch the width or height of object.
00721 // This function is called when the ScrollView is embedded within a Layout.
00722   void ScrollView::PositionChildLayout (float offsetX, float offsetY)
00723   {
00724     Geometry geo = GetGeometry();
00725     int w = 0;
00726     int h = 0;
00727 
00728     w = _vscrollbar->GetBaseWidth();
00729     h = _hscrollbar->GetBaseHeight();
00730 
00731     m_ViewX = GetBaseX() + m_border + m_ViewContentLeftMargin;
00732     m_ViewY = GetBaseY() + m_top_border + m_ViewContentTopMargin;
00733 
00734     if (m_vertical_scrollbar_enable == false)
00735       m_ViewWidth = GetBaseWidth() - 2 * m_border - m_ViewContentRightMargin - m_ViewContentLeftMargin;
00736     else
00737       m_ViewWidth = GetBaseWidth() - w - 2 * m_border - m_ViewContentRightMargin - m_ViewContentLeftMargin;
00738 
00739     if (m_horizontal_scrollbar_enable == false)
00740       m_ViewHeight = GetBaseHeight() - m_top_border - m_border - m_ViewContentBottomMargin - m_ViewContentTopMargin;
00741     else
00742       m_ViewHeight = GetBaseHeight() - h - m_top_border - m_border - m_ViewContentBottomMargin - m_ViewContentTopMargin;
00743 
00744 
00745     if (m_ViewX + _delta_x +  m_ViewContentWidth < m_ViewX + m_ViewWidth)
00746     {
00747       _delta_x = - (m_ViewContentWidth > m_ViewWidth ? m_ViewContentWidth - m_ViewWidth : 0);
00748     }
00749 
00750     if (m_ViewY + _delta_y + m_ViewContentHeight < m_ViewY + m_ViewHeight)
00751     {
00752       _delta_y = - (m_ViewContentHeight > m_ViewHeight ? m_ViewContentHeight - m_ViewHeight : 0);
00753     }
00754 
00755     if (m_CompositionLayout)
00756     {
00757       m_CompositionLayout->SetBaseX (m_ViewX);
00758       m_CompositionLayout->SetBaseY (m_ViewY);
00759     }
00760 
00761     // Horizontal scrollbar Geometry
00762     if (m_horizontal_scrollbar_enable)
00763     {
00764       if (m_vertical_scrollbar_enable == false)
00765         _hscrollbar->SetBaseWidth (GetBaseWidth() - 2 * m_border);
00766       else
00767         _hscrollbar->SetBaseWidth (GetBaseWidth() - w - 2 * m_border);
00768 
00769       _hscrollbar->SetBaseX (geo.x + m_border);
00770       _hscrollbar->SetBaseY (geo.y + geo.GetHeight() - _hscrollbar->GetBaseHeight() - m_border);
00771       _hscrollbar->ComputeChildLayout();
00772     }
00773 
00774     // Vertical scrollbar Geometry
00775     if (m_vertical_scrollbar_enable)
00776     {
00777       if (m_horizontal_scrollbar_enable == false)
00778         _vscrollbar->SetBaseHeight (GetBaseHeight() - m_top_border - m_border);
00779       else
00780         _vscrollbar->SetBaseHeight (GetBaseHeight() - h - m_top_border - m_border);
00781 
00782       _vscrollbar->SetBaseX (geo.x + geo.GetWidth() - w - m_border);
00783       _vscrollbar->SetBaseY (geo.y + m_top_border);
00784       _vscrollbar->ComputeChildLayout();
00785     }
00786 
00787     if (m_CompositionLayout)
00788     {
00789       m_ViewContentX = m_CompositionLayout->GetBaseX();
00790       m_ViewContentY = m_CompositionLayout->GetBaseY();
00791     }
00792     else
00793     {
00794       m_ViewContentX = m_ViewX;
00795       m_ViewContentY = m_ViewY;
00796     }
00797 
00798     _vscrollbar->SetContentOffset (_delta_x, _delta_y);
00799     _hscrollbar->SetContentOffset (_delta_x, _delta_y);
00800 
00801     if (m_CompositionLayout)
00802     {
00803       m_CompositionLayout->ComputePosition2 (0, 0);
00804     }
00805   }
00806 
00807 
00808   void ScrollView::ScrollLeft (float stepx, int mousedx)
00809   {
00810     if (m_CompositionLayout)
00811     {
00812       _delta_x += (float) stepx * (float) mousedx;;
00813 
00814       if (_delta_x > 0)
00815       {
00816         _delta_x = 0;
00817       }
00818       m_CompositionLayout->Set2DTranslation (_delta_x, _delta_y, 0);
00819     }
00820 
00821     if (m_CompositionLayout)
00822     {
00823       _hscrollbar->SetContentOffset (_delta_x, _delta_y);
00824       _hscrollbar->QueueDraw();
00825     }
00826 
00827     QueueDraw();
00828   }
00829 
00830   void ScrollView::ScrollRight (float stepx, int mousedx)
00831   {
00832     if (m_CompositionLayout)
00833     {
00834       _delta_x -= (float) stepx * (float) mousedx;
00835 
00836       if (m_ViewX + _delta_x +  m_ViewContentWidth < m_ViewX + m_ViewWidth)
00837       {
00838         _delta_x = - (m_ViewContentWidth > m_ViewWidth ? m_ViewContentWidth - m_ViewWidth : 0);
00839       }
00840       m_CompositionLayout->Set2DTranslation (_delta_x, _delta_y, 0);
00841     }
00842 
00843     if (m_CompositionLayout)
00844     {
00845       _hscrollbar->SetContentOffset (_delta_x, _delta_y);
00846       _hscrollbar->QueueDraw();
00847     }
00848 
00849     QueueDraw();
00850   }
00851 
00852   void ScrollView::ScrollUp (float stepy, int mousedy)
00853   {
00854     if (m_CompositionLayout)
00855     {
00856       _delta_y += (float) stepy * (float) mousedy;
00857 
00858       if (_delta_y > 0)
00859       {
00860         _delta_y = 0;
00861       }
00862       m_CompositionLayout->Set2DTranslation (_delta_x, _delta_y, 0);
00863     }
00864 
00865     if (m_CompositionLayout)
00866     {
00867       _vscrollbar->SetContentOffset (_delta_x, _delta_y);
00868       _vscrollbar->QueueDraw();
00869     }
00870 
00871     QueueDraw();
00872   }
00873 
00874   void ScrollView::ScrollDown (float stepy, int mousedy)
00875   {
00876     if (m_CompositionLayout)
00877     {
00878       _delta_y -= (float) stepy * (float) mousedy;
00879 
00880       if (m_ViewY + _delta_y + m_ViewContentHeight < m_ViewY + m_ViewHeight)
00881       {
00882         _delta_y = - (m_ViewContentHeight > m_ViewHeight ? m_ViewContentHeight - m_ViewHeight : 0);
00883       }
00884       m_CompositionLayout->Set2DTranslation (_delta_x, _delta_y, 0);
00885     }
00886 
00887     if (m_CompositionLayout)
00888     {
00889       _vscrollbar->SetContentOffset (_delta_x, _delta_y);
00890       _vscrollbar->QueueDraw();
00891     }
00892 
00893     QueueDraw();
00894   }
00895 
00896   void ScrollView::SetSizeMatchContent (bool b)
00897   {
00898     m_bSizeMatchContent = b;
00899 
00900     if (m_CompositionLayout)
00901       m_CompositionLayout->ComputeLayout2();
00902   }
00903 
00904   bool ScrollView::IsSizeMatchContent() const
00905   {
00906     return m_bSizeMatchContent;
00907   }
00908 
00909   void ScrollView::ResetScrollToLeft()
00910   {
00911     _delta_x = 0;
00912     if (m_CompositionLayout)
00913       m_CompositionLayout->Set2DTranslation (_delta_x, _delta_y, 0);
00914 
00915     _hscrollbar->SetContentOffset (_delta_x, _delta_y);
00916     _hscrollbar->QueueDraw();
00917 
00918     QueueDraw();
00919   }
00920 
00921   void ScrollView::ResetScrollToRight()
00922   {
00923     if (m_CompositionLayout)
00924     {
00925       _delta_x = - (m_ViewContentWidth > m_ViewWidth ? m_ViewContentWidth - m_ViewWidth : 0);
00926       m_CompositionLayout->Set2DTranslation (_delta_x, _delta_y, 0);
00927     }
00928     else
00929     {
00930       _delta_x = 0;
00931     }
00932 
00933 
00934 
00935     _hscrollbar->SetContentOffset (_delta_x, _delta_y);
00936     _hscrollbar->QueueDraw();
00937 
00938     QueueDraw();
00939   }
00940 
00941   void ScrollView::ResetScrollToUp()
00942   {
00943     _delta_y = 0;
00944     if (m_CompositionLayout)
00945       m_CompositionLayout->Set2DTranslation (_delta_x, _delta_y, 0);
00946 
00947     _vscrollbar->SetContentOffset (_delta_x, _delta_y);
00948     _vscrollbar->QueueDraw();
00949 
00950     QueueDraw();
00951   }
00952 
00953   void ScrollView::ResetScrollToDown()
00954   {
00955     if (m_CompositionLayout)
00956     {
00957       _delta_y = - (m_ViewContentHeight > m_ViewHeight ? m_ViewContentHeight - m_ViewHeight : 0);
00958       m_CompositionLayout->Set2DTranslation (_delta_x, _delta_y, 0);
00959     }
00960     else
00961     {
00962       _delta_y = 0;
00963     }
00964 
00965     _vscrollbar->SetContentOffset (_delta_x, _delta_y);
00966     _vscrollbar->QueueDraw();
00967 
00968     QueueDraw();
00969   }
00970 
00971   void ScrollView::RecvMouseWheel(int x, int y, int wheel_delta, long button_flags, unsigned long key_flags)
00972   {
00973     // nux can't tell the difference between horizontal and vertical mouse wheel events
00974     // so we are only going to support vertical
00975     if (wheel_delta < 0)
00976     {
00977       ScrollDown (abs (wheel_delta / NUX_MOUSEWHEEL_DELTA), m_MouseWheelScrollSize);
00978     }
00979     else
00980     {
00981       ScrollUp (abs (wheel_delta / NUX_MOUSEWHEEL_DELTA), m_MouseWheelScrollSize);
00982     }
00983     QueueDraw();
00984   }
00985 
00986   bool ScrollView::AcceptKeyNavFocus()
00987   {
00988     return false;
00989   }
00990 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends