From 84532012aa58275e3cfa44e6e55ce358ae49b567 Mon Sep 17 00:00:00 2001 From: dltkd1395 Date: Tue, 21 Nov 2023 01:40:22 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat(#8):=20=EB=9D=BC=EC=9D=B8=EC=9D=84=20?= =?UTF-8?q?=EA=B3=A1=EC=84=A0=20=ED=98=95=ED=83=9C=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../and07/mindsync/ui/view/LineView.kt | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/LineView.kt b/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/LineView.kt index 8885aeb8..2d956b22 100644 --- a/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/LineView.kt +++ b/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/LineView.kt @@ -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 @@ -24,14 +26,14 @@ 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) } } @@ -39,7 +41,7 @@ class LineView constructor( head = rightLayoutManager.arrangeNode(head) } - private fun traverseLine(canvas: Canvas, node: Node, depth: Int) { + fun traverseLine(canvas: Canvas, node: Node, depth: Int) { for (toNode in node.nodes) { drawLine(node, toNode, canvas) traverseLine(canvas, toNode, depth + 1) @@ -47,17 +49,26 @@ class LineView constructor( } 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 + } } From 6bae9c5b1aa7ac4125323049fbc0ac1ff06fecb0 Mon Sep 17 00:00:00 2001 From: dltkd1395 Date: Tue, 21 Nov 2023 14:17:36 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix(#70):=20=EB=85=B8=EB=93=9C=EC=9D=98=20?= =?UTF-8?q?=ED=81=AC=EA=B8=B0=20=EB=B3=80=ED=99=94=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=EB=9D=BC=EC=9D=B8=20=EA=B7=B8=EB=A6=AC=EA=B8=B0=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../and07/mindsync/ui/view/LineView.kt | 5 +++ .../mindsync/ui/view/MindmapContainer.kt | 16 ++++++++ .../and07/mindsync/ui/view/NodeView.kt | 41 +++++++++++-------- .../and07/mindsync/ui/view/ZoomLayout.kt | 15 +++++++ 4 files changed, 61 insertions(+), 16 deletions(-) create mode 100644 AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/MindmapContainer.kt diff --git a/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/LineView.kt b/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/LineView.kt index 2d956b22..a51a4679 100644 --- a/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/LineView.kt +++ b/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/LineView.kt @@ -41,6 +41,11 @@ class LineView constructor( head = rightLayoutManager.arrangeNode(head) } + fun updateWithNewHead(newHead: Node) { + head = newHead + invalidate() + } + fun traverseLine(canvas: Canvas, node: Node, depth: Int) { for (toNode in node.nodes) { drawLine(node, toNode, canvas) diff --git a/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/MindmapContainer.kt b/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/MindmapContainer.kt new file mode 100644 index 00000000..c05cb0d5 --- /dev/null +++ b/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/MindmapContainer.kt @@ -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) + } +} \ No newline at end of file diff --git a/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/NodeView.kt b/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/NodeView.kt index 24c9d071..12882ded 100644 --- a/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/NodeView.kt +++ b/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/NodeView.kt @@ -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) } @@ -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) @@ -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) } @@ -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) } @@ -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)) } @@ -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() diff --git a/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/ZoomLayout.kt b/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/ZoomLayout.kt index 61c3527b..b00d895f 100644 --- a/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/ZoomLayout.kt +++ b/AOS/app/src/main/java/boostcamp/and07/mindsync/ui/view/ZoomLayout.kt @@ -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) {