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 "CommandSet.h" 9 10 #include "SkCanvas.h" 11 #include "SkTSort.h" 12 13 namespace sk_app { 14 15 CommandSet::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 33 void CommandSet::attach(Window* window) { 34 fWindow = window; 35 } 36 37 bool CommandSet::onKey(Window::Key key, Window::InputState state, uint32_t modifiers) { 38 if (Window::kDown_InputState == 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 50 bool CommandSet::onChar(SkUnichar c, uint32_t 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 61 bool 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 71 void 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 76 void CommandSet::addCommand(Window::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 87 bool CommandSet::compareCommandKey(const Command& first, const Command& second) { 88 return SK_strcasecmp(first.fKeyName.c_str(), second.fKeyName.c_str()) < 0; 89 } 90 91 bool CommandSet::compareCommandGroup(const Command& first, const Command& second) { 92 return SK_strcasecmp(first.fGroup.c_str(), second.fGroup.c_str()) < 0; 93 } 94 95 void CommandSet::drawHelp(SkCanvas* canvas) { 96 if (kNone_HelpMode == fHelpMode) { 97 return; 98 } 99 100 // Sort commands for current mode: 101 SkTQSort(fCommands.begin(), fCommands.end() - 1, 102 kAlphabetical_HelpMode == fHelpMode ? compareCommandKey : compareCommandGroup); 103 104 SkPaint bgPaint; 105 bgPaint.setColor(0xC0000000); 106 canvas->drawPaint(bgPaint); 107 108 SkPaint paint; 109 paint.setTextSize(16); 110 paint.setAntiAlias(true); 111 paint.setColor(0xFFFFFFFF); 112 113 SkPaint groupPaint; 114 groupPaint.setTextSize(18); 115 groupPaint.setAntiAlias(true); 116 groupPaint.setColor(0xFFFFFFFF); 117 118 SkScalar x = SkIntToScalar(10); 119 SkScalar y = SkIntToScalar(10); 120 121 // Measure all key strings: 122 SkScalar keyWidth = 0; 123 for (Command& cmd : fCommands) { 124 keyWidth = SkMaxScalar(keyWidth, 125 paint.measureText(cmd.fKeyName.c_str(), cmd.fKeyName.size())); 126 } 127 keyWidth += paint.measureText(" ", 1); 128 129 // If we're grouping by category, we'll be adding text height on every new group (including the 130 // first), so no need to do that here. Otherwise, skip down so the first line is where we want. 131 if (kGrouped_HelpMode != fHelpMode) { 132 y += paint.getTextSize(); 133 } 134 135 // Print everything: 136 SkString lastGroup; 137 for (Command& cmd : fCommands) { 138 if (kGrouped_HelpMode == fHelpMode && lastGroup != cmd.fGroup) { 139 // Group change. Advance and print header: 140 y += paint.getTextSize(); 141 canvas->drawString(cmd.fGroup, x, y, groupPaint); 142 y += groupPaint.getTextSize() + 2; 143 lastGroup = cmd.fGroup; 144 } 145 146 canvas->drawString(cmd.fKeyName, x, y, paint); 147 SkString text = SkStringPrintf(": %s", cmd.fDescription.c_str()); 148 canvas->drawString(text, x + keyWidth, y, paint); 149 y += paint.getTextSize() + 2; 150 } 151 } 152 153 std::vector<SkString> CommandSet::getCommandsAsSoftkeys() const { 154 std::vector<SkString> result; 155 for(const Command& command : fCommands) { 156 result.push_back(command.getSoftkeyString()); 157 } 158 return result; 159 } 160 161 } // namespace sk_app 162