/* GWEN Copyright (c) 2010 Facepunch Studios See license in Gwen.h */ #include "gwen_scrollcontrol.h" #include "gwen_scrollbar.h" #include "gwen_verticalscrollbar.h" #include "gwen_horizontalscrollbar.h" #include "../gwen_utility.h" using namespace Gwen; using namespace Gwen::Controls; using namespace Gwen::ControlsInternal; GWEN_CONTROL_CONSTRUCTOR( ScrollControl ) { SetMouseInputEnabled( false ); m_VerticalScrollBar = new VerticalScrollBar( this ); m_VerticalScrollBar->Dock( Pos::Right ); m_VerticalScrollBar->onBarMoved.Add( this, &ScrollControl::VBarMoved ); m_VerticalScrollBar->SetNudgeAmount( 30 ); m_bCanScrollV = true; m_HorizontalScrollBar = new HorizontalScrollBar( this ); m_HorizontalScrollBar->Dock( Pos::Bottom ); m_HorizontalScrollBar->onBarMoved.Add( this, &ScrollControl::HBarMoved ); m_bCanScrollH = true; m_HorizontalScrollBar->SetNudgeAmount( 30 ); m_InnerPanel = new Base( this ); m_InnerPanel->SetPos(0, 0); m_InnerPanel->SetMargin( Margin(5,5,5,5)); m_InnerPanel->SendToBack(); m_InnerPanel->SetMouseInputEnabled( false ); m_bAutoHideBars = true; } void ScrollControl::SetScroll( bool h, bool v ) { m_bCanScrollV = v; m_bCanScrollH = h; m_VerticalScrollBar->SetHidden( !m_bCanScrollV ); m_HorizontalScrollBar->SetHidden( !m_bCanScrollH ); } void ScrollControl::SetInnerSize( int w, int h ) { m_InnerPanel->SetSize( w, h ); } void ScrollControl::VBarMoved( Controls::Base * /*control*/ ) { Invalidate(); } void ScrollControl::HBarMoved( Controls::Base * /*control*/ ) { Invalidate(); } void ScrollControl::OnChildBoundsChanged( Gwen::Rect /*oldChildBounds*/, Base* /*pChild*/ ) { UpdateScrollBars(); Invalidate(); } void ScrollControl::Layout( Skin::Base* skin ) { UpdateScrollBars(); BaseClass::Layout(skin); } bool ScrollControl::OnMouseWheeled( int iDelta ) { if ( CanScrollV() && m_VerticalScrollBar->Visible() ) { if ( m_VerticalScrollBar->SetScrolledAmount( m_VerticalScrollBar->GetScrolledAmount() - m_VerticalScrollBar->GetNudgeAmount() * ( (float)iDelta / 60.0f ), true) ) return true; } if ( CanScrollH() && m_HorizontalScrollBar->Visible() ) { if ( m_HorizontalScrollBar->SetScrolledAmount( m_HorizontalScrollBar->GetScrolledAmount() - m_HorizontalScrollBar->GetNudgeAmount() * ( (float)iDelta / 60.0f ), true) ) return true; } return false; } void ScrollControl::Render( Skin::Base* skin ) { #if 0 // Debug render - this shouldn't render ANYTHING REALLY - it should be up to the parent! Gwen::Rect rect = GetRenderBounds(); Gwen::Renderer::Base* render = skin->GetRender(); render->SetDrawColor( Gwen::Color( 255, 255, 0, 100 ) ); render->DrawFilledRect( rect ); render->SetDrawColor( Gwen::Color( 255, 0, 0, 100 ) ); render->DrawFilledRect( m_InnerPanel->GetBounds() ); render->RenderText( skin->GetDefaultFont(), Gwen::Point( 0, 0 ), Utility::Format( "Offset: %i %i", m_InnerPanel->X(), m_InnerPanel->Y() ) ); #else //0 (void)skin; #endif //0 } bool ScrollControl::ContentsAreDocked() { if ( !m_InnerPanel ) return false; for ( Base::List::iterator iter = m_InnerPanel->Children.begin(); iter != m_InnerPanel->Children.end(); ++iter ) { Base* pChild = *iter; if ( pChild->GetDock() == Pos::None ) return false; } return true; } void ScrollControl::UpdateScrollBars() { if ( !m_InnerPanel ) return; if ( ContentsAreDocked() ) { m_VerticalScrollBar->SetHidden( true ); m_HorizontalScrollBar->SetHidden( true ); m_InnerPanel->SetSize( GetSize() ); m_InnerPanel->SetPos( 0, 0 ); return; } int childrenWidth = 0; int childrenHeight = 0; //Get the max size of all our children together for ( Base::List::iterator iter = m_InnerPanel->Children.begin(); iter != m_InnerPanel->Children.end(); ++iter ) { Base* pChild = *iter; childrenWidth = Utility::Max( childrenWidth, pChild->Right() ); childrenHeight = Utility::Max( childrenHeight, pChild->Bottom() ); } if ( m_bCanScrollH ) { m_InnerPanel->SetSize( Utility::Max( Width(), childrenWidth), Utility::Max( Height(), childrenHeight ) ); } else { m_InnerPanel->SetSize( Width() - (m_VerticalScrollBar->Hidden() ? 0 : m_VerticalScrollBar->Width()-1), Utility::Max( Height(), childrenHeight ) ); } float wPercent = (float)Width() / (float)(childrenWidth + (m_VerticalScrollBar->Hidden() ? 0 : m_VerticalScrollBar->Width())); float hPercent = (float)Height() / (float)(childrenHeight + (m_HorizontalScrollBar->Hidden() ? 0 : m_HorizontalScrollBar->Height())); if ( m_bCanScrollV ) SetVScrollRequired( hPercent >= 1 ); else m_VerticalScrollBar->SetHidden( true ); if ( m_bCanScrollH ) SetHScrollRequired( wPercent >= 1 ); else m_HorizontalScrollBar->SetHidden( true ); m_VerticalScrollBar->SetContentSize( m_InnerPanel->Height() ); m_VerticalScrollBar->SetViewableContentSize( Height() - (m_HorizontalScrollBar->Hidden() ? 0 : m_HorizontalScrollBar->Height())); m_HorizontalScrollBar->SetContentSize( m_InnerPanel->Width() ); m_HorizontalScrollBar->SetViewableContentSize( Width() - (m_VerticalScrollBar->Hidden() ? 0 : m_VerticalScrollBar->Width()) ); int newInnerPanelPosX = 0; int newInnerPanelPosY = 0; if ( CanScrollV() && !m_VerticalScrollBar->Hidden() ) { newInnerPanelPosY = -( ( m_InnerPanel->Height() ) - Height() + (m_HorizontalScrollBar->Hidden() ? 0 : m_HorizontalScrollBar->Height()) ) * m_VerticalScrollBar->GetScrolledAmount(); } if ( CanScrollH() && !m_HorizontalScrollBar->Hidden() ) { newInnerPanelPosX = - ( ( m_InnerPanel->Width() ) - Width() + (m_VerticalScrollBar->Hidden() ? 0 : m_VerticalScrollBar->Width())) * m_HorizontalScrollBar->GetScrolledAmount(); } m_InnerPanel->SetPos( newInnerPanelPosX , newInnerPanelPosY ); } void ScrollControl::SetVScrollRequired(bool req) { if ( req ) { m_VerticalScrollBar->SetScrolledAmount( 0, true ); m_VerticalScrollBar->SetDisabled( true ); if ( m_bAutoHideBars ) m_VerticalScrollBar->SetHidden( true ); } else { m_VerticalScrollBar->SetHidden( false ); m_VerticalScrollBar->SetDisabled( false ); } } void ScrollControl::SetHScrollRequired(bool req) { if ( req ) { m_HorizontalScrollBar->SetScrolledAmount( 0, true ); m_HorizontalScrollBar->SetDisabled( true ); if ( m_bAutoHideBars ) m_HorizontalScrollBar->SetHidden( true ); } else { m_HorizontalScrollBar->SetHidden( false ); m_HorizontalScrollBar->SetDisabled( true ); } } void ScrollControl::ScrollToBottom() { if ( !CanScrollV() ) return; UpdateScrollBars(); m_VerticalScrollBar->ScrollToBottom(); } void ScrollControl::ScrollToTop() { if ( CanScrollV() ) { UpdateScrollBars(); m_VerticalScrollBar->ScrollToTop(); } } void ScrollControl::ScrollToLeft() { if ( CanScrollH() ) { UpdateScrollBars(); m_HorizontalScrollBar->ScrollToLeft(); } } void ScrollControl::ScrollToRight() { if ( CanScrollH() ) { UpdateScrollBars(); m_HorizontalScrollBar->ScrollToRight(); } } void ScrollControl::Clear() { m_InnerPanel->RemoveAllChildren(); }