diff --git a/README.md b/README.md index b643e6143..cab028933 100644 --- a/README.md +++ b/README.md @@ -186,7 +186,7 @@ its submodules, in order to achieve this easily you can simply clone with: ### ecode - Text Editor -Text editor inspired in [lite](https://github.com/rxi/lite) (in development, already fully functional). +Text editor inspired in [lite](https://github.com/rxi/lite). It's using the newest pure CSS theme based on the default [Plasma](https://kde.org/plasma-desktop) dark theme: Breeze Dark. @@ -635,7 +635,7 @@ Probably deprecate the Maps module, since I will focus my efforts on the UI syst * Yuri Kobets for [litehtml](https://github.com/litehtml/litehtml) -* Michael R. P. Ragazzon [RmlUI](https://github.com/mikke89/RmlUi) +* Michael R. P. Ragazzon for [RmlUI](https://github.com/mikke89/RmlUi) * rxi for [lite](https://github.com/rxi/lite) diff --git a/bin/assets/ui/breeze.css b/bin/assets/ui/breeze.css index 87f95a2a8..58d5fc64c 100644 --- a/bin/assets/ui/breeze.css +++ b/bin/assets/ui/breeze.css @@ -59,7 +59,8 @@ TextInputPassword, TextView, Tooltip, MenuBar::button, -Window::title { +Window::title, +ListView::cell { color: var(--font); } @@ -157,7 +158,8 @@ RadioButton::active { ListBox, DropDownList::ListBox, ComboBox::DropDownList::ListBox, -Table { +Table, +ListView { background-color: var(--list-back); border-color: var(--button-border); border-radius: var(--button-radius); @@ -173,15 +175,29 @@ ListBox::item { background-position: left bottom, right bottom; } -ListBox:hover { +ListView::row { + background-color: transparent; + background-image: linear-gradient( to right, var(--list-back), var(--separator) ), linear-gradient( to right, var(--separator), var(--list-back) ); + background-size: 50% 1dp, 50% 1dp; + background-position: left bottom, right bottom; +} + +ListView::cell { + padding-left: 4dp; +} + +ListBox:hover, +ListView:hover { border-color: var(--primary); } -ListBox::item:hover { +ListBox::item:hover, +ListView::row:hover { background-color: var(--item-hover); } -ListBox::item:selected { +ListBox::item:selected, +ListView::row:selected { background-color: var(--primary); } @@ -734,11 +750,14 @@ Splitter::separator:hover { background-color: var(--primary); } -table::header { +tableview::header, +listview::header { background-color: var(--back); } -table::header::column { +tableview::header::column, +treeview::header::column, +listview::header::column { background-color: var(--back); border-right-color: var(--tab-line); border-right-width: 1dp; @@ -751,24 +770,29 @@ table::header::column { text-align: left; } -table::header::column:hover { +tableview::header::column:hover, +treeview::header::column:hover, +listview::header::column:hover { background-color: var(--tab-hover); } -table::row { +tableview::row, +treeview::row { background-color: var(--list-back); } -table::row:hover { +tableview::row:hover, +treeview::row:hover { background-color: var(--tab-hover); } -table::row:selected { +tableview::row:selected, +treeview::row:selected { background-color: var(--primary); } -table::cell, -TreeView::cell { +tableview::cell, +treeview::cell { padding-left: 6dp; padding-right: 6dp; } @@ -783,13 +807,17 @@ TableView > ScrollBar { background-color: var(--list-back); } -table::header::column::arrow-up { +tableview::header::column::arrow-up, +treeview::header::column::arrow-up, +listview::header::column::arrow-up { width: 16dp; height: 12dp; foreground-image: poly(line, var(--icon), "1dp 4dp, 5dp 7dp"), poly(line, var(--icon), "5dp 7dp, 9dp 4dp"); } -table::header::column::arrow-down { +tableview::header::column::arrow-down, +treeview::header::column::arrow-down, +listview::header::column::arrow-down { width: 16dp; height: 12dp; foreground-image: poly(line, var(--icon), "1dp 7dp, 5dp 4dp"), poly(line, var(--icon), "5dp 4dp, 9dp 7dp"); diff --git a/bin/assets/ui/uitheme.css b/bin/assets/ui/uitheme.css index 3e148fe4f..544304ed5 100644 --- a/bin/assets/ui/uitheme.css +++ b/bin/assets/ui/uitheme.css @@ -65,7 +65,8 @@ Menu::SubMenu:hover, ListBox::item:hover, Tab:selected, Tab:hover, -Tab:pressed { +Tab:pressed, +ListView::cell:hover, { color: #FFF; } @@ -92,6 +93,18 @@ Tab::text { padding-right: 4dp; } +ListView { + row-height: 16dp; +} + +ListView::cell { + padding-left: 4dp; +} + +ListView::row { + skin: listboxitem; +} + Tooltip { padding: 8dp; color: #020203; diff --git a/docs/articles/cssspecification.md b/docs/articles/cssspecification.md index 1aab38424..b3ab1ef78 100644 --- a/docs/articles/cssspecification.md +++ b/docs/articles/cssspecification.md @@ -1282,7 +1282,7 @@ rotation-origin-point-y: 100%; Sets the row height in any element that contains fixed size rows. -* Applicable to: EE::UI::UIListBox (ListBox), EE::UI::UIDropDownList (DropDownList), EE::UI::UIWidgetTable (WidgetTable), EE::UI::UIGridLayout (GridLayout) +* Applicable to: EE::UI::UIListBox (ListBox), EE::UI::UIDropDownList (DropDownList), EE::UI::UIWidgetTable (WidgetTable), EE::UI::UIGridLayout (GridLayout), EE::UI::TableView (TableView), EE::UI::TreeView (TreeView), EE::UI::ListView (ListView) * Data Type: [length](#length-data-type) * Default value: Varies on each case. ListBox and DropDownList will guess the value based on the [font-size](#font-size). Table requires this value to be manually set in order to work. GridLayout will require the value only if [row-mode](#row-mode) is `size`. diff --git a/include/eepp/ui/abstract/uiabstracttableview.hpp b/include/eepp/ui/abstract/uiabstracttableview.hpp index 976b91747..1d2e1f8e3 100644 --- a/include/eepp/ui/abstract/uiabstracttableview.hpp +++ b/include/eepp/ui/abstract/uiabstracttableview.hpp @@ -78,6 +78,15 @@ class EE_API UIAbstractTableView : public UIAbstractView { void setColumnsVisible( const std::vector columns ); + virtual bool applyProperty( const StyleSheetProperty& attribute ); + + virtual std::string getPropertyString( const PropertyDefinition* propertyDef, + const Uint32& propertyIndex = 0 ); + + bool getRowSearchByName() const; + + void setRowSearchByName( bool rowSearchByName ); + protected: friend class EE::UI::UITableHeaderColumn; @@ -97,6 +106,9 @@ class EE_API UIAbstractTableView : public UIAbstractView { size_t mIconSize{12}; size_t mSortIconSize{16}; bool mAutoExpandOnSingleColumn{false}; + bool mRowSearchByName{true}; + Action* mSearchTextAction{nullptr}; + std::string mSearchText; virtual ~UIAbstractTableView(); @@ -134,6 +146,10 @@ class EE_API UIAbstractTableView : public UIAbstractView { virtual void onSortColumn( const size_t& colIndex ); + virtual Uint32 onTextInput( const TextInputEvent& event ); + + virtual ModelIndex findRowWithText( const std::string& text ); + void updateHeaderSize(); int visibleColumn(); diff --git a/include/eepp/ui/models/filesystemmodel.hpp b/include/eepp/ui/models/filesystemmodel.hpp index 95448266c..d63b496b2 100644 --- a/include/eepp/ui/models/filesystemmodel.hpp +++ b/include/eepp/ui/models/filesystemmodel.hpp @@ -14,14 +14,20 @@ class EE_API FileSystemModel : public Model { struct DisplayConfig { DisplayConfig() {} - DisplayConfig( bool sortByName, bool foldersFirst, bool ignoreHidden ) : - sortByName( sortByName ), foldersFirst( foldersFirst ), ignoreHidden( ignoreHidden ) {} + DisplayConfig( bool sortByName, bool foldersFirst, bool ignoreHidden, + std::vector acceptedExtensions = {} ) : + sortByName( sortByName ), + foldersFirst( foldersFirst ), + ignoreHidden( ignoreHidden ), + acceptedExtensions( acceptedExtensions ) {} bool sortByName{true}; bool foldersFirst{true}; bool ignoreHidden{false}; + std::vector acceptedExtensions; bool operator==( const DisplayConfig& other ) { return sortByName == other.sortByName && foldersFirst == other.foldersFirst && - ignoreHidden == other.ignoreHidden; + ignoreHidden == other.ignoreHidden && + acceptedExtensions == other.acceptedExtensions; } bool operator!=( const DisplayConfig& other ) { return !( *this == other ); } }; diff --git a/include/eepp/ui/models/model.hpp b/include/eepp/ui/models/model.hpp index 5f441115d..781717d9e 100644 --- a/include/eepp/ui/models/model.hpp +++ b/include/eepp/ui/models/model.hpp @@ -76,6 +76,8 @@ class EE_API Model { virtual SortOrder sortOrder() const { return SortOrder::None; } + virtual bool isSortable() { return false; } + virtual void setKeyColumnAndSortOrder( const size_t& /*column*/, const SortOrder& /*order*/ ) {} void registerView( UIAbstractView* ); diff --git a/include/eepp/ui/models/sortingproxymodel.hpp b/include/eepp/ui/models/sortingproxymodel.hpp index 3259d4d86..38ed0b1c8 100644 --- a/include/eepp/ui/models/sortingproxymodel.hpp +++ b/include/eepp/ui/models/sortingproxymodel.hpp @@ -28,6 +28,10 @@ class EE_API SortingProxyModel final : public Model, private Model::Client { virtual int keyColumn() const; + virtual size_t treeColumn() const; + + virtual bool isSortable() { return true; } + virtual SortOrder sortOrder() const; virtual void setKeyColumnAndSortOrder( const size_t&, const SortOrder& ); diff --git a/include/eepp/ui/uifiledialog.hpp b/include/eepp/ui/uifiledialog.hpp index 3c82276c0..e547fca12 100644 --- a/include/eepp/ui/uifiledialog.hpp +++ b/include/eepp/ui/uifiledialog.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -60,7 +60,7 @@ class EE_API UIFileDialog : public UIWindow { UIPushButton* getButtonUp() const; - UIListBox* getList() const; + UIListView* getList() const; UITextInput* getPathInput() const; @@ -103,7 +103,7 @@ class EE_API UIFileDialog : public UIWindow { UIPushButton* mButtonOpen; UIPushButton* mButtonCancel; UIPushButton* mButtonUp; - UIListBox* mList; + UIListView* mList; UITextInput* mPath; UITextInput* mFile; UIDropDownList* mFiletype; @@ -120,8 +120,6 @@ class EE_API UIFileDialog : public UIWindow { void openSaveClick(); - std::string getTempFullPath(); - void disableButtons(); void openFileOrFolder(); diff --git a/include/eepp/ui/uihelper.hpp b/include/eepp/ui/uihelper.hpp index ea4bc080f..537a0058e 100644 --- a/include/eepp/ui/uihelper.hpp +++ b/include/eepp/ui/uihelper.hpp @@ -97,6 +97,7 @@ enum UINodeType { UI_TYPE_TREEVIEW_CELL, UI_TYPE_TABLEVIEW, UI_TYPE_TABLECELL, + UI_TYPE_LISTVIEW, UI_TYPE_USER = 10000 }; diff --git a/include/eepp/ui/uilistview.hpp b/include/eepp/ui/uilistview.hpp new file mode 100644 index 000000000..b80d89237 --- /dev/null +++ b/include/eepp/ui/uilistview.hpp @@ -0,0 +1,24 @@ +#ifndef EE_UI_UILISTVIEW_HPP +#define EE_UI_UILISTVIEW_HPP + +#include + +namespace EE { namespace UI { + +class EE_API UIListView : public UITableView { + public: + static UIListView* New(); + + Uint32 getType() const; + + bool isType( const Uint32& type ) const; + + void setTheme( UITheme* Theme ); + + protected: + UIListView(); +}; + +}} // namespace EE::UI + +#endif // EE_UI_UILISTVIEW_HPP diff --git a/include/eepp/ui/uitablecell.hpp b/include/eepp/ui/uitablecell.hpp index 33450d524..84a6b0ba2 100644 --- a/include/eepp/ui/uitablecell.hpp +++ b/include/eepp/ui/uitablecell.hpp @@ -24,12 +24,18 @@ class EE_API UITableCell : public UIPushButton { void setCurIndex( const ModelIndex& curIndex ) { mCurIndex = curIndex; } + void setTheme( UITheme* Theme ) { + UIPushButton::setTheme( Theme ); + setThemeSkin( Theme, "tablerow" ); + onThemeLoaded(); + } + protected: ModelIndex mCurIndex; - UITableCell() : UIPushButton( "table::cell" ) {} + UITableCell() : UITableCell( "table::cell" ) {} - UITableCell( const std::string& tag ) : UIPushButton( tag ) {} + UITableCell( const std::string& tag ) : UIPushButton( tag ) { applyDefaultTheme(); } }; }} // namespace EE::UI diff --git a/include/eepp/ui/uitableheadercolumn.hpp b/include/eepp/ui/uitableheadercolumn.hpp index 951aba637..112333cbd 100644 --- a/include/eepp/ui/uitableheadercolumn.hpp +++ b/include/eepp/ui/uitableheadercolumn.hpp @@ -12,7 +12,8 @@ using namespace Abstract; class EE_API UITableHeaderColumn : public UIPushButton { public: - UITableHeaderColumn( UIAbstractTableView* view, const size_t& colIndex ); + UITableHeaderColumn( const std::string& parentTag, UIAbstractTableView* view, + const size_t& colIndex ); virtual UIWidget* getExtraInnerWidget() const; diff --git a/include/eepp/ui/uitablerow.hpp b/include/eepp/ui/uitablerow.hpp index 63c7897fd..b1fbcdfbd 100644 --- a/include/eepp/ui/uitablerow.hpp +++ b/include/eepp/ui/uitablerow.hpp @@ -18,8 +18,14 @@ class EE_API UITableRow : public UIWidget { void setCurIndex( const ModelIndex& curIndex ) { mCurIndex = curIndex; } + void setTheme( UITheme* Theme ) { + UIWidget::setTheme( Theme ); + setThemeSkin( Theme, "tablerow" ); + onThemeLoaded(); + } + protected: - UITableRow( const std::string& tag ) : UIWidget( tag ) {} + UITableRow( const std::string& tag ) : UIWidget( tag ) { applyDefaultTheme(); } UITableRow() : UIWidget( "table::row" ) {} diff --git a/include/eepp/ui/uitableview.hpp b/include/eepp/ui/uitableview.hpp index 0a0a743a0..4a08d13db 100644 --- a/include/eepp/ui/uitableview.hpp +++ b/include/eepp/ui/uitableview.hpp @@ -26,6 +26,8 @@ class EE_API UITableView : public UIAbstractTableView { UITableView(); + UITableView( const std::string& tag ); + virtual void createOrUpdateColumns(); void updateContentSize(); @@ -34,6 +36,7 @@ class EE_API UITableView : public UIAbstractTableView { virtual Uint32 onKeyDown( const KeyEvent& event ); + virtual ModelIndex findRowWithText( const std::string& text ); }; }} // namespace EE::UI diff --git a/include/eepp/ui/uitreeview.hpp b/include/eepp/ui/uitreeview.hpp index 5fba8d1ed..8d0f596cb 100644 --- a/include/eepp/ui/uitreeview.hpp +++ b/include/eepp/ui/uitreeview.hpp @@ -100,6 +100,10 @@ class EE_API UITreeView : public UIAbstractTableView { virtual void onOpenTreeModelIndex( const ModelIndex& index, bool open ); + virtual void onSortColumn( const size_t& colIndex ); + + virtual ModelIndex findRowWithText( const std::string& text ); + void updateContentSize(); void setAllExpanded( const ModelIndex& index = {}, bool expanded = true ); diff --git a/projects/linux/ee.creator.user b/projects/linux/ee.creator.user index 743393d53..27d8c0d51 100644 --- a/projects/linux/ee.creator.user +++ b/projects/linux/ee.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -89,7 +89,7 @@ {6d057187-158a-4883-8d5b-d470a6b6b025} 10 0 - 15 + 19 ../../make/linux diff --git a/projects/linux/ee.files b/projects/linux/ee.files index 71c34d65d..14d74e6ea 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -369,6 +369,7 @@ ../../include/eepp/ui/uilinearlayout.hpp ../../include/eepp/ui/uilistbox.hpp ../../include/eepp/ui/uilistboxitem.hpp +../../include/eepp/ui/uilistview.hpp ../../include/eepp/ui/uiloader.hpp ../../include/eepp/ui/uimanager.hpp ../../include/eepp/ui/uimenubar.hpp @@ -842,6 +843,7 @@ ../../src/eepp/ui/uilinearlayout.cpp ../../src/eepp/ui/uilistbox.cpp ../../src/eepp/ui/uilistboxitem.cpp +../../src/eepp/ui/uilistview.cpp ../../src/eepp/ui/uiloader.cpp ../../src/eepp/ui/uimanager.cpp ../../src/eepp/ui/uimenubar.cpp diff --git a/src/eepp/ui/abstract/uiabstracttableview.cpp b/src/eepp/ui/abstract/uiabstracttableview.cpp index a9c44dcb0..f98d5eeb9 100644 --- a/src/eepp/ui/abstract/uiabstracttableview.cpp +++ b/src/eepp/ui/abstract/uiabstracttableview.cpp @@ -13,7 +13,7 @@ UIAbstractTableView::UIAbstractTableView( const std::string& tag ) : mDragBorderDistance( PixelDensity::dpToPx( 4 ) ), mIconSize( PixelDensity::dpToPxI( 12 ) ), mSortIconSize( PixelDensity::dpToPxI( 20 ) ) { - mHeader = UILinearLayout::NewWithTag( "table::header", UIOrientation::Horizontal ); + mHeader = UILinearLayout::NewWithTag( mTag + "::header", UIOrientation::Horizontal ); mHeader->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed ); mHeader->setParent( this ); mHeader->setVisible( true ); @@ -87,7 +87,7 @@ void UIAbstractTableView::createOrUpdateColumns() { for ( size_t i = 0; i < count; i++ ) { ColumnData& col = columnData( i ); if ( !col.widget ) { - col.widget = eeNew( UITableHeaderColumn, ( this, i ) ); + col.widget = eeNew( UITableHeaderColumn, ( mTag, this, i ) ); col.widget->setParent( mHeader ); col.widget->setEnabled( true ); col.widget->setVisible( true ); @@ -273,7 +273,7 @@ void UIAbstractTableView::setColumnsVisible( const std::vector columns ) if ( !getModel() ) return; for ( size_t i = 0; i < getModel()->columnCount(); i++ ) - columnData( i).visible = false; + columnData( i ).visible = false; for ( auto col : columns ) columnData( col ).visible = true; createOrUpdateColumns(); @@ -282,7 +282,7 @@ void UIAbstractTableView::setColumnsVisible( const std::vector columns ) UITableRow* UIAbstractTableView::createRow() { mUISceneNode->invalidateStyle( this ); mUISceneNode->invalidateStyleState( this, true ); - UITableRow* rowWidget = UITableRow::New(); + UITableRow* rowWidget = UITableRow::New( mTag + "::row" ); rowWidget->setParent( this ); rowWidget->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed ); rowWidget->reloadStyle( true, true, true ); @@ -324,7 +324,7 @@ void UIAbstractTableView::onScrollChange() { } UIWidget* UIAbstractTableView::createCell( UIWidget* rowWidget, const ModelIndex& index ) { - UITableCell* widget = UITableCell::New(); + UITableCell* widget = UITableCell::New( mTag + "::cell" ); widget->setParent( rowWidget ); widget->unsetFlags( UI_AUTO_SIZE ); widget->clipEnable(); @@ -424,7 +424,7 @@ void UIAbstractTableView::onSortColumn( const size_t& colIndex ) { Model* model = getModel(); if ( !model ) return; - if ( model->isColumnSortable( colIndex ) ) { + if ( model->isSortable() && model->isColumnSortable( colIndex ) ) { if ( -1 != model->keyColumn() && (Int64)colIndex != model->keyColumn() && columnData( model->keyColumn() ).widget ) { UIImage* image = @@ -448,4 +448,63 @@ void UIAbstractTableView::onSortColumn( const size_t& colIndex ) { } } +Uint32 UIAbstractTableView::onTextInput( const TextInputEvent& event ) { + if ( !mRowSearchByName ) + return 0; + if ( mSearchTextAction ) + removeAction( mSearchTextAction ); + mSearchTextAction = Actions::Runnable::New( + [&] { + mSearchTextAction = nullptr; + mSearchText = ""; + }, + Milliseconds( 350 ) ); + runAction( mSearchTextAction ); + mSearchText += String::toLower( event.getText() ); + ModelIndex index = findRowWithText( mSearchText ); + if ( index.isValid() ) + getSelection().set( index ); + return 1; +} + +ModelIndex UIAbstractTableView::findRowWithText( const std::string& ) { + return {}; +} + +bool UIAbstractTableView::applyProperty( const StyleSheetProperty& attribute ) { + if ( !checkPropertyDefinition( attribute ) ) + return false; + + switch ( attribute.getPropertyDefinition()->getPropertyId() ) { + case PropertyId::RowHeight: + setRowHeight( lengthFromValue( attribute.getValue(), PropertyRelativeTarget::None ) ); + break; + default: + return UIAbstractView::applyProperty( attribute ); + } + + return true; +} + +std::string UIAbstractTableView::getPropertyString( const PropertyDefinition* propertyDef, + const Uint32& propertyIndex ) { + if ( NULL == propertyDef ) + return ""; + + switch ( propertyDef->getPropertyId() ) { + case PropertyId::RowHeight: + return String::format( "%.2fdp", getRowHeight() ); + default: + return UIAbstractView::getPropertyString( propertyDef, propertyIndex ); + } +} + +bool UIAbstractTableView::getRowSearchByName() const { + return mRowSearchByName; +} + +void UIAbstractTableView::setRowSearchByName( bool rowSearchByName ) { + mRowSearchByName = rowSearchByName; +} + }}} // namespace EE::UI::Abstract diff --git a/src/eepp/ui/models/filesystemmodel.cpp b/src/eepp/ui/models/filesystemmodel.cpp index 0f276aed6..3eb0b18b5 100644 --- a/src/eepp/ui/models/filesystemmodel.cpp +++ b/src/eepp/ui/models/filesystemmodel.cpp @@ -54,10 +54,29 @@ void FileSystemModel::Node::traverseIfNeeded( const FileSystemModel& model ) { mInfo.getFilepath(), true, model.getDisplayConfig().sortByName, model.getDisplayConfig().foldersFirst, model.getDisplayConfig().ignoreHidden ); + const auto& patterns = model.getDisplayConfig().acceptedExtensions; + bool accepted; for ( auto file : files ) { if ( ( model.getMode() == Mode::DirectoriesOnly && file.isDirectory() ) || - model.getMode() == Mode::FilesAndDirectories ) - mChildren.emplace_back( Node( std::move( file ), this ) ); + model.getMode() == Mode::FilesAndDirectories ) { + if ( file.isDirectory() || patterns.empty() ) { + mChildren.emplace_back( Node( std::move( file ), this ) ); + } else { + accepted = false; + if ( patterns.size() ) { + for ( size_t z = 0; z < patterns.size(); z++ ) { + if ( patterns[z] == FileSystem::fileExtension( file.getFilepath() ) ) { + accepted = true; + break; + } + } + } else { + accepted = true; + } + if ( accepted ) + mChildren.emplace_back( Node( std::move( file ), this ) ); + } + } } } @@ -266,13 +285,8 @@ UIIcon* FileSystemModel::iconFor( const Node& node, const ModelIndex& index ) co if ( index.column() == (Int64)treeColumn() || Column::Icon == index.column() ) { auto* scene = SceneManager::instance()->getUISceneNode(); auto* d = scene->findIcon( node.getMimeType() ); - if ( !d ) { - if ( !node.info().isDirectory() ) { - return scene->findIcon( "file" ); - } else { - return scene->findIcon( "folder" ); - } - } + if ( !d ) + return scene->findIcon( !node.info().isDirectory() ? "file" : "folder" ); return d; } return nullptr; diff --git a/src/eepp/ui/models/sortingproxymodel.cpp b/src/eepp/ui/models/sortingproxymodel.cpp index 7a914cd5e..ecb7060bc 100644 --- a/src/eepp/ui/models/sortingproxymodel.cpp +++ b/src/eepp/ui/models/sortingproxymodel.cpp @@ -75,6 +75,10 @@ int SortingProxyModel::keyColumn() const { return mKeyColumn; } +size_t SortingProxyModel::treeColumn() const { + return target().treeColumn(); +} + SortOrder SortingProxyModel::sortOrder() const { return mSortOrder; } diff --git a/src/eepp/ui/uifiledialog.cpp b/src/eepp/ui/uifiledialog.cpp index 7fcb829e1..c833ee825 100644 --- a/src/eepp/ui/uifiledialog.cpp +++ b/src/eepp/ui/uifiledialog.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -83,7 +84,7 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa ->setLayoutSizePolicy( SizePolicy::WrapContent, SizePolicy::MatchParent ) ->setParent( hLayout ); - mList = UIListBox::New(); + mList = UIListView::New(); mList->setParent( linearLayout ); mList->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) ->setLayoutWeight( 1 ) @@ -94,14 +95,27 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa goFolderUp(); } } ); - mList->addEventListener( Event::OnItemKeyDown, [&]( const Event* event ) { - const KeyEvent* KEvent = reinterpret_cast( event ); - if ( KEvent->getKeyCode() == KEY_RETURN || KEvent->getKeyCode() == KEY_KP_ENTER ) { - openFileOrFolder(); - } else if ( KEvent->getKeyCode() == KEY_BACKSPACE ) { - goFolderUp(); + mList->addEventListener( Event::OnModelEvent, [&]( const Event* event ) { + const ModelEvent* modelEvent = static_cast( event ); + if ( modelEvent->getModelEventType() == ModelEventType::Open ) { + Variant vPath( + modelEvent->getModel()->data( modelEvent->getModelIndex(), Model::Role::Custom ) ); + if ( vPath.isValid() && vPath.is( Variant::Type::cstr ) ) + openFileOrFolder(); } } ); + mList->setOnSelectionChange( [&] { + if ( mList->getSelection().isEmpty() ) + return; + auto* node = (FileSystemModel::Node*)mList->getSelection().first().data(); + if ( !isSaveDialog() ) { + if ( getAllowFolderSelect() || !FileSystem::isDirectory( node->fullPath() ) ) + mFile->setText( node->getName() ); + } else if ( !FileSystem::isDirectory( node->fullPath() ) ) { + mFile->setText( node->getName() ); + } + } ); + mList->setAutoExpandOnSingleColumn( true ); hLayout = UILinearLayout::NewHorizontal(); hLayout->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) @@ -203,41 +217,23 @@ void UIFileDialog::refreshFolder() { String( mCurPath ), getSortAlphabetically(), getFoldersFirst(), !getShowHidden() ); std::vector files; std::vector patterns; - bool accepted; - Uint32 i, z; if ( "*" != mFiletype->getText() ) { patterns = String::split( mFiletype->getText().toUtf8(), ';' ); - for ( i = 0; i < patterns.size(); i++ ) + for ( size_t i = 0; i < patterns.size(); i++ ) patterns[i] = FileSystem::fileExtension( patterns[i] ); } - for ( i = 0; i < flist.size(); i++ ) { - if ( FileSystem::isDirectory( mCurPath + flist[i] ) ) { - files.push_back( flist[i] ); - } else if ( !getShowOnlyFolders() ) { - accepted = false; + mList->setModel( FileSystemModel::New( + mCurPath, + getShowOnlyFolders() ? FileSystemModel::Mode::DirectoriesOnly + : FileSystemModel::Mode::FilesAndDirectories, + FileSystemModel::DisplayConfig( getSortAlphabetically(), getFoldersFirst(), + !getShowHidden(), patterns ) ) ); - if ( patterns.size() ) { - for ( z = 0; z < patterns.size(); z++ ) { - if ( patterns[z] == FileSystem::fileExtension( flist[i] ) ) { - accepted = true; - break; - } - } - } else { - accepted = true; - } - - if ( accepted ) - files.push_back( flist[i] ); - } - } - - mList->clear(); - - mList->addListBoxItems( files ); + mList->setColumnsVisible( {FileSystemModel::Name} ); + mList->setHeadersVisible( false ); updateClickStep(); @@ -247,7 +243,7 @@ void UIFileDialog::refreshFolder() { void UIFileDialog::updateClickStep() { if ( NULL != mList->getVerticalScrollBar() ) { mList->getVerticalScrollBar()->setClickStep( - 1.f / ( ( mList->getCount() * mList->getRowHeight() ) / + 1.f / ( ( mList->getModel()->rowCount() * mList->getRowHeight() ) / (Float)mList->getSize().getHeight() ) ); } } @@ -287,7 +283,11 @@ void UIFileDialog::disableButtons() { } void UIFileDialog::openFileOrFolder() { - std::string newPath = mCurPath + mList->getItemSelectedText(); + if ( mList->getSelection().isEmpty() ) + return; + auto* node = (FileSystemModel::Node*)mList->getSelection().first().data(); + + std::string newPath = mCurPath + node->getName(); if ( FileSystem::isDirectory( newPath ) ) { setCurPath( newPath ); @@ -327,21 +327,7 @@ Uint32 UIFileDialog::onMessage( const NodeMessage* Msg ) { break; } case NodeMessage::Selected: { - if ( Msg->getSender() == mList ) { - if ( !isSaveDialog() ) { - if ( getAllowFolderSelect() ) { - mFile->setText( mList->getItemSelectedText() ); - } else { - if ( !FileSystem::isDirectory( getTempFullPath() ) ) { - mFile->setText( mList->getItemSelectedText() ); - } - } - } else { - if ( !FileSystem::isDirectory( getTempFullPath() ) ) { - mFile->setText( mList->getItemSelectedText() ); - } - } - } else if ( Msg->getSender() == mFiletype ) { + if ( Msg->getSender() == mFiletype ) { refreshFolder(); } @@ -361,7 +347,12 @@ void UIFileDialog::save() { } void UIFileDialog::open() { - if ( "" != mList->getItemSelectedText() || getAllowFolderSelect() ) { + if ( mList->getSelection().isEmpty() ) + return; + + auto* node = (FileSystemModel::Node*)mList->getSelection().first().data(); + + if ( "" != node->getName() || getAllowFolderSelect() ) { if ( !getAllowFolderSelect() ) { if ( FileSystem::isDirectory( getFullPath() ) ) return; @@ -453,16 +444,6 @@ std::string UIFileDialog::getFullPath() { return tPath; } -std::string UIFileDialog::getTempFullPath() { - std::string tPath = mCurPath; - - FileSystem::dirAddSlashAtEnd( tPath ); - - tPath += mList->getItemSelectedText().toUtf8(); - - return tPath; -} - std::string UIFileDialog::getCurPath() const { return mCurPath; } @@ -470,8 +451,10 @@ std::string UIFileDialog::getCurPath() const { std::string UIFileDialog::getCurFile() const { if ( mDialogFlags & SaveDialog ) return mFile->getText(); - - return mList->getItemSelectedText().toUtf8(); + if ( mList->getSelection().isEmpty() ) + return ""; + auto* node = (FileSystemModel::Node*)mList->getSelection().first().data(); + return node->getName(); } UIPushButton* UIFileDialog::getButtonOpen() const { @@ -486,7 +469,7 @@ UIPushButton* UIFileDialog::getButtonUp() const { return mButtonUp; } -UIListBox* UIFileDialog::getList() const { +UIListView* UIFileDialog::getList() const { return mList; } @@ -518,9 +501,8 @@ const KeyBindings::Shortcut& UIFileDialog::getCloseShortcut() const { } void UIFileDialog::setFileName( const std::string& name ) { - if ( mFile ) { + if ( mFile ) mFile->setText( name ); - } } void UIFileDialog::setCloseShortcut( const KeyBindings::Shortcut& closeWithKey ) { diff --git a/src/eepp/ui/uilistbox.cpp b/src/eepp/ui/uilistbox.cpp index 744dd0bd4..0c28f3c5a 100644 --- a/src/eepp/ui/uilistbox.cpp +++ b/src/eepp/ui/uilistbox.cpp @@ -306,7 +306,7 @@ void UIListBox::setRowHeight() { FontSize = fontStyleConfig.getFont()->getFontHeight( PixelDensity::dpToPxI( fontStyleConfig.getFontCharacterSize() ) ); - mRowHeight = (Uint32)PixelDensity::pxToDpI( FontSize ) + 4; + mRowHeight = (Uint32)PixelDensity::pxToDpI( FontSize + 4 ); } if ( tOldRowHeight != mRowHeight ) { diff --git a/src/eepp/ui/uilistview.cpp b/src/eepp/ui/uilistview.cpp new file mode 100644 index 000000000..94de336e0 --- /dev/null +++ b/src/eepp/ui/uilistview.cpp @@ -0,0 +1,28 @@ +#include + +namespace EE { namespace UI { + +UIListView* UIListView::New() { + return eeNew( UIListView, () ); +} + +UIListView::UIListView() : UITableView( "listview" ) { + setHeadersVisible( false ); + applyDefaultTheme(); +} + +Uint32 UIListView::getType() const { + return UI_TYPE_LISTVIEW; +} + +bool UIListView::isType( const Uint32& type ) const { + return UIListView::getType() == type ? true : UITableView::isType( type ); +} + +void UIListView::setTheme( UITheme* Theme ) { + UIWidget::setTheme( Theme ); + setThemeSkin( Theme, "listbox" ); + onThemeLoaded(); +} + +}} // namespace EE::UI diff --git a/src/eepp/ui/uitableheadercolumn.cpp b/src/eepp/ui/uitableheadercolumn.cpp index af49f2d4f..b7f32d554 100644 --- a/src/eepp/ui/uitableheadercolumn.cpp +++ b/src/eepp/ui/uitableheadercolumn.cpp @@ -4,8 +4,9 @@ namespace EE { namespace UI { -UITableHeaderColumn::UITableHeaderColumn( UIAbstractTableView* view, const size_t& colIndex ) : - UIPushButton( "table::header::column" ), mView( view ), mColIndex( colIndex ) { +UITableHeaderColumn::UITableHeaderColumn( const std::string& parentTag, UIAbstractTableView* view, + const size_t& colIndex ) : + UIPushButton( parentTag + "::header::column" ), mView( view ), mColIndex( colIndex ) { setDragEnabled( true ); mInnerWidgetOrientation = InnerWidgetOrientation::Right; auto cb = [&]( const Event* ) { updateLayout(); }; diff --git a/src/eepp/ui/uitableview.cpp b/src/eepp/ui/uitableview.cpp index 1e574abbd..ee7d2bc2d 100644 --- a/src/eepp/ui/uitableview.cpp +++ b/src/eepp/ui/uitableview.cpp @@ -10,10 +10,12 @@ UITableView* UITableView::New() { return eeNew( UITableView, () ); } -UITableView::UITableView() : UIAbstractTableView( "tableview" ) { +UITableView::UITableView( const std::string& tag ) : UIAbstractTableView( tag ) { clipEnable(); } +UITableView::UITableView() : UITableView( "tableview" ) {} + Uint32 UITableView::getType() const { return UI_TYPE_TABLEVIEW; } @@ -238,4 +240,20 @@ Uint32 UITableView::onKeyDown( const KeyEvent& event ) { return UIAbstractTableView::onKeyDown( event ); } +ModelIndex UITableView::findRowWithText( const std::string& text ) { + Model* model = getModel(); + if ( !model || model->rowCount() == 0 ) + return {}; + size_t rc = model->rowCount(); + for ( size_t i = 0; i < rc; i++ ) { + ModelIndex index = model->index( + i, model->keyColumn() != -1 ? model->keyColumn() + : ( model->treeColumn() >= 0 ? model->treeColumn() : 0 ) ); + Variant var = model->data( index ); + if ( var.isValid() && String::startsWith( String::toLower( var.toString() ), text ) ) + return model->index( index.row(), 0 ); + } + return {}; +} + }} // namespace EE::UI diff --git a/src/eepp/ui/uitreeview.cpp b/src/eepp/ui/uitreeview.cpp index 8775a8856..b5a5d5ddc 100644 --- a/src/eepp/ui/uitreeview.cpp +++ b/src/eepp/ui/uitreeview.cpp @@ -664,4 +664,25 @@ void UITreeView::onOpenTreeModelIndex( const ModelIndex& index, bool open ) { sendEvent( &event ); } +void UITreeView::onSortColumn( const size_t& ) { + // Do nothing. + return; +} + +ModelIndex UITreeView::findRowWithText( const std::string& text ) { + Model* model = getModel(); + if ( !model || model->rowCount() == 0 ) + return {}; + ModelIndex foundIndex = {}; + traverseTree( [&]( const int&, const ModelIndex& index, const size_t&, const Float& ) { + Variant var = model->data( index ); + if ( var.isValid() && String::startsWith( String::toLower( var.toString() ), text ) ) { + foundIndex = index; + return IterationDecision::Stop; + } + return IterationDecision::Continue; + } ); + return foundIndex; +} + }} // namespace EE::UI diff --git a/src/eepp/ui/uiwidgetcreator.cpp b/src/eepp/ui/uiwidgetcreator.cpp index a9929179c..1a41539bd 100644 --- a/src/eepp/ui/uiwidgetcreator.cpp +++ b/src/eepp/ui/uiwidgetcreator.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -20,8 +21,6 @@ #include #include #include -#include -#include #include #include #include @@ -33,6 +32,8 @@ #include #include #include +#include +#include #include namespace EE { namespace UI { @@ -84,6 +85,7 @@ void UIWidgetCreator::createBaseWidgetList() { registeredWidget["splitter"] = UISplitter::New; registeredWidget["treeview"] = UITreeView::New; registeredWidget["tableview"] = UITableView::New; + registeredWidget["listview"] = UIListView::New; registeredWidget["hbox"] = UILinearLayout::NewHorizontal; registeredWidget["vbox"] = UILinearLayout::NewVertical; diff --git a/src/tests/ui_perf_test/ui_perf_test.cpp b/src/tests/ui_perf_test/ui_perf_test.cpp index dccb40c0b..149f50a1c 100644 --- a/src/tests/ui_perf_test/ui_perf_test.cpp +++ b/src/tests/ui_perf_test/ui_perf_test.cpp @@ -203,6 +203,7 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) { view->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); view->setParent( vlay ); view->setModel( SortingProxyModel::New( model ) ); + //view->setModel( model ); eePRINTL( "Total time: %.2fms", clock.getElapsedTime().asMilliseconds() ); UIWindow* uiWin = UIWindow::NewOpt( UIWindow::LINEAR_LAYOUT ); diff --git a/src/thirdparty/SOIL2 b/src/thirdparty/SOIL2 index 5adc6cd56..200fac61d 160000 --- a/src/thirdparty/SOIL2 +++ b/src/thirdparty/SOIL2 @@ -1 +1 @@ -Subproject commit 5adc6cd56b6b1deda7c7273e0c9ce232950893d1 +Subproject commit 200fac61db85e538efc64f54d523f98074604d8a diff --git a/src/thirdparty/efsw b/src/thirdparty/efsw index 36f27d7cc..2dd7e484d 160000 --- a/src/thirdparty/efsw +++ b/src/thirdparty/efsw @@ -1 +1 @@ -Subproject commit 36f27d7ccf0cfc1b0aa5c43476affc432760b59c +Subproject commit 2dd7e484d3f90192eceaf2cbd79ac60eaaa7d2a2 diff --git a/src/tools/codeeditor/codeeditor.cpp b/src/tools/codeeditor/codeeditor.cpp index 424b1b722..c67f534d1 100644 --- a/src/tools/codeeditor/codeeditor.cpp +++ b/src/tools/codeeditor/codeeditor.cpp @@ -2016,10 +2016,10 @@ void App::init( const std::string& file, const Float& pidelDensity ) { #search_replace.error { border-color: #ff4040; } - TableView#locate_bar_table > table::row > table::cell:nth-child(2) { + TableView#locate_bar_table > tableview::row > tableview::cell:nth-child(2) { color: var(--font-hint); } - TableView#locate_bar_table > table::row:selected > table::cell:nth-child(2) { + TableView#locate_bar_table > tableview::row:selected > tableview::cell:nth-child(2) { color: var(--font); } #search_tree treeview::cell { @@ -2127,7 +2127,6 @@ void App::init( const std::string& file, const Float& pidelDensity ) { addIcon( "tree-expanded", 0xea50 ); addIcon( "tree-contracted", 0xea54 ); addIcon( "search", 0xf0d1 ); - addIcon( "go-up", 0xea78 ); addIcon( "ok", 0xeb7a ); addIcon( "cancel", 0xeb98 );