Redesigned the shortcut API to use the new keybinding class.

This commit is contained in:
Martín Lucas Golini
2020-06-23 23:45:27 -03:00
parent 99ee9743bc
commit 39c6c65cba
12 changed files with 210 additions and 173 deletions
+2 -4
View File
@@ -23,6 +23,8 @@ Keep improving it:
* Support single instance (when a new file is opened while a previous instance exists, open it in the first instance).
* Search and replace only over selection.
## UI Editor
* Integrate the `UICodeEditor` into the editor in order to be able to edit the layouts and CSS in app.
@@ -33,10 +35,6 @@ Keep improving it:
Detect errors and log them.
## UISceneNode and UIWindow
Redesign the shortcut API to use the new keybinding class.
## UITreeView
Implement a simple tree view widget, to at least cover the most common use cases.
+3 -2
View File
@@ -8,6 +8,7 @@
#include <eepp/ui/tools/textureatlaseditor.hpp>
#include <eepp/ui/uicheckbox.hpp>
#include <eepp/ui/uifiledialog.hpp>
#include <eepp/ui/uimenubar.hpp>
#include <eepp/ui/uimenucheckbox.hpp>
#include <eepp/ui/uimessagebox.hpp>
#include <eepp/ui/uipopupmenu.hpp>
@@ -17,7 +18,6 @@
#include <eepp/ui/uitextureregion.hpp>
#include <eepp/ui/uithememanager.hpp>
#include <eepp/ui/uiwindow.hpp>
#include <eepp/ui/uimenubar.hpp>
namespace EE { namespace UI {
class UIMessageBox;
@@ -251,7 +251,8 @@ class EE_API MapEditor {
void updateScroll();
bool addShortcut( const Keycode& KeyCode, const Uint32& Mod, UIWidget* Widget );
void addShortcut( const KeyBindings::Shortcut& shortcut, const std::string& cmd,
std::function<void()> func );
};
}} // namespace EE::Maps
-14
View File
@@ -16,20 +16,6 @@ namespace EE { namespace UI {
class UIWidget;
class EE_API UIKeyShortcut {
public:
UIKeyShortcut() : KeyCode( KEY_UNKNOWN ), Mod( 0 ), Widget( NULL ) {}
UIKeyShortcut( const Keycode& KeyCode, const Uint32& Mod, UIWidget* Widget ) :
KeyCode( KeyCode ), Mod( Mod ), Widget( Widget ) {}
Keycode KeyCode;
Uint32 Mod;
UIWidget* Widget;
};
typedef std::vector<UIKeyShortcut> UIKeyboardShortcuts;
class EE_API KeyBindings {
public:
struct Shortcut {
+2 -2
View File
@@ -181,10 +181,10 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
void replaceKeyBinding( const KeyBindings::Shortcut& shortcut, const std::string& command,
const bool& allowLocked = false );
void addKeybindsString( const std::map<std::string, std::string>& binds,
void addKeyBindsString( const std::map<std::string, std::string>& binds,
const bool& allowLocked = false );
void addKeybinds( const std::map<KeyBindings::Shortcut, std::string>& binds,
void addKeyBinds( const std::map<KeyBindings::Shortcut, std::string>& binds,
const bool& allowLocked = false );
const bool& getHighlightCurrentLine() const;
+25 -10
View File
@@ -81,10 +81,6 @@ class EE_API UISceneNode : public SceneNode {
UIWidget* getRoot() const;
bool addShortcut( const Keycode& KeyCode, const Uint32& Mod, UIWidget* Widget );
bool removeShortcut( const Keycode& KeyCode, const Uint32& Mod );
bool getVerbose() const;
void setVerbose( bool verbose );
@@ -109,6 +105,28 @@ class EE_API UISceneNode : public SceneNode {
Drawable* findIcon( const std::string& iconName );
typedef std::function<void()> KeyBindingCommand;
KeyBindings& getKeyBindings();
void setKeyBindings( const KeyBindings& keyBindings );
void addKeyBindingString( const std::string& shortcut, const std::string& command );
void addKeyBinding( const KeyBindings::Shortcut& shortcut, const std::string& command );
void replaceKeyBindingString( const std::string& shortcut, const std::string& command );
void replaceKeyBinding( const KeyBindings::Shortcut& shortcut, const std::string& command );
void addKeyBindsString( const std::map<std::string, std::string>& binds );
void addKeyBinds( const std::map<KeyBindings::Shortcut, std::string>& binds );
void setKeyBindingCommand( const std::string& command, KeyBindingCommand func );
void executeKeyBindingCommand( const std::string& command );
protected:
friend class EE::UI::UIWindow;
friend class EE::UI::UIWidget;
@@ -124,7 +142,8 @@ class EE_API UISceneNode : public SceneNode {
UIThemeManager* mUIThemeManager;
UIIconThemeManager* mUIIconThemeManager;
std::vector<Font*> mFontFaces;
UIKeyboardShortcuts mKbShortcuts;
KeyBindings mKeyBindings;
std::map<std::string, KeyBindingCommand> mKeyBindingCommands;
std::unordered_set<UIWidget*> mDirtyStyle;
std::unordered_set<UIWidget*> mDirtyStyleState;
std::unordered_map<UIWidget*, bool> mDirtyStyleStateCSSAnimations;
@@ -165,11 +184,7 @@ class EE_API UISceneNode : public SceneNode {
std::vector<UIWidget*> loadNode( pugi::xml_node node, Node* parent );
virtual Uint32 onKeyDown( const KeyEvent& Event );
void checkShortcuts( const Uint32& KeyCode, const Uint32& Mod );
UIKeyboardShortcuts::iterator existsShortcut( const Uint32& KeyCode, const Uint32& Mod );
virtual Uint32 onKeyDown( const KeyEvent& event );
void onWidgetDelete( Node* node );
+25 -9
View File
@@ -111,10 +111,6 @@ class EE_API UIWindow : public UIWidget {
UITextView* getTitleTextBox() const;
bool addShortcut( const Keycode& KeyCode, const Uint32& Mod, UIWidget* Widget );
bool removeShortcut( const Keycode& KeyCode, const Uint32& Mod );
bool isModal();
UIWidget* getModalWidget() const;
@@ -164,6 +160,28 @@ class EE_API UIWindow : public UIWidget {
Sizef getSizeWithoutDecoration();
typedef std::function<void()> KeyBindingCommand;
KeyBindings& getKeyBindings();
void setKeyBindings( const KeyBindings& keyBindings );
void addKeyBindingString( const std::string& shortcut, const std::string& command );
void addKeyBinding( const KeyBindings::Shortcut& shortcut, const std::string& command );
void replaceKeyBindingString( const std::string& shortcut, const std::string& command );
void replaceKeyBinding( const KeyBindings::Shortcut& shortcut, const std::string& command );
void addKeyBindsString( const std::map<std::string, std::string>& binds );
void addKeyBinds( const std::map<KeyBindings::Shortcut, std::string>& binds );
void setKeyBindingCommand( const std::string& command, KeyBindingCommand func );
void executeKeyBindingCommand( const std::string& command );
protected:
enum UI_RESIZE_TYPE {
RESIZE_NONE,
@@ -196,10 +214,12 @@ class EE_API UIWindow : public UIWidget {
Sizef mNonMaxSize;
UI_RESIZE_TYPE mResizeType;
Vector2f mResizePos;
UIKeyboardShortcuts mKbShortcuts;
bool mFrameBufferBound;
KeyBindings mKeyBindings;
std::map<std::string, KeyBindingCommand> mKeyBindingCommands;
virtual void onSizeChange();
virtual void onAlphaChange();
@@ -236,10 +256,6 @@ class EE_API UIWindow : public UIWidget {
Uint32 onMouseDoubleClick( const Vector2i& position, const Uint32& flags );
void checkShortcuts( const Uint32& KeyCode, const Uint32& Mod );
UIKeyboardShortcuts::iterator existsShortcut( const Keycode& KeyCode, const Uint32& Mod );
void createModalNode();
void resizeCursor();
+14 -9
View File
@@ -93,11 +93,15 @@ void MapEditor::createME() {
createUIMap();
}
bool MapEditor::addShortcut( const Keycode& KeyCode, const Uint32& Mod, UIWidget* Widget ) {
void MapEditor::addShortcut( const KeyBindings::Shortcut& shortcut, const std::string& cmd,
std::function<void()> func ) {
if ( NULL != mUIWindow ) {
return mUIWindow->addShortcut( KeyCode, Mod, Widget );
mUIWindow->setKeyBindingCommand( cmd, func );
mUIWindow->addKeyBinding( shortcut, cmd );
} else {
return mUIContainer->asType<UISceneNode>()->addShortcut( KeyCode, Mod, Widget );
UISceneNode* sceneNode = mUIContainer->asType<UISceneNode>();
sceneNode->setKeyBindingCommand( cmd, func );
sceneNode->addKeyBinding( shortcut, cmd );
}
}
@@ -142,12 +146,13 @@ void MapEditor::createMenuBar() {
PU3->addSeparator();
addShortcut( KEY_KP_PLUS, KEYMOD_CTRL,
PU3->add( "Zoom In", PU3->getUISceneNode()->findIcon( "zoom-in" ) ) );
addShortcut( KEY_KP_MINUS, KEYMOD_CTRL,
PU3->add( "Zoom Out", PU3->getUISceneNode()->findIcon( "zoom-out" ) ) );
addShortcut( KEY_0, KEYMOD_CTRL,
PU3->add( "Normal Size", PU3->getUISceneNode()->findIcon( "zoom-original" ) ) );
PU3->add( "Zoom In", PU3->getUISceneNode()->findIcon( "zoom-in" ) );
PU3->add( "Zoom Out", PU3->getUISceneNode()->findIcon( "zoom-out" ) );
PU3->add( "Normal Size", PU3->getUISceneNode()->findIcon( "zoom-original" ) );
addShortcut( {KEY_KP_PLUS, KEYMOD_CTRL}, "zoom-in", [&] { zoomIn(); } );
addShortcut( {KEY_KP_MINUS, KEYMOD_CTRL}, "zoom-out", [&] { zoomOut(); } );
addShortcut( {KEY_0, KEYMOD_CTRL}, "zoom-reset", [&] { mUIMap->Map()->setScale( 1 ); } );
PU3->addSeparator();
PU3->addEventListener( Event::OnItemClicked, cb::Make1( this, &MapEditor::viewMenuClick ) );
+2 -2
View File
@@ -976,7 +976,7 @@ void UICodeEditor::replaceKeyBinding( const KeyBindings::Shortcut& shortcut,
mUnlockedCmd.insert( command );
}
void UICodeEditor::addKeybindsString( const std::map<std::string, std::string>& binds,
void UICodeEditor::addKeyBindsString( const std::map<std::string, std::string>& binds,
const bool& allowLocked ) {
mKeyBindings.addKeybindsString( binds );
for ( auto bind : binds ) {
@@ -986,7 +986,7 @@ void UICodeEditor::addKeybindsString( const std::map<std::string, std::string>&
}
}
void UICodeEditor::addKeybinds( const std::map<KeyBindings::Shortcut, std::string>& binds,
void UICodeEditor::addKeyBinds( const std::map<KeyBindings::Shortcut, std::string>& binds,
const bool& allowLocked ) {
mKeyBindings.addKeybinds( binds );
for ( auto bind : binds ) {
+58 -52
View File
@@ -37,7 +37,8 @@ UISceneNode::UISceneNode( EE::Window::Window* window ) :
mVerbose( false ),
mUpdatingLayouts( false ),
mUIThemeManager( UIThemeManager::New() ),
mUIIconThemeManager( UIIconThemeManager::New()->setFallbackThemeManager( mUIThemeManager ) ) {
mUIIconThemeManager( UIIconThemeManager::New()->setFallbackThemeManager( mUIThemeManager ) ),
mKeyBindings( mWindow->getInput() ) {
// Reset size since the SceneNode already set it but needs to set the size from zero to emmit
// the required events to its childs.
mSize = Sizef();
@@ -776,57 +777,6 @@ void UISceneNode::loadFontFaces( const StyleSheetStyleVector& styles ) {
}
}
Uint32 UISceneNode::onKeyDown( const KeyEvent& Event ) {
checkShortcuts( Event.getKeyCode(), Event.getMod() );
return SceneNode::onKeyDown( Event );
}
void UISceneNode::checkShortcuts( const Uint32& KeyCode, const Uint32& Mod ) {
if ( NULL == getEventDispatcher() )
return;
for ( auto& kb : mKbShortcuts ) {
if ( KeyCode == kb.KeyCode && ( Mod & kb.Mod ) ) {
getEventDispatcher()->sendMouseUp( kb.Widget, Vector2i( -1, -1 ), EE_BUTTON_LMASK );
getEventDispatcher()->sendMouseClick( kb.Widget, Vector2i( -1, -1 ), EE_BUTTON_LMASK );
}
}
}
UIKeyboardShortcuts::iterator UISceneNode::existsShortcut( const Uint32& KeyCode,
const Uint32& Mod ) {
for ( UIKeyboardShortcuts::iterator it = mKbShortcuts.begin(); it != mKbShortcuts.end();
++it ) {
if ( it->KeyCode == KeyCode && it->Mod == Mod )
return it;
}
return mKbShortcuts.end();
}
bool UISceneNode::addShortcut( const Keycode& KeyCode, const Uint32& Mod, UIWidget* Widget ) {
if ( inParentTreeOf( Widget ) && mKbShortcuts.end() == existsShortcut( KeyCode, Mod ) ) {
mKbShortcuts.push_back( UIKeyShortcut( KeyCode, Mod, Widget ) );
return true;
}
return false;
}
bool UISceneNode::removeShortcut( const Keycode& KeyCode, const Uint32& Mod ) {
UIKeyboardShortcuts::iterator it = existsShortcut( KeyCode, Mod );
if ( mKbShortcuts.end() != it ) {
mKbShortcuts.erase( it );
return true;
}
return false;
}
void UISceneNode::setInternalPixelsSize( const Sizef& size ) {
Sizef s( size );
if ( s != mSize ) {
@@ -839,4 +789,60 @@ void UISceneNode::setInternalPixelsSize( const Sizef& size ) {
}
}
Uint32 UISceneNode::onKeyDown( const KeyEvent& event ) {
std::string cmd = mKeyBindings.getCommandFromKeyBind( {event.getKeyCode(), event.getMod()} );
if ( !cmd.empty() ) {
executeKeyBindingCommand( cmd );
return 0;
}
return SceneNode::onKeyDown( event );
}
KeyBindings& UISceneNode::getKeyBindings() {
return mKeyBindings;
}
void UISceneNode::setKeyBindings( const KeyBindings& keyBindings ) {
mKeyBindings = keyBindings;
}
void UISceneNode::addKeyBindingString( const std::string& shortcut, const std::string& command ) {
mKeyBindings.addKeybindString( shortcut, command );
}
void UISceneNode::addKeyBinding( const KeyBindings::Shortcut& shortcut,
const std::string& command ) {
mKeyBindings.addKeybind( shortcut, command );
}
void UISceneNode::replaceKeyBindingString( const std::string& shortcut,
const std::string& command ) {
mKeyBindings.replaceKeybindString( shortcut, command );
}
void UISceneNode::replaceKeyBinding( const KeyBindings::Shortcut& shortcut,
const std::string& command ) {
mKeyBindings.replaceKeybind( shortcut, command );
}
void UISceneNode::addKeyBindsString( const std::map<std::string, std::string>& binds ) {
mKeyBindings.addKeybindsString( binds );
}
void UISceneNode::addKeyBinds( const std::map<KeyBindings::Shortcut, std::string>& binds ) {
mKeyBindings.addKeybinds( binds );
}
void UISceneNode::setKeyBindingCommand( const std::string& command,
UISceneNode::KeyBindingCommand func ) {
mKeyBindingCommands[command] = func;
}
void UISceneNode::executeKeyBindingCommand( const std::string& command ) {
auto cmdIt = mKeyBindingCommands.find( command );
if ( cmdIt != mKeyBindingCommands.end() ) {
cmdIt->second();
}
}
}} // namespace EE::UI
+58 -52
View File
@@ -44,7 +44,8 @@ UIWindow::UIWindow( UIWindow::WindowBaseContainerType type, const StyleConfig& w
mTitle( NULL ),
mModalNode( NULL ),
mResizeType( RESIZE_NONE ),
mFrameBufferBound( false ) {
mFrameBufferBound( false ),
mKeyBindings( getEventDispatcher()->getInput() ) {
subscribeScheduledUpdate();
bool loading = isSceneNodeLoading();
@@ -1210,12 +1211,6 @@ Uint32 UIWindow::onMouseDoubleClick( const Vector2i&, const Uint32& Flags ) {
return 1;
}
Uint32 UIWindow::onKeyDown( const KeyEvent& Event ) {
checkShortcuts( Event.getKeyCode(), Event.getMod() );
return UIWidget::onKeyDown( Event );
}
void UIWindow::internalDraw() {
if ( mVisible && 0 != mAlpha ) {
updateScreenPos();
@@ -1322,51 +1317,6 @@ bool UIWindow::ownsFrameBuffer() {
return 0 != ( mStyleConfig.WinFlags & UI_WIN_FRAME_BUFFER );
}
void UIWindow::checkShortcuts( const Uint32& KeyCode, const Uint32& Mod ) {
if ( NULL == getEventDispatcher() )
return;
for ( auto& kb : mKbShortcuts ) {
if ( KeyCode == kb.KeyCode && ( Mod & kb.Mod ) ) {
getEventDispatcher()->sendMouseUp( kb.Widget, Vector2i( -1, -1 ), EE_BUTTON_LMASK );
getEventDispatcher()->sendMouseClick( kb.Widget, Vector2i( -1, -1 ), EE_BUTTON_LMASK );
}
}
}
UIKeyboardShortcuts::iterator UIWindow::existsShortcut( const Keycode& KeyCode,
const Uint32& Mod ) {
for ( UIKeyboardShortcuts::iterator it = mKbShortcuts.begin(); it != mKbShortcuts.end();
++it ) {
if ( ( *it ).KeyCode == KeyCode && ( *it ).Mod == Mod )
return it;
}
return mKbShortcuts.end();
}
bool UIWindow::addShortcut( const Keycode& KeyCode, const Uint32& Mod, UIWidget* Widget ) {
if ( inParentTreeOf( Widget ) && mKbShortcuts.end() == existsShortcut( KeyCode, Mod ) ) {
mKbShortcuts.push_back( UIKeyShortcut( KeyCode, Mod, Widget ) );
return true;
}
return false;
}
bool UIWindow::removeShortcut( const Keycode& KeyCode, const Uint32& Mod ) {
UIKeyboardShortcuts::iterator it = existsShortcut( KeyCode, Mod );
if ( mKbShortcuts.end() != it ) {
mKbShortcuts.erase( it );
return true;
}
return false;
}
bool UIWindow::isMaximizable() {
return isResizeable() && 0 != ( mStyleConfig.WinFlags & UI_WIN_MAXIMIZE_BUTTON );
}
@@ -1684,4 +1634,60 @@ void UIWindow::preDraw() {}
void UIWindow::postDraw() {}
Uint32 UIWindow::onKeyDown( const KeyEvent& event ) {
std::string cmd = mKeyBindings.getCommandFromKeyBind( {event.getKeyCode(), event.getMod()} );
if ( !cmd.empty() ) {
executeKeyBindingCommand( cmd );
return 0;
}
return UIWidget::onKeyDown( event );
}
KeyBindings& UIWindow::getKeyBindings() {
return mKeyBindings;
}
void UIWindow::setKeyBindings( const KeyBindings& keyBindings ) {
mKeyBindings = keyBindings;
}
void UIWindow::addKeyBindingString( const std::string& shortcut, const std::string& command ) {
mKeyBindings.addKeybindString( shortcut, command );
}
void UIWindow::addKeyBinding( const KeyBindings::Shortcut& shortcut,
const std::string& command ) {
mKeyBindings.addKeybind( shortcut, command );
}
void UIWindow::replaceKeyBindingString( const std::string& shortcut,
const std::string& command ) {
mKeyBindings.replaceKeybindString( shortcut, command );
}
void UIWindow::replaceKeyBinding( const KeyBindings::Shortcut& shortcut,
const std::string& command ) {
mKeyBindings.replaceKeybind( shortcut, command );
}
void UIWindow::addKeyBindsString( const std::map<std::string, std::string>& binds ) {
mKeyBindings.addKeybindsString( binds );
}
void UIWindow::addKeyBinds( const std::map<KeyBindings::Shortcut, std::string>& binds ) {
mKeyBindings.addKeybinds( binds );
}
void UIWindow::setKeyBindingCommand( const std::string& command,
UIWindow::KeyBindingCommand func ) {
mKeyBindingCommands[command] = func;
}
void UIWindow::executeKeyBindingCommand( const std::string& command ) {
auto cmdIt = mKeyBindingCommands.find( command );
if ( cmdIt != mKeyBindingCommands.end() ) {
cmdIt->second();
}
}
}} // namespace EE::UI
+19 -17
View File
@@ -1136,7 +1136,8 @@ void EETest::createDecoratedWindow() {
->setParent( lay );
Button->addEventListener( Event::MouseClick, cb::Make1( this, &EETest::onButtonClick ) );
mUIWindow->addShortcut( KEY_C, KEYMOD_ALT, Button );
mUIWindow->setKeyBindingCommand( "button-click", [&] { addFlyingIcon(); } );
mUIWindow->addKeyBinding( {KEY_C, KEYMOD_LALT}, "button-click" );
UITabWidget* TabWidget = UITabWidget::New();
TabWidget->setLayoutMargin( Rect( 5, 5, 5, 5 ) )
@@ -1286,24 +1287,25 @@ void EETest::onMainClick( const Event* event ) {
using namespace EE::Scene::Actions;
void EETest::addFlyingIcon() {
UIImage* Gfx = UIImage::New();
Gfx->setDrawable( mSceneNode->findIcon( "ok" ) );
Gfx->setEnabled( false );
Gfx->runAction( Spawn::New(
Move::New( Vector2f( Math::randi( 0, mWindow->getWidth() ), -64 ),
Vector2f( Math::randi( 0, mWindow->getWidth() ), mWindow->getHeight() + 64 ),
Milliseconds( 2500 ) ),
Rotate::New( 0.f, 2500.f, Milliseconds( 2500 ) ),
Sequence::New( Scale::New( Vector2f( 1.f, 1.f ), Vector2f( 2.f, 2.f ), Seconds( 0.5f ) ),
Scale::New( Vector2f( 2.f, 2.f ), Vector2f( 1.f, 1.f ), Seconds( 0.5f ) ) ),
Sequence::New( FadeOut::New( Milliseconds( 3500 ) ), Close::New() ) ) );
}
void EETest::onButtonClick( const Event* event ) {
const MouseEvent* mouseEvent = reinterpret_cast<const MouseEvent*>( event );
if ( mouseEvent->getFlags() & EE_BUTTONS_LRM ) {
UIImage* Gfx = UIImage::New();
Gfx->setDrawable( mSceneNode->findIcon( "ok" ) );
Gfx->setEnabled( false );
Gfx->runAction( Spawn::New(
Move::New( Vector2f( Math::randi( 0, mWindow->getWidth() ), -64 ),
Vector2f( Math::randi( 0, mWindow->getWidth() ), mWindow->getHeight() + 64 ),
Milliseconds( 2500 ) ),
Rotate::New( 0.f, 2500.f, Milliseconds( 2500 ) ),
Sequence::New(
Scale::New( Vector2f( 1.f, 1.f ), Vector2f( 2.f, 2.f ), Seconds( 0.5f ) ),
Scale::New( Vector2f( 2.f, 2.f ), Vector2f( 1.f, 1.f ), Seconds( 0.5f ) ) ),
Sequence::New( FadeOut::New( Milliseconds( 3500 ) ), Close::New() ) ) );
}
if ( mouseEvent->getFlags() & EE_BUTTONS_LRM )
addFlyingIcon();
}
void EETest::setScreen( Uint32 num ) {
+2
View File
@@ -155,6 +155,8 @@ class EETest : private Thread {
void createDecoratedWindow();
void createUIThemeTextureAtlas();
void addFlyingIcon();
UINode* C;
UIScrollBar* mScrollBar;
UITextView* mTextBoxValue;