Revised SkOSMenu
http://codereview.appspot.com/4827042/ git-svn-id: http://skia.googlecode.com/svn/trunk@2013 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
12d177d1f3
commit
654d72f94c
@ -15,30 +15,123 @@
|
|||||||
|
|
||||||
class SkOSMenu {
|
class SkOSMenu {
|
||||||
public:
|
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
|
||||||
|
* 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 TriState {
|
||||||
|
kMixedState = -1,
|
||||||
|
kOffState = 0,
|
||||||
|
kOnState = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
kAction_Type,
|
||||||
|
kList_Type,
|
||||||
|
kSlider_Type,
|
||||||
|
kSwitch_Type,
|
||||||
|
kTriState_Type,
|
||||||
|
kTextField_Type,
|
||||||
|
kCustom_Type
|
||||||
|
};
|
||||||
|
|
||||||
|
class Item {
|
||||||
|
public:
|
||||||
|
//Auto increments a global to generate an unique ID for each new item
|
||||||
|
//Thread safe
|
||||||
|
Item(const char label[], SkOSMenu::Type type, const char slotName[],
|
||||||
|
SkEvent* evt, SkEventSinkID target);
|
||||||
|
~Item() { delete fEvent; }
|
||||||
|
|
||||||
|
SkEvent* getEvent() const { return fEvent; }
|
||||||
|
int getID() { return fID; }
|
||||||
|
const char* getLabel() const { return fLabel.c_str(); }
|
||||||
|
const char* getSlotName() const { return fSlotName.c_str(); }
|
||||||
|
Type getType() const { return fType; }
|
||||||
|
|
||||||
|
//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(fTarget); }
|
||||||
|
|
||||||
|
//Helper functions for predefined types
|
||||||
|
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
|
||||||
|
|
||||||
const char* getTitle() const { return fTitle; }
|
|
||||||
|
private:
|
||||||
void appendItem(const char title[], const char eventType[], int32_t eventData);
|
int fID;
|
||||||
|
SkEvent* fEvent;
|
||||||
|
SkString fLabel;
|
||||||
|
SkString fSlotName;
|
||||||
|
SkEventSinkID fTarget;
|
||||||
|
Type fType;
|
||||||
|
};
|
||||||
|
|
||||||
|
//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, SkEventSinkID target);
|
||||||
|
|
||||||
|
//Predefined items and helper functions:
|
||||||
|
//Identifiers
|
||||||
|
static const char* EventType;
|
||||||
|
static const char* Delimiter;
|
||||||
|
static const char* List_Items_Str;
|
||||||
|
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 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, SkOSMenu::TriState defaultState = kOffState);
|
||||||
|
int appendTextField(const char label[], const char slotName[],
|
||||||
|
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
|
||||||
|
static bool FindAction(const SkEvent* evt, const char label[]);
|
||||||
|
static bool FindListIndex(const SkEvent* evt, const char slotName[], int* selected);
|
||||||
|
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* state);
|
||||||
|
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
|
// called by SkOSWindow when it receives an OS menu event
|
||||||
int countItems() const;
|
int countItems() const;
|
||||||
const char* getItem(int index, uint32_t* cmdID) const;
|
const Item* getItem(int index) const;
|
||||||
|
|
||||||
SkEvent* createEvent(uint32_t os_cmd);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* fTitle;
|
SkString fTitle;
|
||||||
|
SkTDArray<Item*> fItems;
|
||||||
struct Item {
|
|
||||||
const char* fTitle;
|
|
||||||
const char* fEventType;
|
|
||||||
uint32_t fEventData;
|
|
||||||
uint32_t fOSCmd; // internal
|
|
||||||
};
|
|
||||||
SkTDArray<Item> fItems;
|
|
||||||
|
|
||||||
// illegal
|
// illegal
|
||||||
SkOSMenu(const SkOSMenu&);
|
SkOSMenu(const SkOSMenu&);
|
||||||
SkOSMenu& operator=(const SkOSMenu&);
|
SkOSMenu& operator=(const SkOSMenu&);
|
||||||
|
@ -51,9 +51,9 @@ public:
|
|||||||
bool handleChar(SkUnichar);
|
bool handleChar(SkUnichar);
|
||||||
bool handleKey(SkKey);
|
bool handleKey(SkKey);
|
||||||
bool handleKeyUp(SkKey);
|
bool handleKeyUp(SkKey);
|
||||||
bool handleMenu(uint32_t os_cmd);
|
|
||||||
|
|
||||||
void addMenu(SkOSMenu*);
|
void addMenu(SkOSMenu*);
|
||||||
|
const SkTDArray<SkOSMenu*>* getMenus() { return &fMenus; }
|
||||||
|
|
||||||
const char* getTitle() const { return fTitle.c_str(); }
|
const char* getTitle() const { return fTitle.c_str(); }
|
||||||
void setTitle(const char title[]);
|
void setTitle(const char title[]);
|
||||||
@ -73,7 +73,8 @@ protected:
|
|||||||
virtual bool onHandleChar(SkUnichar);
|
virtual bool onHandleChar(SkUnichar);
|
||||||
virtual bool onHandleKey(SkKey);
|
virtual bool onHandleKey(SkKey);
|
||||||
virtual bool onHandleKeyUp(SkKey);
|
virtual bool onHandleKeyUp(SkKey);
|
||||||
virtual void onAddMenu(const SkOSMenu*) {}
|
virtual void onAddMenu(const SkOSMenu*) {};
|
||||||
|
virtual void onUpdateMenu(const SkOSMenu*) {};
|
||||||
virtual void onSetTitle(const char title[]) {}
|
virtual void onSetTitle(const char title[]) {}
|
||||||
|
|
||||||
// overrides from SkView
|
// overrides from SkView
|
||||||
|
@ -1,60 +1,185 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Google Inc.
|
* Copyright 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
#include <stdarg.h>
|
||||||
#include "SkOSMenu.h"
|
#include "SkOSMenu.h"
|
||||||
|
#include "SkThread.h"
|
||||||
|
|
||||||
static int gOSMenuCmd = 7000;
|
static int gOSMenuCmd = 7000;
|
||||||
|
|
||||||
SkOSMenu::SkOSMenu(const char title[])
|
SkOSMenu::SkOSMenu(const char title[]) {
|
||||||
{
|
fTitle.set(title);
|
||||||
fTitle = title;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SkOSMenu::~SkOSMenu()
|
SkOSMenu::~SkOSMenu() {
|
||||||
{
|
this->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SkOSMenu::countItems() const
|
void SkOSMenu::reset() {
|
||||||
{
|
fItems.deleteAll();
|
||||||
|
fTitle.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SkOSMenu::countItems() const {
|
||||||
return fItems.count();
|
return fItems.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkOSMenu::appendItem(const char title[], const char eventType[], int32_t eventData)
|
const SkOSMenu::Item* SkOSMenu::getItem(int index) const{
|
||||||
{
|
return fItems[index];
|
||||||
Item* item = fItems.append();
|
|
||||||
|
|
||||||
item->fTitle = title;
|
|
||||||
item->fEventType = eventType;
|
|
||||||
item->fEventData = eventData;
|
|
||||||
item->fOSCmd = ++gOSMenuCmd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SkEvent* SkOSMenu::createEvent(uint32_t os_cmd)
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
{
|
|
||||||
const Item* iter = fItems.begin();
|
|
||||||
const Item* stop = fItems.end();
|
|
||||||
|
|
||||||
while (iter < stop)
|
SkOSMenu::Item::Item(const char label[], SkOSMenu::Type type,
|
||||||
{
|
const char slotName[], SkEvent* evt, SkEventSinkID target) {
|
||||||
if (iter->fOSCmd == os_cmd)
|
fLabel.set(label);
|
||||||
{
|
fSlotName.set(slotName);
|
||||||
SkEvent* evt = new SkEvent(iter->fEventType);
|
fType = type;
|
||||||
evt->setFast32(iter->fEventData);
|
fTarget = target;
|
||||||
return evt;
|
fEvent = evt;
|
||||||
}
|
fID = sk_atomic_inc(&gOSMenuCmd);
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* SkOSMenu::getItem(int index, uint32_t* cmdID) const
|
void SkOSMenu::Item::postEventWithBool(bool value) const {
|
||||||
{
|
SkASSERT(SkOSMenu::kSwitch_Type == fType);
|
||||||
if (cmdID)
|
fEvent->setBool(fSlotName.c_str(), value);
|
||||||
*cmdID = fItems[index].fOSCmd;
|
this->postEvent();
|
||||||
return fItems[index].fTitle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkOSMenu::Item::postEventWithScalar(SkScalar value) const {
|
||||||
|
SkASSERT(SkOSMenu::kSlider_Type == fType);
|
||||||
|
fEvent->setScalar(fSlotName.c_str(), value);
|
||||||
|
this->postEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkOSMenu::Item::postEventWithInt(int value) const {
|
||||||
|
SkASSERT(SkOSMenu::kList_Type == fType || SkOSMenu::kTriState_Type == fType);
|
||||||
|
fEvent->setS32(fSlotName.c_str(), value);
|
||||||
|
this->postEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkOSMenu::Item::postEventWithString(const char value[]) const {
|
||||||
|
SkASSERT(SkOSMenu::kTextField_Type == fType);
|
||||||
|
fEvent->setString(fSlotName.c_str(), value);
|
||||||
|
this->postEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const char* SkOSMenu::EventType = "SkOSMenuEventType";
|
||||||
|
const char* SkOSMenu::Delimiter = "|";
|
||||||
|
const char* SkOSMenu::Slider_Min_Scalar = "SkOSMenuSlider_Min";
|
||||||
|
const char* SkOSMenu::Slider_Max_Scalar = "SkOSMenuSlider_Max";
|
||||||
|
const char* SkOSMenu::List_Items_Str = "SkOSMenuList_Items";
|
||||||
|
|
||||||
|
int SkOSMenu::appendItem(const char label[], Type type, const char slotName[],
|
||||||
|
SkEvent* evt, SkEventSinkID target) {
|
||||||
|
SkOSMenu::Item* item = new Item(label, type, slotName, evt, target);
|
||||||
|
fItems.append(1, &item);
|
||||||
|
return item->getID();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SkOSMenu::appendAction(const char label[], SkEventSinkID target) {
|
||||||
|
SkEvent* evt = new SkEvent(SkOSMenu::EventType);
|
||||||
|
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
|
||||||
|
evt->setString(label, "");
|
||||||
|
fItems.append(1, &item);
|
||||||
|
return item->getID();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SkOSMenu::appendList(const char label[], const char slotName[],
|
||||||
|
SkEventSinkID target, int index, const char option[], ...) {
|
||||||
|
SkEvent* evt = new SkEvent(SkOSMenu::EventType);
|
||||||
|
va_list args;
|
||||||
|
if (option) {
|
||||||
|
SkString str(option);
|
||||||
|
va_start(args, option);
|
||||||
|
for (const char* arg = va_arg(args, const char*); arg != NULL; arg = va_arg(args, const char*)) {
|
||||||
|
str += SkOSMenu::Delimiter;
|
||||||
|
str += arg;
|
||||||
|
}
|
||||||
|
va_end(args);
|
||||||
|
evt->setString(SkOSMenu::List_Items_Str, str);
|
||||||
|
evt->setS32(slotName, index);
|
||||||
|
}
|
||||||
|
SkOSMenu::Item* item = new Item(label, SkOSMenu::kList_Type, slotName, evt, target);
|
||||||
|
fItems.append(1, &item);
|
||||||
|
return item->getID();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SkOSMenu::appendSlider(const char label[], const char slotName[],
|
||||||
|
SkEventSinkID target, SkScalar min, SkScalar max,
|
||||||
|
SkScalar defaultValue) {
|
||||||
|
SkEvent* evt = new SkEvent(SkOSMenu::EventType);
|
||||||
|
evt->setScalar(SkOSMenu::Slider_Min_Scalar, min);
|
||||||
|
evt->setScalar(SkOSMenu::Slider_Max_Scalar, max);
|
||||||
|
evt->setScalar(slotName, defaultValue);
|
||||||
|
SkOSMenu::Item* item = new Item(label, SkOSMenu::kSlider_Type, slotName, evt, target);
|
||||||
|
fItems.append(1, &item);
|
||||||
|
return item->getID();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SkOSMenu::appendSwitch(const char label[], const char slotName[],
|
||||||
|
SkEventSinkID target, bool defaultState) {
|
||||||
|
SkEvent* evt = new SkEvent(SkOSMenu::EventType);
|
||||||
|
evt->setBool(slotName, defaultState);
|
||||||
|
SkOSMenu::Item* item = new Item(label, SkOSMenu::kSwitch_Type, slotName, evt, target);
|
||||||
|
fItems.append(1, &item);
|
||||||
|
return item->getID();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SkOSMenu::appendTriState(const char label[], const char slotName[],
|
||||||
|
SkEventSinkID target, SkOSMenu::TriState defaultState) {
|
||||||
|
SkEvent* evt = new SkEvent(SkOSMenu::EventType);
|
||||||
|
evt->setS32(slotName, defaultState);
|
||||||
|
SkOSMenu::Item* item = new Item(label, SkOSMenu::kTriState_Type, slotName, evt, target);
|
||||||
|
fItems.append(1, &item);
|
||||||
|
return item->getID();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SkOSMenu::appendTextField(const char label[], const char slotName[],
|
||||||
|
SkEventSinkID target, const char placeholder[]) {
|
||||||
|
SkEvent* evt = new SkEvent(SkOSMenu::EventType);
|
||||||
|
evt->setString(slotName, placeholder);
|
||||||
|
SkOSMenu::Item* item = new Item(label, SkOSMenu::kTextField_Type, slotName, evt, target);
|
||||||
|
fItems.append(1, &item);
|
||||||
|
return item->getID();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SkOSMenu::FindAction(const SkEvent* evt, const char label[]) {
|
||||||
|
return evt->isType(SkOSMenu::EventType) && evt->findString(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkOSMenu::FindListIndex(const SkEvent* evt, const char slotName[], int* selected) {
|
||||||
|
return evt->isType(SkOSMenu::EventType) && evt->findS32(slotName, selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkOSMenu::FindSliderValue(const SkEvent* evt, const char slotName[], SkScalar* value) {
|
||||||
|
return evt->isType(SkOSMenu::EventType) && evt->findScalar(slotName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkOSMenu::FindSwitchState(const SkEvent* evt, const char slotName[], bool* value) {
|
||||||
|
return evt->isType(SkOSMenu::EventType) && evt->findBool(slotName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkOSMenu::FindTriState(const SkEvent* evt, const char slotName[], SkOSMenu::TriState* state) {
|
||||||
|
return evt->isType(SkOSMenu::EventType) && evt->findS32(slotName, (int*)state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkOSMenu::FindText(const SkEvent* evt, const char slotName[], SkString* value) {
|
||||||
|
if (evt->isType(SkOSMenu::EventType)) {
|
||||||
|
const char* text = evt->findString(slotName);
|
||||||
|
if (!text || !*text)
|
||||||
|
return false;
|
||||||
|
else {
|
||||||
|
value->set(text);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -290,8 +290,7 @@ bool SkWindow::handleKeyUp(SkKey key)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkWindow::addMenu(SkOSMenu* menu)
|
void SkWindow::addMenu(SkOSMenu* menu) {
|
||||||
{
|
|
||||||
*fMenus.append() = menu;
|
*fMenus.append() = menu;
|
||||||
this->onAddMenu(menu);
|
this->onAddMenu(menu);
|
||||||
}
|
}
|
||||||
@ -304,20 +303,6 @@ void SkWindow::setTitle(const char title[]) {
|
|||||||
this->onSetTitle(title);
|
this->onSetTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkWindow::handleMenu(uint32_t cmd)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < fMenus.count(); i++)
|
|
||||||
{
|
|
||||||
SkEvent* evt = fMenus[i]->createEvent(cmd);
|
|
||||||
if (evt)
|
|
||||||
{
|
|
||||||
evt->post(this->getSinkID());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool SkWindow::onEvent(const SkEvent& evt)
|
bool SkWindow::onEvent(const SkEvent& evt)
|
||||||
|
Loading…
Reference in New Issue
Block a user