1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     TenKey.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 <string.h>
17 #include "TenKey.h"
18 #include "Gui.h"
19 #include "Util.h"
20 
21 //////////////////////////////////////////////////////////////////////////////////////////
22 // Constant definitions
23 //////////////////////////////////////////////////////////////////////////////////////////
24 
25 // Control ID
26 #define CONTROL_ID_OK         1000
27 #define CONTROL_ID_CANCEL     1001
28 #define CONTROL_ID_BACK       1002
29 #define CONTROL_ID_CLEAR      1003
30 #define CONTROL_ID_INPUT_BASE 2000
31 
32 // Size of the input box
33 #define BOX_SIZE 16
34 // Hyphen size
35 #define HYPHEN_SIZE 6
36 
37 //////////////////////////////////////////////////////////////////////////////////////////
38 // Function definitions
39 //////////////////////////////////////////////////////////////////////////////////////////
40 
41 namespace
42 {
CreateInputBox(u32 id,u16 x,const wchar_t * pText)43     scene::Label* CreateInputBox(u32 id, u16 x, const wchar_t* pText)
44     {
45         // Label
46         scene::Label* pLabel = new scene::Label(id, x, 8, BOX_SIZE, 36, pText);
47         // Border color
48         nn::util::Color8 borderColor = nn::util::Color8(64, 64, 64, 255);
49 
50         pLabel->SetTextAlign(scene::TEXT_ALIGN_CENTER);
51         pLabel->SetBorderColor(scene::CONTROL_STATE_DEFAULT, borderColor);
52         pLabel->SetBorderWidth(1.0f);
53 
54         return pLabel;
55     }
56 
CreateHyphen(u16 x)57     scene::Label* CreateHyphen(u16 x)
58     {
59         // Label
60         scene::Label* pLabel = new scene::Label(scene::CONTROL_ID_UNUSED, x, 12, HYPHEN_SIZE, 30, L"-");
61 
62         pLabel->SetTextAlign(scene::TEXT_ALIGN_CENTER);
63 
64         return pLabel;
65     }
66 }
67 
68 //////////////////////////////////////////////////////////////////////////////////////////
69 namespace scene
70 {
71 
72 // Constructor.
TenKey()73 TenKey::TenKey()
74 {
75     m_pInput         = NULL;
76     m_length         = 0;
77     m_split          = 0;
78     m_numLowestChars = 1;
79     m_cursor         = 0;
80     m_state          = STATE_NORMAL;
81 }
82 
83 // Destructor.
~TenKey()84 TenKey::~TenKey()
85 {
86     Finalize();
87 }
88 
89 // Performs initialization.
Initialize(u32 length,u32 split,const wchar_t * pInitial,u32 numLowestChars,bool isPassword)90 void TenKey::Initialize(u32 length, u32 split, const wchar_t* pInitial, u32 numLowestChars, bool isPassword)
91 {
92     NN_ASSERT(m_pInput == NULL);
93 
94     m_pInput = new wchar_t[length + 1];
95     NN_ASSERT(m_pInput != NULL);
96 
97     memset(m_pInput, 0, (length + 1) * sizeof (m_pInput[0]));
98 
99     m_length         = length;
100     m_split          = split;
101     m_numLowestChars = numLowestChars;
102     m_isPassword     = isPassword;
103 
104     // Return icon
105     wchar_t backIcon[] = {0xE072, '\0'};
106 
107     scene::AddYesNoButtons(&m_controlManager, CONTROL_ID_OK, CONTROL_ID_CANCEL, L"OK", L"Cancel");
108 
109     m_controlManager.Add(new scene::Button(CONTROL_ID_BACK,   258,  58,  60, 30, backIcon));
110     m_controlManager.Add(new scene::Button(CONTROL_ID_CLEAR,    2,  58,  60, 30, L"CLR"));
111     m_controlManager.Add(new scene::Button(1,                  66,  58,  60, 30, L"1"));
112     m_controlManager.Add(new scene::Button(2,                 130,  58,  60, 30, L"2"));
113     m_controlManager.Add(new scene::Button(3,                 194,  58,  60, 30, L"3"));
114     m_controlManager.Add(new scene::Button(4,                  66,  92,  60, 30, L"4"));
115     m_controlManager.Add(new scene::Button(5,                 130,  92,  60, 30, L"5"));
116     m_controlManager.Add(new scene::Button(6,                 194,  92,  60, 30, L"6"));
117     m_controlManager.Add(new scene::Button(7,                  66, 126,  60, 30, L"7"));
118     m_controlManager.Add(new scene::Button(8,                 130, 126,  60, 30, L"8"));
119     m_controlManager.Add(new scene::Button(9,                 194, 126,  60, 30, L"9"));
120     m_controlManager.Add(new scene::Button(0,                 130, 160,  60, 30, L"0"));
121 
122     // Input information
123     {
124         // Margin
125         const u16 margin = 2;
126         // Number of hyphens
127         u16 hyphenNum = split > 0 ? ((length - 1) / split) : 0;
128         // Size of field where the input box is placed
129         u16 fieldWidth = BOX_SIZE * length + HYPHEN_SIZE * hyphenNum + (margin * (length + hyphenNum - 1));
130         // Position of the input box
131         u16 x = (NN_GX_DISPLAY1_HEIGHT - fieldWidth) / 2;
132 
133         for (u32 i = 0; i < length; i++)
134         {
135             u32 id = CONTROL_ID_INPUT_BASE + i;
136 
137             m_controlManager.Add(CreateInputBox(id, x, L""));
138             x += BOX_SIZE + margin;
139 
140             if (hyphenNum > 0 && i != (length - 1) && ((i + 1) % split) == 0)
141             {
142                 m_controlManager.Add(CreateHyphen(x));
143                 x += HYPHEN_SIZE + margin;
144             }
145         }
146     }
147 
148     if (pInitial)
149     {
150         Reset(pInitial);
151     }
152 
153     m_controlManager.RegisterControlEventCallback(TenKey::MyControlEventCallback, this);
154 }
155 
156 // Performs shutdown.
Finalize()157 void TenKey::Finalize()
158 {
159     if (m_pInput)
160     {
161         delete[] m_pInput;
162     }
163 
164     m_pInput         = NULL;
165     m_length         = 0;
166     m_split          = 0;
167     m_numLowestChars = 1;
168     m_cursor         = 0;
169     m_state          = STATE_NORMAL;
170 
171     m_controlManager.Clear();
172 }
173 
174 // Perform update processing.
Update()175 void TenKey::Update()
176 {
177     m_controlManager.Update();
178 }
179 
180 // Performs rendering.
Draw()181 void TenKey::Draw()
182 {
183     m_controlManager.Draw();
184 }
185 
186 // Resets the state.
Reset(const wchar_t * pInitial)187 void TenKey::Reset(const wchar_t* pInitial)
188 {
189     m_cursor = 0;
190     m_state  = STATE_NORMAL;
191 
192     if (m_pInput)
193     {
194         memset(m_pInput, 0, (m_length + 1) * sizeof (m_pInput[0]));
195 
196         if (pInitial)
197         {
198             m_cursor = scene::wstrlen(pInitial);
199             memcpy(m_pInput, pInitial, (m_cursor > m_length ? m_length : m_cursor) *  sizeof (m_pInput[0]));
200         }
201 
202         if (m_cursor >= m_numLowestChars)
203         {
204             // Enable the OK button
205             m_controlManager.FindBy(CONTROL_ID_OK)->SetState(scene::CONTROL_STATE_DEFAULT);
206         }
207         else
208         {
209             // Disable the OK button
210             m_controlManager.FindBy(CONTROL_ID_OK)->SetState(scene::CONTROL_STATE_DISABLED);
211         }
212 
213         for (u32 i = 0; i < m_length; i++)
214         {
215             if (m_pInput[i] != '\0' && m_isPassword)
216             {
217                 // *
218                 m_controlManager.FindBy(CONTROL_ID_INPUT_BASE + i)->SetText(L"*");
219             }
220             else
221             {
222                 // Character
223                 wchar_t text[] = {m_pInput[i], '\0'};
224 
225                 m_controlManager.FindBy(CONTROL_ID_INPUT_BASE + i)->SetText(text);
226             }
227         }
228     }
229 }
230 
231 // Get values that were input.
GetInputInteger() const232 u32 TenKey::GetInputInteger() const
233 {
234     return scene::wtoi(m_pInput);
235 }
236 
237 // Event callback
MyControlEventCallback(scene::ControlEvent event,scene::ControlBase * pControl,s16 x,s16 y,void * pParam)238 void TenKey::MyControlEventCallback(scene::ControlEvent event, scene::ControlBase* pControl, s16 x, s16 y, void* pParam)
239 {
240     (void)x;
241     (void)y;
242 
243     if (event == scene::CONTROL_EVENT_TOUCH)
244     {
245         // Numeric keypad
246         TenKey* pTenKey = (TenKey*)pParam;
247         // ID of the tapped control
248         u16 controlId = pControl->GetId();
249 
250         switch (controlId)
251         {
252         case CONTROL_ID_OK:
253             {
254                 pTenKey->m_state = STATE_OK;
255             }
256             break;
257         case CONTROL_ID_CANCEL:
258             {
259                 pTenKey->m_state = STATE_CANCELLED;
260             }
261             break;
262         case CONTROL_ID_CLEAR:
263             {
264                 pTenKey->Reset(NULL);
265             }
266             break;
267         case CONTROL_ID_BACK:
268             {
269                 if (pTenKey->m_cursor > 0)
270                 {
271                     // Makes the text at the cursor position blank
272                     pTenKey->m_pInput[--pTenKey->m_cursor] = '\0';
273                     pTenKey->m_controlManager.FindBy(CONTROL_ID_INPUT_BASE + pTenKey->m_cursor)->SetText(L"");
274 
275                     if (pTenKey->m_cursor < pTenKey->m_numLowestChars)
276                     {
277                         // Disable the OK button
278                         pTenKey->m_controlManager.FindBy(CONTROL_ID_OK)->SetState(scene::CONTROL_STATE_DISABLED);
279                     }
280                 }
281             }
282             break;
283         default:
284             {
285                 if (controlId < 10)
286                 {
287                     if (pTenKey->m_cursor < pTenKey->m_length)
288                     {
289                         if (pTenKey->m_isPassword)
290                         {
291                             pTenKey->m_controlManager.FindBy(CONTROL_ID_INPUT_BASE + pTenKey->m_cursor)->SetText(L"*");
292                         }
293                         else
294                         {
295                             // Character
296                             wchar_t text[] = {'0' + controlId, '\0'};
297 
298                             pTenKey->m_controlManager.FindBy(CONTROL_ID_INPUT_BASE + pTenKey->m_cursor)->SetText(text);
299                         }
300 
301                         pTenKey->m_pInput[pTenKey->m_cursor++] = '0' + controlId;
302                     }
303 
304                     if (pTenKey->m_cursor >= pTenKey->m_numLowestChars)
305                     {
306                         // Enable the OK button
307                         pTenKey->m_controlManager.FindBy(CONTROL_ID_OK)->SetState(scene::CONTROL_STATE_DEFAULT);
308                     }
309                 }
310             }
311         }
312     }
313 }
314 
315 } // namespace scene
316