/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "CommandSet.h" #include "SkCanvas.h" #include "SkTSort.h" namespace sk_app { static bool on_key_handler(Window::Key key, Window::InputState state, uint32_t modifiers, void* userData) { CommandSet* cs = reinterpret_cast(userData); return cs->onKey(key, state, modifiers); } static bool on_char_handler(SkUnichar c, uint32_t modifiers, void* userData) { CommandSet* cs = reinterpret_cast(userData); return cs->onChar(c, modifiers); } CommandSet::CommandSet() : fHelpMode(kNone_HelpMode) { this->addCommand('h', "Overlays", "Show help screen", [this]() { switch (this->fHelpMode) { case kNone_HelpMode: this->fHelpMode = kGrouped_HelpMode; break; case kGrouped_HelpMode: this->fHelpMode = kAlphabetical_HelpMode; break; case kAlphabetical_HelpMode: this->fHelpMode = kNone_HelpMode; break; } fWindow->inval(); }); } void CommandSet::attach(Window* window) { fWindow = window; window->registerKeyFunc(on_key_handler, this); window->registerCharFunc(on_char_handler, this); } bool CommandSet::onKey(Window::Key key, Window::InputState state, uint32_t modifiers) { if (Window::kDown_InputState == state) { for (Command& cmd : fCommands) { if (Command::kKey_CommandType == cmd.fType && key == cmd.fKey) { cmd.fFunction(); return true; } } } return false; } bool CommandSet::onChar(SkUnichar c, uint32_t modifiers) { for (Command& cmd : fCommands) { if (Command::kChar_CommandType == cmd.fType && c == cmd.fChar) { cmd.fFunction(); return true; } } return false; } void CommandSet::addCommand(SkUnichar c, const char* group, const char* description, std::function function) { fCommands.push_back(Command(c, group, description, function)); } void CommandSet::addCommand(Window::Key k, const char* keyName, const char* group, const char* description, std::function function) { fCommands.push_back(Command(k, keyName, group, description, function)); } #if defined(SK_BUILD_FOR_WIN32) #define SK_strcasecmp _stricmp #else #define SK_strcasecmp strcasecmp #endif bool CommandSet::compareCommandKey(const Command& first, const Command& second) { return SK_strcasecmp(first.fKeyName.c_str(), second.fKeyName.c_str()) < 0; } bool CommandSet::compareCommandGroup(const Command& first, const Command& second) { return SK_strcasecmp(first.fGroup.c_str(), second.fGroup.c_str()) < 0; } void CommandSet::drawHelp(SkCanvas* canvas) { if (kNone_HelpMode == fHelpMode) { return; } // Sort commands for current mode: SkTQSort(fCommands.begin(), fCommands.end() - 1, kAlphabetical_HelpMode == fHelpMode ? compareCommandKey : compareCommandGroup); SkPaint bgPaint; bgPaint.setColor(0xC0000000); canvas->drawPaint(bgPaint); SkPaint paint; paint.setTextSize(16); paint.setAntiAlias(true); paint.setColor(0xFFFFFFFF); SkPaint groupPaint; groupPaint.setTextSize(18); groupPaint.setUnderlineText(true); groupPaint.setAntiAlias(true); groupPaint.setColor(0xFFFFFFFF); SkScalar x = SkIntToScalar(10); SkScalar y = SkIntToScalar(10); // Measure all key strings: SkScalar keyWidth = 0; for (Command& cmd : fCommands) { keyWidth = SkMaxScalar(keyWidth, paint.measureText(cmd.fKeyName.c_str(), cmd.fKeyName.size())); } keyWidth += paint.measureText(" ", 1); // If we're grouping by category, we'll be adding text height on every new group (including the // first), so no need to do that here. Otherwise, skip down so the first line is where we want. if (kGrouped_HelpMode != fHelpMode) { y += paint.getTextSize(); } // Print everything: SkString lastGroup; for (Command& cmd : fCommands) { if (kGrouped_HelpMode == fHelpMode && lastGroup != cmd.fGroup) { // Group change. Advance and print header: y += paint.getTextSize(); canvas->drawText(cmd.fGroup.c_str(), cmd.fGroup.size(), x, y, groupPaint); y += groupPaint.getTextSize() + 2; lastGroup = cmd.fGroup; } canvas->drawText(cmd.fKeyName.c_str(), cmd.fKeyName.size(), x, y, paint); SkString text = SkStringPrintf(": %s", cmd.fDescription.c_str()); canvas->drawText(text.c_str(), text.size(), x + keyWidth, y, paint); y += paint.getTextSize() + 2; } } } // namespace sk_app