1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     GuiControlManager.cpp
4 
5   Copyright (C)2009-2012 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 46365 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "GuiControlManager.h"
17 
18 namespace scene
19 {
20 
21 // Constructor.
ControlManager()22 ControlManager::ControlManager()
23 {
24     m_touchStatusOld.x     = 0;
25     m_touchStatusOld.y     = 0;
26     m_touchStatusOld.touch = false;
27 
28     m_activeId  = CONTROL_ID_UNUSED;
29     m_pCallback = NULL;
30     m_pParam    = NULL;
31 }
32 
33 // Destructor.
~ControlManager()34 ControlManager::~ControlManager()
35 {
36     Clear();
37 }
38 
39 // Adds controls.
Add(ControlBase * pControl)40 void ControlManager::Add(ControlBase* pControl)
41 {
42     if (pControl)
43     {
44         if (pControl->GetId() != CONTROL_ID_UNUSED)
45         {
46             for (ControlList::iterator it = m_controlList.begin(); it != m_controlList.end(); it++)
47             {
48                 // ID duplication check
49                 NN_ASSERT((*it)->GetId() != pControl->GetId());
50             }
51         }
52 
53         // Set the control manager
54         pControl->SetControlManager(this);
55 
56         m_controlList.push_front(pControl);
57     }
58 }
59 
60 // Delete all controls.
Clear()61 void ControlManager::Clear()
62 {
63     for (ControlList::iterator it = m_controlList.begin(); it != m_controlList.end(); it++)
64     {
65         delete *it;
66     }
67 
68     m_controlList.clear();
69 }
70 
71 // Search for controls.
FindBy(u32 id)72 ControlBase* ControlManager::FindBy(u32 id)
73 {
74     if (id == CONTROL_ID_UNUSED)
75     {
76         return NULL;
77     }
78 
79     for (ControlList::iterator it = m_controlList.begin(); it != m_controlList.end(); it++)
80     {
81         if ((*it)->GetId() == id)
82         {
83             return (*it);
84         }
85     }
86 
87     return NULL;
88 }
89 
90 // Get the control list.
GetList()91 ControlList* ControlManager::GetList()
92 {
93     return &m_controlList;
94 }
95 
96 // Perform update processing.
Update()97 void ControlManager::Update()
98 {
99     // Get the input
100     m_touchReader.ReadLatest(&m_touchStatus);
101 
102     // Current input
103     u16  nowX     = m_touchStatus.x;
104     u16  nowY     = m_touchStatus.y;
105     bool nowTouch = m_touchStatus.touch;
106     // Input for 1 frame prior
107     u16  prevX     = m_touchStatusOld.x;
108     u16  prevY     = m_touchStatusOld.y;
109     bool prevTouch = m_touchStatusOld.touch;
110 
111     for (ControlList::iterator it = m_controlList.begin(); it != m_controlList.end(); it++)
112     {
113         if ((*it)->GetId() == CONTROL_ID_UNUSED)
114         {
115             continue;
116         }
117 
118         s32 x = (*it)->GetX();
119         s32 y = (*it)->GetY();
120 
121         u32 width  = (*it)->GetWidth();
122         u32 height = (*it)->GetHeight();
123 
124         // Current status
125         ControlState nowState = (*it)->GetState();
126 
127         // Do nothing when disabled or hidden
128         if (nowState == CONTROL_STATE_DISABLED || nowState == CONTROL_STATE_HIDE)
129         {
130             continue;
131         }
132 
133         // In control
134         if (nowX >= x && nowX <= x + width && nowY >= y && nowY <= y + height)
135         {
136             // Not tapped last time & tapped this time -> stylus down
137             if (!prevTouch && nowTouch && m_activeId == CONTROL_ID_UNUSED)
138             {
139                 (*it)->OnPenDown();
140                 m_activeId = (*it)->GetId();
141 
142                 if (m_pCallback)
143                 {
144                     m_pCallback(CONTROL_EVENT_PENDOWN, *it, nowX - x, nowY - y, m_pParam);
145                 }
146             }
147             // Tapped last time & tapped this time -> stylus slide
148             if (prevTouch && nowTouch && m_activeId == (*it)->GetId())
149             {
150                 (*it)->OnPenSlide(true);
151 
152                 if (m_pCallback)
153                 {
154                     m_pCallback(CONTROL_EVENT_SLIDE, *it, nowX - x, nowY - y, m_pParam);
155                 }
156             }
157 
158             // Call the callback if state is changed
159             if (nowState != (*it)->GetState() && m_pCallback)
160             {
161                 m_pCallback(CONTROL_EVENT_CHANGE_STATE, *it, nowX - x, nowY - y, m_pParam);
162             }
163         }
164         else
165         {
166             if (m_activeId == (*it)->GetId())
167             {
168                 // If the previous stylus position was inside the control
169                 bool isIn = (prevX >= x && prevX <= x + width && prevY >= y && prevY <= y + height);
170 
171                 // Still being tapped -> stylus slide
172                 if (nowTouch)
173                 {
174                     (*it)->OnPenSlide(false);
175 
176                     if (m_pCallback)
177                     {
178                         m_pCallback(CONTROL_EVENT_SLIDE, *it, nowX - x, nowY - y, m_pParam);
179                     }
180                 }
181                 else
182                 {
183                     (*it)->OnPenUp(isIn);
184 
185                     if (m_pCallback)
186                     {
187                         m_pCallback(CONTROL_EVENT_PENUP, *it, nowX - x, nowY - y, m_pParam);
188                     }
189 
190                     // Stylus released inside the control -> stylus tap
191                     if (isIn)
192                     {
193                         (*it)->OnPenTouch();
194 
195                         if (m_pCallback)
196                         {
197                             m_pCallback(CONTROL_EVENT_TOUCH, *it, nowX - x, nowY - y, m_pParam);
198                         }
199                     }
200 
201                     m_activeId = CONTROL_ID_UNUSED;
202                 }
203 
204                 // Call the callback if state is changed
205                 if (nowState != (*it)->GetState() && m_pCallback)
206                 {
207                     m_pCallback(CONTROL_EVENT_CHANGE_STATE, *it, nowX - x, nowY - y, m_pParam);
208                 }
209             }
210         }
211     }
212 
213     if (nowTouch)
214     {
215         // If nowTouch is not valid, nowX and nowY values are also not valid
216         m_touchStatusOld.x = nowX;
217         m_touchStatusOld.y = nowY;
218     }
219 
220     m_touchStatusOld.touch = nowTouch;
221 }
222 
223 // Performs rendering.
Draw()224 void ControlManager::Draw()
225 {
226     for (ControlList::iterator it = m_controlList.begin(); it != m_controlList.end(); it++)
227     {
228         if ((*it)->GetState() != CONTROL_STATE_HIDE)
229         {
230             (*it)->OnDraw();
231         }
232     }
233 }
234 
235 }
236