1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot* Copyright 2016 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot*
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot* Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot* found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot*/
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef CommandSet_DEFINED
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define CommandSet_DEFINED
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkString.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Window.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <functional>
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <vector>
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkCanvas;
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotnamespace sk_app {
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/**
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Helper class used by applications that want to hook keypresses to trigger events.
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * An app can simply store an instance of CommandSet and then use it as follows:
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 1) Attach to the Window at initialization time.
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 2) Register commands to be executed for characters or keys. Each command needs a Group and a
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *    description (both just strings). Commands attached to Keys (rather than characters) also need
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *    a displayable name for the Key. Finally, a function to execute when the key or character is
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *    pressed must be supplied. The easiest option to is pass in a lambda that captures [this]
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *    (your application object), and performs whatever action is desired.
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 3) Register key and char handlers with the Window, and - depending on your state - forward those
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *    events to the CommandSet's onKey, onChar, and onSoftKey.
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4) At the end of your onPaint, call drawHelp, and pass in the application's canvas.
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * The CommandSet always binds 'h' to cycle through two different help screens. The first shows
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * all commands, organized by Group (with headings for each Group). The second shows all commands
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * alphabetically by key/character.
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass CommandSet {
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    CommandSet();
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void attach(Window* window);
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers);
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onChar(SkUnichar, uint32_t modifiers);
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onSoftkey(const SkString& softkey);
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void addCommand(SkUnichar c, const char* group, const char* description,
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    std::function<void(void)> function);
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void addCommand(Window::Key k, const char* keyName, const char* group, const char* description,
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    std::function<void(void)> function);
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void drawHelp(SkCanvas* canvas);
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    std::vector<SkString> getCommandsAsSoftkeys() const;
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    struct Command {
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        enum CommandType {
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            kChar_CommandType,
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            kKey_CommandType,
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        Command(SkUnichar c, const char* group, const char* description,
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                std::function<void(void)> function)
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            : fType(kChar_CommandType)
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fChar(c)
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fKeyName(' ' == c ? SkString("Space") : SkStringPrintf("%c", c))
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fGroup(group)
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fDescription(description)
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fFunction(function) {}
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        Command(Window::Key k, const char* keyName, const char* group, const char* description,
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                std::function<void(void)> function)
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            : fType(kKey_CommandType)
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fKey(k)
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fKeyName(keyName)
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fGroup(group)
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fDescription(description)
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fFunction(function) {}
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        CommandType fType;
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // For kChar_CommandType
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkUnichar fChar;
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // For kKey_CommandType
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        Window::Key fKey;
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Common to all command types
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkString fKeyName;
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkString fGroup;
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkString fDescription;
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        std::function<void(void)> fFunction;
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkString getSoftkeyString() const {
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return SkStringPrintf("%s (%s)", fKeyName.c_str(), fDescription.c_str());
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static bool compareCommandKey(const Command& first, const Command& second);
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static bool compareCommandGroup(const Command& first, const Command& second);
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum HelpMode {
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kNone_HelpMode,
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kGrouped_HelpMode,
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kAlphabetical_HelpMode,
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Window*           fWindow;
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTArray<Command> fCommands;
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    HelpMode          fHelpMode;
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}   // namespace sk_app
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
118