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
16class SkOSMenu {
17public:
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);
58        ~Item() { delete fEvent; }
59
60        SkEvent*    getEvent() const { return fEvent; }
61        int         getID() const { return fID; }
62        const char* getLabel() const { return fLabel.c_str(); }
63        const char* getSlotName() const { return fSlotName.c_str(); }
64        Type        getType() const { return fType; }
65        void        setKeyEquivalent(SkUnichar key) { fKey = key; }
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         */
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();
93    const char* getTitle() const { return fTitle.c_str(); }
94    void        setTitle (const char title[]) { fTitle.set(title); }
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
173private:
174    SkString fTitle;
175    SkTDArray<Item*> fItems;
176
177    // illegal
178    SkOSMenu(const SkOSMenu&);
179    SkOSMenu& operator=(const SkOSMenu&);
180};
181
182#endif
183