/*
* 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 "../private/SkTDArray.h"
#include "SkEvent.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