1 /*
2 	GWEN
3 	Copyright (c) 2010 Facepunch Studios
4 	See license in Gwen.h
5 */
6 
7 #include "Gwen/Gwen.h"
8 #include "Gwen/Controls/Canvas.h"
9 #include "Gwen/Skin.h"
10 #include "Gwen/Controls/Menu.h"
11 #include "Gwen/DragAndDrop.h"
12 #include "Gwen/ToolTip.h"
13 
14 #ifndef GWEN_NO_ANIMATION
15 #include "Gwen/Anim.h"
16 #endif
17 
18 using namespace Gwen::Controls;
19 
Canvas(Gwen::Skin::Base * pSkin)20 Canvas::Canvas(Gwen::Skin::Base* pSkin) : BaseClass(NULL), m_bAnyDelete(false), m_fScale(-1)
21 {
22 	SetBounds(0, 0, 10000, 10000);
23 	SetSkin(pSkin);
24 	SetScale(1.0f);
25 	SetBackgroundColor(Color(255, 255, 255, 255));
26 	SetDrawBackground(false);
27 }
28 
RenderCanvas()29 void Canvas::RenderCanvas()
30 {
31 	DoThink();
32 
33 	Gwen::Renderer::Base* render = m_Skin->GetRender();
34 	render->Begin();
35 
36 	RecurseLayout(m_Skin);
37 
38 	render->SetClipRegion(GetBounds());
39 	render->SetRenderOffset(Gwen::Point(0, 0));
40 	render->SetScale(Scale());
41 
42 	if (m_bDrawBackground)
43 	{
44 		render->SetDrawColor(m_BackgroundColor);
45 		render->DrawFilledRect(GetRenderBounds());
46 	}
47 
48 	DoRender(m_Skin);
49 
50 	DragAndDrop::RenderOverlay(this, m_Skin);
51 
52 	ToolTip::RenderToolTip(m_Skin);
53 
54 	render->EndClip();
55 
56 	render->End();
57 	ProcessDelayedDeletes();
58 }
59 
Render(Gwen::Skin::Base *)60 void Canvas::Render(Gwen::Skin::Base* /*pRender*/)
61 {
62 	m_bNeedsRedraw = false;
63 }
64 
OnBoundsChanged(Gwen::Rect oldBounds)65 void Canvas::OnBoundsChanged(Gwen::Rect oldBounds)
66 {
67 	BaseClass::OnBoundsChanged(oldBounds);
68 	InvalidateChildren(true);
69 }
70 
DoThink()71 void Canvas::DoThink()
72 {
73 	if (Hidden()) return;
74 
75 #ifndef GWEN_NO_ANIMATION
76 	Gwen::Anim::Think();
77 #endif
78 
79 	// Reset tabbing
80 	{
81 		NextTab = NULL;
82 		FirstTab = NULL;
83 	}
84 
85 	ProcessDelayedDeletes();
86 	// Check has focus etc..
87 	RecurseLayout(m_Skin);
88 
89 	// If we didn't have a next tab, cycle to the start.
90 	if (NextTab == NULL)
91 		NextTab = FirstTab;
92 
93 	Gwen::Input::OnCanvasThink(this);
94 }
95 
SetScale(float f)96 void Canvas::SetScale(float f)
97 {
98 	if (m_fScale == f) return;
99 
100 	m_fScale = f;
101 
102 	if (m_Skin && m_Skin->GetRender())
103 		m_Skin->GetRender()->SetScale(m_fScale);
104 
105 	OnScaleChanged();
106 	Redraw();
107 }
108 
AddDelayedDelete(Gwen::Controls::Base * pControl)109 void Canvas::AddDelayedDelete(Gwen::Controls::Base* pControl)
110 {
111 	if (!m_bAnyDelete || m_DeleteSet.find(pControl) == m_DeleteSet.end())
112 	{
113 		m_bAnyDelete = true;
114 		m_DeleteSet.insert(pControl);
115 		m_DeleteList.push_back(pControl);
116 	}
117 }
118 
PreDelete(Controls::Base * pControl)119 void Canvas::PreDelete(Controls::Base* pControl)
120 {
121 	if (m_bAnyDelete)
122 	{
123 		std::set<Controls::Base*>::iterator itFind;
124 		if ((itFind = m_DeleteSet.find(pControl)) != m_DeleteSet.end())
125 		{
126 			m_DeleteList.remove(pControl);
127 			m_DeleteSet.erase(pControl);
128 			m_bAnyDelete = !m_DeleteSet.empty();
129 		}
130 	}
131 }
132 
ProcessDelayedDeletes()133 void Canvas::ProcessDelayedDeletes()
134 {
135 	while (m_bAnyDelete)
136 	{
137 		m_bAnyDelete = false;
138 
139 		Controls::Base::List deleteList = m_DeleteList;
140 
141 		m_DeleteList.clear();
142 		m_DeleteSet.clear();
143 
144 		for (Gwen::Controls::Base::List::iterator it = deleteList.begin(); it != deleteList.end(); ++it)
145 		{
146 			Gwen::Controls::Base* pControl = *it;
147 			delete pControl;
148 		}
149 	}
150 }
151 
Release()152 void Canvas::Release()
153 {
154 	Base::List::iterator iter = Children.begin();
155 	while (iter != Children.end())
156 	{
157 		Base* pChild = *iter;
158 		iter = Children.erase(iter);
159 		delete pChild;
160 	}
161 
162 	delete this;
163 }
164 
InputMouseMoved(int x,int y,int deltaX,int deltaY)165 bool Canvas::InputMouseMoved(int x, int y, int deltaX, int deltaY)
166 {
167 	if (Hidden()) return false;
168 
169 	// Todo: Handle scaling here..
170 	//float fScale = 1.0f / Scale();
171 
172 	Gwen::Input::OnMouseMoved(this, x, y, deltaX, deltaY);
173 
174 	if (!Gwen::HoveredControl) return false;
175 	if (Gwen::HoveredControl == this) return false;
176 	if (Gwen::HoveredControl->GetCanvas() != this) return false;
177 
178 	Gwen::HoveredControl->OnMouseMoved(x, y, deltaX, deltaY);
179 	Gwen::HoveredControl->UpdateCursor();
180 
181 	DragAndDrop::OnMouseMoved(Gwen::HoveredControl, x, y);
182 	return true;
183 }
184 
InputMouseButton(int iButton,bool bDown)185 bool Canvas::InputMouseButton(int iButton, bool bDown)
186 {
187 	if (Hidden()) return false;
188 
189 	return Gwen::Input::OnMouseClicked(this, iButton, bDown);
190 }
191 
InputKey(int iKey,bool bDown)192 bool Canvas::InputKey(int iKey, bool bDown)
193 {
194 	if (Hidden()) return false;
195 	if (iKey <= Gwen::Key::Invalid) return false;
196 	if (iKey >= Gwen::Key::Count) return false;
197 
198 	return Gwen::Input::OnKeyEvent(this, iKey, bDown);
199 }
200 
InputCharacter(Gwen::UnicodeChar chr)201 bool Canvas::InputCharacter(Gwen::UnicodeChar chr)
202 {
203 	if (Hidden()) return false;
204 	if (!iswprint(chr)) return false;
205 
206 	//Handle Accelerators
207 	if (Gwen::Input::HandleAccelerator(this, chr))
208 		return true;
209 
210 	//Handle characters
211 	if (!Gwen::KeyboardFocus) return false;
212 	if (Gwen::KeyboardFocus->GetCanvas() != this) return false;
213 	if (!Gwen::KeyboardFocus->Visible()) return false;
214 	if (Gwen::Input::IsControlDown()) return false;
215 
216 	return KeyboardFocus->OnChar(chr);
217 }
218 
InputMouseWheel(int val)219 bool Canvas::InputMouseWheel(int val)
220 {
221 	if (Hidden()) return false;
222 	if (!Gwen::HoveredControl) return false;
223 	if (Gwen::HoveredControl == this) return false;
224 	if (Gwen::HoveredControl->GetCanvas() != this) return false;
225 
226 	return Gwen::HoveredControl->OnMouseWheeled(val);
227 }