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 }