1 /*
2 	GWEN
3 	Copyright (c) 2010 Facepunch Studios
4 	See license in Gwen.h
5 */
6 
7 #include "Gwen/Controls/ScrollControl.h"
8 #include "Gwen/Controls/ScrollBar.h"
9 #include "Gwen/Controls/VerticalScrollBar.h"
10 #include "Gwen/Controls/HorizontalScrollBar.h"
11 #include "Gwen/Utility.h"
12 
13 using namespace Gwen;
14 using namespace Gwen::Controls;
15 using namespace Gwen::ControlsInternal;
16 
GWEN_CONTROL_CONSTRUCTOR(ScrollControl)17 GWEN_CONTROL_CONSTRUCTOR(ScrollControl)
18 {
19 	SetMouseInputEnabled(false);
20 
21 	m_VerticalScrollBar = new VerticalScrollBar(this);
22 	m_VerticalScrollBar->Dock(Pos::Right);
23 	m_VerticalScrollBar->onBarMoved.Add(this, &ScrollControl::VBarMoved);
24 	m_VerticalScrollBar->SetNudgeAmount(30);
25 	m_bCanScrollV = true;
26 
27 	m_HorizontalScrollBar = new HorizontalScrollBar(this);
28 	m_HorizontalScrollBar->Dock(Pos::Bottom);
29 	m_HorizontalScrollBar->onBarMoved.Add(this, &ScrollControl::HBarMoved);
30 	m_bCanScrollH = true;
31 	m_HorizontalScrollBar->SetNudgeAmount(30);
32 
33 	m_InnerPanel = new Base(this);
34 	m_InnerPanel->SetPos(0, 0);
35 	m_InnerPanel->SetMargin(Margin(5, 5, 5, 5));
36 	m_InnerPanel->SendToBack();
37 	m_InnerPanel->SetMouseInputEnabled(false);
38 
39 	m_bAutoHideBars = false;
40 }
41 
SetScroll(bool h,bool v)42 void ScrollControl::SetScroll(bool h, bool v)
43 {
44 	m_bCanScrollV = v;
45 	m_bCanScrollH = h;
46 	m_VerticalScrollBar->SetHidden(!m_bCanScrollV);
47 	m_HorizontalScrollBar->SetHidden(!m_bCanScrollH);
48 }
49 
SetInnerSize(int w,int h)50 void ScrollControl::SetInnerSize(int w, int h)
51 {
52 	m_InnerPanel->SetSize(w, h);
53 }
54 
VBarMoved(Controls::Base *)55 void ScrollControl::VBarMoved(Controls::Base* /*control*/)
56 {
57 	Invalidate();
58 }
59 
HBarMoved(Controls::Base *)60 void ScrollControl::HBarMoved(Controls::Base* /*control*/)
61 {
62 	Invalidate();
63 }
64 
OnChildBoundsChanged(Gwen::Rect,Base *)65 void ScrollControl::OnChildBoundsChanged(Gwen::Rect /*oldChildBounds*/, Base* /*pChild*/)
66 {
67 	UpdateScrollBars();
68 }
69 
Layout(Skin::Base * skin)70 void ScrollControl::Layout(Skin::Base* skin)
71 {
72 	UpdateScrollBars();
73 	BaseClass::Layout(skin);
74 }
75 
OnMouseWheeled(int iDelta)76 bool ScrollControl::OnMouseWheeled(int iDelta)
77 {
78 	if (CanScrollV() && m_VerticalScrollBar->Visible())
79 	{
80 		if (m_VerticalScrollBar->SetScrolledAmount(m_VerticalScrollBar->GetScrolledAmount() - m_VerticalScrollBar->GetNudgeAmount() * ((float)iDelta / 60.0f), true))
81 			return true;
82 	}
83 
84 	if (CanScrollH() && m_HorizontalScrollBar->Visible())
85 	{
86 		if (m_HorizontalScrollBar->SetScrolledAmount(m_HorizontalScrollBar->GetScrolledAmount() - m_HorizontalScrollBar->GetNudgeAmount() * ((float)iDelta / 60.0f), true))
87 			return true;
88 	}
89 
90 	return false;
91 }
Render(Skin::Base * skin)92 void ScrollControl::Render(Skin::Base* skin)
93 {
94 #if 0
95 
96 	// Debug render - this shouldn't render ANYTHING REALLY - it should be up to the parent!
97 
98 	Gwen::Rect rect = GetRenderBounds();
99 	Gwen::Renderer::Base* render = skin->GetRender();
100 
101 	render->SetDrawColor( Gwen::Color( 255, 255, 0, 100 ) );
102 	render->DrawFilledRect( rect );
103 
104 	render->SetDrawColor( Gwen::Color( 255, 0, 0, 100 ) );
105 	render->DrawFilledRect( m_InnerPanel->GetBounds() );
106 
107 	render->RenderText( skin->GetDefaultFont(), Gwen::Point( 0, 0 ), Utility::Format( L"Offset: %i %i", m_InnerPanel->X(), m_InnerPanel->Y() ) );
108 
109 #else  //0
110 
111 	(void)skin;
112 
113 #endif  //0
114 }
115 
UpdateScrollBars()116 void ScrollControl::UpdateScrollBars()
117 {
118 	if (!m_InnerPanel)
119 		return;
120 
121 	int childrenWidth = 0;
122 	int childrenHeight = 0;
123 
124 	//Get the max size of all our children together
125 	for (Base::List::iterator iter = m_InnerPanel->Children.begin(); iter != m_InnerPanel->Children.end(); ++iter)
126 	{
127 		Base* pChild = *iter;
128 
129 		childrenWidth = Utility::Max(childrenWidth, pChild->Right());
130 		childrenHeight = Utility::Max(childrenHeight, pChild->Bottom());
131 	}
132 
133 	m_InnerPanel->SetSize(Utility::Max(Width(), childrenWidth), Utility::Max(Height(), childrenHeight));
134 
135 	float hg = (float)(childrenWidth + (m_VerticalScrollBar->Hidden() ? 0 : m_VerticalScrollBar->Width()));
136 	if (hg == 0.f)
137 		hg = 0.00001f;
138 	float wPercent = (float)Width() / hg;
139 	hg = (float)(childrenHeight + (m_HorizontalScrollBar->Hidden() ? 0 : m_HorizontalScrollBar->Height()));
140 	if (hg == 0.f)
141 		hg = 0.00001f;
142 	float hPercent = (float)Height() / hg;
143 
144 	if (m_bCanScrollV)
145 		SetVScrollRequired(hPercent >= 1);
146 	else
147 		m_VerticalScrollBar->SetHidden(true);
148 
149 	if (m_bCanScrollH)
150 		SetHScrollRequired(wPercent >= 1);
151 	else
152 		m_HorizontalScrollBar->SetHidden(true);
153 
154 	m_VerticalScrollBar->SetContentSize(m_InnerPanel->Height());
155 	m_VerticalScrollBar->SetViewableContentSize(Height() - (m_HorizontalScrollBar->Hidden() ? 0 : m_HorizontalScrollBar->Height()));
156 
157 	m_HorizontalScrollBar->SetContentSize(m_InnerPanel->Width());
158 	m_HorizontalScrollBar->SetViewableContentSize(Width() - (m_VerticalScrollBar->Hidden() ? 0 : m_VerticalScrollBar->Width()));
159 
160 	int newInnerPanelPosX = 0;
161 	int newInnerPanelPosY = 0;
162 
163 	if (CanScrollV() && !m_VerticalScrollBar->Hidden())
164 	{
165 		newInnerPanelPosY = -((m_InnerPanel->Height()) - Height() + (m_HorizontalScrollBar->Hidden() ? 0 : m_HorizontalScrollBar->Height())) * m_VerticalScrollBar->GetScrolledAmount();
166 	}
167 	if (CanScrollH() && !m_HorizontalScrollBar->Hidden())
168 	{
169 		newInnerPanelPosX = -((m_InnerPanel->Width()) - Width() + (m_VerticalScrollBar->Hidden() ? 0 : m_VerticalScrollBar->Width())) * m_HorizontalScrollBar->GetScrolledAmount();
170 	}
171 
172 	m_InnerPanel->SetPos(newInnerPanelPosX, newInnerPanelPosY);
173 }
174 
SetVScrollRequired(bool req)175 void ScrollControl::SetVScrollRequired(bool req)
176 {
177 	if (req)
178 	{
179 		m_VerticalScrollBar->SetScrolledAmount(0, true);
180 		m_VerticalScrollBar->SetDisabled(true);
181 
182 		if (m_bAutoHideBars)
183 			m_VerticalScrollBar->SetHidden(true);
184 	}
185 	else
186 	{
187 		m_VerticalScrollBar->SetHidden(false);
188 		m_VerticalScrollBar->SetDisabled(false);
189 	}
190 }
191 
SetHScrollRequired(bool req)192 void ScrollControl::SetHScrollRequired(bool req)
193 {
194 	if (req)
195 	{
196 		m_HorizontalScrollBar->SetScrolledAmount(0, true);
197 		m_HorizontalScrollBar->SetDisabled(true);
198 		if (m_bAutoHideBars)
199 			m_HorizontalScrollBar->SetHidden(true);
200 	}
201 	else
202 	{
203 		m_HorizontalScrollBar->SetHidden(false);
204 		m_HorizontalScrollBar->SetDisabled(true);
205 	}
206 }
207 
ScrollToBottom()208 void ScrollControl::ScrollToBottom()
209 {
210 	if (CanScrollV())
211 	{
212 		UpdateScrollBars();
213 		m_VerticalScrollBar->ScrollToBottom();
214 	}
215 }
ScrollToTop()216 void ScrollControl::ScrollToTop()
217 {
218 	if (CanScrollV())
219 	{
220 		UpdateScrollBars();
221 		m_VerticalScrollBar->ScrollToTop();
222 	}
223 }
ScrollToLeft()224 void ScrollControl::ScrollToLeft()
225 {
226 	if (CanScrollH())
227 	{
228 		UpdateScrollBars();
229 		m_HorizontalScrollBar->ScrollToLeft();
230 	}
231 }
ScrollToRight()232 void ScrollControl::ScrollToRight()
233 {
234 	if (CanScrollH())
235 	{
236 		UpdateScrollBars();
237 		m_HorizontalScrollBar->ScrollToRight();
238 	}
239 }
240 
Clear()241 void ScrollControl::Clear()
242 {
243 	m_InnerPanel->RemoveAllChildren();
244 }