nux-1.14.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->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 }