Merge branch '1.0'

Conflicts:
	data/gui.xml
	src/config.h
	src/main/resources_win32.rc
This commit is contained in:
David Capello 2014-11-16 13:26:02 -03:00
commit c0078809f7
15 changed files with 381 additions and 133 deletions

View File

@ -18,7 +18,8 @@
<key command="RepeatLastExport" shortcut="Ctrl+Shift+X" mac="Cmd+Shift+X" />
<key command="AdvancedMode" shortcut="F11" />
<key command="DeveloperConsole" shortcut="F12" />
<key command="Exit" shortcut="Alt+F4" mac="Cmd+Q" />
<key command="Exit" win="Ctrl+Q" linux="Ctrl+Q" mac="Cmd+Q" />
<key command="Exit" win="Alt+F4" />
<key command="Cancel" shortcut="Esc">
<param name="type" value="all" />
</key>

View File

@ -82,12 +82,13 @@ private:
void onChangeAccel(int index) {
Accelerator origAccel = m_key->accels()[index];
SelectAccelerator window(origAccel);
SelectAccelerator window(origAccel, m_key->keycontext());
window.openWindowInForeground();
if (window.isModified()) {
m_key->disableAccel(origAccel);
m_key->add(window.accel(), KeySource::UserDefined);
if (!window.accel().isEmpty())
m_key->add(window.accel(), KeySource::UserDefined);
}
getRoot()->layout();
@ -106,7 +107,7 @@ private:
void onAddAccel() {
ui::Accelerator accel;
SelectAccelerator window(accel);
SelectAccelerator window(accel, m_key->keycontext());
window.openWindowInForeground();
if (window.isModified()) {
@ -359,8 +360,14 @@ private:
fillList(this->menus(), AppMenus::instance()->getRootMenu(), 0);
for (Key* key : *app::KeyboardShortcuts::instance()) {
std::string text = key->triggerString();
if (key->keycontext() == KeyContext::Selection)
text += " (w/selection)";
switch (key->keycontext()) {
case KeyContext::Selection:
text = "Selection context: " + text;
break;
case KeyContext::MovingPixels:
text = "Moving pixels context: " + text;
break;
}
KeyItem* keyItem = new KeyItem(text, key, NULL, 0);
ListBox* listBox = NULL;

View File

@ -49,9 +49,10 @@ public:
Command* clone() const override { return new NewFrameCommand(*this); }
protected:
void onLoadParams(Params* params);
bool onEnabled(Context* context);
void onExecute(Context* context);
void onLoadParams(Params* params) override;
bool onEnabled(Context* context) override;
void onExecute(Context* context) override;
std::string onGetFriendlyName() const override;
private:
Content m_content;
@ -106,6 +107,22 @@ void NewFrameCommand::onExecute(Context* context)
App::instance()->getMainWindow()->popTimeline();
}
std::string NewFrameCommand::onGetFriendlyName() const
{
std::string text = "New Frame";
switch (m_content) {
case Content::CurrentFrame:
text = "New Frame (duplicated)";
break;
case Content::EmptyFrame:
text = "New Frame (empty)";
break;
}
return text;
}
Command* CommandFactory::createNewFrameCommand()
{
return new NewFrameCommand;

View File

@ -1008,15 +1008,29 @@ void Editor::updateQuicktool()
return;
}
tools::Tool* old_quicktool = m_quicktool;
tools::Tool* new_quicktool = m_customizationDelegate->getQuickTool(current_tool);
// Check if the current state accept the given quicktool.
if (new_quicktool && !m_state->acceptQuickTool(new_quicktool))
return;
// Hide the drawing cursor with the current tool brush size before
// we change the quicktool. In this way we avoid using the
// quicktool brush size to clean the current tool cursor.
hideDrawingCursor();
//
// TODO Remove EditorState::regenerateDrawingCursor() creating a
// new Document concept of multiple extra cels: we need an extra
// cel for the drawing cursor, other for the moving pixels,
// etc. In this way we'll not have conflicts between different
// uses of the same extra cel.
if (m_state->regenerateDrawingCursor())
hideDrawingCursor();
tools::Tool* old_quicktool = m_quicktool;
m_quicktool = m_customizationDelegate->getQuickTool(current_tool);
m_quicktool = new_quicktool;
showDrawingCursor();
if (m_state->regenerateDrawingCursor())
showDrawingCursor();
// If the tool has changed, we must to update the status bar because
// the new tool can display something different in the status bar (e.g. Eyedropper)

View File

@ -32,6 +32,10 @@ namespace app {
class Editor;
class EditorDecorator;
namespace tools {
class Tool;
}
// Represents one state of the sprite's editor (Editor class). This
// is a base class, a dummy state that ignores all events from the
// Editor. Subclasses overrides these methods to customize the
@ -103,6 +107,13 @@ namespace app {
// drawing cursor.
virtual bool requireBrushPreview() { return false; }
// Returns true if this state accept the given quicktool.
virtual bool acceptQuickTool(tools::Tool* tool) { return true; }
// Returns true if this state supports changing the drawing cursor
// extra cel.
virtual bool regenerateDrawingCursor() { return true; }
private:
DISABLE_COPYING(EditorState);
};

View File

@ -413,6 +413,16 @@ bool MovingPixelsState::onUpdateStatusBar(Editor* editor)
return true;
}
bool MovingPixelsState::acceptQuickTool(tools::Tool* tool)
{
return
(!m_pixelsMovement ||
tool->getInk(0)->isSelection() ||
tool->getInk(0)->isEyedropper() ||
tool->getInk(0)->isScrollMovement() ||
tool->getInk(0)->isZoom());
}
// Before executing any command, we drop the pixels (go back to standby).
void MovingPixelsState::onBeforeCommandExecution(Command* command)
{

View File

@ -58,6 +58,8 @@ namespace app {
virtual bool onKeyDown(Editor* editor, ui::KeyMessage* msg) override;
virtual bool onKeyUp(Editor* editor, ui::KeyMessage* msg) override;
virtual bool onUpdateStatusBar(Editor* editor) override;
virtual bool acceptQuickTool(tools::Tool* tool) override;
virtual bool regenerateDrawingCursor() override { return false; }
// EditorObserver
virtual void onBeforeFrameChanged(Editor* editor) override;

View File

@ -194,52 +194,51 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
return true;
}
// Transform selected pixels
if (document->isMaskVisible() &&
m_decorator->getTransformHandles(editor)) {
TransformHandles* transfHandles = m_decorator->getTransformHandles(editor);
// Get the handle covered by the mouse.
HandleType handle = transfHandles->getHandleAtPoint(editor,
msg->position(),
document->getTransformation());
if (handle != NoHandle) {
int x, y, opacity;
Image* image = location.image(&x, &y, &opacity);
if (image) {
if (!layer->isWritable()) {
Alert::show(PACKAGE "<<The layer is locked.||&Close");
return true;
}
// Change to MovingPixelsState
transformSelection(editor, msg, handle);
}
return true;
}
}
// Move selected pixels
if (editor->isInsideSelection() &&
currentTool->getInk(0)->isSelection() &&
msg->left()) {
if (!layer->isWritable()) {
Alert::show(PACKAGE "<<The layer is locked.||&Close");
return true;
}
// Change to MovingPixelsState
transformSelection(editor, msg, MoveHandle);
return true;
}
// Call the eyedropper command
if (clickedInk->isEyedropper()) {
onMouseMove(editor, msg);
callEyedropper(editor);
return true;
}
if (clickedInk->isSelection()) {
// Transform selected pixels
if (document->isMaskVisible() && m_decorator->getTransformHandles(editor)) {
TransformHandles* transfHandles = m_decorator->getTransformHandles(editor);
// Get the handle covered by the mouse.
HandleType handle = transfHandles->getHandleAtPoint(editor,
msg->position(),
document->getTransformation());
if (handle != NoHandle) {
int x, y, opacity;
Image* image = location.image(&x, &y, &opacity);
if (image) {
if (!layer->isWritable()) {
Alert::show(PACKAGE "<<The layer is locked.||&Close");
return true;
}
// Change to MovingPixelsState
transformSelection(editor, msg, handle);
}
return true;
}
}
// Move selected pixels
if (editor->isInsideSelection() && msg->left()) {
if (!layer->isWritable()) {
Alert::show(PACKAGE "<<The layer is locked.||&Close");
return true;
}
// Change to MovingPixelsState
transformSelection(editor, msg, MoveHandle);
return true;
}
}
// Start the Tool-Loop
if (layer) {
tools::ToolLoop* toolLoop = create_tool_loop(editor, context);
@ -262,16 +261,8 @@ bool StandbyState::onMouseMove(Editor* editor, MouseMessage* msg)
// We control eyedropper tool from here. TODO move this to another place
if (msg->left() || msg->right()) {
tools::Ink* clickedInk = editor->getCurrentEditorInk();
if (clickedInk->isEyedropper()) {
Command* eyedropper_cmd =
CommandsModule::instance()->getCommandByName(CommandId::Eyedropper);
bool fg = (static_cast<tools::PickInk*>(clickedInk)->target() == tools::PickInk::Fg);
Params params;
params.set("target", fg ? "foreground": "background");
UIContext::instance()->executeCommand(eyedropper_cmd, &params);
}
if (clickedInk->isEyedropper())
callEyedropper(editor);
}
editor->moveDrawingCursor();
@ -560,6 +551,22 @@ void StandbyState::transformSelection(Editor* editor, MouseMessage* msg, HandleT
}
}
void StandbyState::callEyedropper(Editor* editor)
{
tools::Ink* clickedInk = editor->getCurrentEditorInk();
if (!clickedInk->isEyedropper())
return;
Command* eyedropper_cmd =
CommandsModule::instance()->getCommandByName(CommandId::Eyedropper);
bool fg = (static_cast<tools::PickInk*>(clickedInk)->target() == tools::PickInk::Fg);
Params params;
params.set("target", fg ? "foreground": "background");
UIContext::instance()->executeCommand(eyedropper_cmd, &params);
}
//////////////////////////////////////////////////////////////////////
// Decorator

View File

@ -76,6 +76,7 @@ namespace app {
private:
void transformSelection(Editor* editor, ui::MouseMessage* msg, HandleType handle);
void callEyedropper(Editor* editor);
Decorator* m_decorator;
};

View File

@ -39,8 +39,6 @@
#include "ui/accelerator.h"
#include "ui/message.h"
#include <algorithm>
#define XML_KEYBOARD_FILE_VERSION "1"
namespace {
@ -80,6 +78,13 @@ namespace {
return shortcut;
}
bool bool_attr_is_true(const TiXmlElement* elem, const char* attribute_name)
{
const char* value = elem->Attribute(attribute_name);
return (value != NULL) && (strcmp(value, "true") == 0);
}
std::string get_user_friendly_string_for_keyaction(app::KeyAction action)
{
for (int c=0; actions[c].name; ++c) {
@ -118,6 +123,9 @@ namespace app {
using namespace ui;
//////////////////////////////////////////////////////////////////////
// Key
Key::Key(Command* command, const Params* params, KeyContext keyContext)
: m_type(KeyType::Command)
, m_useUsers(false)
@ -141,12 +149,38 @@ Key::Key(KeyAction action)
, m_keycontext(KeyContext::Any)
, m_action(action)
{
}
void Key::setUserAccels(const Accelerators& accels)
{
m_useUsers = true;
m_users = accels;
switch (action) {
case KeyAction::None:
m_keycontext = KeyContext::Any;
break;
case KeyAction::CopySelection:
m_keycontext = KeyContext::MovingPixels;
break;
case KeyAction::SnapToGrid:
m_keycontext = KeyContext::MovingPixels;
break;
case KeyAction::AngleSnap:
m_keycontext = KeyContext::MovingPixels;
break;
case KeyAction::MaintainAspectRatio:
m_keycontext = KeyContext::MovingPixels;
break;
case KeyAction::LockAxis:
m_keycontext = KeyContext::MovingPixels;
break;
case KeyAction::AddSelection:
m_keycontext = KeyContext::Selection;
break;
case KeyAction::SubtractSelection:
m_keycontext = KeyContext::Selection;
break;
case KeyAction::LeftMouseButton:
m_keycontext = KeyContext::Any;
break;
case KeyAction::RightMouseButton:
m_keycontext = KeyContext::Any;
break;
}
}
void Key::add(const ui::Accelerator& accel, KeySource source)
@ -159,11 +193,16 @@ void Key::add(const ui::Accelerator& accel, KeySource source)
m_users = m_accels;
}
accels = &m_users;
KeyboardShortcuts::instance()->disableAccel(accel);
}
accels->push_back(accel);
// Remove the accelerator from other commands
if (source == KeySource::UserDefined) {
KeyboardShortcuts::instance()->disableAccel(accel, m_keycontext);
m_userRemoved.remove(accel);
}
// Add the accelerator
accels->add(accel);
}
bool Key::isPressed(Message* msg) const
@ -194,7 +233,7 @@ bool Key::checkFromAllegroKeyArray()
bool Key::hasAccel(const ui::Accelerator& accel) const
{
return (std::find(accels().begin(), accels().end(), accel) != accels().end());
return accels().has(accel);
}
void Key::disableAccel(const ui::Accelerator& accel)
@ -204,14 +243,16 @@ void Key::disableAccel(const ui::Accelerator& accel)
m_users = m_accels;
}
Accelerators::iterator it = std::find(m_users.begin(), m_users.end(), accel);
if (it != m_users.end())
m_users.erase(it);
m_users.remove(accel);
if (m_accels.has(accel))
m_userRemoved.add(accel);
}
void Key::reset()
{
m_users.clear();
m_userRemoved.clear();
m_useUsers = false;
}
@ -235,6 +276,9 @@ std::string Key::triggerString() const
return "Unknown";
}
//////////////////////////////////////////////////////////////////////
// KeyboardShortcuts
KeyboardShortcuts* KeyboardShortcuts::instance()
{
static KeyboardShortcuts* singleton = NULL;
@ -270,6 +314,7 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
while (xmlKey) {
const char* command_name = xmlKey->Attribute("command");
const char* command_key = get_shortcut(xmlKey);
bool removed = bool_attr_is_true(xmlKey, "removed");
if (command_name && command_key) {
Command* command = CommandsModule::instance()->getCommandByName(command_name);
@ -303,15 +348,21 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
// add the keyboard shortcut to the command
Key* key = this->command(command_name, &params, keycontext);
if (key) {
key->add(Accelerator(command_key), source);
Accelerator accel(command_key);
// Add the shortcut to the menuitems with this
// command (this is only visual, the "manager_msg_proc"
// is the only one that process keyboard shortcuts)
if (key->accels().size() == 1) {
AppMenus::instance()->applyShortcutToMenuitemsWithCommand(
command, &params, key);
if (!removed) {
key->add(accel, source);
// Add the shortcut to the menuitems with this
// command (this is only visual, the "manager_msg_proc"
// is the only one that process keyboard shortcuts)
if (key->accels().size() == 1) {
AppMenus::instance()->applyShortcutToMenuitemsWithCommand(
command, &params, key);
}
}
else
key->disableAccel(accel);
}
}
}
@ -327,6 +378,7 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
while (xmlKey) {
const char* tool_id = xmlKey->Attribute("tool");
const char* tool_key = get_shortcut(xmlKey);
bool removed = bool_attr_is_true(xmlKey, "removed");
if (tool_id && tool_key) {
tools::Tool* tool = App::instance()->getToolBox()->getToolById(tool_id);
@ -334,8 +386,14 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
PRINTF(" - Shortcut for tool `%s': <%s>\n", tool_id, tool_key);
Key* key = this->tool(tool);
if (key)
key->add(Accelerator(tool_key), source);
if (key) {
Accelerator accel(tool_key);
if (!removed)
key->add(accel, source);
else
key->disableAccel(accel);
}
}
}
xmlKey = xmlKey->NextSiblingElement();
@ -349,14 +407,22 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
while (xmlKey) {
const char* tool_id = xmlKey->Attribute("tool");
const char* tool_key = get_shortcut(xmlKey);
bool removed = bool_attr_is_true(xmlKey, "removed");
if (tool_id && tool_key) {
tools::Tool* tool = App::instance()->getToolBox()->getToolById(tool_id);
if (tool) {
PRINTF(" - Shortcut for quicktool `%s': <%s>\n", tool_id, tool_key);
Key* key = this->quicktool(tool);
if (key)
key->add(Accelerator(tool_key), source);
if (key) {
Accelerator accel(tool_key);
if (!removed)
key->add(accel, source);
else
key->disableAccel(accel);
}
}
}
xmlKey = xmlKey->NextSiblingElement();
@ -370,6 +436,7 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
while (xmlKey) {
const char* tool_action = xmlKey->Attribute("action");
const char* tool_key = get_shortcut(xmlKey);
bool removed = bool_attr_is_true(xmlKey, "removed");
if (tool_action && tool_key) {
PRINTF(" - Shortcut for sprite editor `%s': <%s>\n", tool_action, tool_key);
@ -378,8 +445,14 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
if (action != KeyAction::None) {
Key* key = this->action(action);
if (key)
key->add(Accelerator(tool_key), source);
if (key) {
Accelerator accel(tool_key);
if (!removed)
key->add(accel, source);
else
key->disableAccel(accel);
}
}
}
xmlKey = xmlKey->NextSiblingElement();
@ -424,41 +497,77 @@ void KeyboardShortcuts::exportKeys(TiXmlElement& parent, KeyType type)
{
for (Key* key : m_keys) {
// Save only user defined accelerators.
if (key->type() != type || key->userAccels().empty())
if (key->type() != type)
continue;
for (const ui::Accelerator& accel : key->userAccels()) {
TiXmlElement elem("key");
for (const ui::Accelerator& accel : key->userRemovedAccels())
exportAccel(parent, key, accel, true);
switch (key->type()) {
case KeyType::Command:
elem.SetAttribute("command", key->command()->short_name());
if (key->params()) {
for (const auto& param : *key->params()) {
if (param.second.empty())
continue;
for (const ui::Accelerator& accel : key->userAccels())
exportAccel(parent, key, accel, false);
}
}
TiXmlElement paramElem("param");
paramElem.SetAttribute("name", param.first.c_str());
paramElem.SetAttribute("value", param.second.c_str());
elem.InsertEndChild(paramElem);
}
}
void KeyboardShortcuts::exportAccel(TiXmlElement& parent, Key* key, const ui::Accelerator& accel, bool removed)
{
TiXmlElement elem("key");
switch (key->type()) {
case KeyType::Command: {
const char* keycontextStr = NULL;
elem.SetAttribute("command", key->command()->short_name());
switch (key->keycontext()) {
case KeyContext::Any:
// Without "context" attribute
break;
case KeyType::Tool:
case KeyType::Quicktool:
elem.SetAttribute("tool", key->tool()->getId().c_str());
case KeyContext::Normal:
keycontextStr = "Normal";
break;
case KeyType::Action:
elem.SetAttribute("action",
base::convert_to<std::string>(key->action()).c_str());
case KeyContext::Selection:
keycontextStr = "Selection";
break;
case KeyContext::MovingPixels:
keycontextStr = "MovingPixels";
break;
}
elem.SetAttribute("shortcut", accel.toString().c_str());
parent.InsertEndChild(elem);
if (keycontextStr)
elem.SetAttribute("context", keycontextStr);
if (key->params()) {
for (const auto& param : *key->params()) {
if (param.second.empty())
continue;
TiXmlElement paramElem("param");
paramElem.SetAttribute("name", param.first.c_str());
paramElem.SetAttribute("value", param.second.c_str());
elem.InsertEndChild(paramElem);
}
}
break;
}
case KeyType::Tool:
case KeyType::Quicktool:
elem.SetAttribute("tool", key->tool()->getId().c_str());
break;
case KeyType::Action:
elem.SetAttribute("action",
base::convert_to<std::string>(key->action()).c_str());
break;
}
elem.SetAttribute("shortcut", accel.toString().c_str());
if (removed)
elem.SetAttribute("removed", "true");
parent.InsertEndChild(elem);
}
void KeyboardShortcuts::reset()
@ -531,10 +640,10 @@ Key* KeyboardShortcuts::action(KeyAction action)
return key;
}
void KeyboardShortcuts::disableAccel(const ui::Accelerator& accel)
void KeyboardShortcuts::disableAccel(const ui::Accelerator& accel, KeyContext keyContext)
{
for (Key* key : m_keys) {
if (key->hasAccel(accel))
if (key->keycontext() == keyContext && key->hasAccel(accel))
key->disableAccel(accel);
}
}

View File

@ -44,6 +44,7 @@ namespace app {
Any,
Normal,
Selection,
MovingPixels,
};
enum class KeySource {
@ -83,8 +84,7 @@ namespace app {
}
const ui::Accelerators& origAccels() const { return m_accels; }
const ui::Accelerators& userAccels() const { return m_users; }
void setUserAccels(const ui::Accelerators& accels);
const ui::Accelerators& userRemovedAccels() const { return m_userRemoved; }
void add(const ui::Accelerator& accel, KeySource source);
bool isPressed(ui::Message* msg) const;
@ -109,8 +109,9 @@ namespace app {
private:
KeyType m_type;
ui::Accelerators m_accels;
ui::Accelerators m_users;
ui::Accelerators m_accels; // Default accelerators (from gui.xml)
ui::Accelerators m_users; // User-defined accelerators
ui::Accelerators m_userRemoved; // Default accelerators removed by user
bool m_useUsers;
KeyContext m_keycontext;
@ -149,7 +150,7 @@ namespace app {
Key* quicktool(tools::Tool* tool);
Key* action(KeyAction action);
void disableAccel(const ui::Accelerator& accel);
void disableAccel(const ui::Accelerator& accel, KeyContext keyContext);
KeyContext getCurrentKeyContext();
bool getCommandFromKeyMessage(ui::Message* msg, Command** command, Params** params);
@ -159,6 +160,7 @@ namespace app {
KeyboardShortcuts();
void exportKeys(TiXmlElement& parent, KeyType type);
void exportAccel(TiXmlElement& parent, Key* key, const ui::Accelerator& accel, bool removed);
Keys m_keys;

View File

@ -63,6 +63,12 @@ protected:
keymsg->scancode(),
keymsg->unicodeChar() > 32 ?
std::tolower(keymsg->unicodeChar()): 0);
// Convert the accelerator to a string, and parse it
// again. Just to obtain the exact accelerator we'll read
// when we import the gui.xml file or an .aseprite-keys file.
m_accel = Accelerator(m_accel.toString());
updateText();
AccelChange(&m_accel);
@ -84,8 +90,9 @@ protected:
Accelerator m_accel;
};
SelectAccelerator::SelectAccelerator(const ui::Accelerator& accel)
SelectAccelerator::SelectAccelerator(const ui::Accelerator& accel, KeyContext keyContext)
: m_keyField(new KeyField(accel))
, m_keyContext(keyContext)
, m_accel(accel)
, m_modified(false)
{
@ -170,7 +177,8 @@ void SelectAccelerator::updateAssignedTo()
std::string res = "None";
for (Key* key : *KeyboardShortcuts::instance()) {
if (key->hasAccel(m_accel)) {
if (key->keycontext() == m_keyContext &&
key->hasAccel(m_accel)) {
res = key->triggerString();
break;
}

View File

@ -20,6 +20,7 @@
#define APP_UI_SELECT_ACCELERATOR_H_INCLUDED
#pragma once
#include "app/ui/keyboard_shortcuts.h"
#include "ui/accelerator.h"
#include "generated_select_accelerator.h"
@ -28,7 +29,7 @@ namespace app {
class SelectAccelerator : public app::gen::SelectAccelerator {
public:
explicit SelectAccelerator(const ui::Accelerator& accelerator);
SelectAccelerator(const ui::Accelerator& accelerator, KeyContext keyContext);
bool isModified() const { return m_modified; }
const ui::Accelerator& accel() const { return m_accel; }
@ -45,6 +46,7 @@ namespace app {
class KeyField;
KeyField* m_keyField;
KeyContext m_keyContext;
ui::Accelerator m_origAccel;
ui::Accelerator m_accel;
bool m_modified;

View File

@ -18,11 +18,16 @@
#include <string>
#include <vector>
#include <algorithm>
// #define REPORT_KEYS
#define PREPROCESS_KEYS
namespace ui {
//////////////////////////////////////////////////////////////////////
// Accelerator
Accelerator::Accelerator()
: m_modifiers(kKeyNoneModifier)
, m_scancode(kKeyNil)
@ -196,6 +201,8 @@ bool Accelerator::operator==(const Accelerator& other) const
return true;
else if (m_unicodeChar != 0)
return (std::tolower(m_unicodeChar) == std::tolower(other.m_unicodeChar));
else // Only comparing modifiers, and they are equal
return true;
}
return false;
@ -344,11 +351,6 @@ std::string Accelerator::toString() const
bool Accelerator::check(KeyModifiers modifiers, KeyScancode scancode, int unicodeChar) const
{
#ifdef REPORT_KEYS
char buf[256];
std::string buf2;
#endif
// Preprocess the character to be compared with the accelerator
#ifdef PREPROCESS_KEYS
// Directly scancode
@ -410,15 +412,18 @@ bool Accelerator::check(KeyModifiers modifiers, KeyScancode scancode, int unicod
if ((m_modifiers == modifiers) &&
((m_scancode != kKeyNil && m_scancode == scancode) ||
(m_unicodeChar && m_unicodeChar == unicodeChar))) {
(m_unicodeChar && m_unicodeChar == unicodeChar) ||
(m_scancode == kKeyNil && scancode == kKeyNil && !m_unicodeChar && !unicodeChar))) {
#ifdef REPORT_KEYS
printf("true\n");
fflush(stdout);
#endif
return true;
}
#ifdef REPORT_KEYS
printf("false\n");
fflush(stdout);
#endif
return false;
}
@ -438,4 +443,25 @@ bool Accelerator::checkFromAllegroKeyArray() const
(m_modifiers == modifiers));
}
//////////////////////////////////////////////////////////////////////
// Accelerators
bool Accelerators::has(const Accelerator& accel) const
{
return (std::find(begin(), end(), accel) != end());
}
void Accelerators::add(const Accelerator& accel)
{
if (!has(accel))
m_list.push_back(accel);
}
void Accelerators::remove(const Accelerator& accel)
{
auto it = std::find(begin(), end(), accel);
if (it != end())
m_list.erase(it);
}
} // namespace ui

View File

@ -43,7 +43,38 @@ namespace ui {
int m_unicodeChar;
};
typedef std::vector<Accelerator> Accelerators;
class Accelerators {
public:
typedef std::vector<Accelerator> List;
typedef List::iterator iterator;
typedef List::const_iterator const_iterator;
iterator begin() { return m_list.begin(); }
iterator end() { return m_list.end(); }
const_iterator begin() const { return m_list.begin(); }
const_iterator end() const { return m_list.end(); }
bool empty() const { return m_list.empty(); }
size_t size() const { return m_list.size(); }
const ui::Accelerator& front() const { return m_list.front(); }
const ui::Accelerator& operator[](int index) const {
return m_list[index];
}
ui::Accelerator& operator[](int index) {
return m_list[index];
}
void clear() { m_list.clear(); }
bool has(const Accelerator& accel) const;
void add(const Accelerator& accel);
void remove(const Accelerator& accel);
private:
List m_list;
};
} // namespace ui