1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     Menu.h
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:$
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NN_SAMPLE_DEMOS_PHTSEL_MENU_H_
17 #define NN_SAMPLE_DEMOS_PHTSEL_MENU_H_
18 
19 #include <nn.h>
20 #include "demo.h"
21 #include "PadEx.h"
22 
23 class ItemBase;
24 
25 
26 ////////////////////////////////////////////////////////////////////////////////////////////////
27 /// Menu
28 ///
29 ////////////////////////////////////////////////////////////////////////////////////////////////
30 class Menu
31 {
32 public:
Menu()33     Menu()
34         : m_nItemNum(0)
35         , m_nCurItem(0)
36     {
37         // Nop
38     }
39 
40     /// Add item
Append(ItemBase * pItem)41     void  Append( ItemBase* pItem )
42     {
43         NN_ASSERT( m_nItemNum < ITEM_MAX );
44         const ItemInfo  info = { pItem };
45         m_itemInfoList[m_nItemNum] = info;
46         ++m_nItemNum;
47     }
48 
49     //==============================
50 
51     /// Get number of items
GetItemNum()52     int  GetItemNum() const  { return m_nItemNum; }
53 
54     /// Get selected item
GetSelectItemIndex()55     int  GetSelectItemIndex() const  { return m_nCurItem; }
56 
57     /// Switch selected item
AddSelectItemIndex(int inc)58     void  AddSelectItemIndex( int inc )
59     {
60         m_nCurItem += inc;
61         if( m_nCurItem >= m_nItemNum ) m_nCurItem = 0;
62         if( m_nCurItem < 0 ) m_nCurItem = m_nItemNum-1;
63     }
64 
65     /// Get item
GetItemPtr(int nItemIdx)66     const ItemBase*  GetItemPtr( int nItemIdx ) const
67     {
68         return m_itemInfoList[nItemIdx].pItem;
69     }
GetItemPtr(int nItemIdx)70     ItemBase*  GetItemPtr( int nItemIdx )
71     {
72         return m_itemInfoList[nItemIdx].pItem;
73     }
74 
75     /// Get selected item
GetSelectItemPtr()76     const ItemBase*  GetSelectItemPtr() const  { return GetItemPtr( GetSelectItemIndex() ); }
GetSelectItemPtr()77           ItemBase*  GetSelectItemPtr()        { return GetItemPtr( GetSelectItemIndex() ); }
78 
79 private:
80     struct ItemInfo
81     {
82         ItemBase*  pItem;
83     };
84     // Dynamic memory allocation failed, so let's try a fixed-length array
85     static const int  ITEM_MAX  = 32;
86     typedef ItemInfo  ItemInfoContainer[ITEM_MAX];
87 
88 private:
89     s32  m_nItemNum;
90     s32  m_nCurItem;
91     ItemInfoContainer  m_itemInfoList;
92 };
93 
94 
95 ////////////////////////////////////////////////////////////////////////////////////////////////
96 /// Item base class
97 ///
98 ////////////////////////////////////////////////////////////////////////////////////////////////
99 class ItemBase
100 {
101 public:
102     explicit ItemBase( const char* pName, s32 nValueNum, bool bEnableDetailEditMode=false )
m_pName(pName)103         : m_pName(pName)
104         , m_nValueNum(nValueNum)
105         , m_bEnableDetailEditMode(bEnableDetailEditMode)
106         , m_nSelectIdx(0)
107         , m_bDetailEdit(false)
108     {};
~ItemBase()109     virtual ~ItemBase() {};
110 
111     /// Number of values
GetValueNum()112     s32  GetValueNum() const  { return m_nValueNum; }
113 
114     /// Item name
GetItemName()115     const char*  GetItemName() const  { return m_pName; }
116 
117     /// Is there an advanced edit mode?
IsEnableDetailEditMode()118     bool  IsEnableDetailEditMode() const  { return m_bEnableDetailEditMode; }
119 
120     /// Advanced edit mode
SetDetailEditMode(bool bDetailEdit)121     void  SetDetailEditMode( bool bDetailEdit )  { m_bDetailEdit = bDetailEdit; }
IsDetailEditMode()122     bool  IsDetailEditMode() const  { return m_bDetailEdit; }
123 
124     /// Selection
SetSelectIndex(int idx)125     void  SetSelectIndex( int idx )
126     {
127         NN_ASSERT( idx>=0 && idx<GetValueNum() );
128         m_nSelectIdx = idx;
129     }
130 
131     /// Change selection
AddSelectIndex(int add)132     void  AddSelectIndex( int add )
133     {
134         if( GetValueNum() > 0 )
135         {
136             m_nSelectIdx += add;
137             if( m_nSelectIdx >= GetValueNum() ) m_nSelectIdx = 0;
138             if( m_nSelectIdx < 0 ) m_nSelectIdx = GetValueNum()-1;
139         }
140     }
141 
142     /// Get selection
GetSelectIndex()143     s32  GetSelectIndex() const  { return m_nSelectIdx; }
144 
145     //==============================
146 
147     /// Manipulate individual items
Proc(const PadEx & padEx)148     virtual void  Proc( const PadEx& padEx )
149     {
150         if ( (padEx.GetRepeat() & (nn::hid::BUTTON_LEFT)) )
151         {
152             AddSelectIndex( -1 );
153         }
154         else if ( (padEx.GetRepeat() & (nn::hid::BUTTON_RIGHT)) )
155         {
156             AddSelectIndex( 1 );
157         }
158     }
159 
160     /// Render
161     virtual void  Draw( demo::RenderSystemDrawing& df, s32 x, s32 y, bool bSelectItem ) const = 0;
162 
163 protected:
164     /// Common rendering of item name
DrawItemNameCommon(demo::RenderSystemDrawing & df,s32 x,s32 y,bool bSelectItem)165     void  DrawItemNameCommon( demo::RenderSystemDrawing& df, s32 x, s32 y, bool bSelectItem ) const
166     {
167         const bool  bColor = bSelectItem && !IsDetailEditMode();
168         if( bColor ) df.SetColor(1.0f, 0.5f, 0.1f);
169         else         df.SetColor(1.0f, 1.0f, 1.0f);
170 
171         df.DrawText( x, y, "%s", GetItemName() );
172         if( IsEnableDetailEditMode() )
173         {
174             df.SetColor(1.0f, 1.0f, 0.0f);
175             df.DrawText( x+160-8*2, y, IsDetailEditMode() ? "B<" : "A>" );
176 
177             if( bColor ) df.SetColor(1.0f, 0.5f, 0.1f);
178             else         df.SetColor(1.0f, 1.0f, 1.0f);
179         }
180     }
181 
182 private:
183     const char* const  m_pName;
184     const s32          m_nValueNum;
185     const bool         m_bEnableDetailEditMode;
186 
187     NN_PADDING3;
188 
189     s32                 m_nSelectIdx;
190     bool               m_bDetailEdit;
191 
192     NN_PADDING3;
193 };
194 
195 
196 ////////////////////////////////////////////////////////////////////////////////////////////////
197 /// Array definition item
198 ///
199 ////////////////////////////////////////////////////////////////////////////////////////////////
200 template <typename ValueType>
201 class ArrayItem : public ItemBase
202 {
203 public:
204     typedef ValueType  value_type;
205 
206 public:
207     template <int ArraySize>
ArrayItem(const char * pName,const value_type (& pValueArray)[ArraySize],const char * const (& pNameArray)[ArraySize])208     ArrayItem(
209         const char* pName,
210         const value_type   (&pValueArray)[ArraySize],
211         const char* const  (&pNameArray)[ArraySize]
212     )
213         : ItemBase(pName, ArraySize)
214         , m_pValueArray(pValueArray)
215         , m_pNameArray(pNameArray)
216         , m_nArraySize(ArraySize)
217     {
218         // Nop
219     }
220 
221     /// Render
Draw(demo::RenderSystemDrawing & df,s32 x,s32 y,bool bSelectItem)222     virtual void  Draw( demo::RenderSystemDrawing& df, s32 x, s32 y, bool bSelectItem ) const
223     {
224         DrawItemNameCommon( df, x, y, bSelectItem );
225         NN_ASSERT( GetSelectValueName() );
226         //df.DrawText( x+160, y, "%d/%d:%s", GetSelectIndex()+1, GetValueNum(), GetSelectValueName() );
227         df.DrawText( x+160, y, "%s", GetSelectValueName() );
228     }
229 
230     //==============================
231 
232     /// Get value
GetValue(s32 idx)233     value_type  GetValue( s32 idx ) const
234     {
235         NN_ASSERT( idx>=0 && idx<GetValueNum() );
236         return m_pValueArray[idx];
237     }
238 
239     /// Get selected value
GetSelectValue()240     value_type  GetSelectValue() const
241     {
242         return GetValue( GetSelectIndex() );
243     }
244 
245     /// Set selection from value
SetSelectValue(value_type value)246     void  SetSelectValue( value_type value )
247     {
248         for( s32 i=0; i<GetValueNum(); ++i )
249         {
250             if( GetValue(i) == value )
251             {
252                 SetSelectIndex(i);
253                 return;
254             }
255         }
256         NN_ASSERTMSG(0,"SetSelectValue: bad value.");
257     }
258 
259 private:
260     /// Get value name
GetSelectValueName()261     const char*  GetSelectValueName() const
262     {
263         return m_pNameArray[GetSelectIndex()];
264     }
265 
266 private:
267     const value_type*   m_pValueArray;
268     const char* const*  m_pNameArray;
269     s32  m_nArraySize;
270 };
271 
272 
273 ////////////////////////////////////////////////////////////////////////////////////////////////
274 /// Range definition
275 ///
276 ////////////////////////////////////////////////////////////////////////////////////////////////
277 template <s32 MinValue, s32 MaxValue>
278 class RangeItem : public ItemBase
279 {
280     NN_STATIC_ASSERT( MinValue <= MaxValue );
281 public:
282     typedef s32  value_type;
283 
284 public:
RangeItem(const char * pName)285     RangeItem( const char* pName ) : ItemBase(pName, MaxValue - MinValue + 1) {}
286 
287     /// Render
Draw(demo::RenderSystemDrawing & df,s32 x,s32 y,bool bSelectItem)288     virtual void  Draw( demo::RenderSystemDrawing& df, s32 x, s32 y, bool bSelectItem ) const
289     {
290         DrawItemNameCommon( df, x, y, bSelectItem );
291         //df.DrawText( x+160, y, "%d/%d:%d", GetSelectIndex()+1, GetValueNum(), GetSelectValue() );
292         df.DrawText( x+160, y, "%d", GetSelectValue() );
293     }
294 
295     //==============================
296 
297     /// Get value
GetValue(s32 idx)298     value_type  GetValue( s32 idx ) const
299     {
300         NN_ASSERT( idx>=0 && idx<GetValueNum() );
301         return MinValue + idx;
302     }
303 
304     /// Get selected value
GetSelectValue()305     value_type  GetSelectValue() const
306     {
307         return GetValue( GetSelectIndex() );
308     }
309 
310     /// Set selection from value
SetSelectValue(value_type value)311     void  SetSelectValue( value_type value )
312     {
313         for( s32 i=0; i<GetValueNum(); ++i )
314         {
315             if( GetValue(i) == value )
316             {
317                 SetSelectIndex(i);
318                 return;
319             }
320         }
321         NN_ASSERTMSG(0,"SetSelectValue: bad value.");
322     }
323 };
324 
325 /* NN_SAMPLE_DEMOS_PHTSEL_MENU_H_ */
326 #endif
327 
328 /*---------------------------------------------------------------------------*
329   End of file
330  *---------------------------------------------------------------------------*/
331