blob: d59cb4584f3f215b6afa1a963c53dbcd47f6968d [file] [log] [blame]
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef CommandSet_DEFINED
#define CommandSet_DEFINED
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkTArray.h"
#include "tools/skui/InputState.h"
#include "tools/skui/Key.h"
#include "tools/skui/ModifierKey.h"
#include <functional>
#include <vector>
class SkCanvas;
namespace sk_app {
class Window;
/**
* Helper class used by applications that want to hook keypresses to trigger events.
*
* An app can simply store an instance of CommandSet and then use it as follows:
* 1) Attach to the Window at initialization time.
* 2) Register commands to be executed for characters or keys. Each command needs a Group and a
* description (both just strings). Commands attached to Keys (rather than characters) also need
* a displayable name for the Key. Finally, a function to execute when the key or character is
* pressed must be supplied. The easiest option to is pass in a lambda that captures [this]
* (your application object), and performs whatever action is desired.
* 3) Register key and char handlers with the Window, and - depending on your state - forward those
* events to the CommandSet's onKey, onChar, and onSoftKey.
* 4) At the end of your onPaint, call drawHelp, and pass in the application's canvas.
* The CommandSet always binds 'h' to cycle through two different help screens. The first shows
* all commands, organized by Group (with headings for each Group). The second shows all commands
* alphabetically by key/character.
*/
class CommandSet {
public:
CommandSet();
void attach(Window* window);
bool onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers);
bool onChar(SkUnichar, skui::ModifierKey modifiers);
bool onSoftkey(const SkString& softkey);
void addCommand(SkUnichar c, const char* group, const char* description,
std::function<void(void)> function);
void addCommand(skui::Key k, const char* keyName, const char* group, const char* description,
std::function<void(void)> function);
void drawHelp(SkCanvas* canvas);
std::vector<SkString> getCommandsAsSoftkeys() const;
private:
struct Command {
enum CommandType {
kChar_CommandType,
kKey_CommandType,
};
Command(SkUnichar c, const char* group, const char* description,
std::function<void(void)> function)
: fType(kChar_CommandType)
, fChar(c)
, fKeyName(' ' == c ? SkString("Space") : SkStringPrintf("%c", c))
, fGroup(group)
, fDescription(description)
, fFunction(function) {}
Command(skui::Key k, const char* keyName, const char* group, const char* description,
std::function<void(void)> function)
: fType(kKey_CommandType)
, fKey(k)
, fKeyName(keyName)
, fGroup(group)
, fDescription(description)
, fFunction(function) {}
CommandType fType;
// For kChar_CommandType
SkUnichar fChar;
// For kKey_CommandType
skui::Key fKey;
// Common to all command types
SkString fKeyName;
SkString fGroup;
SkString fDescription;
std::function<void(void)> fFunction;
SkString getSoftkeyString() const {
return SkStringPrintf("%s (%s)", fKeyName.c_str(), fDescription.c_str());
}
};
static bool compareCommandKey(const Command& first, const Command& second);
static bool compareCommandGroup(const Command& first, const Command& second);
enum HelpMode {
kNone_HelpMode,
kGrouped_HelpMode,
kAlphabetical_HelpMode,
};
Window* fWindow;
SkTArray<Command> fCommands;
HelpMode fHelpMode;
};
} // namespace sk_app
#endif