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