aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/views/SkOSMenu.h
blob: 8801a52f505c3bf35338fa65cae5a6ad1a30ae4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#ifndef SkOSMenu_DEFINED
#define SkOSMenu_DEFINED

#include "SkEvent.h"
#include "SkTDArray.h"

class SkOSMenu {
public:
    explicit SkOSMenu(const char title[] = "");
    ~SkOSMenu();

    /**
     * Each of these (except action) has an associated value, which is stored in
     * the event payload for the item.
     * Each type has a specific type for its value...
     *     Action : none
     *     List : int (selected index)
     *     Segmented : int (selected index)
     *     Slider : float
     *     Switch : bool
     *     TextField : string
     *     TriState : TriState
     *     Custom : custom object/value
     */
    enum Type {
        kAction_Type,
        kList_Type,
        kSlider_Type,
        kSwitch_Type,
        kTriState_Type,
        kTextField_Type,
        kCustom_Type
    };

    enum TriState {
        kMixedState = -1,
        kOffState = 0,
        kOnState = 1
    };

    class Item {
    public:
        /**
         * Auto increments a global to generate an unique ID for each new item
         * Note: Thread safe
         */
        Item(const char label[], SkOSMenu::Type type, const char slotName[],
             SkEvent* evt);
        ~Item() { delete fEvent; }

        SkEvent*    getEvent() const { return fEvent; }
        int         getID() const { return fID; }
        const char* getLabel() const { return fLabel.c_str(); }
        const char* getSlotName() const { return fSlotName.c_str(); }
        Type        getType() const { return fType; }
        void        setKeyEquivalent(SkUnichar key) { fKey = key; }
        SkUnichar   getKeyEquivalent() const { return fKey; }

        /**
         * Helper functions for predefined types
         */
        void setBool(bool value) const;             //For Switch
        void setScalar(SkScalar value) const;       //For Slider
        void setInt(int value) const;               //For List
        void setTriState(TriState value) const;     //For Tristate
        void setString(const char value[]) const;   //For TextField

        /**
         * Post event associated with the menu item to target, any changes to
         * the associated event must be made prior to calling this method
         */
        void postEvent() const { (new SkEvent(*(fEvent)))->post(); }

    private:
        int             fID;
        SkEvent*        fEvent;
        SkString        fLabel;
        SkString        fSlotName;
        Type            fType;
        SkUnichar       fKey;
    };

    void        reset();
    const char* getTitle() const { return fTitle.c_str(); }
    void        setTitle (const char title[]) { fTitle.set(title); }
    int         getCount() const { return fItems.count(); }
    const Item* getItemByID(int itemID) const;
    void        getItems(const Item* items[]) const;

    /**
     * Assign key to the menu item with itemID, will do nothing if there's no
     * item with the id given
     */
    void        assignKeyEquivalentToItem(int itemID, SkUnichar key);
    /**
     * Call this in a SkView's onHandleChar to trigger any menu items with the
     * given key equivalent. If such an item is found, the method will return
     * true and its corresponding event will be triggered (default behavior
     * defined for switches(toggling), tristates(cycle), and lists(cycle),
     * for anything else, the event attached is posted without state changes)
     * If no menu item can be matched with the key, false will be returned
     */
    bool        handleKeyEquivalent(SkUnichar key);

    /**
     * The following functions append new items to the menu and returns their
     * associated unique id, which can be used to by the client to refer to
     * the menu item created and change its state. slotName specifies the string
     * identifier of any state/value to be returned in the item's SkEvent object
     * NOTE: evt must be dynamically allocated
     */
    int appendItem(const char label[], Type type, const char slotName[],
                   SkEvent* evt);

    /**
     * Create predefined items with the given parameters. To be used with the
     * other helper functions below to retrive/update state information.
     * Note: the helper functions below assume that slotName is UNIQUE for all
     * menu items of the same type since it's used to identify the event
     */
    int appendAction(const char label[], SkEventSinkID target);
    int appendList(const char label[], const char slotName[],
                   SkEventSinkID target, int defaultIndex, const char[] ...);
    int appendSlider(const char label[], const char slotName[],
                     SkEventSinkID target, SkScalar min, SkScalar max,
                     SkScalar defaultValue);
    int appendSwitch(const char label[], const char slotName[],
                     SkEventSinkID target, bool defaultState = false);
    int appendTriState(const char label[], const char slotName[],
                       SkEventSinkID target, TriState defaultState = kOffState);
    int appendTextField(const char label[], const char slotName[],
                        SkEventSinkID target, const char placeholder[] = "");


    /**
     * Helper functions to retrieve information other than the stored value for
     * some predefined types
     */
    static bool FindListItemCount(const SkEvent& evt, int* count);
    /**
     * Ensure that the items array can store n SkStrings where n is the count
     * extracted using FindListItemCount
     */
    static bool FindListItems(const SkEvent& evt, SkString items[]);
    static bool FindSliderMin(const SkEvent& evt, SkScalar* min);
    static bool FindSliderMax(const SkEvent& evt, SkScalar* max);

    /**
     * Returns true if an action with the given label is found, false otherwise
     */
    static bool FindAction(const SkEvent& evt, const char label[]);
    /**
     * The following helper functions will return true if evt is generated from
     * a predefined item type and retrieve the corresponding state information.
     * They will return false and leave value unchanged if there's a type
     * mismatch or slotName is incorrect
     */
    static bool FindListIndex(const SkEvent& evt, const char slotName[], int* value);
    static bool FindSliderValue(const SkEvent& evt, const char slotName[], SkScalar* value);
    static bool FindSwitchState(const SkEvent& evt, const char slotName[], bool* value);
    static bool FindTriState(const SkEvent& evt, const char slotName[], TriState* value);
    static bool FindText(const SkEvent& evt, const char slotName[], SkString* value);

private:
    SkString fTitle;
    SkTDArray<Item*> fItems;

    // illegal
    SkOSMenu(const SkOSMenu&);
    SkOSMenu& operator=(const SkOSMenu&);
};

#endif