diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/views/SkOSMenu.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/views/SkOSMenu.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,263 @@ +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include +#include "SkOSMenu.h" +#include "SkThread.h" + +static int gOSMenuCmd = 7000; + +SkOSMenu::SkOSMenu(const char title[]) { + fTitle.set(title); +} + +SkOSMenu::~SkOSMenu() { + this->reset(); +} + +void SkOSMenu::reset() { + fItems.deleteAll(); + fTitle.reset(); +} + +const SkOSMenu::Item* SkOSMenu::getItemByID(int itemID) const { + for (int i = 0; i < fItems.count(); ++i) { + if (itemID == fItems[i]->getID()) + return fItems[i]; + } + return NULL; +} + +void SkOSMenu::getItems(const SkOSMenu::Item* items[]) const { + if (NULL != items) { + for (int i = 0; i < fItems.count(); ++i) { + items[i] = fItems[i]; + } + } +} + +void SkOSMenu::assignKeyEquivalentToItem(int itemID, SkUnichar key) { + for (int i = 0; i < fItems.count(); ++i) { + if (itemID == fItems[i]->getID()) + fItems[i]->setKeyEquivalent(key); + } +} + +bool SkOSMenu::handleKeyEquivalent(SkUnichar key) { + 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->setInt(value); + break; + case kSwitch_Type: + SkOSMenu::FindSwitchState(*item->getEvent(), item->getSlotName(), &state); + item->setBool(!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->setTriState(tristate); + break; + case kAction_Type: + case kCustom_Type: + case kSlider_Type: + case kTextField_Type: + default: + break; + } + item->postEvent(); + return true; + } + } + return false; +} + +//////////////////////////////////////////////////////////////////////////////// + +SkOSMenu::Item::Item(const char label[], SkOSMenu::Type type, + const char slotName[], SkEvent* evt) { + fLabel.set(label); + fSlotName.set(slotName); + fType = type; + fEvent = evt; + fKey = 0; + fID = sk_atomic_inc(&gOSMenuCmd); +} + +void SkOSMenu::Item::setBool(bool value) const { + SkASSERT(SkOSMenu::kSwitch_Type == fType); + fEvent->setBool(fSlotName.c_str(), value); +} + +void SkOSMenu::Item::setScalar(SkScalar value) const { + SkASSERT(SkOSMenu::kSlider_Type == fType); + fEvent->setScalar(fSlotName.c_str(), value); +} + +void SkOSMenu::Item::setInt(int value) const { + SkASSERT(SkOSMenu::kList_Type == fType); + fEvent->setS32(fSlotName.c_str(), value); +} + +void SkOSMenu::Item::setTriState(TriState value) const { + SkASSERT(SkOSMenu::kTriState_Type == fType); + fEvent->setS32(fSlotName.c_str(), value); +} + +void SkOSMenu::Item::setString(const char value[]) const { + SkASSERT(SkOSMenu::kTextField_Type == fType); + fEvent->setString(fSlotName.c_str(), value); +} + +//////////////////////////////////////////////////////////////////////////////// + +static const char* gMenuEventType = "SkOSMenuEventType"; +static const char* gSlider_Min_Scalar = "SkOSMenuSlider_Min"; +static const char* gSlider_Max_Scalar = "SkOSMenuSlider_Max"; +static const char* gDelimiter = "|"; +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[], + SkEvent* evt) { + SkOSMenu::Item* item = new Item(label, type, slotName, evt); + fItems.append(1, &item); + return item->getID(); +} + +int SkOSMenu::appendAction(const char label[], SkEventSinkID target) { + SkEvent* evt = new SkEvent(gMenuEventType, target); + //Store label in event so it can be used to identify the action later + evt->setString(label, label); + return appendItem(label, SkOSMenu::kAction_Type, "", evt); +} + +int SkOSMenu::appendList(const char label[], const char slotName[], + SkEventSinkID target, int index, const char option[], ...) { + SkEvent* evt = new SkEvent(gMenuEventType, target); + va_list args; + if (option) { + SkString str(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*)) { + str += gDelimiter; + str += arg; + ++count; + } + va_end(args); + evt->setString(gList_Items_Str, str); + evt->setS32(gList_ItemCount_S32, count); + evt->setS32(slotName, index); + } + return appendItem(label, SkOSMenu::kList_Type, slotName, evt); +} + +int SkOSMenu::appendSlider(const char label[], const char slotName[], + SkEventSinkID target, SkScalar min, SkScalar max, + SkScalar defaultValue) { + SkEvent* evt = new SkEvent(gMenuEventType, target); + evt->setScalar(gSlider_Min_Scalar, min); + evt->setScalar(gSlider_Max_Scalar, max); + evt->setScalar(slotName, defaultValue); + return appendItem(label, SkOSMenu::kSlider_Type, slotName, evt); +} + +int SkOSMenu::appendSwitch(const char label[], const char slotName[], + SkEventSinkID target, bool defaultState) { + SkEvent* evt = new SkEvent(gMenuEventType, target); + evt->setBool(slotName, defaultState); + return appendItem(label, SkOSMenu::kSwitch_Type, slotName, evt); +} + +int SkOSMenu::appendTriState(const char label[], const char slotName[], + SkEventSinkID target, SkOSMenu::TriState defaultState) { + SkEvent* evt = new SkEvent(gMenuEventType, target); + evt->setS32(slotName, defaultState); + return appendItem(label, SkOSMenu::kTriState_Type, slotName, evt); +} + +int SkOSMenu::appendTextField(const char label[], const char slotName[], + SkEventSinkID target, const char placeholder[]) { + SkEvent* evt = new SkEvent(gMenuEventType, target); + evt->setString(slotName, placeholder); + return appendItem(label, SkOSMenu::kTextField_Type, slotName, evt); +} + +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); + if (text != NULL) { + SkString temp(text); + char* token = strtok((char*)temp.c_str(), 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[]) { + return evt.isType(gMenuEventType) && evt.findString(label); +} + +bool SkOSMenu::FindListIndex(const SkEvent& evt, const char slotName[], int* value) { + return evt.isType(gMenuEventType) && evt.findS32(slotName, value); +} + +bool SkOSMenu::FindSliderValue(const SkEvent& evt, const char slotName[], SkScalar* value) { + return evt.isType(gMenuEventType) && evt.findScalar(slotName, value); +} + +bool SkOSMenu::FindSwitchState(const SkEvent& evt, const char slotName[], bool* value) { + return evt.isType(gMenuEventType) && evt.findBool(slotName, value); +} + +bool SkOSMenu::FindTriState(const SkEvent& evt, const char slotName[], SkOSMenu::TriState* value) { + return evt.isType(gMenuEventType) && evt.findS32(slotName, (int*)value); +} + +bool SkOSMenu::FindText(const SkEvent& evt, const char slotName[], SkString* value) { + if (evt.isType(gMenuEventType)) { + const char* text = evt.findString(slotName); + if (!text || !*text) + return false; + else { + value->set(text); + return true; + } + } + return false; +}