Skip to content

Commit

Permalink
Merge pull request #332 from boostcampwm2023/AOS-refactor/#331
Browse files Browse the repository at this point in the history
�value class 및 contract를 이용한 when 문 제거
  • Loading branch information
hegleB authored May 4, 2024
2 parents 70f035f + 36ff3ef commit 13a789a
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 128 deletions.
4 changes: 4 additions & 0 deletions AOS/app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import java.util.Properties

plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
Expand All @@ -12,6 +14,8 @@ android {
namespace = "boostcamp.and07.mindsync"
compileSdk = 34

val properties = Properties()
properties.load(project.rootProject.file("local.properties").inputStream())
val url = properties["BASE_URL"] ?: ""
val googleServerClientId = properties["GOOGLE_SERVER_CLIENT_ID"] ?: ""
val kakaoClientId = properties["KAKAO_CLIENT_ID"] ?: ""
Expand Down
11 changes: 11 additions & 0 deletions AOS/app/src/main/java/boostcamp/and07/mindsync/data/model/Node.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package boostcamp.and07.mindsync.data.model

import boostcamp.and07.mindsync.ui.util.Dp
import kotlinx.serialization.Serializable
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract

@Serializable
sealed class Node(
Expand All @@ -15,6 +17,15 @@ sealed class Node(
horizontalSpacing: Dp,
totalHeight: Dp,
): Node

@OptIn(ExperimentalContracts::class)
fun isRectangle(): Boolean {
contract {
returns(true) implies (this@Node is RectangleNode)
returns(false) implies (this@Node is CircleNode)
}
return this is RectangleNode
}
}

data class CircleNode(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@ package boostcamp.and07.mindsync.ui.mindmap

import android.widget.ImageButton
import androidx.databinding.BindingAdapter
import boostcamp.and07.mindsync.data.model.CircleNode
import boostcamp.and07.mindsync.data.model.Node
import boostcamp.and07.mindsync.data.model.RectangleNode

@BindingAdapter("app:removeBtn")
fun ImageButton.setEnabled(selectedNode: Node?) {
this.isEnabled =
when (selectedNode) {
is CircleNode -> false
is RectangleNode -> true
else -> false
}
if (selectedNode != null) {
this.isEnabled =
selectedNode.isRectangle()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.navArgs
import boostcamp.and07.mindsync.R
import boostcamp.and07.mindsync.data.crdt.OperationType
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.data.model.Tree
import boostcamp.and07.mindsync.data.util.NodeGenerator
import boostcamp.and07.mindsync.databinding.FragmentMindMapBinding
Expand Down Expand Up @@ -98,14 +96,18 @@ class MindMapFragment :
editDescriptionDialog.setSubmitListener { description ->
when (operationType) {
OperationType.ADD -> {
mindMapViewModel.addNode(selectedNode, NodeGenerator.makeNode(description, selectedNode.id))
mindMapViewModel.addNode(
selectedNode,
NodeGenerator.makeNode(description, selectedNode.id),
)
}

OperationType.UPDATE -> {
val newNode =
when (selectedNode) {
is CircleNode -> selectedNode.copy(description = description)
is RectangleNode -> selectedNode.copy(description = description)
if (selectedNode.isRectangle()) {
selectedNode.copy(description = description)
} else {
selectedNode.copy(description = description)
}
mindMapViewModel.updateNode(newNode)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import android.content.Context
import android.util.TypedValue
import kotlinx.serialization.Serializable

@JvmInline
@Serializable
data class Dp(val dpVal: Float) {
value class Dp(val dpVal: Float) {
operator fun plus(dpValue: Dp): Dp {
return Dp(dpVal + dpValue.dpVal)
}
Expand Down Expand Up @@ -67,7 +68,8 @@ data class Dp(val dpVal: Float) {
}
}

data class Px(val pxVal: Float) {
@JvmInline
value class Px(val pxVal: Float) {
operator fun plus(pxValue: Px): Px {
return Px(pxVal + pxValue.pxVal)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import android.graphics.Paint
import android.graphics.Path
import android.util.AttributeSet
import android.view.View
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.data.model.Tree
import boostcamp.and07.mindsync.ui.util.toPx
import boostcamp.and07.mindsync.ui.view.model.DrawInfo
Expand Down Expand Up @@ -98,9 +96,10 @@ class LineView constructor(
): 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
if (node.isRectangle()) {
node.path.width.toPx(context) / 2
} else {
node.path.radius.toPx(context)
}
return if (isStart) nodeCenterX + widthOffset else nodeCenterX - widthOffset
}
Expand Down
173 changes: 82 additions & 91 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 @@ -138,11 +138,12 @@ class NodeView(
dy: Float,
) {
mindMapContainer.selectNode?.let { selectedNode ->
if (selectedNode is CircleNode) return
traverseMovedNode(tree.getRootNode(), selectedNode, dx, dy)
if (selectedNode.isRectangle()) {
traverseMovedNode(tree.getRootNode(), selectedNode, dx, dy)

mindMapContainer.update(tree)
rightLayoutManager.arrangeNode(tree, selectedNode as RectangleNode)
mindMapContainer.update(tree)
rightLayoutManager.arrangeNode(tree, selectedNode)
}
}
lineView.updateTree(tree)
invalidate()
Expand Down Expand Up @@ -200,16 +201,15 @@ class NodeView(

private fun drawAttachedNode(canvas: Canvas) {
attachedNode?.let { attachedNode ->
val height =
when (attachedNode) {
is RectangleNode -> attachedNode.path.height
is CircleNode -> attachedNode.path.radius + Dp(ATTACH_CIRCLE_NODE_RANGE_VALUE)
}
val width =
when (attachedNode) {
is RectangleNode -> attachedNode.path.width
is CircleNode -> attachedNode.path.radius + Dp(ATTACH_CIRCLE_NODE_RANGE_VALUE)
}
val height: Dp
val width: Dp
if (attachedNode.isRectangle()) {
height = attachedNode.path.height
width = attachedNode.path.width
} else {
height = attachedNode.path.radius + Dp(ATTACH_CIRCLE_NODE_RANGE_VALUE)
width = height
}
val radius = maxOf(height.toPx(context), width.toPx(context))
canvas.drawCircle(
attachedNode.path.centerX.toPx(context),
Expand All @@ -225,27 +225,23 @@ class NodeView(
canvas: Canvas,
node: Node,
) {
when (node) {
is CircleNode -> {
canvas.drawCircle(
node.path.centerX.toPx(context),
node.path.centerY.toPx(context),
node.path.radius.toPx(context),
drawInfo.strokePaint,
)
}

is RectangleNode -> {
canvas.drawRoundRect(
node.path.leftX().toPx(context),
node.path.topY().toPx(context),
node.path.rightX().toPx(context),
node.path.bottomY().toPx(context),
Dp(ROUNDED_CORNER_RADIUS).toPx(context),
Dp(ROUNDED_CORNER_RADIUS).toPx(context),
drawInfo.strokePaint,
)
}
if (node.isRectangle()) {
canvas.drawRoundRect(
node.path.leftX().toPx(context),
node.path.topY().toPx(context),
node.path.rightX().toPx(context),
node.path.bottomY().toPx(context),
Dp(ROUNDED_CORNER_RADIUS).toPx(context),
Dp(ROUNDED_CORNER_RADIUS).toPx(context),
drawInfo.strokePaint,
)
} else {
canvas.drawCircle(
node.path.centerX.toPx(context),
node.path.centerY.toPx(context),
node.path.radius.toPx(context),
drawInfo.strokePaint,
)
}
}

Expand All @@ -254,34 +250,28 @@ class NodeView(
x: Float,
y: Float,
): Boolean {
when (node) {
is CircleNode -> {
if (x in (node.path.centerX - node.path.radius).toPx(context)..(node.path.centerX + node.path.radius).toPx(context) &&
y in (node.path.centerY - node.path.radius).toPx(context)..(node.path.centerY + node.path.radius).toPx(context)
) {
return true
}
}

is RectangleNode -> {
if (x in node.path.leftX().toPx(context)..node.path.rightX().toPx(context) &&
if (node.isRectangle()) {
return (
x in node.path.leftX().toPx(context)..node.path.rightX().toPx(context) &&
y in node.path.topY().toPx(context)..node.path.bottomY().toPx(context)
) {
return true
}
}
)
} else {
return (
x in (node.path.centerX - node.path.radius).toPx(context)..(node.path.centerX + node.path.radius).toPx(context) &&
y in (node.path.centerY - node.path.radius).toPx(context)..(node.path.centerY + node.path.radius).toPx(context)
)
}
return false
}

private fun drawNode(
canvas: Canvas,
node: Node,
depth: Int,
) {
when (node) {
is CircleNode -> drawCircleNode(canvas, node)
is RectangleNode -> drawRectangleNode(canvas, node, depth)
if (node.isRectangle()) {
drawRectangleNode(canvas, node, depth)
} else {
drawCircleNode(canvas, node)
}
drawText(canvas, node)
}
Expand Down Expand Up @@ -321,55 +311,56 @@ class NodeView(
) {
val lines = node.description.split("\n")
val bounds = Rect()
when (node) {
is CircleNode -> {
drawInfo.textPaint.color = Color.WHITE
if (lines.size > 1) {
var y =
node.path.centerY.toPx(context) - node.path.radius.toPx(context) + drawInfo.padding.toPx(context)
for (line in lines) {
drawInfo.textPaint.getTextBounds(line, 0, line.length, bounds)
canvas.drawText(
line,
node.path.centerX.toPx(context),
y + bounds.height(),
drawInfo.textPaint,
)
y += bounds.height() + drawInfo.lineHeight.dpVal
}
} else {
if (node.isRectangle()) {
drawInfo.textPaint.color = Color.BLACK
if (lines.size > 1) {
var y =
node.path.centerY.toPx(context) - node.path.height.toPx(context) / 2 + drawInfo.padding.toPx(
context,
) / 2
for (line in lines) {
drawInfo.textPaint.getTextBounds(line, 0, line.length, bounds)
canvas.drawText(
node.description,
line,
node.path.centerX.toPx(context),
node.path.centerY.toPx(context) + drawInfo.lineHeight.dpVal / 2,
y + bounds.height(),
drawInfo.textPaint,
)
y += bounds.height() + drawInfo.lineHeight.dpVal
}
} else {
canvas.drawText(
node.description,
node.path.centerX.toPx(context),
node.path.centerY.toPx(context) + drawInfo.lineHeight.dpVal / 2,
drawInfo.textPaint,
)
}

is RectangleNode -> {
drawInfo.textPaint.color = Color.BLACK
if (lines.size > 1) {
var y =
node.path.centerY.toPx(context) - node.path.height.toPx(context) / 2 + drawInfo.padding.toPx(context) / 2
for (line in lines) {
drawInfo.textPaint.getTextBounds(line, 0, line.length, bounds)
canvas.drawText(
line,
node.path.centerX.toPx(context),
y + bounds.height(),
drawInfo.textPaint,
} else {
drawInfo.textPaint.color = Color.WHITE
if (lines.size > 1) {
var y =
node.path.centerY.toPx(context) - node.path.radius.toPx(context) +
drawInfo.padding.toPx(
context,
)
y += bounds.height() + drawInfo.lineHeight.dpVal
}
} else {
for (line in lines) {
drawInfo.textPaint.getTextBounds(line, 0, line.length, bounds)
canvas.drawText(
node.description,
line,
node.path.centerX.toPx(context),
node.path.centerY.toPx(context) + drawInfo.lineHeight.dpVal / 2,
y + bounds.height(),
drawInfo.textPaint,
)
y += bounds.height() + drawInfo.lineHeight.dpVal
}
} else {
canvas.drawText(
node.description,
node.path.centerX.toPx(context),
node.path.centerY.toPx(context) + drawInfo.lineHeight.dpVal / 2,
drawInfo.textPaint,
)
}
}
}
Expand Down
Loading

0 comments on commit 13a789a

Please sign in to comment.