Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

value class 및 contract를 이용한 when 문 제거 #332

Merged
merged 11 commits into from
May 4, 2024
10 changes: 9 additions & 1 deletion .github/workflows/AOS-ktlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ jobs:
with:
java-version: '17'
distribution: 'adopt'

- name: Create Properties File
env:
RELEASE_KEYSTORE: ${{ secrets.KEY_STORE_BASE_64 }}
KEYSTORE_PROPERTIES: ${{ secrets.KEYSTORE_PROPERTIES }}
LOCAL_PROPERTIES: ${{ secrets.LOCAL_PROPERTIES }}
run: |
echo "$RELEASE_KEYSTORE" | base64 -d > AOS/app/release.keystore
echo "$KEYSTORE_PROPERTIES" > AOS/keystore.properties
echo "$LOCAL_PROPERTIES" > AOS/local.properties
- name: Run ktlint
run: cd AOS && chmod +x ./gradlew &&./gradlew ktlintCheck
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
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
Loading