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