Skip to content

Commit 970fe93

Browse files
committed
♻️ refactor dijkstra screen
1 parent 30598e0 commit 970fe93

File tree

9 files changed

+96
-128
lines changed

9 files changed

+96
-128
lines changed

app/src/main/java/com/waleska404/algorithms/ui/core/components/CustomButton.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fun CustomIconButton(
5151
) {
5252
Row(
5353
horizontalArrangement = Arrangement.Center,
54-
verticalAlignment = Alignment.CenterVertically
54+
verticalAlignment = Alignment.Bottom
5555
) {
5656
Box(
5757
modifier = Modifier.size(30.dp),

app/src/main/java/com/waleska404/algorithms/ui/dijkstra/DijkstraModel.kt

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,8 @@ import com.waleska404.algorithms.ui.core.components.CellType
66
data class DijkstraGrid(
77
val grid: List<List<CellData>>
88
) {
9-
fun toLinearGrid(): MutableList<CellData> {
10-
val mutableList = mutableListOf<CellData>()
11-
for (i in this.grid.indices) {
12-
for (j in this.grid[i].indices) {
13-
mutableList.add(this.grid[i][j])
14-
}
15-
}
16-
return mutableList
17-
}
9+
fun toLinearGrid(): MutableList<CellData> =
10+
grid.flatten().toMutableList()
1811
}
1912

2013
data class CellData(

app/src/main/java/com/waleska404/algorithms/ui/dijkstra/DijkstraScreen.kt

Lines changed: 73 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,26 @@ import androidx.compose.foundation.layout.height
1414
import androidx.compose.foundation.layout.padding
1515
import androidx.compose.foundation.layout.width
1616
import androidx.compose.foundation.layout.wrapContentWidth
17+
import androidx.compose.material3.MaterialTheme
1718
import androidx.compose.material3.Text
1819
import androidx.compose.runtime.Composable
19-
import androidx.compose.runtime.LaunchedEffect
2020
import androidx.compose.runtime.collectAsState
2121
import androidx.compose.runtime.getValue
22-
import androidx.compose.runtime.mutableStateOf
23-
import androidx.compose.runtime.remember
2422
import androidx.compose.ui.Alignment
2523
import androidx.compose.ui.Modifier
2624
import androidx.compose.ui.graphics.Color
25+
import androidx.compose.ui.res.stringResource
26+
import androidx.compose.ui.text.font.FontWeight
2727
import androidx.compose.ui.unit.dp
28+
import androidx.compose.ui.unit.sp
2829
import androidx.hilt.navigation.compose.hiltViewModel
2930
import com.waleska404.algorithms.R
30-
import com.waleska404.algorithms.domain.dijkstra.Position
3131
import com.waleska404.algorithms.ui.core.components.CELL_FINISH
3232
import com.waleska404.algorithms.ui.core.components.CELL_START
3333
import com.waleska404.algorithms.ui.core.components.CELL_VISITED
3434
import com.waleska404.algorithms.ui.core.components.CELL_WALL
3535
import com.waleska404.algorithms.ui.core.components.CustomIconButton
3636
import com.waleska404.algorithms.ui.core.components.PathFindingGrid
37-
import kotlinx.coroutines.delay
3837

3938

4039
@OptIn(ExperimentalFoundationApi::class)
@@ -43,86 +42,92 @@ fun DijkstraScreen(
4342
navigateToHome: () -> Unit,
4443
viewModel: DijkstraViewModel = hiltViewModel(),
4544
) {
46-
//val currentGridState = remember { mutableStateOf(state.drawCurrentGridState()) }
4745
val currentGridState: DijkstraGrid by viewModel.gridState.collectAsState()
46+
val isVisualizing: Boolean by viewModel.isVisualizing.collectAsState()
4847

49-
val onCellClicked = { p: Position ->
50-
if (viewModel.isPositionNotAtStartOrFinish(p) && !viewModel.isVisualizing) {
51-
viewModel.toggleCellTypeToWall(p)
52-
//currentGridState.value = viewModel.drawCurrentGridState()
53-
}
54-
}
55-
56-
PathFindingUi(
57-
grid = currentGridState,
58-
onClick = onCellClicked,
59-
onVisualize = {
60-
viewModel.animatedShortestPath()
61-
},
62-
onRandomizeWalls = {
63-
viewModel.randomizeWalls()
64-
},
65-
onClear = {
66-
viewModel.clear()
67-
}
68-
)
69-
LaunchedEffect(Unit) {
70-
while (true) {
71-
delay(GAME_DELAY_IN_MS)
72-
//currentGridState.value = viewModel.drawCurrentGridState()
73-
}
48+
Column(
49+
horizontalAlignment = Alignment.CenterHorizontally,
50+
verticalArrangement = Arrangement.Center,
51+
) {
52+
Text(
53+
text = stringResource(id = R.string.dijkstras_algorithm),
54+
fontWeight = FontWeight.Bold,
55+
fontSize = 22.sp,
56+
color = MaterialTheme.colorScheme.secondary
57+
)
58+
Spacer(modifier = Modifier.height(10.dp))
59+
PathFindingGrid(
60+
cellData = currentGridState.toLinearGrid(),
61+
onClick = viewModel::onCellClicked
62+
)
63+
Spacer(modifier = Modifier.height(10.dp))
64+
Legend()
65+
Spacer(modifier = Modifier.height(10.dp))
66+
BottomButtons(
67+
onVisualize = { viewModel.animatedShortestPath() },
68+
onRandomizeWalls = { viewModel.randomizeWalls() },
69+
onClear = { viewModel.clear() },
70+
isVisualizing = isVisualizing
71+
)
7472
}
7573
}
7674

77-
@ExperimentalFoundationApi
75+
7876
@Composable
79-
fun PathFindingUi(
80-
grid: DijkstraGrid,
81-
onClick: (Position) -> Unit,
77+
fun BottomButtons(
8278
onVisualize: () -> Unit,
8379
onRandomizeWalls: () -> Unit,
8480
onClear: () -> Unit,
81+
isVisualizing: Boolean,
8582
) {
86-
val isVisualizeEnabled = remember { mutableStateOf(true) }
87-
88-
Column(
89-
modifier = Modifier.padding(8.dp),
90-
verticalArrangement = Arrangement.Center,
91-
horizontalAlignment = Alignment.CenterHorizontally,
83+
Row(
84+
verticalAlignment = Alignment.CenterVertically,
85+
horizontalArrangement = Arrangement.Center,
9286
) {
93-
PathFindingGrid(grid.toLinearGrid(), onClick)
87+
CustomIconButton(
88+
modifier = Modifier.padding(start = 7.dp),
89+
onClick = onVisualize,
90+
text = stringResource(id = R.string.run),
91+
enabled = !isVisualizing,
92+
iconResource = R.drawable.sort,
93+
iconDescriptionResource = R.string.sort_icon,
94+
)
95+
CustomIconButton(
96+
modifier = Modifier.padding(start = 7.dp),
97+
onClick = onRandomizeWalls,
98+
text = stringResource(id = R.string.walls),
99+
enabled = !isVisualizing,
100+
iconResource = R.drawable.shuffle,
101+
iconDescriptionResource = R.string.random,
102+
)
103+
CustomIconButton(
104+
modifier = Modifier.padding(horizontal = 7.dp),
105+
onClick = onClear,
106+
text = stringResource(id = R.string.clear),
107+
iconResource = R.drawable.broom,
108+
iconDescriptionResource = R.string.broom_icon,
109+
)
110+
}
111+
}
94112

95-
Column {
96-
Spacer(modifier = Modifier.height(30.dp))
97-
Row(
98-
modifier = Modifier.fillMaxWidth(),
99-
horizontalArrangement = Arrangement.Center
100-
) {
101-
Legend("Start", CELL_START)
102-
Legend("Finish", CELL_FINISH)
103-
Legend("Visited", CELL_VISITED)
104-
Legend("Wall", CELL_WALL)
105-
}
106-
Row {
107-
VisualizeButton(
108-
modifier = Modifier.padding(start = 16.dp),
109-
onClick = onVisualize,
110-
enabled = isVisualizeEnabled.value
111-
)
112-
RandomWallsButton(
113-
modifier = Modifier.padding(start = 16.dp),
114-
onClick = onRandomizeWalls,
115-
enabled = isVisualizeEnabled.value
116-
)
117-
ClearButton(modifier = Modifier.padding(horizontal = 16.dp), onClick = onClear)
118-
}
119-
}
113+
@OptIn(ExperimentalFoundationApi::class)
114+
@Composable
115+
fun Legend() {
116+
Row(
117+
modifier = Modifier.fillMaxWidth(),
118+
horizontalArrangement = Arrangement.Center
119+
) {
120+
LegendItem(stringResource(id = R.string.start), CELL_START)
121+
LegendItem(stringResource(id = R.string.finish), CELL_FINISH)
122+
LegendItem(stringResource(id = R.string.visited), CELL_VISITED)
123+
LegendItem(stringResource(id = R.string.wall), CELL_WALL)
120124
}
121125
}
122126

127+
123128
@ExperimentalFoundationApi
124129
@Composable
125-
fun Legend(
130+
fun LegendItem(
126131
label: String,
127132
color: Color,
128133
hasBorder: Boolean = false
@@ -146,44 +151,3 @@ fun Legend(
146151

147152
}
148153

149-
@ExperimentalFoundationApi
150-
@Composable
151-
fun VisualizeButton(modifier: Modifier = Modifier, onClick: () -> (Unit), enabled: Boolean = true) {
152-
CustomIconButton(
153-
modifier,
154-
onClick = onClick,
155-
text = "Vis",
156-
enabled = enabled,
157-
iconResource = R.drawable.sort,
158-
iconDescriptionResource = R.string.sort_icon,
159-
)
160-
}
161-
162-
@ExperimentalFoundationApi
163-
@Composable
164-
fun ClearButton(modifier: Modifier = Modifier, onClick: () -> (Unit)) {
165-
CustomIconButton(
166-
modifier,
167-
onClick = onClick,
168-
text = "Clear",
169-
iconResource = R.drawable.sortdescending,
170-
iconDescriptionResource = R.string.sort_icon,
171-
)
172-
}
173-
174-
@ExperimentalFoundationApi
175-
@Composable
176-
fun RandomWallsButton(
177-
modifier: Modifier = Modifier,
178-
onClick: () -> (Unit),
179-
enabled: Boolean = true
180-
) {
181-
CustomIconButton(
182-
modifier,
183-
onClick = onClick,
184-
text = "Walls",
185-
enabled = enabled,
186-
iconResource = R.drawable.shuffle,
187-
iconDescriptionResource = R.string.random,
188-
)
189-
}

app/src/main/java/com/waleska404/algorithms/ui/dijkstra/DijkstraViewModel.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,12 @@ class DijkstraViewModel @Inject constructor(
3535
private var _gridState = MutableStateFlow(getInitialGrid())
3636
val gridState: StateFlow<DijkstraGrid> = _gridState
3737

38-
//private var walls: MutableList<Position> = mutableListOf()
39-
40-
41-
var isVisualizing = false
42-
private set
38+
private var _isVisualizing = MutableStateFlow(false)
39+
val isVisualizing: StateFlow<Boolean> = _isVisualizing
4340

4441
fun clear() {
4542
walls = mutableListOf()
46-
isVisualizing = false
43+
_isVisualizing.value = false
4744
_gridState.value = getInitialGrid()
4845
}
4946

@@ -105,10 +102,15 @@ class DijkstraViewModel @Inject constructor(
105102
}
106103
}
107104

108-
fun isPositionNotAtStartOrFinish(p: Position) =
105+
private fun isPositionNotAtStartOrFinish(p: Position) =
109106
getCellAtPosition(p).type != CellType.START &&
110107
getCellAtPosition(p).type != CellType.FINISH
111108

109+
fun onCellClicked(p: Position) {
110+
if (isPositionNotAtStartOrFinish(p) && !isVisualizing.value) {
111+
toggleCellTypeToWall(p)
112+
}
113+
}
112114

113115
private fun updateCellTypeAtPosition(position: Position, cellType: CellType) {
114116
val i = position.row
@@ -147,7 +149,7 @@ class DijkstraViewModel @Inject constructor(
147149

148150
fun animatedShortestPath() {
149151
viewModelScope.launch {
150-
isVisualizing = true
152+
_isVisualizing.value = true
151153
val shortestPath = dijkstra.animatedDijkstra(
152154
gridSize = NUMBER_OF_ROWS * NUMBER_OF_COLUMNS,
153155
row = NUMBER_OF_ROWS,

app/src/main/java/com/waleska404/algorithms/ui/home/HomeScreen.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ fun HomeScreen(
6565
Algorithm(
6666
title = R.string.dijkstras_algorithm,
6767
//TODO: change icon
68-
icon = R.drawable.sortdescending,
68+
icon = R.drawable.route,
6969
iconDescription = R.string.sort_descending_icon,
7070
navigateToAlgorithm = navigateToDijkstra
7171
)
13.1 KB
Loading
8.35 KB
Loading
13.6 KB
Loading

app/src/main/res/values/strings.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,16 @@
66
<string name="random">Random</string>
77
<string name="sort">Sort</string>
88
<string name="sort_descending_icon">sort descending icon</string>
9+
<string name="route_icon">route icon</string>
910
<string name="quick_sort_title">Quick Sort</string>
1011
<string name="home_screen_title">Algorithms Visualization</string>
1112
<string name="dijkstras_algorithm">Dijkstra\'s Algorithm</string>
13+
<string name="start">Start</string>
14+
<string name="finish">Finish</string>
15+
<string name="visited">Visited</string>
16+
<string name="wall">Wall</string>
17+
<string name="walls">Walls</string>
18+
<string name="broom_icon">broom icon</string>
19+
<string name="clear">Clear</string>
20+
<string name="run">Run</string>
1221
</resources>

0 commit comments

Comments
 (0)