1 
2 /*
3  * Copyright 2006 The Android Open Source Project
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #ifndef SkOSMenu_DEFINED
11 #define SkOSMenu_DEFINED
12 
13 #include "SkEvent.h"
14 #include "SkTDArray.h"
15 
16 class SkOSMenu {
17 public:
18     explicit SkOSMenu(const char title[] = "");
19     ~SkOSMenu();
20 
21     /**
22      * Each of these (except action) has an associated value, which is stored in
23      * the event payload for the item.
24      * Each type has a specific type for its value...
25      *     Action : none
26      *     List : int (selected index)
27      *     Segmented : int (selected index)
28      *     Slider : float
29      *     Switch : bool
30      *     TextField : string
31      *     TriState : TriState
32      *     Custom : custom object/value
33      */
34     enum Type {
35         kAction_Type,
36         kList_Type,
37         kSlider_Type,
38         kSwitch_Type,
39         kTriState_Type,
40         kTextField_Type,
41         kCustom_Type
42     };
43 
44     enum TriState {
45         kMixedState = -1,
46         kOffState = 0,
47         kOnState = 1
48     };
49 
50     class Item {
51     public:
52         /**
53          * Auto increments a global to generate an unique ID for each new item
54          * Note: Thread safe
55          */
56         Item(const char label[], SkOSMenu::Type type, const char slotName[],
57              SkEvent* evt);
~Item()58         ~Item() { delete fEvent; }
59 
getEvent()60         SkEvent*    getEvent() const { return fEvent; }
getID()61         int         getID() const { return fID; }
getLabel()62         const char* getLabel() const { return fLabel.c_str(); }
getSlotName()63         const char* getSlotName() const { return fSlotName.c_str(); }
getType()64         Type        getType() const { return fType; }
setKeyEquivalent(SkUnichar key)65         void        setKeyEquivalent(SkUnichar key) { fKey = key; }
getKeyEquivalent()66         SkUnichar   getKeyEquivalent() const { return fKey; }
67 
68         /**
69          * Helper functions for predefined types
70          */
71         void setBool(bool value) const;             //For Switch
72         void setScalar(SkScalar value) const;       //For Slider
73         void setInt(int value) const;               //For List
74         void setTriState(TriState value) const;     //For Tristate
75         void setString(const char value[]) const;   //For TextField
76 
77         /**
78          * Post event associated with the menu item to target, any changes to
79          * the associated event must be made prior to calling this method
80          */
postEvent()81         void postEvent() const { (new SkEvent(*(fEvent)))->post(); }
82 
83     private:
84         int             fID;
85         SkEvent*        fEvent;
86         SkString        fLabel;
87         SkString        fSlotName;
88         Type            fType;
89         SkUnichar       fKey;
90     };
91 
92     void        reset();
getTitle()93     const char* getTitle() const { return fTitle.c_str(); }
setTitle(const char title[])94     void        setTitle (const char title[]) { fTitle.set(title); }
getCount()95     int         getCount() const { return fItems.count(); }
96     const Item* getItemByID(int itemID) const;
97     void        getItems(const Item* items[]) const;
98 
99     /**
100      * Assign key to the menu item with itemID, will do nothing if there's no
101      * item with the id given
102      */
103     void        assignKeyEquivalentToItem(int itemID, SkUnichar key);
104     /**
105      * Call this in a SkView's onHandleChar to trigger any menu items with the
106      * given key equivalent. If such an item is found, the method will return
107      * true and its corresponding event will be triggered (default behavior
108      * defined for switches(toggling), tristates(cycle), and lists(cycle),
109      * for anything else, the event attached is posted without state changes)
110      * If no menu item can be matched with the key, false will be returned
111      */
112     bool        handleKeyEquivalent(SkUnichar key);
113 
114     /**
115      * The following functions append new items to the menu and returns their
116      * associated unique id, which can be used to by the client to refer to
117      * the menu item created and change its state. slotName specifies the string
118      * identifier of any state/value to be returned in the item's SkEvent object
119      * NOTE: evt must be dynamically allocated
120      */
121     int appendItem(const char label[], Type type, const char slotName[],
122                    SkEvent* evt);
123 
124     /**
125      * Create predefined items with the given parameters. To be used with the
126      * other helper functions below to retrive/update state information.
127      * Note: the helper functions below assume that slotName is UNIQUE for all
128      * menu items of the same type since it's used to identify the event
129      */
130     int appendAction(const char label[], SkEventSinkID target);
131     int appendList(const char label[], const char slotName[],
132                    SkEventSinkID target, int defaultIndex, const char* ...);
133     int appendSlider(const char label[], const char slotName[],
134                      SkEventSinkID target, SkScalar min, SkScalar max,
135                      SkScalar defaultValue);
136     int appendSwitch(const char label[], const char slotName[],
137                      SkEventSinkID target, bool defaultState = false);
138     int appendTriState(const char label[], const char slotName[],
139                        SkEventSinkID target, TriState defaultState = kOffState);
140     int appendTextField(const char label[], const char slotName[],
141                         SkEventSinkID target, const char placeholder[] = "");
142 
143 
144     /**
145      * Helper functions to retrieve information other than the stored value for
146      * some predefined types
147      */
148     static bool FindListItemCount(const SkEvent& evt, int* count);
149     /**
150      * Ensure that the items array can store n SkStrings where n is the count
151      * extracted using FindListItemCount
152      */
153     static bool FindListItems(const SkEvent& evt, SkString items[]);
154     static bool FindSliderMin(const SkEvent& evt, SkScalar* min);
155     static bool FindSliderMax(const SkEvent& evt, SkScalar* max);
156 
157     /**
158      * Returns true if an action with the given label is found, false otherwise
159      */
160     static bool FindAction(const SkEvent& evt, const char label[]);
161     /**
162      * The following helper functions will return true if evt is generated from
163      * a predefined item type and retrieve the corresponding state information.
164      * They will return false and leave value unchanged if there's a type
165      * mismatch or slotName is incorrect
166      */
167     static bool FindListIndex(const SkEvent& evt, const char slotName[], int* value);
168     static bool FindSliderValue(const SkEvent& evt, const char slotName[], SkScalar* value);
169     static bool FindSwitchState(const SkEvent& evt, const char slotName[], bool* value);
170     static bool FindTriState(const SkEvent& evt, const char slotName[], TriState* value);
171     static bool FindText(const SkEvent& evt, const char slotName[], SkString* value);
172 
173 private:
174     SkString fTitle;
175     SkTDArray<Item*> fItems;
176 
177     // illegal
178     SkOSMenu(const SkOSMenu&);
179     SkOSMenu& operator=(const SkOSMenu&);
180 };
181 
182 #endif
183