Skip to content

Commit

Permalink
Merge pull request #25 from spbu-coding-2023/feature/addEdge
Browse files Browse the repository at this point in the history
Add edge button
  • Loading branch information
Demon32123 authored Sep 24, 2024
2 parents ffd989b + 2209f0f commit 7c17efe
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 15 deletions.
3 changes: 2 additions & 1 deletion src/main/kotlin/view/MenuView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ fun MenuView(
viewModel: MenuViewModel
) {
var isNodeCreating by viewModel::isNodeCreating
var isEdgeCreating by viewModel::isEdgeCreating
var isClustering by viewModel::isClustering
var isRanked by viewModel::isRanked
var isAlgorithmMenuOpen by viewModel::isAlgorithmMenuOpen
Expand All @@ -97,7 +98,7 @@ fun MenuView(
) {
Spacer(Modifier.height(25f.dp))
MenuIcon("Nodes.svg", "AddNode.svg", Modifier.glow(isNodeCreating)) { isNodeCreating = !isNodeCreating }
MenuIcon("Ribs.svg", "AddEdge.svg", modifier = Modifier.alpha(0.2f))
MenuIcon("Ribs.svg", "AddEdge.svg", Modifier.glow(isEdgeCreating)) { isEdgeCreating = !isEdgeCreating }
MenuIcon("Clustering.svg", "ClusterD.svg", Modifier.glow(isClustering)) { isClustering = !isClustering }
MenuIcon("PageRank.svg", "AnalysisGraph.svg", Modifier.glow(viewModel.isRanked)) { isRanked = !isRanked }
MenuIcon(
Expand Down
7 changes: 5 additions & 2 deletions src/main/kotlin/view/canvas/CanvasView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ fun CanvasView(
}
.clipToBounds()
) {
viewModel.edges.forEach {
EdgeCanvasView(it)
// for rerender when update
if (viewModel.edgesCount > 0) {
viewModel.edges.flatten().forEach {
EdgeCanvasView(it)
}
}

viewModel.vertices.forEach {
Expand Down
8 changes: 7 additions & 1 deletion src/main/kotlin/view/canvas/VertexCanvasView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.compose.foundation.gestures.onDrag
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.onClick
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
Expand All @@ -26,8 +27,13 @@ fun VertexCanvasView(
modifier
.size(viewModel.radius * 2)
.offset(viewModel.offset.x.dp, viewModel.offset.y.dp)
.border(color = viewModel.color, width = viewModel.strokeWidth.dp, shape = CircleShape)
.border(
color = if (viewModel.canvasViewModel.pickedNodeForEdgeCreating != viewModel) viewModel.color else Color.Green,
width = viewModel.strokeWidth.dp,
shape = CircleShape
)
.background(color = Color(0xFF242424), shape = CircleShape)
.onClick { viewModel.onClickWhenEdgeCreating() }
.onDrag(onDrag = viewModel::onDrag),
contentAlignment = Alignment.Center
) {
Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/viewModel/MenuViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class MenuViewModel(
val canvasViewModel: CanvasViewModel
) {
var isNodeCreating by canvasViewModel::isNodeCreatingMode
var isEdgeCreating by canvasViewModel::isEdgeCreatingMode
var isClustering by canvasViewModel::isClustering
var isRanked by canvasViewModel::isRanked
var isAlgorithmMenuOpen by mutableStateOf(false)
Expand Down
54 changes: 45 additions & 9 deletions src/main/kotlin/viewModel/canvas/CanvasViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.awt.awtEventOrNull
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Canvas
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.AwaitPointerEventScope
import androidx.compose.ui.input.pointer.PointerEvent
Expand All @@ -29,13 +30,18 @@ class CanvasViewModel(
var isClustering by graphViewModel::clustering
var isRanked by graphViewModel::ranked

var isEdgeCreatingMode by mutableStateOf(false)
var pickedNodeForEdgeCreating by mutableStateOf<VertexCanvasViewModel?>(null)

var isNodeCreatingMode by mutableStateOf(false)
var edgesCount by mutableStateOf(0)
var zoom by mutableStateOf(1f)
var center by mutableStateOf(Offset(0f, 0f))
var canvasSize by mutableStateOf(Offset(400f, 400f))
var isOrientated by mutableStateOf(false)

private val _vertices = mutableStateMapOf<VertexViewModel, VertexCanvasViewModel>()
private val _edges = mutableStateMapOf<VertexCanvasViewModel, ArrayList<EdgeCanvasViewModel>>()

private fun getVertex(vm: VertexViewModel): VertexCanvasViewModel {
return _vertices[vm] ?: throw IllegalArgumentException("There is no VertexCanvasViewModel for $vm")
Expand All @@ -54,24 +60,24 @@ class CanvasViewModel(
graphViewModel.vertices.forEach { v ->
_vertices[v] = VertexCanvasViewModel(v, this)
}
}

private val _edges = graphViewModel.adjacencyList.mapValues {
it.value.map { edgeViewModel ->
val vertex1 = getVertex(edgeViewModel.first)
val vertex2 = getVertex(edgeViewModel.second)
graphViewModel.adjacencyList.forEach {
_edges[getVertex(it.key)] = ArrayList(it.value.map { edgeViewModel ->
val vertex1 = getVertex(edgeViewModel.first)
val vertex2 = getVertex(edgeViewModel.second)

EdgeCanvasViewModel(vertex1, vertex2, edgeViewModel, this)
EdgeCanvasViewModel(vertex1, vertex2, edgeViewModel, this)
}.toList())
}
}.mapKeys {
getVertex(it.key)

edgesCount = _edges.values.flatten().size
}

val vertices
get() = _vertices.values

val edges
get() = _edges.values.flatten()
get() = _edges.values

val onScroll: AwaitPointerEventScope.(PointerEvent) -> Unit = {
if (it.changes.first().scrollDelta.y > 0) {
Expand Down Expand Up @@ -121,4 +127,34 @@ class CanvasViewModel(
fun resetEdgesColorToDefault() {
graphViewModel.resetEdgesColorToDefault()
}

fun createEdge(first: VertexCanvasViewModel, second: VertexCanvasViewModel) {
val edgesVM = graphViewModel.createEdge(first.vertexViewModel, second.vertexViewModel)
val firstCanvasEdgeList = _edges[first] ?: return
val secondCanvasEdgeList = _edges[second] ?: return

if (edgesVM != null) {
firstCanvasEdgeList.add(EdgeCanvasViewModel(first, second, edgesVM.first, this))
secondCanvasEdgeList.add(EdgeCanvasViewModel(second, first, edgesVM.second, this))
}

edgesCount++
}

fun onClickNodeEdgeCreating(vm: VertexCanvasViewModel) {
if (!isEdgeCreatingMode) return

if (pickedNodeForEdgeCreating == vm) {
pickedNodeForEdgeCreating = null
return
}

if (pickedNodeForEdgeCreating == null) {
pickedNodeForEdgeCreating = vm
return
}

createEdge(pickedNodeForEdgeCreating ?: return, vm)
pickedNodeForEdgeCreating = null
}
}
8 changes: 6 additions & 2 deletions src/main/kotlin/viewModel/canvas/VertexCanvasViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import androidx.compose.ui.geometry.Offset
import viewModel.graph.VertexViewModel

class VertexCanvasViewModel(
private val vertexViewModel: VertexViewModel,
private val canvasViewModel: CanvasViewModel,
val vertexViewModel: VertexViewModel,
val canvasViewModel: CanvasViewModel,
) {
val color by vertexViewModel::color
val label by vertexViewModel::label
Expand All @@ -24,6 +24,10 @@ class VertexCanvasViewModel(
vertexViewModel.onDrag(it * (1f / canvasViewModel.zoom))
}

fun onClickWhenEdgeCreating() {
canvasViewModel.onClickNodeEdgeCreating(this)
}

private fun calculateOffset() = Offset(
(canvasViewModel.canvasSize.x / 2) + ((vertexViewModel.x - canvasViewModel.center.x) * canvasViewModel.zoom),
(canvasViewModel.canvasSize.y / 2) + ((vertexViewModel.y - canvasViewModel.center.y) * canvasViewModel.zoom)
Expand Down
12 changes: 12 additions & 0 deletions src/main/kotlin/viewModel/graph/UndirectedViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,18 @@ class UndirectedViewModel(
updateSizes()
}

fun createEdge(first: VertexViewModel, second: VertexViewModel): Pair<EdgeViewModel, EdgeViewModel>? {
val edge = graph.addEdge(first.getKey(), second.getKey()) ?: return null

val firstEdge = EdgeViewModel(first, second, edge, mutableStateOf(false))
val secondEdge = EdgeViewModel(second, first, edge, mutableStateOf(false))

_adjacencyList[first]?.add(EdgeViewModel(first, second, edge, mutableStateOf(false)))
_adjacencyList[second]?.add(EdgeViewModel(second, first, edge, mutableStateOf(false)))

return Pair(firstEdge, secondEdge)
}

private fun getColor(group: Int): Color {
if (clustering) {
val color = groupColors[group]
Expand Down
4 changes: 4 additions & 0 deletions src/main/kotlin/viewModel/graph/VertexViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ class VertexViewModel(
val labelVisibility
get() = _labelVisible

fun getKey(): Int {
return vertex.key
}

fun onDrag(it: Offset): Unit {
x += it.x
y += it.y
Expand Down

0 comments on commit 7c17efe

Please sign in to comment.