Skip to content

Commit

Permalink
Merge pull request #69 from boostcampwm2023/AOS-feature/mindmap-line
Browse files Browse the repository at this point in the history
��Line 곡선 그리기 및  Node의 크기 변화에 따른 라인 그리기
  • Loading branch information
jaehan4707 authored Nov 21, 2023
2 parents ca36d5d + 6bae9c5 commit df2ab9b
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 27 deletions.
38 changes: 27 additions & 11 deletions AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/LineView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import android.graphics.Path
import android.util.AttributeSet
import android.view.View
import boostcamp.and07.mindsync.data.SampleNode
import boostcamp.and07.mindsync.data.model.CircleNode
import boostcamp.and07.mindsync.data.model.Node
import boostcamp.and07.mindsync.data.model.RectangleNode
import boostcamp.and07.mindsync.ui.util.Dp
import boostcamp.and07.mindsync.ui.util.toPx
import boostcamp.and07.mindsync.ui.view.layout.MindmapRightLayoutManager
Expand All @@ -24,40 +26,54 @@ class LineView constructor(
isAntiAlias = true
}
private val path = Path()
private var head = SampleNode.head
var head = SampleNode.head
private val rightLayoutManager = MindmapRightLayoutManager()

override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
arrangeNode()
if (head.nodes.isNotEmpty()) {
traverseLine(canvas, head, 1)
traverseLine(canvas, head, 0)
}
}

private fun arrangeNode() {
head = rightLayoutManager.arrangeNode(head)
}

private fun traverseLine(canvas: Canvas, node: Node, depth: Int) {
fun updateWithNewHead(newHead: Node) {
head = newHead
invalidate()
}

fun traverseLine(canvas: Canvas, node: Node, depth: Int) {
for (toNode in node.nodes) {
drawLine(node, toNode, canvas)
traverseLine(canvas, toNode, depth + 1)
}
}

private fun drawLine(fromNode: Node, toNode: Node, canvas: Canvas) {
val startX = getNodeEdgeX(fromNode, true)
val startY = fromNode.path.centerY.toPx(context)
val endX = getNodeEdgeX(toNode, false)
val endY = toNode.path.centerY.toPx(context)
val midX = (startX + endX) / 2

val path = path.apply {
reset()
moveTo(
fromNode.path.centerX.toPx(context),
fromNode.path.centerY.toPx(context),
)
lineTo(
toNode.path.centerX.toPx(context),
toNode.path.centerY.toPx(context),
)
moveTo(startX, startY)
cubicTo(midX, startY, midX, endY, endX, endY)
}
canvas.drawPath(path, paint)
}

private fun getNodeEdgeX(node: Node, isStart: Boolean): Float {
val nodeCenterX = node.path.centerX.toPx(context)
val widthOffset = when (node) {
is CircleNode -> node.path.radius.toPx(context)
is RectangleNode -> node.path.width.toPx(context) / 2
}
return if (isStart) nodeCenterX + widthOffset else nodeCenterX - widthOffset
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package boostcamp.and07.mindsync.ui.view

import boostcamp.and07.mindsync.data.SampleNode
import boostcamp.and07.mindsync.data.model.Node

class MindmapContainer {
var head: Node = SampleNode.head

var nodeView: NodeView? = null
var lineView: LineView? = null

fun updateHead(newHead: Node) {
head = newHead
lineView?.updateWithNewHead(newHead)
}
}
41 changes: 25 additions & 16 deletions AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/NodeView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import boostcamp.and07.mindsync.ui.util.toPx
import boostcamp.and07.mindsync.ui.view.layout.MindmapRightLayoutManager

class NodeView constructor(context: Context, attrs: AttributeSet?) : View(context, attrs) {
private var head = SampleNode.head
var head = SampleNode.head
private val circlePaint = Paint().apply {
color = context.getColor(R.color.mindmap1)
}
Expand All @@ -49,9 +49,9 @@ class NodeView constructor(context: Context, attrs: AttributeSet?) : View(contex
strokeWidth = Dp(5f).toPx(context)
isAntiAlias = true
}

private val lineHeight = Dp(15f)
private var touchedNode: Node? = null
var mindmapContainer: MindmapContainer? = null

override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
Expand All @@ -63,6 +63,11 @@ class NodeView constructor(context: Context, attrs: AttributeSet?) : View(contex
}
}

fun changeNodeSize() {
traverseTextHead()
mindmapContainer?.updateHead(head)
}

private fun arrangeNode() {
head = rightLayoutManager.arrangeNode(head)
}
Expand All @@ -76,7 +81,7 @@ class NodeView constructor(context: Context, attrs: AttributeSet?) : View(contex
return super.onTouchEvent(event)
}

private fun traverseDrawHead(canvas: Canvas) {
fun traverseDrawHead(canvas: Canvas) {
traverseDrawNode(canvas, head, 0)
}

Expand Down Expand Up @@ -106,26 +111,22 @@ class NodeView constructor(context: Context, attrs: AttributeSet?) : View(contex
return newNode
}

private fun changeSize(node: Node, width: Px, height: Float): Node {
private fun changeSize(node: Node, width: Float, height: Float): Node {
when (node) {
is CircleNode -> {
var newRadius = node.path.radius
if (width.toDp(context) > node.path.radius.dpVal && !node.description.contains("\n")
) {
newRadius = Dp(width.toDp(context) / 2) + lineHeight / 2
}
if (node.description.contains("\n")) {
newRadius = (Dp(height) - lineHeight) / 2
}
newRadius = Dp(
maxOf(
(Dp(Px(width).toDp(context) / 2) + lineHeight / 2).dpVal,
((Dp(height) - lineHeight) / 2).dpVal,
),
)
return node.copy(node.path.copy(radius = newRadius))
}

is RectangleNode -> {
var newWidth = node.path.width
if (width.toDp(context) > node.path.width.dpVal && !node.description.contains("\n")
) {
newWidth = Dp(width.toDp(context)) + lineHeight
}
newWidth = Dp(Px(width).toDp(context)) / 2 + lineHeight
val newHeight = Dp(height) / 2 + lineHeight
return node.copy(node.path.copy(width = newWidth, height = newHeight))
}
Expand Down Expand Up @@ -240,7 +241,15 @@ class NodeView constructor(context: Context, attrs: AttributeSet?) : View(contex
return sum
}

private fun sumWidth(description: String) = Px(textPaint.measureText(description))
private fun sumWidth(description: String): Float {
var sum = 0f
Px(textPaint.measureText(description))
description.split("\n").forEach {
sum = maxOf(sum, textPaint.measureText(description))
}
return sum
}

private fun drawText(canvas: Canvas, node: Node) {
val lines = node.description.split("\n")
var bounds = Rect()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,21 @@ class ZoomLayout(context: Context, attrs: AttributeSet? = null) : ConstraintLayo
private var dx = 0f
private var dy = 0f
private var mode = LayoutMode.DRAG
private var nodeView: NodeView
private var lineView: LineView
private val mindmapContainer = MindmapContainer()

init {
nodeView = NodeView(context, attrs)
lineView = LineView(context, attrs)
mindmapContainer.nodeView = nodeView
mindmapContainer.lineView = lineView
nodeView.mindmapContainer = mindmapContainer
nodeView.changeNodeSize()
addView(nodeView)
addView(lineView)
applyScaleAndTranslation()
}

override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
Expand Down

0 comments on commit df2ab9b

Please sign in to comment.