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