xref: /aosp_15_r20/external/skia/tools/sk_app/CommandSet.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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