nux-1.16.0
|
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 }