Implemented row header for TableView.

Added shorthands for border-left, border-right, border-top, border-bottom.
This commit is contained in:
Martín Lucas Golini
2024-02-16 21:17:26 -03:00
parent b2fff897be
commit a40bee583b
9 changed files with 187 additions and 8 deletions

View File

@@ -881,7 +881,9 @@ Splitter::separator:hover {
}
tableview::header,
listview::header {
listview::header,
tableview::rowheader,
listview::rowheader {
background-color: var(--back);
}
@@ -900,9 +902,24 @@ listview::header::column {
text-align: left;
}
tableview::rowheader::row,
treeview::rowheader::row,
listview::rowheader::row {
background-color: var(--back);
border-right-color: var(--tab-line);
border-right-width: 1dp;
border-bottom-color: var(--tab-line);
border-bottom-width: 1dp;
border-type: inside;
color: var(--font);
}
tableview::header::column:hover,
treeview::header::column:hover,
listview::header::column:hover {
listview::header::column:hover,
tableview::rowheader::row:hover,
treeview::rowheader::row:hover,
listview::rowheader::row:hover {
background-color: var(--tab-hover);
}

View File

@@ -2203,24 +2203,52 @@ Read [border](https://developer.mozilla.org/en-US/docs/Web/CSS/border) documenta
---
### border-bottom
Read [border](https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom) documentation.
`border-style` is not implemented yet.
---
### border-color
Read [border-color](https://developer.mozilla.org/en-US/docs/Web/CSS/border-color) documentation.
---
### border-left
Read [border](https://developer.mozilla.org/en-US/docs/Web/CSS/border-left) documentation.
`border-style` is not implemented yet.
---
### border-radius
Read [border-radius](https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius) documentation.
---
### border-right
Read [border](https://developer.mozilla.org/en-US/docs/Web/CSS/border-right) documentation.
`border-style` is not implemented yet.
---
### border-width
Read [border-width](https://developer.mozilla.org/en-US/docs/Web/CSS/border-width) documentation.
---
### border-top
Read [border](https://developer.mozilla.org/en-US/docs/Web/CSS/border-top) documentation.
`border-style` is not implemented yet.
---
### box-margin
Shorthand for [column-margin](#column-margin) and [row-margin](#row-margin) (in that order).

View File

@@ -124,6 +124,14 @@ class EE_API UIAbstractTableView : public UIAbstractView {
virtual void onOpenMenuModelIndex( const ModelIndex& index,
const Event* triggerEvent = nullptr );
bool isRowHeaderVisible() const;
void setRowHeaderVisible( bool rowHeaderVisible );
Float getRowHeaderWidth() const;
void setRowHeaderWidth( Float rowHeaderWidth );
protected:
friend class EE::UI::UITableHeaderColumn;
@@ -140,7 +148,8 @@ class EE_API UIAbstractTableView : public UIAbstractView {
mutable std::vector<UITableRow*> mRows;
mutable std::vector<ColumnData> mColumn;
mutable std::vector<UnorderedMap<int, UIWidget*>> mWidgets;
UILinearLayout* mHeader;
UILinearLayout* mHeader{ nullptr };
UILinearLayout* mRowHeader{ nullptr };
Float mDragBorderDistance{ 8 };
size_t mIconSize{ 12 };
size_t mSortIconSize{ 16 };
@@ -153,6 +162,7 @@ class EE_API UIAbstractTableView : public UIAbstractView {
std::string mSearchText;
size_t mMainColumn{ 0 };
std::unordered_map<UIWidget*, std::vector<Uint32>> mWidgetsClickCbId;
Float mRowHeaderWidth{ 0 };
virtual ~UIAbstractTableView();
@@ -210,6 +220,10 @@ class EE_API UIAbstractTableView : public UIAbstractView {
int visibleColumn();
void resetColumnData();
void buildRowHeader();
void updateRowHeader( int realRowIndex, const ModelIndex& index, Float yOffset );
};
}}} // namespace EE::UI::Abstract

View File

@@ -70,6 +70,8 @@ class EE_API Model {
virtual std::string columnName( const size_t& /*column*/ ) const { return {}; }
virtual std::string rowName( const size_t& /*row*/ ) const { return {}; }
virtual Variant data( const ModelIndex&, ModelRole = ModelRole::Display ) const = 0;
virtual void update() { onModelUpdate(); }

View File

@@ -238,7 +238,7 @@ Sizef UIAbstractTableView::getContentSize() const {
if ( !getModel() )
return {};
size_t count = getModel()->columnCount();
Sizef size;
Sizef size( mRowHeaderWidth, 0.f );
for ( size_t i = 0; i < count; i++ )
if ( !isColumnHidden( i ) )
size.x += columnData( i ).width;
@@ -490,7 +490,8 @@ UITableRow* UIAbstractTableView::updateRow( const int& rowIndex, const ModelInde
}
rowWidget->setCurIndex( index );
rowWidget->setPixelsSize( getContentSize().getWidth(), getRowHeight() );
rowWidget->setPixelsPosition( { -mScrollOffset.x, yOffset - mScrollOffset.y } );
rowWidget->setPixelsPosition(
{ mRowHeaderWidth + -mScrollOffset.x, yOffset - mScrollOffset.y } );
if ( isRowSelection() ) {
if ( getSelection().contains( index ) ) {
rowWidget->pushState( UIState::StateSelected );
@@ -502,7 +503,7 @@ UITableRow* UIAbstractTableView::updateRow( const int& rowIndex, const ModelInde
}
void UIAbstractTableView::onScrollChange() {
mHeader->setPixelsPosition( -mScrollOffset.x, 0 );
mHeader->setPixelsPosition( mRowHeaderWidth + -mScrollOffset.x, 0 );
}
void UIAbstractTableView::bindNavigationClick( UIWidget* widget ) {
@@ -684,6 +685,64 @@ void UIAbstractTableView::onOpenMenuModelIndex( const ModelIndex& index,
sendEvent( &event );
}
Float UIAbstractTableView::getRowHeaderWidth() const {
return mRowHeaderWidth;
}
void UIAbstractTableView::setRowHeaderWidth( Float rowHeaderWidth ) {
if ( mRowHeaderWidth == rowHeaderWidth )
return;
mRowHeaderWidth = rowHeaderWidth;
onScrollChange();
buildRowHeader();
}
void UIAbstractTableView::buildRowHeader() {
if ( mRowHeaderWidth == 0 ) {
if ( mRowHeader )
mRowHeader->setVisible( false )->setEnabled( false );
return;
}
if ( mRowHeader == nullptr ) {
mRowHeader = UILinearLayout::NewWithTag( mTag + "::rowheader", UIOrientation::Vertical );
mRowHeader->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed );
mRowHeader->setParent( this )->setVisible( true )->setEnabled( true );
}
mRowHeader->setPaddingTop( mHeader->getSize().getHeight() );
mRowHeader->setPixelsSize( { mRowHeaderWidth, getPixelsSize().getHeight() } );
mRowHeader->setClipType( ClipType::PaddingBox );
int rowsCount = Math::roundUp( mSize.getHeight() / getRowHeight() ) + 1;
if ( mRowHeader->getChildCount() < rowsCount ) {
int createCount = rowsCount - mRowHeader->getChildCount();
for ( int i = 0; i < createCount; i++ ) {
UIWidget* row = UIPushButton::NewWithTag( mTag + "::rowheader::row" );
row->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed );
row->setParent( mRowHeader );
row->setPixelsSize( mRowHeaderWidth, getRowHeight() );
}
}
}
void UIAbstractTableView::updateRowHeader( int realRowIndex, const ModelIndex& index,
Float yOffset ) {
if ( !mRowHeader || mRowHeaderWidth == 0 )
return;
Node* child = mRowHeader->getChildAt( realRowIndex );
if ( !child )
return;
UIPushButton* row = child->asType<UIPushButton>();
row->setPixelsSize( mRowHeaderWidth, getRowHeight() );
row->setLayoutMarginTop( PixelDensity::pxToDp( yOffset ) );
if ( getModel() )
row->setText( getModel()->rowName( index.row() ) );
}
void UIAbstractTableView::onRowCreated( UITableRow* row ) {
RowCreatedEvent rowEvent( this, Event::OnRowCreated, row );
sendEvent( &rowEvent );

View File

@@ -459,6 +459,17 @@ void StyleSheetSpecification::registerDefaultProperties() {
"color-vector2" );
registerShorthand( "hint-shadow", { "hint-shadow-color", "hint-shadow-offset" },
"color-vector2" );
registerShorthand( "border-left",
{ "border-left-width", "border-left-style", "border-left-color" },
"border-side" );
registerShorthand( "border-right",
{ "border-right-width", "border-right-style", "border-right-color" },
"border-side" );
registerShorthand( "border-top", { "border-top-width", "border-top-style", "border-top-color" },
"border-side" );
registerShorthand( "border-bottom",
{ "border-bottom-width", "border-bottom-style", "border-bottom-color" },
"border-side" );
}
void StyleSheetSpecification::registerNodeSelector( const std::string& name,
@@ -939,6 +950,38 @@ void StyleSheetSpecification::registerDefaultShorthandParsers() {
return properties;
};
mShorthandParsers["border-side"] = []( const ShorthandDefinition* shorthand,
std::string value ) -> std::vector<StyleSheetProperty> {
value = String::trim( value );
if ( value.empty() || "none" == value )
return {};
std::vector<StyleSheetProperty> properties;
const std::vector<std::string>& propNames = shorthand->getProperties();
std::vector<std::string> tokens = String::split( value, " ", "", "(" );
for ( auto& tok : tokens ) {
if ( -1 !=
String::valueIndex(
tok, "none;hidden;dotted;dashed;solid;double;groove;ridge;inset;outset" ) ) {
int pos = getIndexEndingWith( propNames, "-style" );
// boder-style is not implemented yet
if ( pos != -1 )
continue;
} else if ( Color::isColorString( tok ) || String::startsWith( tok, "var(" ) ) {
int pos = getIndexEndingWith( propNames, "-color" );
if ( pos != -1 )
properties.emplace_back( StyleSheetProperty( propNames[pos], tok ) );
} else {
int pos = getIndexEndingWith( propNames, "-width" );
if ( pos != -1 )
properties.emplace_back( StyleSheetProperty( propNames[pos], tok ) );
}
}
return properties;
};
mShorthandParsers["color-vector2"] =
[]( const ShorthandDefinition* shorthand,
std::string value ) -> std::vector<StyleSheetProperty> {

View File

@@ -30,6 +30,7 @@ void UITableView::drawChilds() {
int realRowIndex = 0;
int realColIndex = 0;
ConditionalLock l( getModel() != nullptr, getModel() ? &getModel()->resourceMutex() : nullptr );
buildRowHeader();
if ( getModel() ) {
Float rowHeight = getRowHeight();
size_t start = mScrollOffset.y / rowHeight;
@@ -66,11 +67,18 @@ void UITableView::drawChilds() {
realColIndex++;
}
rowNode->nodeDraw();
if ( mRowHeaderWidth ) {
updateRowHeader( realRowIndex, rowIndex,
realRowIndex == 0 ? std::fmodf( -mScrollOffset.y, rowHeight )
: 0.f );
}
realRowIndex++;
}
}
if ( mHeader && mHeader->isVisible() )
mHeader->nodeDraw();
if ( mRowHeader && mRowHeader->isVisible() )
mRowHeader->nodeDraw();
if ( mHScroll->isVisible() )
mHScroll->nodeDraw();
if ( mVScroll->isVisible() )
@@ -94,6 +102,8 @@ Node* UITableView::overFind( const Vector2f& point ) {
return pOver;
if ( mHeader && ( pOver = mHeader->overFind( point ) ) )
return pOver;
if ( mRowHeader && ( pOver = mRowHeader->overFind( point ) ) )
return pOver;
Float rowHeight = getRowHeight();
Float headerHeight = getHeaderHeight();
Float itemCount = getItemCount();

View File

@@ -2,13 +2,14 @@
#include <eepp/ee.hpp>
// Referece https://eugenkiss.github.io/7guis/tasks/#cells
// Row header pending
EE_MAIN_FUNC int main( int, char** ) {
UIApplication app( { 1024, 768, "eepp - 7GUIs - Cells" } );
UIWidget* rlay = app.getUI()->loadLayoutFromString( R"xml(
<style>
#sheet tableview::cell {
border: 1dp solid var(--button-border);
border-type: inside;
border-right: 1dprd solid var(--button-border);
border-bottom: 1dprd solid var(--button-border);
}
</style>
<RelativeLayout layout_width="match_parent" layout_height="match_parent">
@@ -19,6 +20,7 @@ EE_MAIN_FUNC int main( int, char** ) {
auto model = std::make_shared<Spreadsheet>();
table->setModel( model );
table->setColumnsWidth( PixelDensity::dpToPx( 80 ) );
table->setRowHeaderWidth( PixelDensity::dpToPx( 32 ) );
table->setSelectionType( UITableView::SelectionType::Cell );
table->setEditable( true );
table->setEditTriggers( UIAbstractView::EditTrigger::DoubleClicked |

View File

@@ -83,6 +83,10 @@ class Spreadsheet : public Model {
return String::format( "%c", column + 'A' );
}
virtual std::string rowName( const size_t& row ) const {
return String::format( "%zu", row + 1 );
}
virtual Variant data( const ModelIndex& index, ModelRole role ) const;
void createCell( int col, int row );