diff --git a/TODO.md b/TODO.md index 7a0593023..90205bc3a 100644 --- a/TODO.md +++ b/TODO.md @@ -9,10 +9,6 @@ * Implement a "float" layout. -* Expose properties implemented by each widget. - -* Implement a model to view each widget property. - * Implement a rich text view. ### CSS diff --git a/include/eepp/scene/event.hpp b/include/eepp/scene/event.hpp index 10ad7b921..52e2c0642 100644 --- a/include/eepp/scene/event.hpp +++ b/include/eepp/scene/event.hpp @@ -12,6 +12,7 @@ class KeyEvent; class DropEvent; class TextEvent; class TextInputEvent; +class WindowEvent; class EE_API Event { public: @@ -92,6 +93,8 @@ class EE_API Event { OnMenuHide, OnEditorTabReady, OnTitleChange, + OnWindowAdded, + OnWindowRemoved, NoEvent = eeINDEX_NOT_FOUND }; @@ -115,6 +118,8 @@ class EE_API Event { const TextInputEvent* asTextInputEvent() const; + const WindowEvent* asWindowEvent() const; + protected: friend class Node; Node* mNode; @@ -143,6 +148,16 @@ class EE_API TextEvent : public Event { std::string text; }; +class EE_API WindowEvent : public Event { + public: + WindowEvent( Node* node, Node* window, const Uint32& eventType ) : + Event( node, eventType ), window( window ) {} + Node* getWindow() const { return window; } + + protected: + Node* window; +}; + }} // namespace EE::Scene #endif diff --git a/include/eepp/ui.hpp b/include/eepp/ui.hpp index 18509272b..34d94851d 100644 --- a/include/eepp/ui.hpp +++ b/include/eepp/ui.hpp @@ -75,6 +75,7 @@ #include #include #include +#include #include #include diff --git a/include/eepp/ui/models/widgettreemodel.hpp b/include/eepp/ui/models/widgettreemodel.hpp index 4cb8a272b..43a409c1b 100644 --- a/include/eepp/ui/models/widgettreemodel.hpp +++ b/include/eepp/ui/models/widgettreemodel.hpp @@ -14,6 +14,8 @@ class EE_API WidgetTreeModel : public Model { enum Column { Type = 0, ID, + Classes, + PseudoClasses, Count, }; diff --git a/include/eepp/ui/tools/uiwidgetinspector.hpp b/include/eepp/ui/tools/uiwidgetinspector.hpp new file mode 100644 index 000000000..847017376 --- /dev/null +++ b/include/eepp/ui/tools/uiwidgetinspector.hpp @@ -0,0 +1,30 @@ +#ifndef EE_UI_TOOLS_UIWIDGETINSPECTOR_HPP +#define EE_UI_TOOLS_UIWIDGETINSPECTOR_HPP + +#include +#include + +namespace EE { namespace UI { +class UISceneNode; +class UITreeView; +class UITableView; +class UIWindow; +}} // namespace EE::UI + +namespace EE { namespace UI { namespace Tools { + +class EE_API UIWidgetInspector { + public: + static UIWindow* create( UISceneNode* sceneNode, const Float& menuIconSize = 16.f, + std::function highlightToggle = std::function(), + std::function drawBoxesToggle = std::function(), + std::function drawDebugDataToggle = std::function() ); + + protected: + static void checkWidgetPick( UISceneNode* sceneNode, UITreeView* widgetTree, + bool wasHighlightOver, UITableView* tableView ); +}; + +}}} // namespace EE::UI::Tools + +#endif // EE_UI_TOOLS_ diff --git a/projects/linux/ee.files b/projects/linux/ee.files index ea97e95ae..39e591984 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -355,6 +355,7 @@ ../../include/eepp/ui/tools/uicodeeditorsplitter.hpp ../../include/eepp/ui/tools/uicolorpicker.hpp ../../include/eepp/ui/tools/uidocfindreplace.hpp +../../include/eepp/ui/tools/uiwidgetinspector.hpp ../../include/eepp/ui/uiabstractview.hpp ../../include/eepp/ui/uibackgrounddrawable.hpp ../../include/eepp/ui/uiborderdrawable.hpp @@ -841,6 +842,7 @@ ../../src/eepp/ui/tools/uicodeeditorsplitter.cpp ../../src/eepp/ui/tools/uicolorpicker.cpp ../../src/eepp/ui/tools/uidocfindreplace.cpp +../../src/eepp/ui/tools/uiwidgetinspector.cpp ../../src/eepp/ui/uiabstractview.cpp ../../src/eepp/ui/uibackgrounddrawable.cpp ../../src/eepp/ui/uiborderdrawable.cpp diff --git a/src/eepp/scene/event.cpp b/src/eepp/scene/event.cpp index e466d35ab..ce9fbee90 100644 --- a/src/eepp/scene/event.cpp +++ b/src/eepp/scene/event.cpp @@ -41,4 +41,8 @@ const TextInputEvent* Event::asTextInputEvent() const { return static_cast( this ); } +const WindowEvent* Event::asWindowEvent() const { + return static_cast( this ); +} + }} // namespace EE::Scene diff --git a/src/eepp/ui/models/widgettreemodel.cpp b/src/eepp/ui/models/widgettreemodel.cpp index 413ad6290..7c6357905 100644 --- a/src/eepp/ui/models/widgettreemodel.cpp +++ b/src/eepp/ui/models/widgettreemodel.cpp @@ -19,11 +19,15 @@ size_t WidgetTreeModel::rowCount( const ModelIndex& index ) const { } size_t WidgetTreeModel::columnCount( const ModelIndex& ) const { - return 2; + return Column::Count; } std::string WidgetTreeModel::columnName( const size_t& col ) const { switch ( col ) { + case Column::PseudoClasses: + return "Pseudo Classes"; + case Column::Classes: + return "Classes"; case Column::Type: return "Type"; case Column::ID: @@ -38,6 +42,20 @@ Variant WidgetTreeModel::data( const ModelIndex& index, ModelRole role ) const { if ( role == ModelRole::Display ) { switch ( index.column() ) { + case Column::PseudoClasses: { + if ( node->isWidget() ) { + return Variant( + String::join( node->asType()->getStyleSheetPseudoClasses() ) ); + } + break; + } + case Column::Classes: { + if ( node->isWidget() ) { + return Variant( + String::join( node->asType()->getStyleSheetClasses() ) ); + } + break; + } case Column::Type: { if ( node->isWidget() ) { return Variant( node->asType()->getElementTag().c_str() ); diff --git a/src/eepp/ui/tools/uiwidgetinspector.cpp b/src/eepp/ui/tools/uiwidgetinspector.cpp new file mode 100644 index 000000000..c336a4738 --- /dev/null +++ b/src/eepp/ui/tools/uiwidgetinspector.cpp @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace EE::Window; +using namespace EE::UI::Models; + +namespace EE { namespace UI { namespace Tools { + +UIWindow* UIWidgetInspector::create( UISceneNode* sceneNode, const Float& menuIconSize, + std::function highlightToggle, + std::function drawBoxesToggle, + std::function drawDebugDataToggle ) { + if ( sceneNode->getRoot()->hasChild( "widget-tree-view" ) ) + return nullptr; + UIWindow* uiWin = UIWindow::New(); + uiWin->setId( "widget-tree-view" ); + uiWin->setMinWindowSize( 600, 400 ); + uiWin->setWindowFlags( UI_WIN_DEFAULT_FLAGS | UI_WIN_RESIZEABLE | UI_WIN_MAXIMIZE_BUTTON ); + UIWidget* cont = sceneNode->loadLayoutFromString( R"xml( + + + + + + + + + + + + + )xml", + uiWin->getContainer() ); + UITreeView* widgetTree = cont->findByType( UI_TYPE_TREEVIEW ); + widgetTree->setHeadersVisible( true ); + widgetTree->setExpanderIconSize( menuIconSize ); + widgetTree->setAutoColumnsWidth( true ); + auto model = WidgetTreeModel::New( sceneNode ); + widgetTree->setModel( model ); + widgetTree->tryOpenModelIndex( model->getRoot() ); + UITableView* tableView = cont->findByType( UI_TYPE_TABLEVIEW ); + tableView->setAutoColumnsWidth( true ); + tableView->setHeadersVisible( true ); + widgetTree->setOnSelection( [&, tableView]( const ModelIndex& index ) { + Node* node = static_cast( index.internalData() ); + if ( node->isWidget() ) { + tableView->setModel( node->isWidget() + ? CSSPropertiesModel::create( node->asType() ) + : CSSPropertiesModel::create() ); + } + } ); + + UIPushButton* button = cont->find( "pick_widget" ); + button->addEventListener( + Event::MouseClick, [sceneNode, widgetTree, tableView]( const Event* event ) { + if ( event->asMouseEvent()->getFlags() & EE_BUTTON_LMASK ) { + bool wasHighlightOver = sceneNode->getHighlightOver(); + sceneNode->setHighlightOver( true ); + sceneNode->getEventDispatcher()->setDisableMousePress( true ); + sceneNode->runOnMainThread( [sceneNode, widgetTree, tableView, wasHighlightOver]() { + checkWidgetPick( sceneNode, widgetTree, wasHighlightOver, tableView ); + } ); + } + } ); + + cont->find( "debug-draw-highlight" ) + ->setChecked( sceneNode->getHighlightOver() ) + ->addEventListener( Event::OnValueChange, [sceneNode, highlightToggle]( const auto* ) { + if ( highlightToggle ) { + highlightToggle(); + } else { + sceneNode->setHighlightFocus( !sceneNode->getHighlightFocus() ); + sceneNode->setHighlightOver( !sceneNode->getHighlightOver() ); + } + } ); + + cont->find( "debug-draw-boxes" ) + ->setChecked( sceneNode->getDrawBoxes() ) + ->addEventListener( Event::OnValueChange, [sceneNode, drawBoxesToggle]( const auto* ) { + if ( drawBoxesToggle ) { + drawBoxesToggle(); + } else { + sceneNode->setDrawBoxes( !sceneNode->getDrawBoxes() ); + } + } ); + + cont->find( "debug-draw-debug-data" ) + ->setChecked( sceneNode->getDrawDebugData() ) + ->addEventListener( Event::OnValueChange, [sceneNode, drawDebugDataToggle]( const auto* ) { + if ( drawDebugDataToggle ) { + drawDebugDataToggle(); + } else { + sceneNode->setDrawDebugData( !sceneNode->getDrawDebugData() ); + } + } ); + + uiWin->center(); + + Uint32 winCb = sceneNode->addEventListener( Event::OnWindowAdded, [&, sceneNode, uiWin]( + const Event* event ) { + UIWindow* eWin = event->asWindowEvent()->getWindow()->asType(); + if ( eWin != uiWin ) { + Uint32 winRdCb = + eWin->addEventListener( Event::OnWindowReady, [uiWin]( const Event* eWinEvent ) { + uiWin->toFront(); + eWinEvent->getNode()->removeEventListener( eWinEvent->getCallbackId() ); + } ); + uiWin->addEventListener( Event::OnWindowClose, [sceneNode, winRdCb]( const Event* ) { + sceneNode->removeEventListener( winRdCb ); + } ); + } + } ); + uiWin->addEventListener( Event::OnWindowClose, [sceneNode, winCb]( const Event* ) { + sceneNode->removeEventListener( winCb ); + } ); + return uiWin; +} + +void UIWidgetInspector::checkWidgetPick( UISceneNode* sceneNode, UITreeView* widgetTree, + bool wasHighlightOver, UITableView* tableView ) { + Input* input = sceneNode->getWindow()->getInput(); + if ( input->getClickTrigger() & EE_BUTTON_LMASK ) { + Node* node = sceneNode->getEventDispatcher()->getMouseOverNode(); + WidgetTreeModel* model = static_cast( widgetTree->getModel() ); + ModelIndex index( model->getModelIndex( node ) ); + widgetTree->setSelection( index ); + sceneNode->setHighlightOver( wasHighlightOver ); + sceneNode->getEventDispatcher()->setDisableMousePress( false ); + } else { + sceneNode->runOnMainThread( [sceneNode, widgetTree, wasHighlightOver, tableView]() { + checkWidgetPick( sceneNode, widgetTree, wasHighlightOver, tableView ); + } ); + } +} + +}}} // namespace EE::UI::Tools diff --git a/src/eepp/ui/uifiledialog.cpp b/src/eepp/ui/uifiledialog.cpp index 31168c40d..f0b27de94 100644 --- a/src/eepp/ui/uifiledialog.cpp +++ b/src/eepp/ui/uifiledialog.cpp @@ -256,7 +256,6 @@ UIFileDialog::~UIFileDialog() {} void UIFileDialog::onWindowReady() { updateClickStep(); UIWindow::onWindowReady(); - sendCommonEvent( Event::OnWindowReady ); } Uint32 UIFileDialog::getType() const { diff --git a/src/eepp/ui/uiscenenode.cpp b/src/eepp/ui/uiscenenode.cpp index fe4d99688..fe6e95247 100644 --- a/src/eepp/ui/uiscenenode.cpp +++ b/src/eepp/ui/uiscenenode.cpp @@ -226,6 +226,8 @@ void UISceneNode::setFocusLastWindow( UIWindow* window ) { void UISceneNode::windowAdd( UIWindow* win ) { if ( !windowExists( win ) ) { mWindowsList.push_front( win ); + WindowEvent wevent( this, win, Event::OnWindowAdded ); + sendEvent( &wevent ); } else { //! Send to front mWindowsList.remove( win ); @@ -235,6 +237,8 @@ void UISceneNode::windowAdd( UIWindow* win ) { void UISceneNode::windowRemove( UIWindow* win ) { if ( windowExists( win ) ) { + WindowEvent wevent( this, win, Event::OnWindowRemoved ); + sendEvent( &wevent ); mWindowsList.remove( win ); } } diff --git a/src/eepp/ui/uiwindow.cpp b/src/eepp/ui/uiwindow.cpp index e67786f5f..703b2a9ba 100644 --- a/src/eepp/ui/uiwindow.cpp +++ b/src/eepp/ui/uiwindow.cpp @@ -447,6 +447,8 @@ void UIWindow::onWindowReady() { mShowWhenReady = false; show(); } + + sendCommonEvent( Event::OnWindowReady ); } void UIWindow::createModalNode() { diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 7bb1d3a4a..d16583656 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -548,95 +548,6 @@ App::~App() { eeSAFE_DELETE( mConsole ); } -void App::checkWidgetPick( UITreeView* widgetTree, bool wasHighlightOver, UITableView* tableView ) { - Input* input = mWindow->getInput(); - if ( input->getClickTrigger() & EE_BUTTON_LMASK ) { - Node* node = mUISceneNode->getEventDispatcher()->getMouseOverNode(); - WidgetTreeModel* model = static_cast( widgetTree->getModel() ); - ModelIndex index( model->getModelIndex( node ) ); - widgetTree->setSelection( index ); - mUISceneNode->setHighlightOver( wasHighlightOver ); - mUISceneNode->getEventDispatcher()->setDisableMousePress( false ); - } else { - mUISceneNode->runOnMainThread( [this, widgetTree, wasHighlightOver, tableView]() { - checkWidgetPick( widgetTree, wasHighlightOver, tableView ); - } ); - } -} - -void App::createWidgetInspector() { - if ( mUISceneNode->getRoot()->hasChild( "widget-tree-view" ) ) - return; - UIWindow* uiWin = UIWindow::New(); - uiWin->setId( "widget-tree-view" ); - uiWin->setMinWindowSize( 600, 400 ); - uiWin->setWindowFlags( UI_WIN_DEFAULT_FLAGS | UI_WIN_RESIZEABLE | UI_WIN_MAXIMIZE_BUTTON ); - UIWidget* cont = mUISceneNode->loadLayoutFromString( R"xml( - - - - - - - - - - - - - )xml", - uiWin->getContainer() ); - UITreeView* widgetTree = cont->findByType( UI_TYPE_TREEVIEW ); - widgetTree->setHeadersVisible( true ); - widgetTree->setAutoExpandOnSingleColumn( true ); - widgetTree->setExpanderIconSize( mMenuIconSize ); - widgetTree->setAutoColumnsWidth( true ); - auto model = WidgetTreeModel::New( mUISceneNode ); - widgetTree->setModel( model ); - widgetTree->tryOpenModelIndex( model->getRoot() ); - UITableView* tableView = cont->findByType( UI_TYPE_TABLEVIEW ); - tableView->setAutoColumnsWidth( true ); - tableView->setHeadersVisible( true ); - widgetTree->setOnSelection( [&, tableView]( const ModelIndex& index ) { - Node* node = static_cast( index.internalData() ); - if ( node->isWidget() ) { - tableView->setModel( node->isWidget() - ? CSSPropertiesModel::create( node->asType() ) - : CSSPropertiesModel::create() ); - } - } ); - - UIPushButton* button = cont->find( "pick_widget" ); - button->addEventListener( Event::MouseClick, [&, widgetTree, tableView]( const Event* event ) { - if ( event->asMouseEvent()->getFlags() & EE_BUTTON_LMASK ) { - bool wasHighlightOver = mUISceneNode->getHighlightOver(); - mUISceneNode->setHighlightOver( true ); - mUISceneNode->getEventDispatcher()->setDisableMousePress( true ); - mUISceneNode->runOnMainThread( [this, widgetTree, tableView, wasHighlightOver]() { - checkWidgetPick( widgetTree, wasHighlightOver, tableView ); - } ); - } - } ); - - cont->find( "debug-draw-highlight" ) - ->setChecked( mUISceneNode->getHighlightOver() ) - ->addEventListener( Event::OnValueChange, [this]( const auto* ) { - runCommand( "debug-draw-highlight-toggle" ); - } ); - - cont->find( "debug-draw-boxes" ) - ->setChecked( mUISceneNode->getDrawBoxes() ) - ->addEventListener( Event::OnValueChange, - [this]( const auto* ) { runCommand( "debug-draw-boxes-toggle" ); } ); - - cont->find( "debug-draw-debug-data" ) - ->setChecked( mUISceneNode->getDrawDebugData() ) - ->addEventListener( Event::OnValueChange, - [this]( const auto* ) { runCommand( "debug-draw-debug-data" ); } ); - - uiWin->center(); -} - void App::updateRecentFiles() { UINode* node = nullptr; if ( mSettingsMenu && ( node = mSettingsMenu->getItemId( "menu-recent-files" ) ) ) { @@ -2494,6 +2405,10 @@ void App::showFindView() { mDocSearchController->showFindView(); } +void App::createWidgetInspector() { + UIWidgetInspector::create( mUISceneNode, mMenuIconSize ); +} + void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) { const CodeEditorConfig& config = mConfig.editor; const DocumentConfig& docc = !mCurrentProject.empty() && !mProjectDocConfig.useGlobalSettings diff --git a/src/tools/ecode/ecode.hpp b/src/tools/ecode/ecode.hpp index d164397b6..6227b3d99 100644 --- a/src/tools/ecode/ecode.hpp +++ b/src/tools/ecode/ecode.hpp @@ -30,12 +30,12 @@ class App : public UICodeEditorSplitter::Client { ~App(); - void createWidgetInspector(); - void init( const LogLevel& logLevel, std::string file, const Float& pidelDensity, const std::string& colorScheme, bool terminal, bool frameBuffer, bool benchmarkMode ); + void createWidgetInspector(); + void setAppTitle( const std::string& title ); void openFileDialog(); @@ -357,8 +357,6 @@ class App : public UICodeEditorSplitter::Client { void initPluginManager(); - void checkWidgetPick( UITreeView* widgetTree, bool wasHighlightOver, UITableView* tableView ); - void onPluginEnabled( UICodeEditorPlugin* plugin ); };