X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fcontrols%2Ftable-view%2Ftable-view-impl.cpp;h=4f27bba831e202a4893eef9b49bc7fc1d3ddde4f;hp=742ef5ec83371fa3128420552b82b3e30876c45d;hb=f546dd5d83a968e573f8f053a01ce43df32c71a0;hpb=36a298758d1b6244b7846a0102b528d76002dbda diff --git a/dali-toolkit/internal/controls/table-view/table-view-impl.cpp b/dali-toolkit/internal/controls/table-view/table-view-impl.cpp old mode 100644 new mode 100755 index 742ef5e..4f27bba --- a/dali-toolkit/internal/controls/table-view/table-view-impl.cpp +++ b/dali-toolkit/internal/controls/table-view/table-view-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,21 +22,24 @@ #include #include #include -#include +#include +#include #include #include #include +// INTERNAL INCLUDES +#include + using namespace Dali; namespace { - /** * @brief Should the tableview fit around the given actor * * @param[in] actor The child actor to test against - * @param[dimension] The dimnesion to test against + * @param[dimension] The dimension to test against */ bool FitToChild( Actor actor, Dimension::Type dimension ) { @@ -48,7 +51,7 @@ bool FitToChild( Actor actor, Dimension::Type dimension ) // currently not called from code so compiler will optimize these away, kept here for future debugging #define TABLEVIEW_TAG "DALI Toolkit::TableView " -#define TV_LOG(fmt, args...) Debug::LogMessage(Debug::DebugInfo, TABLEVIEW_TAG fmt, ## args) +#define TV_LOG(fmt, args,...) Debug::LogMessage(Debug::DebugInfo, TABLEVIEW_TAG fmt, ## args) //#define TABLEVIEW_DEBUG 1 #if defined(TABLEVIEW_DEBUG) @@ -66,7 +69,7 @@ void PrintArray( Array2d& array ) if( data.actor ) { actor = 'A'; - actorName = data.actor.GetName(); + actorName = data.actor.GetProperty< std::string >( Dali::Actor::Property::NAME ); } TV_LOG("Array[%d,%d]=%c %s %d,%d,%d,%d ", i, j, actor, actorName.c_str(), data.position.rowIndex, data.position.columnIndex, @@ -129,11 +132,16 @@ BaseHandle Create() // Setup properties, signals and actions using the type-registry. DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TableView, Toolkit::Control, Create ); -DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "rows", UNSIGNED_INTEGER, ROWS ) -DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "columns", UNSIGNED_INTEGER, COLUMNS ) -DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "cell-padding", VECTOR2, CELL_PADDING ) -DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layout-rows", MAP, LAYOUT_ROWS ) -DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layout-columns", MAP, LAYOUT_COLUMNS ) +DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "rows", INTEGER, ROWS ) +DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "columns", INTEGER, COLUMNS ) +DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "cellPadding", VECTOR2, CELL_PADDING ) +DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layoutRows", MAP, LAYOUT_ROWS ) +DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layoutColumns", MAP, LAYOUT_COLUMNS ) +DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "cellIndex", VECTOR2, CELL_INDEX ) +DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "rowSpan", INTEGER, ROW_SPAN ) +DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "columnSpan", INTEGER, COLUMN_SPAN ) +DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "cellHorizontalAlignment", STRING, CELL_HORIZONTAL_ALIGNMENT ) +DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "cellVerticalAlignment", STRING, CELL_VERTICAL_ALIGNMENT ) DALI_TYPE_REGISTRATION_END() @@ -141,11 +149,27 @@ const Scripting::StringEnum LAYOUT_POLICY_STRING_TABLE[] = { { "fixed", Toolkit::TableView::FIXED }, { "relative", Toolkit::TableView::RELATIVE }, - { "fill", Toolkit::TableView::FILL } + { "fill", Toolkit::TableView::FILL }, + { "fit", Toolkit::TableView::FIT } }; - const unsigned int LAYOUT_POLICY_STRING_TABLE_COUNT = sizeof(LAYOUT_POLICY_STRING_TABLE) / sizeof( LAYOUT_POLICY_STRING_TABLE[0] ); +const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] = +{ + {"left", HorizontalAlignment::LEFT}, + {"center", HorizontalAlignment::CENTER}, + {"right", HorizontalAlignment::RIGHT} +}; +const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof(HORIZONTAL_ALIGNMENT_STRING_TABLE) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] ); + +const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] = +{ + {"top", VerticalAlignment::TOP}, + {"center", VerticalAlignment::CENTER}, + {"bottom", VerticalAlignment::BOTTOM} +}; +const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof(VERTICAL_ALIGNMENT_STRING_TABLE) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] ); + } // Unnamed namespace Toolkit::TableView TableView::New( unsigned int initialRows, unsigned int initialColumns ) @@ -169,10 +193,7 @@ bool TableView::AddChild( Actor& child, const Toolkit::TableView::CellPosition& DALI_ASSERT_ALWAYS( child ); // if child is already parented, we adopt it - if( child.GetParent() ) - { - child.GetParent().Remove( child ); - } + child.Unparent(); // check if we need to expand our data array if( position.rowIndex >= mCellData.GetRows() ) @@ -228,6 +249,15 @@ bool TableView::AddChild( Actor& child, const Toolkit::TableView::CellPosition& } // Relayout the whole table + if( mRowData[position.rowIndex].sizePolicy == Toolkit::TableView::FIT && position.rowSpan == 1 ) + { + mRowDirty = true; + } + if( mColumnData[position.columnIndex].sizePolicy == Toolkit::TableView::FIT && position.columnSpan == 1 ) + { + mColumnDirty = true; + } + RelayoutRequest(); return true; // Addition successful @@ -252,12 +282,20 @@ Actor TableView::RemoveChildAt( const Toolkit::TableView::CellPosition& position if( child ) { RelayoutingLock lock( *this ); - // Remove the child, this will trigger a call to OnControlChildRemove + // Remove the child, this will trigger a call to OnChildRemove Self().Remove( child ); // relayout the table only if instances were found if( RemoveAllInstances( child ) ) { + if( mRowData[position.rowIndex].sizePolicy == Toolkit::TableView::FIT ) + { + mRowDirty = true; + } + if( mColumnData[position.columnIndex].sizePolicy == Toolkit::TableView::FIT ) + { + mColumnDirty = true; + } RelayoutRequest(); } } @@ -328,7 +366,7 @@ void TableView::InsertRow( unsigned int rowIndex ) mRowData.Insert( mRowData.Begin() + rowIndex, RowColumnData() ); // Sizes may have changed, so relayout - mRowColumnDirty = true; + mRowDirty = true; RelayoutRequest(); } @@ -369,7 +407,7 @@ void TableView::DeleteRow( unsigned int rowIndex, std::vector& removed ) else if( row >= rowIndex ) // If below of or at the inserted row, decrease row index { // Decrement index - if( position.rowIndex > 1 ) + if( position.rowIndex > 0 ) { position.rowIndex--; } @@ -384,7 +422,10 @@ void TableView::DeleteRow( unsigned int rowIndex, std::vector& removed ) mRowData.Erase( mRowData.Begin() + rowIndex ); // Sizes may have changed, so relayout - mRowColumnDirty = true; + mRowDirty = true; + // it is possible that the deletion of row leads to remove of child which might further lead to the change of FIT column + mColumnDirty = true; + RelayoutRequest(); } @@ -427,7 +468,7 @@ void TableView::InsertColumn( unsigned int columnIndex ) mColumnData.Insert( mColumnData.Begin() + columnIndex, RowColumnData() ); // Sizes may have changed so relayout - mRowColumnDirty = true; + mColumnDirty = true; RelayoutRequest(); } @@ -483,7 +524,10 @@ void TableView::DeleteColumn( unsigned int columnIndex, std::vector& remo mColumnData.Erase( mColumnData.Begin() + columnIndex ); // Size may have changed so relayout - mRowColumnDirty = true; + mColumnDirty = true; + // it is possible that the deletion of column leads to remove of child which might further lead to the change of FIT row + mRowDirty = true; + RelayoutRequest(); } @@ -524,7 +568,8 @@ void TableView::Resize( unsigned int rows, unsigned int columns, std::vector( Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get() ); - for( unsigned int row = 0; row < rowCount; ++row ) + if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection ) { - float cumulatedWidth = 0.0f; + for (auto&& element : mColumnData) + { + totalWidth += element.size; + } + } - for( unsigned int column = 0; column < columnCount; ++column ) + for( unsigned int row = 0, rowCount = mCellData.GetRows(); row < rowCount; ++row ) + { + for( unsigned int column = 0, columnCount = mCellData.GetColumns(); column < columnCount; ++column ) { - Actor& actor = mCellData[ row ][ column ].actor; - const Toolkit::TableView::CellPosition position = mCellData[ row ][ column ].position; + CellData& cellData= mCellData[ row ][ column ]; + Actor& actor = cellData.actor; + const Toolkit::TableView::CellPosition position = cellData.position; // If there is an actor and this is the main cell of the actor. - // An actor can be in multiple cells if its row or columnspan is more than 1. + // An actor can be in multiple cells if its row or column span is more than 1. // We however must lay out each actor only once. - if( actor && ( position.rowIndex == row ) && ( position.columnIndex == column ) ) + if( actor && position.rowIndex == row && position.columnIndex == column ) { - // Anchor actor to top left of table view - actor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - actor.SetParentOrigin( ParentOrigin::TOP_LEFT ); + // Anchor actor to top left of the cell + if( actor.GetProperty( Actor::Property::POSITION_USES_ANCHOR_POINT ).Get< bool >() ) + { + actor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + } + actor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); - Padding padding; - actor.GetPadding( padding ); + Padding padding = actor.GetProperty( Actor::Property::PADDING ); - Vector3 actorPosition( cumulatedWidth + mPadding.width + padding.left, // Left padding - cumulatedHeight + mPadding.height + padding.top, // Top padding - 0.0f ); - actor.SetPosition( actorPosition ); - } + float left = (column > 0) ? mColumnData[column - 1].position : 0.f; + float right; - DALI_ASSERT_DEBUG( column < mColumnData.Size() ); - cumulatedWidth += mColumnData[ column ].size; - } + if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection ) + { + right = totalWidth - left; + left = right - mColumnData[column].size; + } + else + { + right = left + mColumnData[column].size; + } + + float top = row > 0 ? mRowData[row-1].position : 0.f; + float bottom = mRowData[row+position.rowSpan-1].position; - DALI_ASSERT_DEBUG( row < mRowData.Size() ); - cumulatedHeight += mRowData[ row ].size; + if( cellData.horizontalAlignment == HorizontalAlignment::LEFT ) + { + actor.SetProperty( Actor::Property::POSITION_X, left + mPadding.width + padding.left ); + } + else if( cellData.horizontalAlignment == HorizontalAlignment::RIGHT ) + { + actor.SetProperty( Actor::Property::POSITION_X, right - mPadding.width - padding.right - actor.GetRelayoutSize( Dimension::WIDTH ) ); + } + else //if( cellData.horizontalAlignment == HorizontalAlignment::CENTER ) + { + actor.SetProperty( Actor::Property::POSITION_X, (left + right + padding.left - padding.right - actor.GetRelayoutSize( Dimension::WIDTH )) * 0.5f ); + } + + if( cellData.verticalAlignment == VerticalAlignment::TOP ) + { + actor.SetProperty( Actor::Property::POSITION_Y, top + mPadding.height + padding.top ); + } + else if( cellData.verticalAlignment == VerticalAlignment::BOTTOM ) + { + actor.SetProperty( Actor::Property::POSITION_Y, bottom - mPadding.height - padding.bottom - actor.GetRelayoutSize( Dimension::HEIGHT ) ); + } + else //if( cellData.verticalAlignment = VerticalAlignment::CENTER ) + { + actor.SetProperty( Actor::Property::POSITION_Y, (top + bottom + padding.top - padding.bottom - actor.GetRelayoutSize( Dimension::HEIGHT )) * 0.5f ); + } + } + } } } @@ -786,17 +907,25 @@ void TableView::SetProperty( BaseObject* object, Property::Index index, const Pr { case Toolkit::TableView::Property::ROWS: { - if( value.Get() != tableViewImpl.GetRows() ) + int rows = 0; + if( value.Get( rows ) && rows >= 0 ) { - tableViewImpl.Resize( value.Get(), tableViewImpl.GetColumns() ); + if( static_cast(rows) != tableViewImpl.GetRows() ) + { + tableViewImpl.Resize( rows, tableViewImpl.GetColumns() ); + } } break; } case Toolkit::TableView::Property::COLUMNS: { - if( value.Get() != tableViewImpl.GetColumns() ) + int columns = 0; + if( value.Get( columns ) && columns >= 0 ) { - tableViewImpl.Resize( tableViewImpl.GetRows(), value.Get() ); + if( static_cast( columns ) != tableViewImpl.GetColumns() ) + { + tableViewImpl.Resize( tableViewImpl.GetRows(), value.Get() ); + } } break; } @@ -807,12 +936,12 @@ void TableView::SetProperty( BaseObject* object, Property::Index index, const Pr } case Toolkit::TableView::Property::LAYOUT_ROWS: { - SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedHeight, &TableView::SetRelativeHeight, value ); + SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedHeight, &TableView::SetRelativeHeight, &TableView::SetFitHeight, value ); break; } case Toolkit::TableView::Property::LAYOUT_COLUMNS: { - SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedWidth, &TableView::SetRelativeWidth, value ); + SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedWidth, &TableView::SetRelativeWidth, &TableView::SetFitWidth, value ); break; } } @@ -832,12 +961,12 @@ Property::Value TableView::GetProperty( BaseObject* object, Property::Index inde { case Toolkit::TableView::Property::ROWS: { - value = tableViewImpl.GetRows(); + value = static_cast( tableViewImpl.GetRows() ); break; } case Toolkit::TableView::Property::COLUMNS: { - value = tableViewImpl.GetColumns(); + value = static_cast( tableViewImpl.GetColumns() ); break; } case Toolkit::TableView::Property::CELL_PADDING: @@ -861,75 +990,106 @@ Property::Value TableView::GetProperty( BaseObject* object, Property::Index inde return value; } -void TableView::OnControlChildAdd( Actor& child ) +void TableView::OnChildAdd( Actor& child ) { - if( mLayoutingChild ) + if( ! mLayoutingChild ) { - // we're in the middle of laying out children so no point doing anything here - return; - } + // Ensure we're not in the middle of laying out children - RelayoutRequest(); + // Check child properties on actor to decide its position inside the table + HorizontalAlignment::Type horizontalAlignment = HorizontalAlignment::LEFT; + VerticalAlignment::Type verticalAlignment = VerticalAlignment::TOP; - // Test properties on actor - Toolkit::TableView::CellPosition cellPosition; - if( child.GetPropertyIndex(Toolkit::TableView::ROW_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX ) - { - cellPosition.rowSpan = static_cast( child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::ROW_SPAN_PROPERTY_NAME) ).Get() ); - } + if( child.GetPropertyType( Toolkit::TableView::ChildProperty::CELL_HORIZONTAL_ALIGNMENT ) != Property::NONE ) + { + std::string value = child.GetProperty( Toolkit::TableView::ChildProperty::CELL_HORIZONTAL_ALIGNMENT ).Get(); + Scripting::GetEnumeration< HorizontalAlignment::Type >( value.c_str(), + HORIZONTAL_ALIGNMENT_STRING_TABLE, + HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT, + horizontalAlignment ); + } - if( child.GetPropertyIndex(Toolkit::TableView::COLUMN_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX ) - { - cellPosition.columnSpan = static_cast( child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::COLUMN_SPAN_PROPERTY_NAME) ).Get() ); - } + if( child.GetPropertyType( Toolkit::TableView::ChildProperty::CELL_VERTICAL_ALIGNMENT ) != Property::NONE ) + { + std::string value = child.GetProperty( Toolkit::TableView::ChildProperty::CELL_VERTICAL_ALIGNMENT ).Get(); + Scripting::GetEnumeration< VerticalAlignment::Type >( value.c_str(), + VERTICAL_ALIGNMENT_STRING_TABLE, + VERTICAL_ALIGNMENT_STRING_TABLE_COUNT, + verticalAlignment ); + } - if( child.GetPropertyIndex(Toolkit::TableView::CELL_INDICES_PROPERTY_NAME) != Property::INVALID_INDEX ) - { - Vector2 indices = child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::CELL_INDICES_PROPERTY_NAME) ).Get(); - cellPosition.rowIndex = static_cast( indices.x ); - cellPosition.columnIndex = static_cast( indices.y ); + Toolkit::TableView::CellPosition cellPosition; + if( child.GetPropertyType( Toolkit::TableView::ChildProperty::ROW_SPAN ) != Property::NONE ) + { + cellPosition.rowSpan = child.GetProperty( Toolkit::TableView::ChildProperty::ROW_SPAN ).Get< int >(); + } - AddChild( child, cellPosition ); + if( child.GetPropertyType( Toolkit::TableView::ChildProperty::COLUMN_SPAN ) != Property::NONE ) + { + cellPosition.columnSpan = child.GetProperty( Toolkit::TableView::ChildProperty::COLUMN_SPAN ).Get< int >(); + } - // Do not continue - return; - } + if( child.GetPropertyType( Toolkit::TableView::ChildProperty::CELL_INDEX ) != Property::NONE ) + { + Vector2 indices = child.GetProperty( Toolkit::TableView::ChildProperty::CELL_INDEX ).Get(); + cellPosition.rowIndex = static_cast( indices.x ); + cellPosition.columnIndex = static_cast( indices.y ); - // Find the first available cell to store the actor in - const unsigned int rowCount = mCellData.GetRows(); - const unsigned int columnCount = mCellData.GetColumns(); - for( unsigned int row = 0; row < rowCount; ++row ) - { - for( unsigned int column = 0; column < columnCount; ++column ) + AddChild( child, cellPosition ); + SetCellAlignment(cellPosition, horizontalAlignment, verticalAlignment); + } + else { - if( !(mCellData[ row ][ column ].actor) ) + bool availableCellFound = false; + + // Find the first available cell to store the actor in + const unsigned int rowCount = mCellData.GetRows(); + const unsigned int columnCount = mCellData.GetColumns(); + for( unsigned int row = 0; row < rowCount && !availableCellFound; ++row ) { - // Put the actor in the cell + for( unsigned int column = 0; column < columnCount && !availableCellFound; ++column ) + { + if( !(mCellData[ row ][ column ].actor) ) + { + // Put the actor in the cell + CellData data; + data.actor = child; + data.position.columnIndex = column; + data.position.rowIndex = row; + data.horizontalAlignment = horizontalAlignment; + data.verticalAlignment = verticalAlignment; + mCellData[ row ][ column ] = data; + + availableCellFound = true; + break; + } + } + } + + if( ! availableCellFound ) + { + // No empty cells, so increase size of the table + unsigned int newColumnCount = ( columnCount > 0 ) ? columnCount : 1; + ResizeContainers( rowCount + 1, newColumnCount ); + + // Put the actor in the first cell of the new row CellData data; data.actor = child; - data.position.columnIndex = column; - data.position.rowIndex = row; - mCellData[ row ][ column ] = data; - - // Don't continue - return; + data.position.rowIndex = rowCount; + data.position.columnIndex = 0; + data.horizontalAlignment = horizontalAlignment; + data.verticalAlignment = verticalAlignment; + mCellData[ rowCount ][ 0 ] = data; } + + RelayoutRequest(); } } - // No empty cells, so increase size of the table - unsigned int newColumnCount = ( columnCount > 0 ) ? columnCount : 1; - ResizeContainers( rowCount + 1, newColumnCount ); - - // Put the actor in the first cell of the new row - CellData data; - data.actor = child; - data.position.rowIndex = rowCount; - data.position.columnIndex = 0; - mCellData[ rowCount ][ 0 ] = data; + Control::OnChildAdd( child ); } -void TableView::OnControlChildRemove( Actor& child ) +void TableView::OnChildRemove( Actor& child ) { // dont process if we're in the middle of bigger operation like delete row, column or resize if( !mLayoutingChild ) @@ -940,13 +1100,17 @@ void TableView::OnControlChildRemove( Actor& child ) RelayoutRequest(); } } + + Control::OnChildRemove( child ); } TableView::TableView( unsigned int initialRows, unsigned int initialColumns ) -: Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ), +: Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ), mCellData( initialRows, initialColumns ), + mPreviousFocusedActor(), mLayoutingChild( false ), - mRowColumnDirty( true ) // Force recalculation first time + mRowDirty( true ), // Force recalculation first time + mColumnDirty( true ) { SetKeyboardNavigationSupport( true ); ResizeContainers( initialRows, initialColumns ); @@ -956,8 +1120,13 @@ void TableView::OnInitialize() { // Make self as keyboard focusable and focus group Actor self = Self(); - self.SetKeyboardFocusable(true); + self.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true); SetAsKeyboardFocusGroup(true); + + DevelControl::SetAccessibilityConstructor( self, []( Dali::Actor actor ) { + return std::unique_ptr< Dali::Accessibility::Accessible >( + new Control::Impl::AccessibleImpl( actor, Dali::Accessibility::Role::TABLE ) ); + } ); } void TableView::ResizeContainers( unsigned int rows, unsigned int columns ) @@ -1048,23 +1217,24 @@ bool TableView::RemoveAllInstances( const Actor& child ) void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl, void(TableView::*funcFixed)(unsigned int, float), void(TableView::*funcRelative)(unsigned int, float), + void(TableView::*funcFit)(unsigned int), const Property::Value& value ) { - Property::Map* map = value.GetMap(); + const Property::Map* map = value.GetMap(); if( map ) { - unsigned int rowIndex(0); + unsigned int index(0); for ( unsigned int i = 0, count = map->Count(); i < count; ++i ) { Property::Value& item = map->GetValue(i); Property::Map* childMap = item.GetMap(); - std::istringstream( map->GetKey(i) ) >> rowIndex; + std::istringstream( map->GetKey(i) ) >> index; if( childMap ) { Property::Value* policy = childMap->Find( "policy" ); - Property::Value* value = childMap->Find( "value" ); - if( policy && value ) + Property::Value* childMapValue = childMap->Find( "value" ); + if( policy && childMapValue ) { std::string policyValue; policy->Get( policyValue ); @@ -1074,14 +1244,19 @@ void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl, LAYOUT_POLICY_STRING_TABLE_COUNT, policy ) ) { - if( policy == Toolkit::TableView::FIXED ) + if( policy == Toolkit::TableView::FIXED ) { - (tableViewImpl.*funcFixed)( rowIndex, value->Get() ); + (tableViewImpl.*funcFixed)( index, childMapValue->Get() ); } else if( policy == Toolkit::TableView::RELATIVE ) { - (tableViewImpl.*funcRelative)( rowIndex, value->Get() ); + (tableViewImpl.*funcRelative)( index, childMapValue->Get() ); + } + else if( policy == Toolkit::TableView::FIT ) + { + (tableViewImpl.*funcFit)( index ); } + // do nothing for FILL policy } } } @@ -1105,63 +1280,56 @@ Property::Value TableView::GetColumnWidthsPropertyValue() void TableView::GetMapPropertyValue( const RowColumnArray& data, Property::Map& map ) { - const char* name = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIXED, - LAYOUT_POLICY_STRING_TABLE, - LAYOUT_POLICY_STRING_TABLE_COUNT ); - std::string fixedPolicy; - if( name ) - { - fixedPolicy = name; - } - name = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::RELATIVE, - LAYOUT_POLICY_STRING_TABLE, - LAYOUT_POLICY_STRING_TABLE_COUNT ); - std::string relativePolicy; - if( name ) - { - relativePolicy = name; - } + const char* fixedPolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIXED, + LAYOUT_POLICY_STRING_TABLE, + LAYOUT_POLICY_STRING_TABLE_COUNT ); + const char* relativePolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::RELATIVE, + LAYOUT_POLICY_STRING_TABLE, + LAYOUT_POLICY_STRING_TABLE_COUNT ); + const char* fillPolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FILL, + LAYOUT_POLICY_STRING_TABLE, + LAYOUT_POLICY_STRING_TABLE_COUNT ); + const char* fitPolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIT, + LAYOUT_POLICY_STRING_TABLE, + LAYOUT_POLICY_STRING_TABLE_COUNT ); const RowColumnArray::SizeType count = data.Size(); for( RowColumnArray::SizeType i = 0; i < count; i++ ) { const RowColumnData& dataInstance = data[ i ]; + Property::Map item; switch( dataInstance.sizePolicy ) { - case FIXED: + case Toolkit::TableView::FIXED: { - Property::Map item; item[ "policy" ] = fixedPolicy; item[ "value" ] = dataInstance.size; - - std::ostringstream ss; - ss << i; - - map[ ss.str() ] = item; - break; } - - case FILL: + case Toolkit::TableView::RELATIVE: { - Property::Map item; item[ "policy" ] = relativePolicy; item[ "value" ] = dataInstance.fillRatio; - - std::ostringstream ss; - ss << i; - - map[ ss.str() ] = item; - break; } - + case Toolkit::TableView::FIT: + { + item[ "policy" ] = fitPolicy; + item[ "value" ] = 0.f; + break; + } + case Toolkit::TableView::FILL: default: { + item[ "policy" ] = fillPolicy; + item[ "value" ] = 0.f; break; } } + std::ostringstream ss; + ss << i; + map[ ss.str() ] = item; } } @@ -1191,51 +1359,78 @@ Actor TableView::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolki int numberOfColumns = GetColumns(); int numberOfRows = GetRows(); + bool lastCell = false; + Actor nextValidActor; + switch ( direction ) { case Toolkit::Control::KeyboardFocus::LEFT: { - if(--currentColumn < 0) + do { - currentColumn = numberOfColumns - 1; - if(--currentRow < 0) + if(--currentColumn < 0) { - currentRow = loopEnabled ? numberOfRows - 1 : 0; - focusLost = (currentRow == 0); + currentColumn = numberOfColumns - 1; + if(--currentRow < 0) + { + lastCell = true; + currentRow = loopEnabled ? numberOfRows - 1 : 0; + focusLost = (currentRow == 0); + } } - } + nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn)); + } while ( !nextValidActor && !lastCell ); break; } case Toolkit::Control::KeyboardFocus::RIGHT: { - if(++currentColumn > numberOfColumns - 1) + do { - currentColumn = 0; - if(++currentRow > numberOfRows - 1) + if(++currentColumn > numberOfColumns - 1) { - currentRow = loopEnabled ? 0 : numberOfRows - 1; - focusLost = (currentRow == numberOfRows - 1); + currentColumn = 0; + if(++currentRow > numberOfRows - 1) + { + lastCell = true; + currentRow = loopEnabled ? 0 : numberOfRows - 1; + focusLost = (currentRow == numberOfRows - 1); + } } - } + nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn)); + } while ( !nextValidActor && !lastCell ); break; } case Toolkit::Control::KeyboardFocus::UP: { - if(--currentRow < 0) + do { - currentRow = loopEnabled ? numberOfRows - 1 : 0; - focusLost = (currentRow == 0); - } + if(--currentRow < 0) + { + lastCell = true; + currentRow = loopEnabled ? numberOfRows - 1 : 0; + focusLost = (currentRow == 0); + } + nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn)); + } while ( !nextValidActor && !lastCell ); break; } case Toolkit::Control::KeyboardFocus::DOWN: { - if(++currentRow > numberOfRows - 1) + do { - currentRow = loopEnabled ? 0 : numberOfRows - 1; - focusLost = (currentRow == numberOfRows - 1); - } + if(++currentRow > numberOfRows - 1) + { + lastCell = true; + currentRow = loopEnabled ? 0 : numberOfRows - 1; + focusLost = (currentRow == numberOfRows - 1); + } + nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn)); + } while ( !nextValidActor && !lastCell ); + break; + } + default: + { break; } } @@ -1244,12 +1439,49 @@ Actor TableView::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolki if(!focusLost) { nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn)); + + // Save the focused actor in the TableView. + mPreviousFocusedActor = nextFocusableActor; } } else { - // The current focused actor is not within table view, so the child in the first cell should be focused. - nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0)); + // The current focused actor is not within this TableView. + + unsigned int numberOfColumns = GetColumns(); + unsigned int numberOfRows = GetRows(); + + // Check whether the previous focused actor is a focus group (i.e. a layout container) + bool wasFocusedOnLayoutContainer = false; + Actor previousFocusedActor = mPreviousFocusedActor.GetHandle(); + if( previousFocusedActor ) + { + Toolkit::Control control = Toolkit::Control::DownCast( previousFocusedActor ); + if( control ) + { + Internal::Control& controlImpl = static_cast(control.GetImplementation()); + wasFocusedOnLayoutContainer = controlImpl.IsKeyboardFocusGroup(); + } + } + + // Check whether the previous focused actor is a layout container and also a child of this TableView + Toolkit::TableView::CellPosition position; + if( wasFocusedOnLayoutContainer && FindChildPosition( previousFocusedActor, position ) ) + { + nextFocusableActor = GetNextKeyboardFocusableActor(previousFocusedActor, direction, loopEnabled); + } + else + { + // Otherwise, move the focus to either the first or the last cell according to the given direction. + if(direction == Toolkit::Control::KeyboardFocus::LEFT || direction == Toolkit::Control::KeyboardFocus::UP) + { + nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(numberOfRows - 1, numberOfColumns - 1)); + } + else + { + nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0)); + } + } } } @@ -1264,76 +1496,44 @@ Vector3 TableView::GetNaturalSize() float TableView::CalculateChildSize( const Actor& child, Dimension::Type dimension ) { - CalculateRowColumnData(); - - const unsigned int rowCount = mCellData.GetRows(); - const unsigned int columnCount = mCellData.GetColumns(); - - for( unsigned int row = 0; row < rowCount; ++row ) + Toolkit::TableView::CellPosition position; + if( FindChildPosition( child, position) ) { - for( unsigned int column = 0; column < columnCount; ++column ) + switch( dimension ) { - // check if this cell has an actor - Actor& actor = mCellData[ row ][ column ].actor; - - if( actor && ( actor == child ) ) + case Dimension::WIDTH: { - const Toolkit::TableView::CellPosition position = mCellData[ row ][ column ].position; + float cellSize = 0.0f; + cellSize = mColumnData[position.columnIndex+position.columnSpan-1].position + - (position.columnIndex > 0 ? mColumnData[position.columnIndex-1].position : 0.f) + - mPadding.width * 2.0f; - // If there is an actor and this is the main cell of the actor. - // An actor can be in multiple cells if its row or columnspan is more than 1. - if ( ( position.rowIndex == row ) && ( position.columnIndex == column ) ) + if( cellSize < 0.0f ) { - switch( dimension ) - { - case Dimension::WIDTH: - { - float cellSize = 0.0f; - - // Accumulate the width - for( unsigned int i = 0; i < position.columnSpan; ++i ) - { - DALI_ASSERT_DEBUG( column + i < mColumnData.Size() ); - cellSize += mColumnData[ column + i ].size; - } - - // Apply padding - cellSize -= mPadding.width * 2.0f; - if( cellSize < 0.0f ) - { - cellSize = 0.0f; - } - - return cellSize; - } - - case Dimension::HEIGHT: - { - float cellSize = 0.0f; + cellSize = 0.0f; + } - // Accumulate the height - for( unsigned int i = 0; i < position.rowSpan; ++i ) - { - DALI_ASSERT_DEBUG( row + i < mRowData.Size() ); - cellSize += mRowData[ row + i ].size; - } + return cellSize; + } - // Apply padding - cellSize -= mPadding.width * 2.0f; - if( cellSize < 0.0f ) - { - cellSize = 0.0f; - } + case Dimension::HEIGHT: + { + float cellSize = 0.0f; - return cellSize; - } + cellSize = mRowData[position.rowIndex+position.rowSpan-1].position + - (position.rowIndex > 0 ? mRowData[position.rowIndex-1].position : 0.f) + - mPadding.height * 2.0f; - default: - { - return 0.0f; - } - } + if( cellSize < 0.0f ) + { + cellSize = 0.0f; } + + return cellSize; + } + default: + { + return 0.0f; } } } @@ -1372,7 +1572,7 @@ void TableView::SetCellAlignment( Toolkit::TableView::CellPosition position, Hor data.verticalAlignment = vertical; } -void TableView::ComputeRelativeSizes( RowColumnArray& data ) +void TableView::CalculateFillSizes( RowColumnArray& data ) { // First pass: Count number of fill entries and calculate used relative space Dali::Vector< RowColumnData* > fillData; @@ -1384,16 +1584,13 @@ void TableView::ComputeRelativeSizes( RowColumnArray& data ) { RowColumnData& dataInstance = data[ i ]; - if( dataInstance.sizePolicy == FILL ) + if( dataInstance.sizePolicy == Toolkit::TableView::RELATIVE ) { - if( dataInstance.userFillRatio ) - { - relativeTotal += dataInstance.fillRatio; - } - else - { - fillData.PushBack( &dataInstance ); - } + relativeTotal += dataInstance.fillRatio; + } + else if(dataInstance.sizePolicy == Toolkit::TableView::FILL) + { + fillData.PushBack( &dataInstance ); } } @@ -1427,8 +1624,9 @@ float TableView::CalculateTotalFixedSize( const RowColumnArray& data ) switch( dataInstance.sizePolicy ) { - case FIXED: - case FIT: + // we have absolute size to FIXED and FIT column/row and relative size for RELATIVE and FILL column/row + case Toolkit::TableView::FIXED: + case Toolkit::TableView::FIT: { totalSize += dataInstance.size; break; @@ -1465,7 +1663,7 @@ Vector2 TableView::GetCellPadding( Dimension::Type dimension ) return Vector2(); } -void TableView::CalculateFixedSizes( RowColumnArray& data, Dimension::Type dimension ) +void TableView::CalculateFitSizes( RowColumnArray& data, Dimension::Type dimension ) { Vector2 cellPadding = GetCellPadding( dimension ); @@ -1475,7 +1673,7 @@ void TableView::CalculateFixedSizes( RowColumnArray& data, Dimension::Type dimen { RowColumnData& dataInstance = data[ i ]; - if( dataInstance.sizePolicy == FIT ) + if( dataInstance.sizePolicy == Toolkit::TableView::FIT ) { // Find the size of the biggest actor in the row or column float maxActorHeight = 0.0f; @@ -1505,26 +1703,11 @@ void TableView::CalculateFixedSizes( RowColumnArray& data, Dimension::Type dimen } } -void TableView::CalculateRelativeSizes( RowColumnArray& data, float size ) -{ - const unsigned int dataCount = data.Size(); - - for( unsigned int i = 0; i < dataCount; ++i ) - { - RowColumnData& dataInstance = data[ i ]; - - if( dataInstance.sizePolicy == FILL ) - { - dataInstance.size = dataInstance.fillRatio * size; - } - } -} - bool TableView::FindFit( const RowColumnArray& data ) { for( unsigned int i = 0, count = data.Size(); i < count; ++i ) { - if( data[ i ].sizePolicy == FIT ) + if( data[ i ].sizePolicy == Toolkit::TableView::FIT ) { return true; }