| /* | |
| * 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 <stdarg.h> | |
| #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; | |
| } |