1/* 2* Copyright 2016 Google Inc. 3* 4* Use of this source code is governed by a BSD-style license that can be 5* found in the LICENSE file. 6*/ 7 8#include "tools/sk_app/CommandSet.h" 9 10#include "include/core/SkCanvas.h" 11#include "include/core/SkFont.h" 12 13namespace sk_app { 14 15CommandSet::CommandSet() 16 : fHelpMode(kNone_HelpMode) { 17 this->addCommand('h', "Overlays", "Show help screen", [this]() { 18 switch (this->fHelpMode) { 19 case kNone_HelpMode: 20 this->fHelpMode = kGrouped_HelpMode; 21 break; 22 case kGrouped_HelpMode: 23 this->fHelpMode = kAlphabetical_HelpMode; 24 break; 25 case kAlphabetical_HelpMode: 26 this->fHelpMode = kNone_HelpMode; 27 break; 28 } 29 fWindow->inval(); 30 }); 31} 32 33void CommandSet::attach(Window* window) { 34 fWindow = window; 35} 36 37bool CommandSet::onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers) { 38 if (skui::InputState::kDown == state) { 39 for (Command& cmd : fCommands) { 40 if (Command::kKey_CommandType == cmd.fType && key == cmd.fKey) { 41 cmd.fFunction(); 42 return true; 43 } 44 } 45 } 46 47 return false; 48} 49 50bool CommandSet::onChar(SkUnichar c, skui::ModifierKey modifiers) { 51 for (Command& cmd : fCommands) { 52 if (Command::kChar_CommandType == cmd.fType && c == cmd.fChar) { 53 cmd.fFunction(); 54 return true; 55 } 56 } 57 58 return false; 59} 60 61bool CommandSet::onSoftkey(const SkString& softkey) { 62 for (const Command& cmd : fCommands) { 63 if (cmd.getSoftkeyString().equals(softkey)) { 64 cmd.fFunction(); 65 return true; 66 } 67 } 68 return false; 69} 70 71void CommandSet::addCommand(SkUnichar c, const char* group, const char* description, 72 std::function<void(void)> function) { 73 fCommands.push_back(Command(c, group, description, function)); 74} 75 76void CommandSet::addCommand(skui::Key k, const char* keyName, const char* group, 77 const char* description, std::function<void(void)> function) { 78 fCommands.push_back(Command(k, keyName, group, description, function)); 79} 80 81#if defined(SK_BUILD_FOR_WIN) 82 #define SK_strcasecmp _stricmp 83#else 84 #define SK_strcasecmp strcasecmp 85#endif 86 87bool CommandSet::compareCommandKey(const Command& first, const Command& second) { 88 return SK_strcasecmp(first.fKeyName.c_str(), second.fKeyName.c_str()) < 0; 89} 90 91bool CommandSet::compareCommandGroup(const Command& first, const Command& second) { 92 return SK_strcasecmp(first.fGroup.c_str(), second.fGroup.c_str()) < 0; 93} 94 95void CommandSet::drawHelp(SkCanvas* canvas) { 96 if (kNone_HelpMode == fHelpMode) { 97 return; 98 } 99 100 // Sort commands for current mode: 101 std::stable_sort(fCommands.begin(), fCommands.end(), 102 kAlphabetical_HelpMode == fHelpMode ? compareCommandKey : compareCommandGroup); 103 104 SkFont font; 105 font.setSize(16); 106 107 SkFont groupFont; 108 groupFont.setSize(18); 109 110 SkPaint bgPaint; 111 bgPaint.setColor(0xC0000000); 112 canvas->drawPaint(bgPaint); 113 114 SkPaint paint; 115 paint.setAntiAlias(true); 116 paint.setColor(0xFFFFFFFF); 117 118 SkPaint groupPaint; 119 groupPaint.setAntiAlias(true); 120 groupPaint.setColor(0xFFFFFFFF); 121 122 SkScalar x = SkIntToScalar(10); 123 SkScalar y = SkIntToScalar(10); 124 125 // Measure all key strings: 126 SkScalar keyWidth = 0; 127 for (Command& cmd : fCommands) { 128 keyWidth = std::max(keyWidth, 129 font.measureText(cmd.fKeyName.c_str(), cmd.fKeyName.size(), 130 SkTextEncoding::kUTF8)); 131 } 132 keyWidth += font.measureText(" ", 1, SkTextEncoding::kUTF8); 133 134 // If we're grouping by category, we'll be adding text height on every new group (including the 135 // first), so no need to do that here. Otherwise, skip down so the first line is where we want. 136 if (kGrouped_HelpMode != fHelpMode) { 137 y += font.getSize(); 138 } 139 140 // Print everything: 141 SkString lastGroup; 142 for (Command& cmd : fCommands) { 143 if (kGrouped_HelpMode == fHelpMode && lastGroup != cmd.fGroup) { 144 // Group change. Advance and print header: 145 y += font.getSize(); 146 canvas->drawSimpleText(cmd.fGroup.c_str(), cmd.fGroup.size(), SkTextEncoding::kUTF8, 147 x, y, groupFont, groupPaint); 148 y += groupFont.getSize() + 2; 149 lastGroup = cmd.fGroup; 150 } 151 152 canvas->drawSimpleText(cmd.fKeyName.c_str(), cmd.fKeyName.size(), SkTextEncoding::kUTF8, 153 x, y, font, paint); 154 SkString text = SkStringPrintf(": %s", cmd.fDescription.c_str()); 155 canvas->drawString(text, x + keyWidth, y, font, paint); 156 y += font.getSize() + 2; 157 } 158} 159 160std::vector<SkString> CommandSet::getCommandsAsSoftkeys() const { 161 std::vector<SkString> result; 162 for(const Command& command : fCommands) { 163 result.push_back(command.getSoftkeyString()); 164 } 165 return result; 166} 167 168} // namespace sk_app 169