Updated SkOSMenu to use the updated SkEvents

http://codereview.appspot.com/4809075/


git-svn-id: http://skia.googlecode.com/svn/trunk@2055 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
yangsu@google.com 2011-08-05 22:11:41 +00:00
parent a767fa06ca
commit e55f533f4c
2 changed files with 199 additions and 101 deletions

View File

@ -18,7 +18,6 @@ public:
explicit SkOSMenu(const char title[] = ""); explicit SkOSMenu(const char title[] = "");
~SkOSMenu(); ~SkOSMenu();
void reset();
/** /**
* Each of these (except action) has an associated value, which is stored in * Each of these (except action) has an associated value, which is stored in
* the event payload for the item. * the event payload for the item.
@ -32,12 +31,6 @@ public:
* TriState : TriState * TriState : TriState
* Custom : custom object/value * Custom : custom object/value
*/ */
enum TriState {
kMixedState = -1,
kOffState = 0,
kOnState = 1
};
enum Type { enum Type {
kAction_Type, kAction_Type,
kList_Type, kList_Type,
@ -48,59 +41,90 @@ public:
kCustom_Type kCustom_Type
}; };
enum TriState {
kMixedState = -1,
kOffState = 0,
kOnState = 1
};
class Item { class Item {
public: public:
//Auto increments a global to generate an unique ID for each new item /**
//Thread safe * 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[], Item(const char label[], SkOSMenu::Type type, const char slotName[],
SkEvent* evt, SkEventSinkID target); SkEvent* evt);
~Item() { delete fEvent; } ~Item() { delete fEvent; }
SkEvent* getEvent() const { return fEvent; } SkEvent* getEvent() const { return fEvent; }
int getID() { return fID; } int getID() const { return fID; }
const char* getLabel() const { return fLabel.c_str(); } const char* getLabel() const { return fLabel.c_str(); }
const char* getSlotName() const { return fSlotName.c_str(); } const char* getSlotName() const { return fSlotName.c_str(); }
Type getType() const { return fType; } Type getType() const { return fType; }
void setKeyEquivalent(SkUnichar key) { fKey = key; }
SkUnichar getKeyEquivalent() const { return fKey; }
//Post event associated with the menu item to target, any changes to the /**
//associated event must be made prior to calling this method. * Post event associated with the menu item to target, any changes to
void postEvent() const { * the associated event must be made prior to calling this method
(new SkEvent(*(fEvent)))->setTargetID(fTarget)->post(); */
} void postEvent() const { (new SkEvent(*(fEvent)))->post(); }
//Helper functions for predefined types /**
void postEventWithBool(bool value) const; //For Switch * Helper functions for predefined types
void postEventWithScalar(SkScalar value) const; //For Slider */
void postEventWithInt(int value) const; //For List, TriState void postEventWithBool(bool value) const; //For Switch
void postEventWithScalar(SkScalar value) const; //For Slider
void postEventWithInt(int value) const; //For List, TriState
void postEventWithString(const char value[]) const; //For TextField void postEventWithString(const char value[]) const; //For TextField
private: private:
int fID; int fID;
SkEvent* fEvent; SkEvent* fEvent;
SkString fLabel; SkString fLabel;
SkString fSlotName; SkString fSlotName;
SkEventSinkID fTarget;
Type fType; Type fType;
SkUnichar fKey;
}; };
//The following functions append new items to the menu and returns their void reset();
//associated unique id, which can be used to by the client to refer to const char* getTitle() const { return fTitle.c_str(); }
//the menu item created and change its state. slotName specifies the string void setTitle (const char title[]) { fTitle.set(title); }
//identifier of any state/value to be returned in the item's SkEvent object int countItems() const { return fItems.count(); }
//NOTE: evt must be dynamically allocated const Item* getItem(int index) const { return fItems[index]; }
/**
* 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[], int appendItem(const char label[], Type type, const char slotName[],
SkEvent* evt, SkEventSinkID target); SkEvent* evt);
//Predefined items and helper functions: /**
//Identifiers * Create predefined items with the given parameters. To be used with the
static const char* EventType; * other helper functions below to retrive/update state information.
static const char* Delimiter; * Note: the helper functions below assume that slotName is UNIQUE for all
static const char* List_Items_Str; * menu items of the same type since it's used to identify the event
static const char* Slider_Min_Scalar; */
static const char* Slider_Max_Scalar;
//Create predefined items with the given parameters. To be used with the
int appendAction(const char label[], SkEventSinkID target); int appendAction(const char label[], SkEventSinkID target);
int appendList(const char label[], const char slotName[], int appendList(const char label[], const char slotName[],
SkEventSinkID target, int defaultIndex, const char[] ...); SkEventSinkID target, int defaultIndex, const char[] ...);
@ -110,26 +134,40 @@ public:
int appendSwitch(const char label[], const char slotName[], int appendSwitch(const char label[], const char slotName[],
SkEventSinkID target, bool defaultState = false); SkEventSinkID target, bool defaultState = false);
int appendTriState(const char label[], const char slotName[], int appendTriState(const char label[], const char slotName[],
SkEventSinkID target, SkOSMenu::TriState defaultState = kOffState); SkEventSinkID target, TriState defaultState = kOffState);
int appendTextField(const char label[], const char slotName[], int appendTextField(const char label[], const char slotName[],
SkEventSinkID target, const char placeholder[] = ""); SkEventSinkID target, const char placeholder[] = "");
//Returns true if the event is of type SkOSMenu::EventType and retrieves
//value stored in the evt that corresponds to the slotName. Otherwise, /**
//returns false and leaves value unchanged * 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[]); static bool FindAction(const SkEvent* evt, const char label[]);
static bool FindListIndex(const SkEvent* evt, const char slotName[], int* selected); /**
* 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 FindSliderValue(const SkEvent* evt, const char slotName[], SkScalar* value);
static bool FindSwitchState(const SkEvent* evt, const char slotName[], bool* value); static bool FindSwitchState(const SkEvent* evt, const char slotName[], bool* value);
static bool FindTriState(const SkEvent* evt, const char slotName[], TriState* state); static bool FindTriState(const SkEvent* evt, const char slotName[], TriState* value);
static bool FindText(const SkEvent* evt, const char slotName[], SkString* value); static bool FindText(const SkEvent* evt, const char slotName[], SkString* value);
const char* getTitle() const { return fTitle.c_str(); }
void setTitle (const char title[]) { fTitle.set(title); }
// called by SkOSWindow when it receives an OS menu event
int countItems() const;
const Item* getItem(int index) const;
private: private:
SkString fTitle; SkString fTitle;
SkTDArray<Item*> fItems; SkTDArray<Item*> fItems;

View File

@ -23,23 +23,63 @@ void SkOSMenu::reset() {
fTitle.reset(); fTitle.reset();
} }
int SkOSMenu::countItems() const { void SkOSMenu::assignKeyEquivalentToItem(int itemID, SkUnichar key) {
return fItems.count(); for (int i = 0; i < fItems.count(); ++i) {
if (itemID == fItems[i]->getID())
fItems[i]->setKeyEquivalent(key);
}
} }
const SkOSMenu::Item* SkOSMenu::getItem(int index) const{ bool SkOSMenu::handleKeyEquivalent(SkUnichar key) {
return fItems[index]; int value = 0, size = 0;
bool state;
SkOSMenu::TriState tristate;
for (int i = 0; i < fItems.count(); ++i) {
Item* item = fItems[i];
if (item->getKeyEquivalent()== key) {
SkString list;
switch (item->getType()) {
case kList_Type:
SkOSMenu::FindListItemCount(item->getEvent(), &size);
SkOSMenu::FindListIndex(item->getEvent(), item->getSlotName(), &value);
value = (value + 1) % size;
item->postEventWithInt(value);
break;
case kSwitch_Type:
SkOSMenu::FindSwitchState(item->getEvent(), item->getSlotName(), &state);
item->postEventWithBool(!state);
break;
case kTriState_Type:
SkOSMenu::FindTriState(item->getEvent(), item->getSlotName(), &tristate);
if (kOnState == tristate)
tristate = kMixedState;
else
tristate = (SkOSMenu::TriState)((int)tristate + 1);
item->postEventWithInt(tristate);
break;
case kAction_Type:
case kCustom_Type:
case kSlider_Type:
case kTextField_Type:
default:
item->postEvent();
break;
}
return true;
}
}
return false;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
SkOSMenu::Item::Item(const char label[], SkOSMenu::Type type, SkOSMenu::Item::Item(const char label[], SkOSMenu::Type type,
const char slotName[], SkEvent* evt, SkEventSinkID target) { const char slotName[], SkEvent* evt) {
fLabel.set(label); fLabel.set(label);
fSlotName.set(slotName); fSlotName.set(slotName);
fType = type; fType = type;
fTarget = target;
fEvent = evt; fEvent = evt;
fKey = 0;
fID = sk_atomic_inc(&gOSMenuCmd); fID = sk_atomic_inc(&gOSMenuCmd);
} }
@ -69,110 +109,130 @@ void SkOSMenu::Item::postEventWithString(const char value[]) const {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
const char* SkOSMenu::EventType = "SkOSMenuEventType"; static const char* gMenuEventType = "SkOSMenuEventType";
const char* SkOSMenu::Delimiter = "|"; static const char* gSlider_Min_Scalar = "SkOSMenuSlider_Min";
const char* SkOSMenu::Slider_Min_Scalar = "SkOSMenuSlider_Min"; static const char* gSlider_Max_Scalar = "SkOSMenuSlider_Max";
const char* SkOSMenu::Slider_Max_Scalar = "SkOSMenuSlider_Max"; static const char* gDelimiter = "|";
const char* SkOSMenu::List_Items_Str = "SkOSMenuList_Items"; static const char* gList_Items_Str = "SkOSMenuList_Items";
static const char* gList_ItemCount_S32 = "SkOSMenuList_ItemCount";
int SkOSMenu::appendItem(const char label[], Type type, const char slotName[], int SkOSMenu::appendItem(const char label[], Type type, const char slotName[],
SkEvent* evt, SkEventSinkID target) { SkEvent* evt) {
SkOSMenu::Item* item = new Item(label, type, slotName, evt, target); SkOSMenu::Item* item = new Item(label, type, slotName, evt);
fItems.append(1, &item); fItems.append(1, &item);
return item->getID(); return item->getID();
} }
int SkOSMenu::appendAction(const char label[], SkEventSinkID target) { int SkOSMenu::appendAction(const char label[], SkEventSinkID target) {
SkEvent* evt = new SkEvent(SkOSMenu::EventType); SkEvent* evt = new SkEvent(gMenuEventType, target);
SkOSMenu::Item* item = new Item(label, SkOSMenu::kAction_Type, "", evt, target);
//Store label in event so it can be used to identify the action later //Store label in event so it can be used to identify the action later
evt->setString(label, ""); evt->setString(label, label);
fItems.append(1, &item); return appendItem(label, SkOSMenu::kAction_Type, "", evt);
return item->getID();
} }
int SkOSMenu::appendList(const char label[], const char slotName[], int SkOSMenu::appendList(const char label[], const char slotName[],
SkEventSinkID target, int index, const char option[], ...) { SkEventSinkID target, int index, const char option[], ...) {
SkEvent* evt = new SkEvent(SkOSMenu::EventType); SkEvent* evt = new SkEvent(gMenuEventType, target);
va_list args; va_list args;
if (option) { if (option) {
SkString str(option); SkString str(option);
va_start(args, option); va_start(args, option);
int count = 1;
for (const char* arg = va_arg(args, const char*); arg != NULL; arg = va_arg(args, const char*)) { for (const char* arg = va_arg(args, const char*); arg != NULL; arg = va_arg(args, const char*)) {
str += SkOSMenu::Delimiter; str += gDelimiter;
str += arg; str += arg;
++count;
} }
va_end(args); va_end(args);
evt->setString(SkOSMenu::List_Items_Str, str); evt->setString(gList_Items_Str, str);
evt->setS32(gList_ItemCount_S32, count);
evt->setS32(slotName, index); evt->setS32(slotName, index);
} }
SkOSMenu::Item* item = new Item(label, SkOSMenu::kList_Type, slotName, evt, target); return appendItem(label, SkOSMenu::kList_Type, slotName, evt);
fItems.append(1, &item);
return item->getID();
} }
int SkOSMenu::appendSlider(const char label[], const char slotName[], int SkOSMenu::appendSlider(const char label[], const char slotName[],
SkEventSinkID target, SkScalar min, SkScalar max, SkEventSinkID target, SkScalar min, SkScalar max,
SkScalar defaultValue) { SkScalar defaultValue) {
SkEvent* evt = new SkEvent(SkOSMenu::EventType); SkEvent* evt = new SkEvent(gMenuEventType, target);
evt->setScalar(SkOSMenu::Slider_Min_Scalar, min); evt->setScalar(gSlider_Min_Scalar, min);
evt->setScalar(SkOSMenu::Slider_Max_Scalar, max); evt->setScalar(gSlider_Max_Scalar, max);
evt->setScalar(slotName, defaultValue); evt->setScalar(slotName, defaultValue);
SkOSMenu::Item* item = new Item(label, SkOSMenu::kSlider_Type, slotName, evt, target); return appendItem(label, SkOSMenu::kSlider_Type, slotName, evt);
fItems.append(1, &item);
return item->getID();
} }
int SkOSMenu::appendSwitch(const char label[], const char slotName[], int SkOSMenu::appendSwitch(const char label[], const char slotName[],
SkEventSinkID target, bool defaultState) { SkEventSinkID target, bool defaultState) {
SkEvent* evt = new SkEvent(SkOSMenu::EventType); SkEvent* evt = new SkEvent(gMenuEventType, target);
evt->setBool(slotName, defaultState); evt->setBool(slotName, defaultState);
SkOSMenu::Item* item = new Item(label, SkOSMenu::kSwitch_Type, slotName, evt, target); return appendItem(label, SkOSMenu::kSwitch_Type, slotName, evt);
fItems.append(1, &item);
return item->getID();
} }
int SkOSMenu::appendTriState(const char label[], const char slotName[], int SkOSMenu::appendTriState(const char label[], const char slotName[],
SkEventSinkID target, SkOSMenu::TriState defaultState) { SkEventSinkID target, SkOSMenu::TriState defaultState) {
SkEvent* evt = new SkEvent(SkOSMenu::EventType); SkEvent* evt = new SkEvent(gMenuEventType, target);
evt->setS32(slotName, defaultState); evt->setS32(slotName, defaultState);
SkOSMenu::Item* item = new Item(label, SkOSMenu::kTriState_Type, slotName, evt, target); return appendItem(label, SkOSMenu::kTriState_Type, slotName, evt);
fItems.append(1, &item);
return item->getID();
} }
int SkOSMenu::appendTextField(const char label[], const char slotName[], int SkOSMenu::appendTextField(const char label[], const char slotName[],
SkEventSinkID target, const char placeholder[]) { SkEventSinkID target, const char placeholder[]) {
SkEvent* evt = new SkEvent(SkOSMenu::EventType); SkEvent* evt = new SkEvent(gMenuEventType, target);
evt->setString(slotName, placeholder); evt->setString(slotName, placeholder);
SkOSMenu::Item* item = new Item(label, SkOSMenu::kTextField_Type, slotName, evt, target); return appendItem(label, SkOSMenu::kTextField_Type, slotName, evt);
fItems.append(1, &item);
return item->getID();
} }
bool SkOSMenu::FindListItemCount(const SkEvent* evt, int* count) {
return evt->isType(gMenuEventType) && evt->findS32(gList_ItemCount_S32, count);
}
bool SkOSMenu::FindListItems(const SkEvent* evt, SkString items[]) {
if (evt->isType(gMenuEventType) && NULL != items) {
const char* text = evt->findString(gList_Items_Str);
char temp[strlen(text)];
memcpy(temp, text, strlen(text) + 1); //make sure to copy the null terminator
char* token = strtok(temp, gDelimiter);
int index = 0;
while (token != NULL) {
items[index].set(token, strlen(token));
token = strtok (NULL, gDelimiter);
++index;
}
return true;
}
return false;
}
bool SkOSMenu::FindSliderMin(const SkEvent* evt, SkScalar* min) {
return evt->isType(gMenuEventType) && evt->findScalar(gSlider_Min_Scalar, min);
}
bool SkOSMenu::FindSliderMax(const SkEvent* evt, SkScalar* max) {
return evt->isType(gMenuEventType) && evt->findScalar(gSlider_Max_Scalar, max);
}
bool SkOSMenu::FindAction(const SkEvent* evt, const char label[]) { bool SkOSMenu::FindAction(const SkEvent* evt, const char label[]) {
return evt->isType(SkOSMenu::EventType) && evt->findString(label); return evt->isType(gMenuEventType) && evt->findString(label);
} }
bool SkOSMenu::FindListIndex(const SkEvent* evt, const char slotName[], int* selected) { bool SkOSMenu::FindListIndex(const SkEvent* evt, const char slotName[], int* value) {
return evt->isType(SkOSMenu::EventType) && evt->findS32(slotName, selected); return evt->isType(gMenuEventType) && evt->findS32(slotName, value);
} }
bool SkOSMenu::FindSliderValue(const SkEvent* evt, const char slotName[], SkScalar* value) { bool SkOSMenu::FindSliderValue(const SkEvent* evt, const char slotName[], SkScalar* value) {
return evt->isType(SkOSMenu::EventType) && evt->findScalar(slotName, value); return evt->isType(gMenuEventType) && evt->findScalar(slotName, value);
} }
bool SkOSMenu::FindSwitchState(const SkEvent* evt, const char slotName[], bool* value) { bool SkOSMenu::FindSwitchState(const SkEvent* evt, const char slotName[], bool* value) {
return evt->isType(SkOSMenu::EventType) && evt->findBool(slotName, value); return evt->isType(gMenuEventType) && evt->findBool(slotName, value);
} }
bool SkOSMenu::FindTriState(const SkEvent* evt, const char slotName[], SkOSMenu::TriState* state) { bool SkOSMenu::FindTriState(const SkEvent* evt, const char slotName[], SkOSMenu::TriState* value) {
return evt->isType(SkOSMenu::EventType) && evt->findS32(slotName, (int*)state); return evt->isType(gMenuEventType) && evt->findS32(slotName, (int*)value);
} }
bool SkOSMenu::FindText(const SkEvent* evt, const char slotName[], SkString* value) { bool SkOSMenu::FindText(const SkEvent* evt, const char slotName[], SkString* value) {
if (evt->isType(SkOSMenu::EventType)) { if (evt->isType(gMenuEventType)) {
const char* text = evt->findString(slotName); const char* text = evt->findString(slotName);
if (!text || !*text) if (!text || !*text)
return false; return false;