1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

DROID-385 Editor | Enhancement | Simple tables, ability to select rows and columns (#2710)

* DROID-385 table extensions

* DROID-385 table widget state

* DROID-385 simple table widget, tab added

* DROID-385 update editor table mode

* DROID-385 unselect list of targets

* DROID-385 tabs selection logic

* DROID-385 do not support tabs in adapter

* DROID-385 cell selection decorator regfactoring

* DROID-385 remove cell index

* DROID-385 selected cells state as hash map

* DROID-385 update cells blocks stubs

* DROID-385 fix tests

* DROID-385 tests

* DROID-385 fix method

* DROID-385 add columnId and rowId

* DROID-385 fix tests

* DROID-385 number of column-row selected

* DROID-385 selection logic

* DROID-385 test

* DROID-385 top menu refactoring

* DROID-385 refactoring

* DROID-385 ci

* DROID-385 ci off

* DROID-385 pr fix

* DROID-385 pr fix

* DROID-385 block table stub model added

* DROID-385 table blocks diff util tests

Co-authored-by: konstantiniiv <ki@anytype.io>
This commit is contained in:
Konstantin Ivanov 2022-11-21 16:10:58 +01:00 committed by GitHub
parent 00dc75d62e
commit 53c3c85f08
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 1636 additions and 420 deletions

View file

@ -18,6 +18,7 @@ import android.view.animation.LinearInterpolator
import android.view.animation.OvershootInterpolator
import android.widget.TextView
import androidx.activity.addCallback
import androidx.annotation.RequiresApi
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.animation.doOnEnd
@ -599,13 +600,6 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
.onEach { vm.onExitMultiSelectModeClicked() }
.launchIn(lifecycleScope)
binding.cellSelectionTopToolbar
.doneButton
.clicks()
.throttleFirst()
.onEach { vm.onCellSelectionTopToolbarDoneButtonClick() }
.launchIn(lifecycleScope)
binding.bottomToolbar
.homeClicks()
.onEach { vm.onHomeButtonClicked() }
@ -1351,18 +1345,10 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
state.multiSelect.apply {
val behavior = BottomSheetBehavior.from(binding.blockActionToolbar)
if (isVisible) {
binding.multiSelectTopToolbar.visible()
when {
count > 1 -> {
binding.multiSelectTopToolbar.selectText.text =
getString(R.string.number_selected_blocks, count)
}
count == 1 -> {
binding.multiSelectTopToolbar.selectText.setText(R.string.one_selected_block)
}
else -> {
binding.multiSelectTopToolbar.selectText.text = null
}
binding.multiSelectTopToolbar.apply {
setBlockSelectionText(count)
visible()
}
binding.bottomMenu.update(count)
@ -1398,7 +1384,7 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
setState(BottomSheetBehavior.STATE_HIDDEN)
removeBottomSheetCallback(onHideBottomSheetCallback)
}
hideSelectButton()
if (!state.simpleTableWidget.isVisible) hideSelectButton()
binding.recycler.removeItemDecoration(actionToolbarFooter)
}
if (isScrollAndMoveEnabled)
@ -1560,6 +1546,13 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
state.simpleTableWidget.apply {
val behavior = BottomSheetBehavior.from(binding.simpleTableWidget)
if (isVisible) {
binding.multiSelectTopToolbar.apply {
setTableSelectionText(
count = state.simpleTableWidget.selectedCount,
tab = state.simpleTableWidget.tab
)
visible()
}
binding.simpleTableWidget.onStateChanged(
cellItems = state.simpleTableWidget.cellItems,
rowItems = state.simpleTableWidget.rowItems,
@ -1570,12 +1563,16 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
if (binding.recycler.itemDecorationCount == 0) {
binding.recycler.addItemDecoration(styleToolbarFooter)
}
proceedWithHidingSoftInput()
delayKeyboardHide(insets)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
hidingSoftInput()
} else {
proceedWithHidingSoftInput()
}
behavior.apply {
setState(BottomSheetBehavior.STATE_EXPANDED)
addBottomSheetCallback(onHideBottomSheetCallback)
}
showSelectButton()
}
}
} else {
@ -1583,17 +1580,7 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
behavior.removeBottomSheetCallback(onHideBottomSheetCallback)
behavior.state = BottomSheetBehavior.STATE_HIDDEN
}
}
}
state.cellsSelectTopWidget.apply {
if (isVisible) {
binding.cellSelectionTopToolbar.showWithAnimation()
binding.cellSelectionTopToolbar.setCellSelectionText(count)
} else {
binding.cellSelectionTopToolbar.hideWithAnimation {
if (hasBinding) binding.topToolbar.visible()
}
if (!state.multiSelect.isVisible) hideSelectButton()
}
}
}
@ -1613,6 +1600,11 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
)
}
@RequiresApi(Build.VERSION_CODES.R)
private fun hidingSoftInput() {
ViewCompat.getWindowInsetsController(requireView())?.hide(WindowInsetsCompat.Type.ime())
}
private fun proceedWithHidingSoftInput() {
// TODO enable when switching to API 30
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {

View file

@ -58,16 +58,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.anytypeio.anytype.core_ui.widgets.toolbar.MultiSelectTopToolbarWidget
android:id="@+id/cellSelectionTopToolbar"
android:layout_width="0dp"
android:layout_height="48dp"
android:background="@color/defaultCanvasColor"
android:translationY="-48dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.anytypeio.anytype.core_ui.widgets.toolbar.BlockToolbarWidget
android:id="@+id/toolbar"
android:layout_width="0dp"

View file

@ -237,8 +237,6 @@ Do the computation of an expensive paragraph of text on a background thread:
<string name="wait_a_bit_message">Please give us a moment. Were almost there…</string>
<string name="soon">Soon</string>
<string name="one_selected_block">1 selected block</string>
<string name="number_selected_blocks">%1$d selected blocks</string>
<string name="select_all">Select all</string>
<string name="unselect_all">Unselect all (%1$d)</string>
<string name="are_you_sure_delete_one_object">Are you sure you want to delete 1 object?</string>

View file

@ -245,7 +245,7 @@ class BlockViewDiffUtil(
}
if (newBlock is BlockView.Table && oldBlock is BlockView.Table) {
if (newBlock.rowCount != oldBlock.rowCount) {
if (newBlock.rows.size != oldBlock.rows.size) {
changes.add(TABLE_ROW_COUNT_CHANGED)
}
if (newBlock.cells != oldBlock.cells) {
@ -254,6 +254,9 @@ class BlockViewDiffUtil(
if (newBlock.selectedCellsIds != oldBlock.selectedCellsIds) {
changes.add(TABLE_CELLS_SELECTION_CHANGED)
}
if (newBlock.tab != oldBlock.tab) {
changes.add(TABLE_CELLS_SELECTION_CHANGED)
}
}
return if (changes.isNotEmpty())

View file

@ -108,7 +108,7 @@ class TableBlockHolder(
}
private fun applyRowCount(item: BlockView.Table) {
lm.spanCount = item.rowCount
lm.spanCount = item.rows.size
}
private fun updateCellsSelection(item: BlockView.Table) {
@ -122,7 +122,7 @@ class TableBlockHolder(
item.selectedCellsIds.contains(cell.getId())
}
cellsSelectionState.clear()
cellsSelectionState.set(selectedCells)
cellsSelectionState.set(cells = selectedCells, rowsSize = item.rows.size)
if (cellsSelectionState.current().isNotEmpty()) {
cellSelectionDecoration.setSelectionState(cellsSelectionState.current())
if (!recycler.containsItemDecoration(cellSelectionDecoration)) {

View file

@ -12,11 +12,10 @@ class TableCellSelectionDecoration(
private val drawable: Drawable
) : RecyclerView.ItemDecoration() {
private val selectionState: MutableList<BlockView.Table.CellSelection> = mutableListOf()
private var selectionState: Map<Int, BlockView.Table.CellSelection> = emptyMap()
fun setSelectionState(newState: List<BlockView.Table.CellSelection>) {
selectionState.clear()
selectionState.addAll(newState)
fun setSelectionState(newState: Map<Int, BlockView.Table.CellSelection>) {
selectionState = newState
}
override fun onDrawOver(
@ -29,7 +28,7 @@ class TableCellSelectionDecoration(
parent.children.forEach { view ->
val position = parent.getChildAdapterPosition(view)
if (position != RecyclerView.NO_POSITION) {
val cellSelection = selectionState.find { it.cellIndex == position }
val cellSelection = selectionState[position]
if (cellSelection != null) {
parent.getDecoratedBoundsWithMargins(view, rect)
if (cellSelection.left) {

View file

@ -12,6 +12,7 @@ import androidx.core.animation.doOnEnd
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.databinding.WidgetMultiSelectTopToolbarBinding
import com.anytypeio.anytype.core_utils.ext.dimen
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
class MultiSelectTopToolbarWidget @JvmOverloads constructor(
context: Context,
@ -25,17 +26,27 @@ class MultiSelectTopToolbarWidget @JvmOverloads constructor(
val selectText get() : TextView = binding.tvToolbarTitle
val doneButton get() : View = binding.btnDone
fun setCellSelectionText(count: Int) {
when {
count == 1 -> {
selectText.text = context.getString(R.string.one_selected_cell)
fun setTableSelectionText(count: Int, tab: BlockView.Table.Tab) = with(context) {
selectText.text = when {
count == 1 -> when (tab) {
BlockView.Table.Tab.CELL -> getString(R.string.one_selected_cell)
BlockView.Table.Tab.COLUMN -> getString(R.string.one_selected_column)
BlockView.Table.Tab.ROW -> getString(R.string.one_selected_row)
}
count > 1 -> {
selectText.text = context.getString(R.string.number_selected_cells, count)
}
else -> {
selectText.text = null
count > 1 -> when (tab) {
BlockView.Table.Tab.CELL -> getString(R.string.number_selected_cells, count)
BlockView.Table.Tab.COLUMN -> getString(R.string.number_selected_columns, count)
BlockView.Table.Tab.ROW -> getString(R.string.number_selected_rows, count)
}
else -> null
}
}
fun setBlockSelectionText(count: Int) = with(context) {
selectText.text = when {
count > 1 -> getString(R.string.number_selected_blocks, count)
count == 1 -> getString(R.string.one_selected_block)
else -> null
}
}

View file

@ -7,7 +7,7 @@ import androidx.cardview.widget.CardView
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.databinding.WidgetSimpleTableBinding
import com.anytypeio.anytype.presentation.editor.editor.table.SimpleTableWidgetItem
import com.anytypeio.anytype.presentation.editor.markup.MarkupColorView
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
class SimpleTableSettingWidget @JvmOverloads constructor(
@ -23,11 +23,11 @@ class SimpleTableSettingWidget @JvmOverloads constructor(
var onItemClickListener: (SimpleTableWidgetItem) -> Unit = {}
private val cellAdapter = SimpleTableWidgetAdapter(items = listOf(),
onClick = { item -> onItemClickListener.invoke(item)})
onClick = { item -> onItemClickListener.invoke(item) })
private val columnAdapter = SimpleTableWidgetAdapter(items = listOf(),
onClick = { item -> onItemClickListener.invoke(item)})
onClick = { item -> onItemClickListener.invoke(item) })
private val rowAdapter = SimpleTableWidgetAdapter(items = listOf(),
onClick = { item -> onItemClickListener.invoke(item)})
onClick = { item -> onItemClickListener.invoke(item) })
private val pagerAdapter = SimpleTableSettingAdapter(
cellAdapter = cellAdapter,
@ -40,6 +40,15 @@ class SimpleTableSettingWidget @JvmOverloads constructor(
rowItems: List<SimpleTableWidgetItem>,
columnItems: List<SimpleTableWidgetItem>
) {
if (cellItems.isNotEmpty() && binding.tabsLayout.selectedTabPosition != TAB_CELL_POSITION) {
binding.tabsLayout.selectTab(binding.tabsLayout.getTabAt(TAB_CELL_POSITION))
}
if (columnItems.isNotEmpty() && binding.tabsLayout.selectedTabPosition != TAB_COLUMN_POSITION) {
binding.tabsLayout.selectTab(binding.tabsLayout.getTabAt(TAB_COLUMN_POSITION))
}
if (rowItems.isNotEmpty() && binding.tabsLayout.selectedTabPosition != TAB_ROW_POSITION) {
binding.tabsLayout.selectTab(binding.tabsLayout.getTabAt(TAB_ROW_POSITION))
}
cellAdapter.update(cellItems)
columnAdapter.update(columnItems)
rowAdapter.update(rowItems)
@ -47,6 +56,9 @@ class SimpleTableSettingWidget @JvmOverloads constructor(
fun setListener(listener: (SimpleTableWidgetItem) -> Unit = {}) {
onItemClickListener = listener
binding.tabsLayout.apply {
addOnTabSelectedListener(onTabSelectedListener)
}
}
init {
@ -54,11 +66,36 @@ class SimpleTableSettingWidget @JvmOverloads constructor(
binding.viewpager.isUserInputEnabled = false
TabLayoutMediator(binding.tabsLayout, binding.viewpager) { tab, position ->
tab.text = when (position) {
0 -> context.getString(R.string.simple_tables_widget_tab_cell)
1 -> context.getString(R.string.simple_tables_widget_tab_column)
2 -> context.getString(R.string.simple_tables_widget_tab_row)
TAB_CELL_POSITION -> context.getString(R.string.simple_tables_widget_tab_cell)
TAB_COLUMN_POSITION -> context.getString(R.string.simple_tables_widget_tab_column)
TAB_ROW_POSITION -> context.getString(R.string.simple_tables_widget_tab_row)
else -> throw IllegalStateException("Unexpected position: $position")
}
}.attach()
}
private val onTabSelectedListener = object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
when (tab?.text) {
context.getString(R.string.simple_tables_widget_tab_cell) -> {
onItemClickListener(SimpleTableWidgetItem.Tab.Cell)
}
context.getString(R.string.simple_tables_widget_tab_row) -> {
onItemClickListener(SimpleTableWidgetItem.Tab.Row)
}
context.getString(R.string.simple_tables_widget_tab_column) -> {
onItemClickListener(SimpleTableWidgetItem.Tab.Column)
}
}
}
override fun onTabUnselected(tab: TabLayout.Tab?) {}
override fun onTabReselected(tab: TabLayout.Tab?) {}
}
companion object {
const val TAB_CELL_POSITION = 0
const val TAB_COLUMN_POSITION = 1
const val TAB_ROW_POSITION = 2
}
}

View file

@ -115,6 +115,7 @@ class SimpleTableWidgetAdapter(
title.setText(R.string.simple_tables_widget_item_move_up)
icon.setImageResource(R.drawable.ic_move_row_up)
}
else -> Unit
}
}
}

View file

@ -565,6 +565,12 @@
<string name="bookmark_icon">Bookmark icon</string>
<string name="one_selected_cell">1 cell selected</string>
<string name="number_selected_cells">%1$d cells selected</string>
<string name="one_selected_column">1 column selected</string>
<string name="number_selected_columns">%1$d columns selected</string>
<string name="one_selected_row">1 row selected</string>
<string name="number_selected_rows">%1$d rows selected</string>
<string name="one_selected_block">1 selected block</string>
<string name="number_selected_blocks">%1$d selected blocks</string>
<string name="error_find_block">Could\'t find the selected block</string>
<string name="error_block_selection">Block selection error</string>

View file

@ -1,11 +1,15 @@
package com.anytypeio.anytype.core_ui
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.RelationFormat
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil.Companion.CALLOUT_ICON_CHANGED
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil.Companion.DECORATION_CHANGED
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil.Companion.MARKUP_CHANGED
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil.Companion.TABLE_CELLS_CHANGED
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil.Companion.TABLE_CELLS_SELECTION_CHANGED
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil.Companion.TABLE_ROW_COUNT_CHANGED
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil.Companion.TEXT_CHANGED
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil.Payload
import com.anytypeio.anytype.presentation.editor.editor.Markup
@ -1632,4 +1636,145 @@ class BlockViewDiffUtilTest {
expected = null
)
}
@Test
fun `when two table blocks are equal - should be no payloads`() {
//SETUP
val index = 0
val tableId = MockDataFactory.randomUuid()
val oldBlock = StubTwoRowsThreeColumnsSimpleTable(tableId = tableId)
val newBlock = oldBlock
//TESTING
val diff = BlockViewDiffUtil(old = listOf(oldBlock), new = listOf(newBlock))
val payload = diff.getChangePayload(index, index)
//ASSERT
assertEquals(
actual = payload,
expected = null
)
}
@Test
fun `when two table blocks have different texts in cell - should be table cells changed payload`() {
//SETUP
val tableId = MockDataFactory.randomUuid()
val oldBlock = StubTwoRowsThreeColumnsSimpleTable(tableId = tableId)
val oldCells = oldBlock.cells
val newCells = oldCells.mapIndexed { index, cell ->
if (index == 0) cell.copy(
block = cell.block?.copy(text = MockDataFactory.randomString())
) else {
cell
}
}
val newBlock = oldBlock.copy(cells = newCells)
//TESTING
val diff = BlockViewDiffUtil(old = listOf(oldBlock), new = listOf(newBlock))
val payload = diff.getChangePayload(0, 0)
//EXPECTED
val expectedPayloads = Payload(listOf(TABLE_CELLS_CHANGED))
//ASSERT
assertEquals(
actual = payload,
expected = expectedPayloads
)
}
@Test
fun `when two table blocks have different tabs - should be table cells selection changed payload`() {
//SETUP
val tableId = MockDataFactory.randomUuid()
val oldBlock = StubTwoRowsThreeColumnsSimpleTable(
tableId = tableId,
tab = BlockView.Table.Tab.CELL
)
val newBlock = oldBlock.copy(
tab = BlockView.Table.Tab.ROW
)
//TESTING
val diff = BlockViewDiffUtil(old = listOf(oldBlock), new = listOf(newBlock))
val payload = diff.getChangePayload(0, 0)
//EXPECTED
val expectedPayloads = Payload(listOf(TABLE_CELLS_SELECTION_CHANGED))
//ASSERT
assertEquals(
actual = payload,
expected = expectedPayloads
)
}
@Test
fun `when table block have different cells selection state - should be table cells selection changed payload`() {
//SETUP
val tableId = MockDataFactory.randomUuid()
val rowId1 = MockDataFactory.randomUuid()
val columnId1 = MockDataFactory.randomUuid()
val columnId2 = MockDataFactory.randomUuid()
val oldBlock = StubTwoRowsThreeColumnsSimpleTable(
tableId = tableId,
rowId1 = rowId1,
columnId1 = columnId1,
columnId2 = columnId2,
tab = BlockView.Table.Tab.CELL,
selectedCellsIds = listOf("$rowId1-$columnId1")
)
val newBlock = oldBlock.copy(
tab = BlockView.Table.Tab.CELL,
selectedCellsIds = listOf("$rowId1-$columnId1", "$rowId1-$columnId2")
)
//TESTING
val diff = BlockViewDiffUtil(old = listOf(oldBlock), new = listOf(newBlock))
val payload = diff.getChangePayload(0, 0)
//EXPECTED
val expectedPayloads = Payload(listOf(TABLE_CELLS_SELECTION_CHANGED))
//ASSERT
assertEquals(
actual = payload,
expected = expectedPayloads
)
}
@Test
fun `when table block have different rows size - should be rows size and cells changed payloads`() {
//SETUP
val tableId = MockDataFactory.randomUuid()
val oldBlock = StubTableView(
tableId = tableId,
tab = BlockView.Table.Tab.CELL,
rowSize = 10,
columnSize = 10
)
val newBlock = StubTableView(
tableId = tableId,
tab = BlockView.Table.Tab.CELL,
rowSize = 11,
columnSize = 10
)
//TESTING
val diff = BlockViewDiffUtil(old = listOf(oldBlock), new = listOf(newBlock))
val payload = diff.getChangePayload(0, 0)
//EXPECTED
val expectedPayloads = Payload(listOf(TABLE_ROW_COUNT_CHANGED, TABLE_CELLS_CHANGED))
//ASSERT
assertEquals(
actual = payload,
expected = expectedPayloads
)
}
}

View file

@ -1113,7 +1113,6 @@ class BlockViewSearchTextTest {
columnId = columnId1,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(0),
cellIndex = 0,
tableId = tableId
),
BlockView.Table.Cell(
@ -1125,7 +1124,6 @@ class BlockViewSearchTextTest {
columnId = columnId2,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(1),
cellIndex = 2,
tableId = tableId
),
BlockView.Table.Cell(
@ -1137,7 +1135,6 @@ class BlockViewSearchTextTest {
columnId = columnId3,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(2),
cellIndex = 4,
tableId = tableId
),
BlockView.Table.Cell(
@ -1149,7 +1146,6 @@ class BlockViewSearchTextTest {
columnId = columnId1,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(0),
cellIndex = 1,
tableId = tableId
),
BlockView.Table.Cell(
@ -1161,7 +1157,6 @@ class BlockViewSearchTextTest {
columnId = columnId2,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(1),
cellIndex = 3,
tableId = tableId
),
BlockView.Table.Cell(
@ -1173,15 +1168,19 @@ class BlockViewSearchTextTest {
columnId = columnId3,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(2),
cellIndex = 5,
tableId = tableId
)
)
val columns = listOf(
BlockView.Table.Column(id = columnId1, background = ThemeColor.DEFAULT),
BlockView.Table.Column(id = columnId2, background = ThemeColor.DEFAULT),
BlockView.Table.Column(id = columnId3, background = ThemeColor.DEFAULT)
BlockView.Table.ColumnId(value = columnId1),
BlockView.Table.ColumnId(value = columnId2),
BlockView.Table.ColumnId(value = columnId3),
)
val rows = listOf(
BlockView.Table.RowId(value = rowId1),
BlockView.Table.RowId(value = rowId2)
)
val views = listOf<BlockView>(
@ -1189,7 +1188,7 @@ class BlockViewSearchTextTest {
id = tableId,
cells = cells,
columns = columns,
rowCount = 2,
rows = rows,
isSelected = false,
selectedCellsIds = emptyList()
)
@ -1212,7 +1211,6 @@ class BlockViewSearchTextTest {
columnId = columnId1,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(0),
cellIndex = 0,
tableId = tableId
),
BlockView.Table.Cell(
@ -1231,7 +1229,6 @@ class BlockViewSearchTextTest {
columnId = columnId2,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(1),
cellIndex = 2,
tableId = tableId
),
BlockView.Table.Cell(
@ -1250,7 +1247,6 @@ class BlockViewSearchTextTest {
columnId = columnId3,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(2),
cellIndex = 4,
tableId = tableId
),
BlockView.Table.Cell(
@ -1269,7 +1265,6 @@ class BlockViewSearchTextTest {
columnId = columnId1,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(0),
cellIndex = 1,
tableId = tableId
),
BlockView.Table.Cell(
@ -1288,7 +1283,6 @@ class BlockViewSearchTextTest {
columnId = columnId2,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(1),
cellIndex = 3,
tableId = tableId
),
BlockView.Table.Cell(
@ -1307,7 +1301,6 @@ class BlockViewSearchTextTest {
columnId = columnId3,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(2),
cellIndex = 5,
tableId = tableId
)
)
@ -1330,7 +1323,7 @@ class BlockViewSearchTextTest {
id = tableId,
cells = expectedCells,
columns = columns,
rowCount = 2,
rows = rows,
isSelected = false,
selectedCellsIds = emptyList()
)
@ -1369,7 +1362,6 @@ class BlockViewSearchTextTest {
columnId = columnId1,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(0),
cellIndex = 0,
tableId = tableId
),
BlockView.Table.Cell(
@ -1381,7 +1373,6 @@ class BlockViewSearchTextTest {
columnId = columnId2,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(1),
cellIndex = 2,
tableId = tableId
),
BlockView.Table.Cell(
@ -1393,7 +1384,6 @@ class BlockViewSearchTextTest {
columnId = columnId3,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(2),
cellIndex = 4,
tableId = tableId
),
BlockView.Table.Cell(
@ -1405,7 +1395,6 @@ class BlockViewSearchTextTest {
columnId = columnId1,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(0),
cellIndex = 1,
tableId = tableId
),
BlockView.Table.Cell(
@ -1417,7 +1406,6 @@ class BlockViewSearchTextTest {
columnId = columnId2,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(1),
cellIndex = 3,
tableId = tableId
),
BlockView.Table.Cell(
@ -1429,15 +1417,18 @@ class BlockViewSearchTextTest {
columnId = columnId3,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(2),
cellIndex = 5,
tableId = tableId
)
)
val columns = listOf(
BlockView.Table.Column(id = columnId1, background = ThemeColor.DEFAULT),
BlockView.Table.Column(id = columnId2, background = ThemeColor.DEFAULT),
BlockView.Table.Column(id = columnId3, background = ThemeColor.DEFAULT)
BlockView.Table.ColumnId(value = columnId1),
BlockView.Table.ColumnId(value = columnId2),
BlockView.Table.ColumnId(value = columnId3)
)
val rows = listOf(
BlockView.Table.RowId(value = rowId1),
BlockView.Table.RowId(value = rowId2)
)
val views = listOf<BlockView>(
@ -1445,9 +1436,9 @@ class BlockViewSearchTextTest {
id = tableId,
cells = cells,
columns = columns,
rowCount = 2,
isSelected = false,
selectedCellsIds = emptyList()
selectedCellsIds = emptyList(),
rows = rows
)
)
@ -1461,7 +1452,6 @@ class BlockViewSearchTextTest {
columnId = columnId1,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(0),
cellIndex = 0,
tableId = tableId
),
BlockView.Table.Cell(
@ -1473,7 +1463,6 @@ class BlockViewSearchTextTest {
columnId = columnId2,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(1),
cellIndex = 2,
tableId = tableId
),
BlockView.Table.Cell(
@ -1485,7 +1474,6 @@ class BlockViewSearchTextTest {
columnId = columnId3,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(2),
cellIndex = 4,
tableId = tableId
),
BlockView.Table.Cell(
@ -1497,7 +1485,6 @@ class BlockViewSearchTextTest {
columnId = columnId1,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(0),
cellIndex = 1,
tableId = tableId
),
BlockView.Table.Cell(
@ -1509,7 +1496,6 @@ class BlockViewSearchTextTest {
columnId = columnId2,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(1),
cellIndex = 3,
tableId = tableId
),
BlockView.Table.Cell(
@ -1521,7 +1507,6 @@ class BlockViewSearchTextTest {
columnId = columnId3,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(2),
cellIndex = 5,
tableId = tableId
)
)
@ -1546,7 +1531,7 @@ class BlockViewSearchTextTest {
id = tableId,
cells = expectedCells,
columns = columns,
rowCount = 2,
rows = rows,
isSelected = false,
selectedCellsIds = emptyList()
)

View file

@ -330,6 +330,8 @@ fun StubTwoRowsThreeColumnsSimpleTable(
textR2C1: String = MockDataFactory.randomString(),
textR2C2: String = MockDataFactory.randomString(),
textR2C3: String = MockDataFactory.randomString(),
tab: BlockView.Table.Tab = BlockView.Table.Tab.CELL,
selectedCellsIds: List<Id> = emptyList()
): BlockView.Table {
val row1Block1 = StubParagraph(id = "$rowId1-$columnId1", text = textR1C1)
@ -349,7 +351,6 @@ fun StubTwoRowsThreeColumnsSimpleTable(
columnId = columnId1,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(0),
cellIndex = 0,
tableId = tableId
),
BlockView.Table.Cell(
@ -361,7 +362,6 @@ fun StubTwoRowsThreeColumnsSimpleTable(
columnId = columnId2,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(1),
cellIndex = 2,
tableId = tableId
),
BlockView.Table.Cell(
@ -373,7 +373,6 @@ fun StubTwoRowsThreeColumnsSimpleTable(
columnId = columnId3,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(2),
cellIndex = 4,
tableId = tableId
),
BlockView.Table.Cell(
@ -385,7 +384,6 @@ fun StubTwoRowsThreeColumnsSimpleTable(
columnId = columnId1,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(0),
cellIndex = 1,
tableId = tableId
),
BlockView.Table.Cell(
@ -397,7 +395,6 @@ fun StubTwoRowsThreeColumnsSimpleTable(
columnId = columnId2,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(1),
cellIndex = 3,
tableId = tableId
),
BlockView.Table.Cell(
@ -409,27 +406,93 @@ fun StubTwoRowsThreeColumnsSimpleTable(
columnId = columnId3,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(2),
cellIndex = 5,
tableId = tableId
)
)
val columns = listOf(
BlockView.Table.Column(id = columnId1, background = ThemeColor.DEFAULT),
BlockView.Table.Column(id = columnId2, background = ThemeColor.DEFAULT),
BlockView.Table.Column(id = columnId3, background = ThemeColor.DEFAULT)
BlockView.Table.ColumnId(value = columnId1),
BlockView.Table.ColumnId(value = columnId2),
BlockView.Table.ColumnId(value = columnId3),
)
val rows = listOf(
BlockView.Table.RowId(value = rowId1),
BlockView.Table.RowId(value = rowId2)
)
return BlockView.Table(
id = tableId,
cells = cells,
columns = columns,
rowCount = 2,
rows = rows,
isSelected = false,
selectedCellsIds = emptyList()
selectedCellsIds = selectedCellsIds,
tab = tab
)
}
fun StubTableView(
tableId: String = MockDataFactory.randomUuid(),
rowSize: Int,
columnSize: Int,
tab: BlockView.Table.Tab = BlockView.Table.Tab.CELL,
selectedCellsIds: List<Id> = emptyList()
): BlockView.Table {
val columns = mutableListOf<BlockView.Table.ColumnId>()
val rows = mutableListOf<BlockView.Table.RowId>()
val cells = mutableListOf<BlockView.Table.Cell>()
for (i in 0 until rowSize) {
for (j in 0 until columnSize) {
val columnId = BlockView.Table.ColumnId(value = "columnId$j")
val rowId = BlockView.Table.RowId(value = "rowId$i")
val cell = StubCellView(
rowId = "rowId$i",
rowIndex = BlockView.Table.RowIndex(i),
columnId = "columnId$j",
columnIndex = BlockView.Table.ColumnIndex(j),
block = StubParagraphView(
id = "rowId$i-columnId$j",
text = MockDataFactory.randomString()
),
tableId = tableId
)
rows.add(rowId)
columns.add(columnId)
cells.add(cell)
}
}
return BlockView.Table(
id = tableId,
cells = cells,
columns = columns,
rows = rows,
isSelected = false,
selectedCellsIds = selectedCellsIds,
tab = tab
)
}
fun StubCellView(
rowId: Id,
rowIndex: BlockView.Table.RowIndex,
columnId: Id,
columnIndex: BlockView.Table.ColumnIndex,
isHeader: Boolean = false,
block: BlockView.Text.Paragraph?,
tableId: Id
) = BlockView.Table.Cell(
rowId = rowId,
rowIndex = rowIndex,
columnId = columnId,
columnIndex = columnIndex,
isHeader = isHeader,
block = block,
tableId = tableId
)
fun StubPattern(
query: String
): Pattern {

View file

@ -69,7 +69,6 @@ class TableBlockTest {
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(0),
block = null,
cellIndex = 0,
tableId = tableId
),
BlockView.Table.Cell(
@ -81,7 +80,6 @@ class TableBlockTest {
columnId = columnId2,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(1),
cellIndex = 2,
tableId = tableId
),
BlockView.Table.Cell(
@ -93,7 +91,6 @@ class TableBlockTest {
columnId = columnId3,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(2),
cellIndex = 4,
tableId = tableId
),
BlockView.Table.Cell(
@ -102,7 +99,6 @@ class TableBlockTest {
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(3),
block = null,
cellIndex = 6,
tableId = tableId
)
)
@ -114,7 +110,6 @@ class TableBlockTest {
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(0),
block = null,
cellIndex = 0,
tableId = tableId
),
BlockView.Table.Cell(
@ -126,7 +121,6 @@ class TableBlockTest {
columnId = columnId2,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(1),
cellIndex = 2,
tableId = tableId
),
BlockView.Table.Cell(
@ -138,7 +132,6 @@ class TableBlockTest {
columnId = columnId3,
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(2),
cellIndex = 4,
tableId = tableId
),
BlockView.Table.Cell(
@ -147,18 +140,19 @@ class TableBlockTest {
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(3),
block = null,
cellIndex = 6,
tableId = tableId
)
)
val columns = listOf(
BlockView.Table.Column(id = columnId1, background = ThemeColor.DEFAULT),
BlockView.Table.Column(id = columnId2, background = ThemeColor.DEFAULT),
BlockView.Table.Column(id = columnId3, background = ThemeColor.DEFAULT),
BlockView.Table.Column(id = columnId4, background = ThemeColor.DEFAULT)
BlockView.Table.ColumnId(value = columnId1),
BlockView.Table.ColumnId(value = columnId2),
BlockView.Table.ColumnId(value = columnId3),
BlockView.Table.ColumnId(value = columnId4)
)
val rows = listOf(BlockView.Table.RowId(value = rowId1))
scenario.onFragment {
it.view?.updateLayoutParams {
width = 1200
@ -170,7 +164,7 @@ class TableBlockTest {
id = tableId,
cells = cells,
columns = columns,
rowCount = 1,
rows = rows,
isSelected = false,
selectedCellsIds = emptyList()
)
@ -202,7 +196,7 @@ class TableBlockTest {
id = tableId,
cells = cellsNew,
columns = columns,
rowCount = 1,
rows = rows,
isSelected = false,
selectedCellsIds = emptyList()
)

View file

@ -247,12 +247,22 @@ sealed class ControlPanelMachine {
}
sealed class SimpleTableWidget : Event() {
data class Show(
data class ShowCellTab(
val tableId: Id,
val cells: List<BlockView.Table.Cell>,
val cellItems: List<SimpleTableWidgetItem> = emptyList(),
val cellSize: Int
) : SimpleTableWidget()
data class ShowColumnTab(
val tableId: Id,
val columnItems: List<SimpleTableWidgetItem> = emptyList(),
val columnsSize: Int
) : SimpleTableWidget()
data class ShowRowTab(
val tableId: Id,
val rowItems: List<SimpleTableWidgetItem> = emptyList(),
val columnItems: List<SimpleTableWidgetItem> = emptyList()
val rowsSize: Int
) : SimpleTableWidget()
data class Hide(val tableId: Id) : SimpleTableWidget()
@ -1012,47 +1022,44 @@ sealed class ControlPanelMachine {
event: Event.SimpleTableWidget,
state: ControlPanelState
): ControlPanelState = when (event) {
is Event.SimpleTableWidget.Show -> {
state.copy(
simpleTableWidget = state.simpleTableWidget.copy(
isVisible = true,
tableId = event.tableId,
cells = event.cells,
cellItems = event.cellItems,
rowItems = event.rowItems,
columnItems = event.columnItems
),
cellsSelectTopWidget = state.cellsSelectTopWidget.copy(
isVisible = true,
count = event.cells.size
),
mainToolbar = Toolbar.Main.reset(),
styleColorBackgroundToolbar = Toolbar.Styling.ColorBackground.reset(),
styleExtraToolbar = Toolbar.Styling.Extra.reset(),
styleTextToolbar = Toolbar.Styling.reset(),
styleBackgroundToolbar = Toolbar.Styling.Background.reset(),
navigationToolbar = Toolbar.Navigation.reset(),
slashWidget = Toolbar.SlashWidget.reset(),
mentionToolbar = Toolbar.MentionToolbar.reset(),
multiSelect = Toolbar.MultiSelect.reset()
)
}
is Event.SimpleTableWidget.Hide -> {
state.copy(
init().copy(
navigationToolbar = state.navigationToolbar.copy(
isVisible = true
),
multiSelect = Toolbar.MultiSelect.reset(),
mainToolbar = Toolbar.Main.reset(),
styleColorBackgroundToolbar = Toolbar.Styling.ColorBackground.reset(),
styleExtraToolbar = Toolbar.Styling.Extra.reset(),
styleTextToolbar = Toolbar.Styling.reset(),
styleBackgroundToolbar = Toolbar.Styling.Background.reset(),
simpleTableWidget = state.simpleTableWidget.copy(
isVisible = false,
tableId = event.tableId
),
cellsSelectTopWidget = Toolbar.CellSelection.reset()
)
)
}
is Event.SimpleTableWidget.ShowCellTab -> {
init().copy(
simpleTableWidget = Toolbar.SimpleTableWidget(
isVisible = true,
tableId = event.tableId,
cellItems = event.cellItems,
selectedCount = event.cellSize,
tab = BlockView.Table.Tab.CELL
)
)
}
is Event.SimpleTableWidget.ShowColumnTab -> {
init().copy(
simpleTableWidget = Toolbar.SimpleTableWidget(
isVisible = true,
tableId = event.tableId,
columnItems = event.columnItems,
selectedCount = event.columnsSize,
tab = BlockView.Table.Tab.COLUMN
)
)
}
is Event.SimpleTableWidget.ShowRowTab -> {
init().copy(
simpleTableWidget = Toolbar.SimpleTableWidget(
isVisible = true,
tableId = event.tableId,
rowItems = event.rowItems,
selectedCount = event.rowsSize,
tab = BlockView.Table.Tab.ROW
)
)
}
}
@ -1070,7 +1077,7 @@ sealed class ControlPanelMachine {
Timber.i(
"REDUCER, EVENT:${
event::class.qualifiedName?.substringAfter("Event.")
}"
}:\n${event.toPrettyString()}"
)
}
}

View file

@ -78,8 +78,21 @@ interface Editor {
/**
* Editor in simple table menu mode.
* @property[tableId] - the id of the table block for which the menu is shown
* and it is possible to select items only from this table.
* Clicks on cells in other tabled blocks will be omitted.
* @property[initialTargets] - last selected cells for the Tab Cell,
* when changing Tabs will be used as selected state
* @property[targets] - all of these cells are currently selected,
* cell allocation is based on the given list
* @property[tab] - currently selected Tab
*/
data class Table(val tableId: Id, var targets: Set<Id>) : Mode()
data class Table(
val tableId: Id,
var initialTargets: Set<Id>,
val tab: BlockView.Table.Tab,
var targets: Set<Id>,
) : Mode()
}
class Storage {

View file

@ -153,9 +153,16 @@ import com.anytypeio.anytype.presentation.editor.render.BlockViewRenderer
import com.anytypeio.anytype.presentation.editor.render.DefaultBlockViewRenderer
import com.anytypeio.anytype.presentation.editor.search.search
import com.anytypeio.anytype.presentation.editor.selection.SelectionStateHolder
import com.anytypeio.anytype.presentation.editor.selection.getAllSelectedColumns
import com.anytypeio.anytype.presentation.editor.selection.getAllSelectedRows
import com.anytypeio.anytype.presentation.editor.selection.getIdsInColumn
import com.anytypeio.anytype.presentation.editor.selection.getIdsInRow
import com.anytypeio.anytype.presentation.editor.selection.getSimpleTableWidgetColumn
import com.anytypeio.anytype.presentation.editor.selection.getSimpleTableWidgetItems
import com.anytypeio.anytype.presentation.editor.selection.getSimpleTableWidgetRow
import com.anytypeio.anytype.presentation.editor.selection.toggleTableMode
import com.anytypeio.anytype.presentation.editor.selection.updateTableBlockSelection
import com.anytypeio.anytype.presentation.editor.selection.updateTableBlockTab
import com.anytypeio.anytype.presentation.editor.template.EditorTemplateDelegate
import com.anytypeio.anytype.presentation.editor.template.SelectTemplateEvent
import com.anytypeio.anytype.presentation.editor.template.SelectTemplateState
@ -3843,7 +3850,7 @@ class EditorViewModel(
)
proceedWithClickingOnCellInTableMode(
cell = clicked.cell,
tableId = cellTableId
modeTable = m
)
} else {
Timber.e("Cell is from the different table, amend click")
@ -3863,7 +3870,7 @@ class EditorViewModel(
if (cellTableId == modeTableId) {
proceedWithClickingOnCellInTableMode(
cell = clicked.cell,
tableId = cellTableId
modeTable = m
)
} else {
Timber.e("Cell is from the different table, amend click")
@ -5388,7 +5395,10 @@ class EditorViewModel(
}
fun onExitMultiSelectModeClicked() {
proceedWithExitingMultiSelectMode()
when (mode) {
is EditorMode.Table -> proceedWithExitingTableMode()
else -> proceedWithExitingMultiSelectMode()
}
}
private fun proceedWithExitingMultiSelectMode() {
@ -6057,12 +6067,6 @@ class EditorViewModel(
//endregion
//region SIMPLE TABLES
fun onCellSelectionTopToolbarDoneButtonClick() {
Timber.d("onCellSelectionTopToolbarDoneButtonClick, ")
proceedWithExitingTableMode()
}
fun onHideSimpleTableWidget() {
Timber.d("onHideSimpleTableWidget, ")
proceedWithExitingTableMode()
@ -6109,6 +6113,36 @@ class EditorViewModel(
)
)
}
SimpleTableWidgetItem.Tab.Cell -> {
val currentMode = mode
if (currentMode is EditorMode.Table) {
proceedWithUpdateTabInTableMode(
tableId = currentMode.tableId,
tab = BlockView.Table.Tab.CELL,
modeTable = currentMode
)
}
}
SimpleTableWidgetItem.Tab.Row -> {
val currentMode = mode
if (currentMode is EditorMode.Table) {
proceedWithUpdateTabInTableMode(
tableId = currentMode.tableId,
tab = BlockView.Table.Tab.ROW,
modeTable = currentMode
)
}
}
SimpleTableWidgetItem.Tab.Column -> {
val currentMode = mode
if (currentMode is EditorMode.Table) {
proceedWithUpdateTabInTableMode(
tableId = currentMode.tableId,
tab = BlockView.Table.Tab.COLUMN,
modeTable = currentMode
)
}
}
else -> Unit
}
}
@ -6120,7 +6154,12 @@ class EditorViewModel(
viewModelScope.launch {
clearSelections()
toggleSelection(target = cell.getId())
mode = EditorMode.Table(tableId = cell.tableId, targets = currentSelection())
mode = EditorMode.Table(
tableId = cell.tableId,
targets = currentSelection(),
initialTargets = currentSelection(),
tab = BlockView.Table.Tab.CELL
)
orchestrator.stores.focus.update(Editor.Focus.empty())
orchestrator.stores.views.update(
@ -6131,12 +6170,10 @@ class EditorViewModel(
)
renderCommand.send(Unit)
controlPanelInteractor.onEvent(
ControlPanelMachine.Event.SimpleTableWidget.Show(
cellItems = listOf(cell).getSimpleTableWidgetItems(),
rowItems = emptyList(),
columnItems = emptyList(),
cells = listOf(cell),
tableId = cell.tableId
ControlPanelMachine.Event.SimpleTableWidget.ShowCellTab(
cellItems = getSimpleTableWidgetItems(),
tableId = cell.tableId,
cellSize = currentSelection().size
)
)
}
@ -6172,18 +6209,76 @@ class EditorViewModel(
}
private fun proceedWithClickingOnCellInTableMode(
tableId: Id,
cell: BlockView.Table.Cell
cell: BlockView.Table.Cell,
modeTable: EditorMode.Table
) {
toggleSelection(target = cell.getId())
(mode as? EditorMode.Table)?.targets = currentSelection()
val tableBlock = views.find { it.id == modeTable.tableId } as BlockView.Table
val event = when (modeTable.tab) {
BlockView.Table.Tab.CELL -> {
toggleSelection(target = cell.getId())
mode = modeTable.copy(
initialTargets = currentSelection(),
targets = currentSelection()
)
ControlPanelMachine.Event.SimpleTableWidget.ShowCellTab(
cellItems = getSimpleTableWidgetItems(),
tableId = cell.tableId,
cellSize = currentSelection().size
)
}
BlockView.Table.Tab.COLUMN -> {
val columnCellIds = tableBlock.getIdsInColumn(index = cell.columnIndex)
if (isSelected(cell.getId())) {
unselect(columnCellIds)
} else {
select(columnCellIds)
}
val selectedColumns = mutableSetOf<Id>()
tableBlock.cells.forEach {
if (currentSelection().contains(it.getId())) {
selectedColumns.add(it.columnId)
}
}
mode = modeTable.copy(
targets = currentSelection()
)
ControlPanelMachine.Event.SimpleTableWidget.ShowColumnTab(
columnItems = getSimpleTableWidgetColumn(),
tableId = cell.tableId,
columnsSize = selectedColumns.size
)
}
BlockView.Table.Tab.ROW -> {
val rowCellIds = tableBlock.getIdsInRow(index = cell.rowIndex)
if (isSelected(cell.getId())) {
unselect(rowCellIds)
} else {
select(rowCellIds)
}
val selectedRows = mutableSetOf<Id>()
tableBlock.cells.forEach {
if (currentSelection().contains(it.getId())) {
selectedRows.add(it.rowId)
}
}
mode = modeTable.copy(
targets = currentSelection()
)
ControlPanelMachine.Event.SimpleTableWidget.ShowRowTab(
rowItems = getSimpleTableWidgetRow(),
tableId = cell.tableId,
rowsSize = selectedRows.size
)
}
}
if (currentSelection().isEmpty()) {
proceedWithExitingTableMode()
} else {
val tableBlock = views.find { it.id == tableId } as BlockView.Table
val selectedCells = tableBlock.cells.mapNotNull {
if (currentSelection().contains(it.getId())) it else null
}
viewModelScope.launch {
orchestrator.stores.views.update(
views.updateTableBlockSelection(
@ -6192,16 +6287,85 @@ class EditorViewModel(
)
)
renderCommand.send(Unit)
controlPanelInteractor.onEvent(event)
}
controlPanelInteractor.onEvent(
ControlPanelMachine.Event.SimpleTableWidget.Show(
cellItems = listOf(cell).getSimpleTableWidgetItems(),
rowItems = emptyList(),
columnItems = emptyList(),
cells = selectedCells,
tableId = cell.tableId
}
}
private fun proceedWithUpdateTabInTableMode(
tableId: Id,
tab: BlockView.Table.Tab,
modeTable: EditorMode.Table
) {
val tableBlock = views.find { it.id == tableId } as? BlockView.Table
if (tableBlock == null) {
Timber.e("Couldn't find table block by id:$tableId")
return
}
val event = when (tab) {
BlockView.Table.Tab.CELL -> {
clearSelections()
select(modeTable.initialTargets.toList())
mode = modeTable.copy(
initialTargets = currentSelection(),
targets = currentSelection(),
tab = BlockView.Table.Tab.CELL
)
)
ControlPanelMachine.Event.SimpleTableWidget.ShowCellTab(
cellItems = getSimpleTableWidgetItems(),
tableId = tableId,
cellSize = currentSelection().size
)
}
BlockView.Table.Tab.COLUMN -> {
clearSelections()
select(modeTable.initialTargets.toList())
val selectedColumns = tableBlock.getAllSelectedColumns(
selectedCellsIds = currentSelection()
)
select(selectedColumns.columns)
mode = modeTable.copy(
targets = currentSelection(),
tab = BlockView.Table.Tab.COLUMN
)
ControlPanelMachine.Event.SimpleTableWidget.ShowColumnTab(
columnItems = getSimpleTableWidgetColumn(),
tableId = tableId,
columnsSize = selectedColumns.count
)
}
BlockView.Table.Tab.ROW -> {
clearSelections()
select(modeTable.initialTargets.toList())
val selectedRows = tableBlock.getAllSelectedRows(
selectedCellsIds = currentSelection()
)
select(selectedRows.rows)
mode = modeTable.copy(
targets = currentSelection(),
tab = BlockView.Table.Tab.ROW
)
ControlPanelMachine.Event.SimpleTableWidget.ShowRowTab(
rowItems = getSimpleTableWidgetRow(),
tableId = tableId,
rowsSize = selectedRows.count
)
}
}
if (currentSelection().isEmpty()) {
proceedWithExitingTableMode()
} else {
viewModelScope.launch {
orchestrator.stores.views.update(
views.updateTableBlockTab(
tableId = tableId,
selection = currentSelection().toList(),
tab = tab
)
)
renderCommand.send(Unit)
controlPanelInteractor.onEvent(event)
}
}
}

View file

@ -31,7 +31,6 @@ data class ControlPanelState(
val searchToolbar: Toolbar.SearchToolbar = Toolbar.SearchToolbar.reset(),
val objectTypesToolbar: Toolbar.ObjectTypes = Toolbar.ObjectTypes.reset(),
val simpleTableWidget: Toolbar.SimpleTableWidget = Toolbar.SimpleTableWidget.reset(),
val cellsSelectTopWidget: Toolbar.CellSelection = Toolbar.CellSelection.reset()
) {
sealed class Toolbar {
@ -266,31 +265,21 @@ data class ControlPanelState(
data class SimpleTableWidget(
override val isVisible: Boolean,
val tableId: Id,
val cells: List<BlockView.Table.Cell>,
val cellItems: List<SimpleTableWidgetItem> = emptyList(),
val rowItems: List<SimpleTableWidgetItem> = emptyList(),
val columnItems: List<SimpleTableWidgetItem> = emptyList()
val columnItems: List<SimpleTableWidgetItem> = emptyList(),
val selectedCount: Int,
val tab: BlockView.Table.Tab
) : Toolbar() {
companion object {
fun reset(): SimpleTableWidget = SimpleTableWidget(
isVisible = false,
tableId = "",
cells = emptyList(),
cellItems = emptyList(),
rowItems = emptyList(),
columnItems = emptyList()
)
}
}
data class CellSelection(
override val isVisible: Boolean,
val count: Int
) : Toolbar() {
companion object {
fun reset(): CellSelection = CellSelection(
isVisible = false,
count = 0
columnItems = emptyList(),
selectedCount = 0,
tab = BlockView.Table.Tab.CELL
)
}
}
@ -344,8 +333,7 @@ data class ControlPanelState(
),
slashWidget = Toolbar.SlashWidget.reset(),
objectTypesToolbar = Toolbar.ObjectTypes.reset(),
simpleTableWidget = Toolbar.SimpleTableWidget.reset(),
cellsSelectTopWidget = Toolbar.CellSelection.reset()
simpleTableWidget = Toolbar.SimpleTableWidget.reset()
)
}
}

View file

@ -649,8 +649,8 @@ fun List<BlockView>.highlight(
view.copy(searchFields = highlighter(fields))
}
is BlockView.Table -> {
val cells = view.cells
view.copy(cells = cells.map { cell -> cell.addHighlight(highlighter) })
val updatedCells = view.cells.map { it.addHighlight(highlighter) }
view.copy(cells = updatedCells)
}
else -> view.also { check(view !is BlockView.Searchable) }
}

View file

@ -1320,15 +1320,14 @@ sealed class BlockView : ViewType {
override val id: String,
override val isSelected: Boolean,
val background: ThemeColor = ThemeColor.DEFAULT,
val columns: List<Column>,
val columns: List<ColumnId>,
val rows: List<RowId>,
val cells: List<Cell>,
val rowCount: Int,
val selectedCellsIds: List<Id>
val selectedCellsIds: List<Id>,
val tab: Tab = Tab.CELL
) : BlockView(), Selectable {
override fun getViewType(): Int = HOLDER_TABLE
data class Column(val id: String, val background: ThemeColor)
data class Cell(
val rowId: Id,
val rowIndex: RowIndex,
@ -1336,8 +1335,7 @@ sealed class BlockView : ViewType {
val columnIndex: ColumnIndex,
val isHeader: Boolean = false,
val block: Text.Paragraph?,
val tableId: Id,
val cellIndex: Int
val tableId: Id
) {
fun getId() = "$rowId-$columnId"
}
@ -1350,13 +1348,18 @@ sealed class BlockView : ViewType {
var top: Boolean,
var right: Boolean,
var bottom: Boolean,
var cellIndex: Int
)
@JvmInline
value class RowId(val value: String)
@JvmInline
value class RowIndex(val value: Int)
@JvmInline
value class ColumnId(val value: String)
@JvmInline
value class ColumnIndex(val value: Int)
enum class Tab { CELL, COLUMN, ROW }
}
}

View file

@ -34,4 +34,10 @@ sealed class SimpleTableWidgetItem {
object Color : Row()
object Style : Row()
}
sealed class Tab : SimpleTableWidgetItem() {
object Cell : Tab()
object Row : Tab()
object Column : Tab()
}
}

View file

@ -1974,17 +1974,19 @@ class DefaultBlockViewRenderer @Inject constructor(
): BlockView.Table {
var cells: List<BlockView.Table.Cell> = emptyList()
var columns: List<BlockView.Table.Column> = emptyList()
var columnsIds: List<BlockView.Table.ColumnId> = emptyList()
var rowsIds: List<BlockView.Table.RowId> = emptyList()
var rowCount = 0
blocks.getValue(block.id).forEach { container ->
val containerContent = container.content
if (containerContent !is Content.Layout) return@forEach
if (containerContent.type == Content.Layout.Type.TABLE_COLUMN) {
columns = blocks.getValue(container.id).map { tableColumn(it) }
columnsIds = blocks.getValue(container.id).map { BlockView.Table.ColumnId(it.id) }
}
if (containerContent.type == Content.Layout.Type.TABLE_ROW) {
val rows = blocks.getValue(container.id)
rowsIds = rows.map { BlockView.Table.RowId(it.id) }
rowCount = rows.size
cells = tableCells(
mode = mode,
@ -1993,7 +1995,7 @@ class DefaultBlockViewRenderer @Inject constructor(
details = details,
selection = selection,
rows = rows,
columns = columns,
columnIds = columnsIds,
blocks = blocks,
tableId = block.id
)
@ -2001,9 +2003,9 @@ class DefaultBlockViewRenderer @Inject constructor(
}
return BlockView.Table(
id = block.id,
columns = columns,
columns = columnsIds,
rows = rowsIds,
cells = cells,
rowCount = rowCount,
isSelected = checkIfSelected(
mode = mode,
block = block,
@ -2018,7 +2020,7 @@ class DefaultBlockViewRenderer @Inject constructor(
tableId: Id,
blocks: Map<String, List<Block>>,
rows: List<Block>,
columns: List<BlockView.Table.Column>,
columnIds: List<BlockView.Table.ColumnId>,
mode: EditorMode,
focus: Focus,
indent: Int,
@ -2026,10 +2028,10 @@ class DefaultBlockViewRenderer @Inject constructor(
selection: Set<Id>
): List<BlockView.Table.Cell> {
val cells = mutableListOf<BlockView.Table.Cell>()
columns.mapIndexed { columnIndex, column ->
columnIds.mapIndexed { columnIndex, columnId ->
rows.forEachIndexed { rowIndex, row ->
val isHeader = (row.content as? Content.TableRow)?.isHeader ?: false
val cellId = "${row.id}-${column.id}"
val cellId = "${row.id}-${columnId.value}"
val rowsChildren = blocks.getValue(row.id)
val block = rowsChildren.firstOrNull { it.id == cellId }
val paragraph = if (block != null) {
@ -2054,17 +2056,15 @@ class DefaultBlockViewRenderer @Inject constructor(
} else {
null
}
val cellIndex = columnIndex*rows.size + rowIndex
cells.add(
BlockView.Table.Cell(
rowId = row.id,
rowIndex = BlockView.Table.RowIndex(rowIndex),
columnId = column.id,
columnId = columnId.value,
columnIndex = BlockView.Table.ColumnIndex(columnIndex),
isHeader = isHeader,
tableId = tableId,
block = paragraph,
cellIndex = cellIndex
block = paragraph
)
)
}
@ -2072,13 +2072,6 @@ class DefaultBlockViewRenderer @Inject constructor(
return cells
}
private fun tableColumn(block: Block): BlockView.Table.Column {
return BlockView.Table.Column(
id = block.id,
background = block.parseThemeBackgroundColor()
)
}
private fun relation(
ctx: Id,
block: Block,

View file

@ -9,6 +9,7 @@ interface SelectionStateHolder {
fun toggleSelection(target: Id)
fun select(target: Id)
fun unselect(target: Id)
fun unselect(targets: List<Id>)
fun clearSelections()
fun currentSelection(): Set<Id>
@ -40,6 +41,12 @@ interface SelectionStateHolder {
memory[target] = false
}
override fun unselect(targets: List<Id>) {
targets.forEach { target ->
memory[target] = false
}
}
override fun clearSelections() {
memory.clear()
}

View file

@ -4,13 +4,15 @@ import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.editor.editor.table.SimpleTableWidgetItem
typealias CellSelection = BlockView.Table.CellSelection
fun updateTableCellsSelectionState(
cellId: Id,
rowIndex: BlockView.Table.RowIndex,
columnIndex: BlockView.Table.ColumnIndex,
selectionState: List<BlockView.Table.CellSelection>,
cellIndex: Int
): List<BlockView.Table.CellSelection> {
selectionState: Map<Int, BlockView.Table.CellSelection>,
rowsSize: Int
): Map<Int, BlockView.Table.CellSelection> {
val latestSelection = BlockView.Table.CellSelection(
cellId = cellId,
@ -20,44 +22,14 @@ fun updateTableCellsSelectionState(
top = true,
right = true,
bottom = true,
cellIndex = cellIndex
)
val latestSelectionIndex = selectionState.indexOfFirst { it.cellId == cellId }
return if (latestSelectionIndex != -1) {
//Latest selection is already in selection state - move on to deselecting a cell
val newState = selectionState.toMutableList()
newState.removeAt(latestSelectionIndex)
newState.restoreBordersVisibility(deselectedSelection = latestSelection)
newState
val resultMap = selectionState.toMutableMap()
val cellIndex = columnIndex.value * rowsSize + rowIndex.value
return if (selectionState.contains(cellIndex)) {
resultMap.remove(cellIndex)
resultMap.restoreBordersVisibility(deselectedSelection = latestSelection)
} else {
//Latest selection is not in selection state - move on to adding new selection to state
selectionState.forEach { selection ->
if (isLeftBorderMatch(cell1 = selection, cell2 = latestSelection)) {
selection.left = false
latestSelection.right = false
}
if (isRightBorderMatch(cell1 = selection, cell2 = latestSelection)) {
selection.right = false
latestSelection.left = false
}
if (isTopBorderMatch(cell1 = selection, cell2 = latestSelection)) {
selection.top = false
latestSelection.bottom = false
}
if (isBottomBorderMatch(cell1 = selection, cell2 = latestSelection)) {
selection.bottom = false
latestSelection.top = false
}
}
val newState = mutableListOf<BlockView.Table.CellSelection>().apply {
addAll(selectionState)
add(latestSelection)
}
newState
resultMap.addCellSelection(newSelection = latestSelection, cellIndex = cellIndex)
}
}
@ -65,22 +37,53 @@ fun updateTableCellsSelectionState(
* In the case of deselecting the cell it is necessary
* to restore the borders of the remaining selected cells
*/
fun List<BlockView.Table.CellSelection>.restoreBordersVisibility(deselectedSelection: BlockView.Table.CellSelection): List<BlockView.Table.CellSelection> =
map { cellSelection ->
if (isLeftBorderMatch(cell1 = cellSelection, cell2 = deselectedSelection)) {
cellSelection.left = true
fun Map<Int, CellSelection>.restoreBordersVisibility(deselectedSelection: CellSelection): Map<Int, CellSelection> {
return this.mapValues {
if (isLeftBorderMatch(cell1 = it.value, cell2 = deselectedSelection)) {
it.value.left = true
}
if (isRightBorderMatch(cell1 = cellSelection, cell2 = deselectedSelection)) {
cellSelection.right = true
if (isRightBorderMatch(cell1 = it.value, cell2 = deselectedSelection)) {
it.value.right = true
}
if (isTopBorderMatch(cell1 = cellSelection, cell2 = deselectedSelection)) {
cellSelection.top = true
if (isTopBorderMatch(cell1 = it.value, cell2 = deselectedSelection)) {
it.value.top = true
}
if (isBottomBorderMatch(cell1 = cellSelection, cell2 = deselectedSelection)) {
cellSelection.bottom = true
if (isBottomBorderMatch(cell1 = it.value, cell2 = deselectedSelection)) {
it.value.bottom = true
}
cellSelection
it.value
}
}
fun MutableMap<Int, CellSelection>.addCellSelection(
newSelection: CellSelection,
cellIndex: Int
): Map<Int, CellSelection> {
this.mapValues {
if (isLeftBorderMatch(cell1 = it.value, cell2 = newSelection)) {
it.value.left = false
newSelection.right = false
}
if (isRightBorderMatch(cell1 = it.value, cell2 = newSelection)) {
it.value.right = false
newSelection.left = false
}
if (isTopBorderMatch(cell1 = it.value, cell2 = newSelection)) {
it.value.top = false
newSelection.bottom = false
}
if (isBottomBorderMatch(cell1 = it.value, cell2 = newSelection)) {
it.value.bottom = false
newSelection.top = false
}
}
this[cellIndex] = newSelection
return this
}
/**
* Check that the left border of the first cell coincides with the right border of the second cell
@ -368,11 +371,90 @@ fun List<BlockView>.updateTableBlockSelection(tableId: Id, selection: List<Id>):
}
}
fun List<BlockView.Table.Cell>.getSimpleTableWidgetItems(): List<SimpleTableWidgetItem> {
fun List<BlockView>.updateTableBlockTab(
tableId: Id,
selection: List<Id>,
tab: BlockView.Table.Tab
): List<BlockView> =
map {
if (it.id == tableId && it is BlockView.Table) {
it.copy(
selectedCellsIds = selection,
tab = tab
)
} else {
it
}
}
fun getSimpleTableWidgetItems(): List<SimpleTableWidgetItem> {
return listOf(
SimpleTableWidgetItem.Cell.ClearContents,
SimpleTableWidgetItem.Cell.Color,
SimpleTableWidgetItem.Cell.Style,
SimpleTableWidgetItem.Cell.ClearStyle
)
}
}
fun getSimpleTableWidgetColumn(): List<SimpleTableWidgetItem> {
return listOf(
SimpleTableWidgetItem.Column.InsertLeft,
SimpleTableWidgetItem.Column.InsertRight,
SimpleTableWidgetItem.Column.MoveLeft,
SimpleTableWidgetItem.Column.MoveRight,
SimpleTableWidgetItem.Column.ClearContents,
SimpleTableWidgetItem.Column.Color,
SimpleTableWidgetItem.Column.Style,
)
}
fun getSimpleTableWidgetRow(): List<SimpleTableWidgetItem> {
return listOf(
SimpleTableWidgetItem.Row.InsertAbove,
SimpleTableWidgetItem.Row.InsertBelow,
SimpleTableWidgetItem.Row.MoveDown,
SimpleTableWidgetItem.Row.MoveUp,
SimpleTableWidgetItem.Row.ClearContents,
SimpleTableWidgetItem.Row.Color,
SimpleTableWidgetItem.Row.Style,
)
}
fun BlockView.Table.getIdsInRow(index: BlockView.Table.RowIndex): List<Id> =
this.cells.filter { it.rowIndex == index }.map { it.getId() }
fun BlockView.Table.getIdsInColumn(index: BlockView.Table.ColumnIndex): List<Id> =
this.cells.filter { it.columnIndex == index }.map { it.getId() }
fun BlockView.Table.getAllSelectedColumns(selectedCellsIds: Set<Id>): SelectedColumns {
val selectedCells = cells.filter { selectedCellsIds.contains(it.getId()) }
val selectedColumns = mutableSetOf<Id>()
val selectedColumnsIndexes = mutableSetOf<Int>()
selectedCells.forEach { cell ->
selectedColumnsIndexes.add(cell.columnIndex.value)
val column = getIdsInColumn(cell.columnIndex)
selectedColumns.addAll(column)
}
return SelectedColumns(
columns = selectedColumns.toList(),
count = selectedColumnsIndexes.size
)
}
fun BlockView.Table.getAllSelectedRows(selectedCellsIds: Set<Id>): SelectedRows {
val selectedCells = cells.filter { selectedCellsIds.contains(it.getId()) }
val selectedRows = mutableSetOf<Id>()
val selectedRowsIndexes = mutableSetOf<Int>()
selectedCells.forEach { cell ->
selectedRowsIndexes.add(cell.rowIndex.value)
val row = getIdsInRow(cell.rowIndex)
selectedRows.addAll(row)
}
return SelectedRows(
rows = selectedRows.toList(),
count = selectedRowsIndexes.size
)
}
data class SelectedRows(val rows: List<Id>, val count: Int)
data class SelectedColumns(val columns: List<Id>, val count: Int)

View file

@ -4,24 +4,23 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
class TableCellsSelectionState {
private var memory = listOf<BlockView.Table.CellSelection>()
private var memory = mapOf<Int, CellSelection>()
fun set(cells: List<BlockView.Table.Cell>) {
fun set(cells: List<BlockView.Table.Cell>, rowsSize: Int) {
cells.forEach { cell ->
val currentSelection = current()
memory = updateTableCellsSelectionState(
cellId = cell.getId(),
rowIndex = cell.rowIndex,
columnIndex = cell.columnIndex,
selectionState = currentSelection,
cellIndex = cell.cellIndex
selectionState = current(),
rowsSize = rowsSize
)
}
}
fun clear() {
memory = emptyList()
memory = emptyMap()
}
fun current(): List<BlockView.Table.CellSelection> = memory
fun current(): Map<Int, BlockView.Table.CellSelection> = memory
}

View file

@ -1,7 +1,7 @@
package com.anytypeio.anytype.presentation.editor.editor.ext
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView.Table.CellSelection
import com.anytypeio.anytype.presentation.editor.selection.CellSelection
import com.anytypeio.anytype.presentation.editor.selection.TableCellsSelectionState
import com.anytypeio.anytype.test_utils.MockDataFactory
import org.junit.Test
@ -27,17 +27,17 @@ class TableCellsSelectionStateTest {
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(1),
block = null,
cellIndex = 22,
tableId = tableId
)
)
),
rowsSize = 3
)
val actual = cellsSelectionState.current()
//EXPECTED
val expected = listOf(
CellSelection(
val expected = mapOf(
4 to CellSelection(
cellId = "row1-column1",
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(1),
@ -45,7 +45,6 @@ class TableCellsSelectionStateTest {
top = true,
right = true,
bottom = true,
cellIndex = 22
)
)
@ -70,9 +69,9 @@ class TableCellsSelectionStateTest {
columnIndex = BlockView.Table.ColumnIndex(1),
block = null,
tableId = tableId,
cellIndex = 11
)
)
),
rowsSize = 3
)
//second click on cell row1, column1
@ -84,16 +83,16 @@ class TableCellsSelectionStateTest {
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(1),
block = null,
cellIndex = 11,
tableId = tableId
)
)
),
rowsSize = 3
)
val actual = cellsSelectionState.current()
//EXPECTED
val expected = emptyList<CellSelection>()
val expected = emptyMap<Int, CellSelection>()
//ASSERT
assertEquals(expected, actual)
@ -115,10 +114,10 @@ class TableCellsSelectionStateTest {
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(0),
block = null,
cellIndex = 1,
tableId = tableId
)
)
),
rowsSize = 3
)
//click on cell row1, column2
cellsSelectionState.set(
@ -129,10 +128,10 @@ class TableCellsSelectionStateTest {
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(2),
block = null,
cellIndex = 7,
tableId = tableId
)
)
),
rowsSize = 3
)
//click on cell row2, column0
@ -144,10 +143,10 @@ class TableCellsSelectionStateTest {
rowIndex = BlockView.Table.RowIndex(2),
columnIndex = BlockView.Table.ColumnIndex(0),
block = null,
cellIndex = 2,
tableId = tableId
)
)
),
rowsSize = 3
)
//click on cell row0, column2
@ -159,10 +158,10 @@ class TableCellsSelectionStateTest {
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(2),
block = null,
cellIndex = 6,
tableId = tableId
)
)
),
rowsSize = 3
)
//click on cell row1, column1
@ -174,27 +173,26 @@ class TableCellsSelectionStateTest {
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(1),
block = null,
cellIndex = 4,
tableId = tableId
)
)
),
rowsSize = 3
)
val actual = cellsSelectionState.current()
//EXPECTED
val expected = listOf(
CellSelection(
val expected = mapOf(
1 to CellSelection(
cellId = "row1-column0",
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(0),
left = true,
top = true,
right = false,
bottom = false,
cellIndex = 1
bottom = false
),
CellSelection(
7 to CellSelection(
cellId = "row1-column2",
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(2),
@ -202,9 +200,8 @@ class TableCellsSelectionStateTest {
top = false,
right = true,
bottom = true,
cellIndex = 7
),
CellSelection(
2 to CellSelection(
cellId = "row2-column0",
rowIndex = BlockView.Table.RowIndex(2),
columnIndex = BlockView.Table.ColumnIndex(0),
@ -212,9 +209,8 @@ class TableCellsSelectionStateTest {
top = false,
right = true,
bottom = true,
cellIndex = 2
),
CellSelection(
6 to CellSelection(
cellId = "row0-column2",
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(2),
@ -222,9 +218,8 @@ class TableCellsSelectionStateTest {
top = true,
right = true,
bottom = false,
cellIndex = 6
),
CellSelection(
4 to CellSelection(
cellId = "row1-column1",
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(1),
@ -232,7 +227,6 @@ class TableCellsSelectionStateTest {
top = true,
right = false,
bottom = true,
cellIndex = 4
)
)
@ -250,55 +244,51 @@ class TableCellsSelectionStateTest {
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(1),
block = null,
cellIndex = 4,
tableId = tableId
)
)
),
rowsSize = 3
)
val actual2 = cellsSelectionState.current()
//EXPECTED
val expected2 = listOf(
CellSelection(
val expected2 = mapOf(
1 to CellSelection(
cellId = "row1-column0",
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(0),
left = true,
top = true,
right = true,
bottom = false,
cellIndex = 1
bottom = false
),
CellSelection(
7 to CellSelection(
cellId = "row1-column2",
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(2),
left = true,
top = false,
right = true,
bottom = true,
cellIndex = 7
bottom = true
),
CellSelection(
2 to CellSelection(
cellId = "row2-column0",
rowIndex = BlockView.Table.RowIndex(2),
columnIndex = BlockView.Table.ColumnIndex(0),
left = true,
top = false,
right = true,
bottom = true,
cellIndex = 2
bottom = true
),
CellSelection(
6 to CellSelection(
cellId = "row0-column2",
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(2),
left = true,
top = true,
right = true,
bottom = false,
cellIndex = 6
bottom = false
)
)
@ -316,10 +306,10 @@ class TableCellsSelectionStateTest {
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(2),
block = null,
cellIndex = 6,
tableId = tableId
)
)
),
rowsSize = 3
)
//click on cell row0, column2
cellsSelectionState.set(
@ -330,35 +320,33 @@ class TableCellsSelectionStateTest {
rowIndex = BlockView.Table.RowIndex(2),
columnIndex = BlockView.Table.ColumnIndex(0),
block = null,
cellIndex = 2,
tableId = tableId
)
)
),
rowsSize = 3
)
val actual3 = cellsSelectionState.current()
//EXPECTED
val expected3 = listOf(
CellSelection(
val expected3 = mapOf(
1 to CellSelection(
cellId = "row1-column0",
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(0),
left = true,
top = true,
right = true,
bottom = true,
cellIndex = 1
bottom = true
),
CellSelection(
7 to CellSelection(
cellId = "row1-column2",
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(2),
left = true,
top = true,
right = true,
bottom = true,
cellIndex = 7
bottom = true
)
)

View file

@ -1,22 +1,27 @@
package com.anytypeio.anytype.presentation.editor.editor.table
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.StubHeader
import com.anytypeio.anytype.core_models.StubLayoutColumns
import com.anytypeio.anytype.core_models.StubLayoutRows
import com.anytypeio.anytype.core_models.StubParagraph
import com.anytypeio.anytype.core_models.StubSmartBlock
import com.anytypeio.anytype.core_models.StubTable
import com.anytypeio.anytype.core_models.StubTableCells
import com.anytypeio.anytype.core_models.StubTableColumns
import com.anytypeio.anytype.core_models.StubTableRows
import com.anytypeio.anytype.core_models.StubTitle
import com.anytypeio.anytype.core_models.ext.content
import com.anytypeio.anytype.domain.table.FillTableRow
import com.anytypeio.anytype.presentation.editor.Editor
import com.anytypeio.anytype.presentation.editor.editor.EditorPresentationTestSetup
import com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelState
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.editor.selection.getSimpleTableWidgetColumn
import com.anytypeio.anytype.presentation.editor.selection.getSimpleTableWidgetItems
import com.anytypeio.anytype.presentation.editor.selection.getSimpleTableWidgetRow
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Rule
@ -39,6 +44,8 @@ class EditorTableBlockTest : EditorPresentationTestSetup() {
MockitoAnnotations.openMocks(this)
}
private var tableId = MockDataFactory.randomUuid()
@Test
fun `should not amend second empty cell click`() {
@ -79,7 +86,6 @@ class EditorTableBlockTest : EditorPresentationTestSetup() {
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(1),
block = null,
cellIndex = 0,
tableId = table.id
)
)
@ -92,7 +98,6 @@ class EditorTableBlockTest : EditorPresentationTestSetup() {
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(0),
block = null,
cellIndex = 1,
tableId = table.id
)
)
@ -150,7 +155,6 @@ class EditorTableBlockTest : EditorPresentationTestSetup() {
id = cells[0].id,
text = cells[0].content.asText().text
),
cellIndex = 0,
tableId = table.id
)
)
@ -166,7 +170,6 @@ class EditorTableBlockTest : EditorPresentationTestSetup() {
id = cells[1].id,
text = cells[1].content.asText().text
),
cellIndex = 1,
tableId = table.id
)
)
@ -180,4 +183,752 @@ class EditorTableBlockTest : EditorPresentationTestSetup() {
verifyNoInteractions(fillTableRow)
}
}
@Test
fun `when click on menu icon - should enter table mode with 1 selected cell`() {
//SETUP
val columns = StubTableColumns(size = 3)
val rows = StubTableRows(size = 3)
val cells = StubTableCells(columns = columns, rows = rows)
val columnLayout = StubLayoutColumns(children = columns.map { it.id })
val rowLayout = StubLayoutRows(children = rows.map { it.id })
val table = StubTable(children = listOf(columnLayout.id, rowLayout.id))
val title = StubTitle()
val header = StubHeader(children = listOf(title.id))
val page = StubSmartBlock(id = root, children = listOf(header.id, table.id))
val document =
listOf(page, header, title, table, columnLayout, rowLayout) + columns + rows + cells
stubInterceptEvents()
stubOpenDocument(document)
//TESTING
val vm = buildViewModel()
vm.apply {
onStart(root)
onBlockFocusChanged(
id = cells[0].id,
hasFocus = true
)
onBlockToolbarBlockActionsClicked()
onBlockFocusChanged(
id = cells[0].id,
hasFocus = false
)
}
//EXPECTED
val expectedMode = Editor.Mode.Table(
tableId = table.id,
initialTargets = setOf(cells[0].id),
targets = setOf(cells[0].id),
tab = BlockView.Table.Tab.CELL
)
val expectedSelectedState = listOf(cells[0].id)
//ASSERT
assertEquals(
expected = expectedSelectedState,
actual = vm.currentSelection().toList()
)
assertEquals(
expected = expectedMode,
actual = vm.mode as Editor.Mode.Table
)
}
@Test
fun `when click on multiply cells in table - should be proper select state`() {
//SETUP
val columns = StubTableColumns(size = 3)
val rows = StubTableRows(size = 3)
val cells = StubTableCells(columns = columns, rows = rows)
val columnLayout = StubLayoutColumns(children = columns.map { it.id })
val rowLayout = StubLayoutRows(children = rows.map { it.id })
val table = StubTable(children = listOf(columnLayout.id, rowLayout.id))
val title = StubTitle()
val header = StubHeader(children = listOf(title.id))
val page = StubSmartBlock(id = root, children = listOf(header.id, table.id))
val document =
listOf(page, header, title, table, columnLayout, rowLayout) + columns + rows + cells
stubInterceptEvents()
stubOpenDocument(document)
//TESTING
val vm = buildViewModel()
vm.apply {
onStart(root)
onBlockFocusChanged(
id = cells[0].id,
hasFocus = true
)
onBlockToolbarBlockActionsClicked()
onBlockFocusChanged(
id = cells[0].id,
hasFocus = false
)
onClickListener(
clicked = ListenerType.TableTextCell(
cell = BlockView.Table.Cell(
rowId = rows[1].id,
columnId = columns[1].id,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(1),
block = BlockView.Text.Paragraph(
id = cells[4].id,
text = cells[4].content.asText().text
),
tableId = table.id
)
)
)
onClickListener(
clicked = ListenerType.TableTextCell(
cell = BlockView.Table.Cell(
rowId = rows[2].id,
columnId = columns[2].id,
rowIndex = BlockView.Table.RowIndex(2),
columnIndex = BlockView.Table.ColumnIndex(2),
block = BlockView.Text.Paragraph(
id = cells[8].id,
text = cells[8].content.asText().text
),
tableId = table.id
)
)
)
onClickListener(
clicked = ListenerType.TableTextCell(
cell = BlockView.Table.Cell(
rowId = rows[1].id,
columnId = columns[1].id,
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(1),
block = BlockView.Text.Paragraph(
id = cells[4].id,
text = cells[4].content.asText().text
),
tableId = table.id
)
)
)
}
//EXPECTED
val expectedMode = Editor.Mode.Table(
tableId = table.id,
initialTargets = setOf(cells[0].id, cells[8].id),
targets = setOf(cells[0].id, cells[8].id),
tab = BlockView.Table.Tab.CELL
)
val expectedSelectedState = listOf(cells[0].id, cells[8].id)
//ASSERT
assertEquals(
expected = expectedSelectedState,
actual = vm.currentSelection().toList()
)
assertEquals(
expected = expectedMode,
actual = vm.mode as Editor.Mode.Table
)
}
@Test
fun `when enter table mode then change tab then click on cell - two columns should be select`() {
//SETUP
val columns = StubTableColumns(size = 3)
val rows = StubTableRows(size = 3)
val cells = StubTableCells(columns = columns, rows = rows)
val columnLayout = StubLayoutColumns(children = columns.map { it.id })
val rowLayout = StubLayoutRows(children = rows.map { it.id })
val table = StubTable(children = listOf(columnLayout.id, rowLayout.id))
val title = StubTitle()
val header = StubHeader(children = listOf(title.id))
val page = StubSmartBlock(id = root, children = listOf(header.id, table.id))
val document =
listOf(page, header, title, table, columnLayout, rowLayout) + columns + rows + cells
stubInterceptEvents()
stubOpenDocument(document)
//TESTING
val vm = buildViewModel()
vm.apply {
onStart(root)
onBlockFocusChanged(
id = cells[0].id,
hasFocus = true
)
onBlockToolbarBlockActionsClicked()
onBlockFocusChanged(
id = cells[0].id,
hasFocus = false
)
onSimpleTableWidgetItemClicked(
item = SimpleTableWidgetItem.Tab.Column
)
onClickListener(
clicked = ListenerType.TableTextCell(
cell = BlockView.Table.Cell(
rowId = rows[2].id,
columnId = columns[2].id,
rowIndex = BlockView.Table.RowIndex(2),
columnIndex = BlockView.Table.ColumnIndex(2),
block = BlockView.Text.Paragraph(
id = cells[8].id,
text = cells[8].content.asText().text
),
tableId = table.id
)
)
)
}
//EXPECTED
val expectedMode = Editor.Mode.Table(
tableId = table.id,
initialTargets = setOf(cells[0].id),
targets = setOf(
cells[0].id,
cells[3].id,
cells[6].id,
cells[2].id,
cells[5].id,
cells[8].id
),
tab = BlockView.Table.Tab.COLUMN
)
val expectedSelectedState =
listOf(cells[0].id, cells[3].id, cells[6].id, cells[2].id, cells[5].id, cells[8].id)
//ASSERT
assertEquals(
expected = expectedSelectedState,
actual = vm.currentSelection().toList()
)
assertEquals(
expected = expectedMode,
actual = vm.mode as Editor.Mode.Table
)
}
@Test
fun `when enter table mode then change tab then click on cell then unselect cell - one column should be select`() {
//SETUP
val columns = StubTableColumns(size = 3)
val rows = StubTableRows(size = 3)
val cells = StubTableCells(columns = columns, rows = rows)
val columnLayout = StubLayoutColumns(children = columns.map { it.id })
val rowLayout = StubLayoutRows(children = rows.map { it.id })
val table = StubTable(children = listOf(columnLayout.id, rowLayout.id))
val title = StubTitle()
val header = StubHeader(children = listOf(title.id))
val page = StubSmartBlock(id = root, children = listOf(header.id, table.id))
val document =
listOf(page, header, title, table, columnLayout, rowLayout) + columns + rows + cells
stubInterceptEvents()
stubOpenDocument(document)
//TESTING
val vm = buildViewModel()
vm.apply {
onStart(root)
onBlockFocusChanged(
id = cells[0].id,
hasFocus = true
)
onBlockToolbarBlockActionsClicked()
onBlockFocusChanged(
id = cells[0].id,
hasFocus = false
)
onSimpleTableWidgetItemClicked(
item = SimpleTableWidgetItem.Tab.Column
)
onClickListener(
clicked = ListenerType.TableTextCell(
cell = BlockView.Table.Cell(
rowId = rows[2].id,
columnId = columns[2].id,
rowIndex = BlockView.Table.RowIndex(2),
columnIndex = BlockView.Table.ColumnIndex(2),
block = BlockView.Text.Paragraph(
id = cells[8].id,
text = cells[8].content.asText().text
),
tableId = table.id
)
)
)
onClickListener(
clicked = ListenerType.TableTextCell(
cell = BlockView.Table.Cell(
rowId = rows[2].id,
columnId = columns[2].id,
rowIndex = BlockView.Table.RowIndex(2),
columnIndex = BlockView.Table.ColumnIndex(2),
block = BlockView.Text.Paragraph(
id = cells[8].id,
text = cells[8].content.asText().text
),
tableId = table.id
)
)
)
}
//EXPECTED
val expectedMode = Editor.Mode.Table(
tableId = table.id,
initialTargets = setOf(cells[0].id),
targets = setOf(cells[0].id, cells[3].id, cells[6].id),
tab = BlockView.Table.Tab.COLUMN
)
val expectedSelectedState = listOf(cells[0].id, cells[3].id, cells[6].id)
//ASSERT
assertEquals(
expected = expectedSelectedState,
actual = vm.currentSelection().toList()
)
assertEquals(
expected = expectedMode,
actual = vm.mode as Editor.Mode.Table
)
}
@Test
fun `when enter table mode then change tab then click on two cells then unselect cell - two rows should be select`() {
//SETUP
val columns = StubTableColumns(size = 4)
val rows = StubTableRows(size = 4)
val cells = StubTableCells(columns = columns, rows = rows)
val columnLayout = StubLayoutColumns(children = columns.map { it.id })
val rowLayout = StubLayoutRows(children = rows.map { it.id })
val table = StubTable(id = tableId, children = listOf(columnLayout.id, rowLayout.id))
val title = StubTitle()
val header = StubHeader(children = listOf(title.id))
val page = StubSmartBlock(id = root, children = listOf(header.id, table.id))
val document =
listOf(page, header, title, table, columnLayout, rowLayout) + columns + rows + cells
stubInterceptEvents()
stubOpenDocument(document)
//TESTING Focus Cell[0] - Enter Table Mode - Click Cell[13] - Click Cell[11] - Click Tab COLUMN
val vm = buildViewModel()
vm.apply {
onStart(root)
onBlockFocusChanged(
id = cells[0].id,
hasFocus = true
)
onBlockToolbarBlockActionsClicked()
onBlockFocusChanged(
id = cells[0].id,
hasFocus = false
)
onClickListener(
clicked = ListenerType.TableTextCell(
cell = mapToViewCell(
cell = cells[13],
rows = rows,
rowIndex = 3,
columns = columns,
columnIndex = 1
)
)
)
onClickListener(
clicked = ListenerType.TableTextCell(
cell = mapToViewCell(
cell = cells[11],
rows = rows,
rowIndex = 2,
columns = columns,
columnIndex = 3
)
)
)
onSimpleTableWidgetItemClicked(
item = SimpleTableWidgetItem.Tab.Column
)
}
//EXPECTED
val expectedMode = Editor.Mode.Table(
tableId = table.id,
initialTargets = setOf(cells[0].id, cells[13].id, cells[11].id),
targets = setOf(
cells[0].id,
cells[4].id,
cells[8].id,
cells[12].id,
cells[1].id,
cells[5].id,
cells[9].id,
cells[13].id,
cells[3].id,
cells[7].id,
cells[11].id,
cells[15].id
),
tab = BlockView.Table.Tab.COLUMN
)
val expectedSelectedState = listOf(
cells[0].id,
cells[13].id,
cells[11].id,
cells[4].id,
cells[8].id,
cells[12].id,
cells[1].id,
cells[5].id,
cells[9].id,
cells[3].id,
cells[7].id,
cells[15].id
)
val expectedSimpleTableWidget = ControlPanelState.Toolbar.SimpleTableWidget(
isVisible = true,
tableId = tableId,
columnItems = getSimpleTableWidgetColumn(),
selectedCount = 3,
tab = BlockView.Table.Tab.COLUMN
)
//ASSERT
assertEquals(
expected = expectedSelectedState,
actual = vm.currentSelection().toList()
)
assertEquals(
expected = expectedMode,
actual = vm.mode as Editor.Mode.Table
)
assertEquals(
expected = expectedSimpleTableWidget,
actual = vm.controlPanelViewState.value?.simpleTableWidget
)
//TESTING Click Cell[15] - Click Cell[0] - Click Cell[2]
vm.apply {
onStart(root)
onClickListener(
clicked = ListenerType.TableTextCell(
cell = mapToViewCell(
cell = cells[15],
rows = rows,
rowIndex = 3,
columns = columns,
columnIndex = 3
)
)
)
onClickListener(
clicked = ListenerType.TableTextCell(
cell = mapToViewCell(
cell = cells[0],
rows = rows,
rowIndex = 0,
columns = columns,
columnIndex = 0
)
)
)
onClickListener(
clicked = ListenerType.TableTextCell(
cell = mapToViewCell(
cell = cells[2],
rows = rows,
rowIndex = 0,
columns = columns,
columnIndex = 2
)
)
)
}
//EXPECTED
val expectedMode1 = Editor.Mode.Table(
tableId = table.id,
initialTargets = setOf(cells[0].id, cells[13].id, cells[11].id),
targets = setOf(
cells[1].id,
cells[5].id,
cells[9].id,
cells[13].id,
cells[2].id,
cells[6].id,
cells[10].id,
cells[14].id
),
tab = BlockView.Table.Tab.COLUMN
)
val expectedSelectedState1 = listOf(
cells[13].id,
cells[1].id,
cells[5].id,
cells[9].id,
cells[2].id,
cells[6].id,
cells[10].id,
cells[14].id
)
val expectedSimpleTableWidget1 = ControlPanelState.Toolbar.SimpleTableWidget(
isVisible = true,
tableId = tableId,
columnItems = getSimpleTableWidgetColumn(),
selectedCount = 2,
tab = BlockView.Table.Tab.COLUMN
)
//ASSERT
assertEquals(
expected = expectedSelectedState1,
actual = vm.currentSelection().toList()
)
assertEquals(
expected = expectedMode1,
actual = vm.mode as Editor.Mode.Table
)
assertEquals(
expected = expectedSimpleTableWidget1,
actual = vm.controlPanelViewState.value?.simpleTableWidget
)
//TESTING Click Tab ROW
vm.apply {
onSimpleTableWidgetItemClicked(
item = SimpleTableWidgetItem.Tab.Row
)
}
//EXPECTED
val expectedMode2 = Editor.Mode.Table(
tableId = table.id,
initialTargets = setOf(cells[0].id, cells[13].id, cells[11].id),
targets = setOf(
cells[0].id,
cells[13].id,
cells[11].id,
cells[1].id,
cells[2].id,
cells[3].id,
cells[12].id,
cells[14].id,
cells[15].id,
cells[8].id,
cells[9].id,
cells[10].id
),
tab = BlockView.Table.Tab.ROW
)
val expectedSelectedState2 = listOf(
cells[0].id,
cells[13].id,
cells[11].id,
cells[1].id,
cells[2].id,
cells[3].id,
cells[12].id,
cells[14].id,
cells[15].id,
cells[8].id,
cells[9].id,
cells[10].id
)
val expectedSimpleTableWidget2 = ControlPanelState.Toolbar.SimpleTableWidget(
isVisible = true,
tableId = tableId,
rowItems = getSimpleTableWidgetRow(),
selectedCount = 3,
tab = BlockView.Table.Tab.ROW
)
//ASSERT
assertEquals(
expected = expectedSelectedState2,
actual = vm.currentSelection().toList()
)
assertEquals(
expected = expectedMode2,
actual = vm.mode as Editor.Mode.Table
)
assertEquals(
expected = expectedSimpleTableWidget2,
actual = vm.controlPanelViewState.value?.simpleTableWidget
)
//TESTING Click Cell[12] - Click Cell[10]
vm.apply {
onStart(root)
onClickListener(
clicked = ListenerType.TableTextCell(
cell = mapToViewCell(
cell = cells[12],
rows = rows,
rowIndex = 3,
columns = columns,
columnIndex = 0
)
)
)
onClickListener(
clicked = ListenerType.TableTextCell(
cell = mapToViewCell(
cell = cells[10],
rows = rows,
rowIndex = 2,
columns = columns,
columnIndex = 2
)
)
)
}
//EXPECTED
val expectedMode3 = Editor.Mode.Table(
tableId = table.id,
initialTargets = setOf(cells[0].id, cells[13].id, cells[11].id),
targets = setOf(
cells[0].id,
cells[1].id,
cells[2].id,
cells[3].id
),
tab = BlockView.Table.Tab.ROW
)
val expectedSelectedState3 = listOf(
cells[0].id,
cells[1].id,
cells[2].id,
cells[3].id
)
val expectedSimpleTableWidget3 = ControlPanelState.Toolbar.SimpleTableWidget(
isVisible = true,
tableId = tableId,
rowItems = getSimpleTableWidgetRow(),
selectedCount = 1,
tab = BlockView.Table.Tab.ROW
)
//ASSERT
assertEquals(
expected = expectedSelectedState3,
actual = vm.currentSelection().toList()
)
assertEquals(
expected = expectedMode3,
actual = vm.mode as Editor.Mode.Table
)
assertEquals(
expected = expectedSimpleTableWidget3,
actual = vm.controlPanelViewState.value?.simpleTableWidget
)
//TESTING Click Tab CELL
vm.apply {
onSimpleTableWidgetItemClicked(
item = SimpleTableWidgetItem.Tab.Cell
)
}
//EXPECTED
val expectedMode4 = Editor.Mode.Table(
tableId = table.id,
initialTargets = setOf(cells[0].id, cells[13].id, cells[11].id),
targets = setOf(
cells[0].id,
cells[13].id,
cells[11].id
),
tab = BlockView.Table.Tab.CELL
)
val expectedSelectedState4 = listOf(
cells[0].id,
cells[13].id,
cells[11].id
)
val expectedSimpleTableWidget4 = ControlPanelState.Toolbar.SimpleTableWidget(
isVisible = true,
tableId = tableId,
cellItems = getSimpleTableWidgetItems(),
selectedCount = 3,
tab = BlockView.Table.Tab.CELL
)
//ASSERT
assertEquals(
expected = expectedSelectedState4,
actual = vm.currentSelection().toList()
)
assertEquals(
expected = expectedMode4,
actual = vm.mode as Editor.Mode.Table
)
assertEquals(
expected = expectedSimpleTableWidget4,
actual = vm.controlPanelViewState.value?.simpleTableWidget
)
}
private fun mapToViewCell(
cell: Block,
rows: List<Block>,
rowIndex: Int,
columns: List<Block>,
columnIndex: Int
): BlockView.Table.Cell {
return BlockView.Table.Cell(
rowId = rows[rowIndex].id,
columnId = columns[columnIndex].id,
rowIndex = BlockView.Table.RowIndex(rowIndex),
columnIndex = BlockView.Table.ColumnIndex(columnIndex),
block = BlockView.Text.Paragraph(
id = cell.id,
text = cell.content.asText().text
),
tableId = tableId
)
}
}

View file

@ -36,7 +36,6 @@ import org.junit.Test
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import kotlin.test.assertEquals
import kotlin.test.asserter
class TableBlockRendererTest {
@ -201,22 +200,20 @@ class TableBlockRendererTest {
columnId = column.id,
rowIndex = BlockView.Table.RowIndex(rowIndex),
columnIndex = BlockView.Table.ColumnIndex(columnIndex),
cellIndex = columnIndex*rows.size + rowIndex,
tableId = table.id
)
)
}
}
val columnViews = mutableListOf<BlockView.Table.Column>()
val columnViews = mutableListOf<BlockView.Table.ColumnId>()
columns.forEach { column ->
columnViews.add(
BlockView.Table.Column(
id = column.id,
background = ThemeColor.DEFAULT
)
)
columnViews.add(BlockView.Table.ColumnId(value = column.id))
}
val rowViews = mutableListOf<BlockView.Table.RowId>()
rows.forEach { row ->
rowViews.add(BlockView.Table.RowId(value = row.id))
}
val expected = listOf(
@ -245,7 +242,7 @@ class TableBlockRendererTest {
id = table.id,
cells = cells,
columns = columnViews,
rowCount = rowsSize,
rows = rowViews,
isSelected = false,
selectedCellsIds = emptyList()
)
@ -356,22 +353,20 @@ class TableBlockRendererTest {
rowIndex = BlockView.Table.RowIndex(rowIndex),
columnIndex = BlockView.Table.ColumnIndex(columnIndex),
block = null,
cellIndex = columnIndex*rows.size + rowIndex,
tableId = table.id
)
)
}
}
val columnViews = mutableListOf<BlockView.Table.Column>()
val columnViews = mutableListOf<BlockView.Table.ColumnId>()
columns.forEach { column ->
columnViews.add(
BlockView.Table.Column(
id = column.id,
background = ThemeColor.DEFAULT
)
)
columnViews.add(BlockView.Table.ColumnId(value = column.id))
}
val rowViews = mutableListOf<BlockView.Table.RowId>()
rows.forEach { row ->
rowViews.add(BlockView.Table.RowId(value = row.id))
}
val expected = listOf(
@ -400,7 +395,7 @@ class TableBlockRendererTest {
id = table.id,
cells = cells,
columns = columnViews,
rowCount = rowsSize,
rows = rowViews,
isSelected = false,
selectedCellsIds = emptyList()
)
@ -528,7 +523,6 @@ class TableBlockRendererTest {
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(0),
block = null,
cellIndex = 0,
tableId = table.id
),
BlockView.Table.Cell(
@ -540,7 +534,6 @@ class TableBlockRendererTest {
),
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(0),
cellIndex = 1,
tableId = table.id
),
BlockView.Table.Cell(
@ -549,7 +542,6 @@ class TableBlockRendererTest {
rowIndex = BlockView.Table.RowIndex(2),
columnIndex = BlockView.Table.ColumnIndex(0),
block = null,
cellIndex = 2,
tableId = table.id
), //column1
BlockView.Table.Cell(
@ -561,7 +553,6 @@ class TableBlockRendererTest {
),
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(1),
cellIndex = 3,
tableId = table.id
),
BlockView.Table.Cell(
@ -573,7 +564,6 @@ class TableBlockRendererTest {
),
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(1),
cellIndex = 4,
tableId = table.id
),
BlockView.Table.Cell(
@ -582,7 +572,6 @@ class TableBlockRendererTest {
rowIndex = BlockView.Table.RowIndex(2),
columnIndex = BlockView.Table.ColumnIndex(1),
block = null,
cellIndex = 5,
tableId = table.id
),//column2
BlockView.Table.Cell(
@ -591,7 +580,6 @@ class TableBlockRendererTest {
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(2),
block = null,
cellIndex = 6,
tableId = table.id
),
BlockView.Table.Cell(
@ -600,7 +588,6 @@ class TableBlockRendererTest {
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(2),
block = null,
cellIndex = 7,
tableId = table.id
),
BlockView.Table.Cell(
@ -609,7 +596,6 @@ class TableBlockRendererTest {
rowIndex = BlockView.Table.RowIndex(2),
columnIndex = BlockView.Table.ColumnIndex(2),
block = null,
cellIndex = 8,
tableId = table.id
),//column3
BlockView.Table.Cell(
@ -621,7 +607,6 @@ class TableBlockRendererTest {
),
rowIndex = BlockView.Table.RowIndex(0),
columnIndex = BlockView.Table.ColumnIndex(3),
cellIndex = 9,
tableId = table.id
),
BlockView.Table.Cell(
@ -633,7 +618,6 @@ class TableBlockRendererTest {
),
rowIndex = BlockView.Table.RowIndex(1),
columnIndex = BlockView.Table.ColumnIndex(3),
cellIndex = 10,
tableId = table.id
),
BlockView.Table.Cell(
@ -642,20 +626,18 @@ class TableBlockRendererTest {
rowIndex = BlockView.Table.RowIndex(2),
columnIndex = BlockView.Table.ColumnIndex(3),
block = null,
cellIndex = 11,
tableId = table.id
)
)
val columnViews = mutableListOf<BlockView.Table.Column>()
val columnViews = mutableListOf<BlockView.Table.ColumnId>()
columns.forEach { column ->
columnViews.add(
BlockView.Table.Column(
id = column.id,
background = ThemeColor.DEFAULT
)
)
columnViews.add(BlockView.Table.ColumnId(value = column.id))
}
val rowViews = mutableListOf<BlockView.Table.RowId>()
rows.forEach { row ->
rowViews.add(BlockView.Table.RowId(value = row.id))
}
val expected = listOf(
@ -684,7 +666,7 @@ class TableBlockRendererTest {
id = table.id,
cells = cells,
columns = columnViews,
rowCount = rowsSize,
rows = rowViews,
isSelected = false,
selectedCellsIds = listOf("$rowId2-$columnId1")
)

View file

@ -296,8 +296,17 @@ fun StubTableColumn(
backgroundColor = background
)
fun StubTableColumns(size: Int): List<Block> = (0 until size).map { StubTableColumn() }
fun StubTableRows(size: Int): List<Block> = (0 until size).map { StubTableRow() }
fun StubTableColumns(size: Int): List<Block> = (0 until size).map { index ->
StubTableColumn(
id = "c$index"
)
}
fun StubTableRows(size: Int): List<Block> = (0 until size).map { index ->
StubTableRow(
id = "r$index"
)
}
fun StubTableCells(columns: List<Block>, rows: List<Block>): List<Block> {
val cells = mutableListOf<Block>()
for (i in rows.indices) {