Added adjustable eraser thickness and improved tool selection logic for highlighter (#95)
This commit is contained in:
parent
982efb063d
commit
eaf0d4af00
6 changed files with 201 additions and 131 deletions
|
|
@ -67,6 +67,7 @@ fun AnnotationDock(
|
||||||
canUndo: Boolean,
|
canUndo: Boolean,
|
||||||
canRedo: Boolean,
|
canRedo: Boolean,
|
||||||
lastPenTool: InkType,
|
lastPenTool: InkType,
|
||||||
|
lastHighlighterTool: InkType = InkType.HIGHLIGHTER,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
isSticky: Boolean = false,
|
isSticky: Boolean = false,
|
||||||
isMinimized: Boolean,
|
isMinimized: Boolean,
|
||||||
|
|
@ -180,7 +181,15 @@ fun AnnotationDock(
|
||||||
description = "Pen",
|
description = "Pen",
|
||||||
size = buttonSize,
|
size = buttonSize,
|
||||||
iconSize = iconSize,
|
iconSize = iconSize,
|
||||||
onClick = { if(!isMinimized) onToolClick(lastPenTool) }
|
onClick = {
|
||||||
|
if(!isMinimized) {
|
||||||
|
if (selectedTool != InkType.PEN && selectedTool != InkType.FOUNTAIN_PEN && selectedTool != InkType.PENCIL) {
|
||||||
|
onToolClick(lastPenTool)
|
||||||
|
} else {
|
||||||
|
onToolClick(selectedTool)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Highlighter
|
// Highlighter
|
||||||
|
|
@ -195,7 +204,7 @@ fun AnnotationDock(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (!isMinimized) {
|
if (!isMinimized) {
|
||||||
if (selectedTool != InkType.HIGHLIGHTER && selectedTool != InkType.HIGHLIGHTER_ROUND) {
|
if (selectedTool != InkType.HIGHLIGHTER && selectedTool != InkType.HIGHLIGHTER_ROUND) {
|
||||||
onToolClick(InkType.HIGHLIGHTER)
|
onToolClick(lastHighlighterTool)
|
||||||
} else {
|
} else {
|
||||||
onToolClick(selectedTool)
|
onToolClick(selectedTool)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -438,6 +438,7 @@ internal fun PdfPageComposable(
|
||||||
onHighlightUpdate: (String, PdfHighlightColor) -> Unit = { _,_ -> },
|
onHighlightUpdate: (String, PdfHighlightColor) -> Unit = { _,_ -> },
|
||||||
onHighlightDelete: (String) -> Unit = {},
|
onHighlightDelete: (String) -> Unit = {},
|
||||||
onTts: (Int, Int) -> Unit = { _, _ -> },
|
onTts: (Int, Int) -> Unit = { _, _ -> },
|
||||||
|
activeToolThickness: Float = 0f
|
||||||
) {
|
) {
|
||||||
val pdfDocumentItem = pdfDocument.item
|
val pdfDocumentItem = pdfDocument.item
|
||||||
var bitmapState by remember { mutableStateOf(PdfThumbnailCache.get(pageIndex)) }
|
var bitmapState by remember { mutableStateOf(PdfThumbnailCache.get(pageIndex)) }
|
||||||
|
|
@ -3775,6 +3776,7 @@ internal fun PdfPageComposable(
|
||||||
isEditMode = isEditMode,
|
isEditMode = isEditMode,
|
||||||
selectedTool = selectedTool,
|
selectedTool = selectedTool,
|
||||||
eraserPosition = eraserPosition,
|
eraserPosition = eraserPosition,
|
||||||
|
activeToolThickness = activeToolThickness,
|
||||||
richTextController = richTextController,
|
richTextController = richTextController,
|
||||||
textBoxes = textBoxes,
|
textBoxes = textBoxes,
|
||||||
selectedTextBoxId = selectedTextBoxId,
|
selectedTextBoxId = selectedTextBoxId,
|
||||||
|
|
@ -4516,6 +4518,8 @@ private fun PdfPageRenderer(
|
||||||
onHighlightUpdate: (String, PdfHighlightColor) -> Unit,
|
onHighlightUpdate: (String, PdfHighlightColor) -> Unit,
|
||||||
onHighlightDelete: (String) -> Unit,
|
onHighlightDelete: (String) -> Unit,
|
||||||
onTts: (Int, Int) -> Unit,
|
onTts: (Int, Int) -> Unit,
|
||||||
|
activeToolThickness: Float
|
||||||
|
|
||||||
) {
|
) {
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
Box(
|
Box(
|
||||||
|
|
@ -4704,7 +4708,11 @@ private fun PdfPageRenderer(
|
||||||
|
|
||||||
if (isEditMode && selectedTool == InkType.ERASER && eraserPosition != null) {
|
if (isEditMode && selectedTool == InkType.ERASER && eraserPosition != null) {
|
||||||
Canvas(modifier = Modifier.fillMaxSize()) {
|
Canvas(modifier = Modifier.fillMaxSize()) {
|
||||||
val radiusPx = 8.dp.toPx()
|
val radiusPx = if (activeToolThickness > 0f && staticData.targetWidth > 0) {
|
||||||
|
activeToolThickness * staticData.targetWidth * scale // Calculate dynamic size based on tool settings scale
|
||||||
|
} else {
|
||||||
|
8.dp.toPx()
|
||||||
|
}
|
||||||
|
|
||||||
drawCircle(
|
drawCircle(
|
||||||
color = Color.White.copy(alpha = 0.3f),
|
color = Color.White.copy(alpha = 0.3f),
|
||||||
|
|
|
||||||
|
|
@ -231,6 +231,7 @@ internal fun PdfVerticalReader(
|
||||||
onHighlightUpdate: (String, PdfHighlightColor) -> Unit = { _,_ -> },
|
onHighlightUpdate: (String, PdfHighlightColor) -> Unit = { _,_ -> },
|
||||||
onHighlightDelete: (String) -> Unit = {},
|
onHighlightDelete: (String) -> Unit = {},
|
||||||
onTts: (Int, Int) -> Unit = { _, _ -> },
|
onTts: (Int, Int) -> Unit = { _, _ -> },
|
||||||
|
activeToolThickness: Float = 0f
|
||||||
) {
|
) {
|
||||||
SideEffect { Timber.tag("PdfDrawPerf").v("LIST: PdfVerticalReader Recomposing.") }
|
SideEffect { Timber.tag("PdfDrawPerf").v("LIST: PdfVerticalReader Recomposing.") }
|
||||||
var globalEraserPosition by remember { mutableStateOf<Offset?>(null) }
|
var globalEraserPosition by remember { mutableStateOf<Offset?>(null) }
|
||||||
|
|
@ -1512,6 +1513,7 @@ internal fun PdfVerticalReader(
|
||||||
onHighlightUpdate = onHighlightUpdate,
|
onHighlightUpdate = onHighlightUpdate,
|
||||||
onHighlightDelete = onHighlightDelete,
|
onHighlightDelete = onHighlightDelete,
|
||||||
onTts = onTts,
|
onTts = onTts,
|
||||||
|
activeToolThickness = activeToolThickness,
|
||||||
onTextBoxDragStart = { box, localTopLeft, touchOffset ->
|
onTextBoxDragStart = { box, localTopLeft, touchOffset ->
|
||||||
val currentZoom = zoomAnimatable.value
|
val currentZoom = zoomAnimatable.value
|
||||||
val panX = panXAnimatable.value
|
val panX = panXAnimatable.value
|
||||||
|
|
@ -1911,7 +1913,11 @@ internal fun PdfVerticalReader(
|
||||||
if (isEditMode && selectedTool == InkType.ERASER && globalEraserPosition != null) {
|
if (isEditMode && selectedTool == InkType.ERASER && globalEraserPosition != null) {
|
||||||
Canvas(modifier = Modifier.fillMaxSize()) {
|
Canvas(modifier = Modifier.fillMaxSize()) {
|
||||||
val pos = globalEraserPosition!!
|
val pos = globalEraserPosition!!
|
||||||
val radiusPx = 8.dp.toPx()
|
val radiusPx = if (activeToolThickness > 0f) {
|
||||||
|
activeToolThickness * screenWidth * zoomAnimatable.value
|
||||||
|
} else {
|
||||||
|
8.dp.toPx()
|
||||||
|
}
|
||||||
|
|
||||||
drawCircle(color = Color.White.copy(alpha = 0.3f), radius = radiusPx, center = pos)
|
drawCircle(color = Color.White.copy(alpha = 0.3f), radius = radiusPx, center = pos)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1374,8 +1374,9 @@ fun PdfViewerScreen(
|
||||||
val selectedTool = toolSettings.getActiveTool()
|
val selectedTool = toolSettings.getActiveTool()
|
||||||
|
|
||||||
val lastPenTool = toolSettings.getLastPenTool()
|
val lastPenTool = toolSettings.getLastPenTool()
|
||||||
|
val lastHighlighterTool = toolSettings.getLastHighlighterTool()
|
||||||
val dockPenColor = toolSettings.getToolColor(lastPenTool)
|
val dockPenColor = toolSettings.getToolColor(lastPenTool)
|
||||||
val dockHighlighterColor = toolSettings.getToolColor(InkType.HIGHLIGHTER)
|
val dockHighlighterColor = toolSettings.getToolColor(lastHighlighterTool)
|
||||||
|
|
||||||
val activeToolColor = toolSettings.getToolColor(selectedTool)
|
val activeToolColor = toolSettings.getToolColor(selectedTool)
|
||||||
val activeToolThickness = toolSettings.getToolThickness(selectedTool)
|
val activeToolThickness = toolSettings.getToolThickness(selectedTool)
|
||||||
|
|
@ -2714,7 +2715,7 @@ fun PdfViewerScreen(
|
||||||
annotation: PdfAnnotation,
|
annotation: PdfAnnotation,
|
||||||
hitPoint: PdfPoint,
|
hitPoint: PdfPoint,
|
||||||
pageAspectRatio: Float,
|
pageAspectRatio: Float,
|
||||||
threshold: Float = 0.025f
|
threshold: Float
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (annotation.points.isEmpty()) return false
|
if (annotation.points.isEmpty()) return false
|
||||||
|
|
||||||
|
|
@ -4242,7 +4243,7 @@ fun PdfViewerScreen(
|
||||||
val aspectRatio = pageAspectRatios.getOrElse(pageIndex) { 1f }
|
val aspectRatio = pageAspectRatios.getOrElse(pageIndex) { 1f }
|
||||||
val existing = allAnnotations[pageIndex] ?: emptyList()
|
val existing = allAnnotations[pageIndex] ?: emptyList()
|
||||||
val toRemove = existing.filter {
|
val toRemove = existing.filter {
|
||||||
isAnnotationHit(it, point, aspectRatio)
|
isAnnotationHit(it, point, aspectRatio, activeToolThickness)
|
||||||
}
|
}
|
||||||
if (toRemove.isNotEmpty()) {
|
if (toRemove.isNotEmpty()) {
|
||||||
val batch =
|
val batch =
|
||||||
|
|
@ -4289,7 +4290,7 @@ fun PdfViewerScreen(
|
||||||
val aspectRatio = pageAspectRatios.getOrElse(pageIndex) { 1f }
|
val aspectRatio = pageAspectRatios.getOrElse(pageIndex) { 1f }
|
||||||
val existing = allAnnotations[pageIndex] ?: emptyList()
|
val existing = allAnnotations[pageIndex] ?: emptyList()
|
||||||
val toRemove = existing.filter {
|
val toRemove = existing.filter {
|
||||||
isAnnotationHit(it, point, aspectRatio)
|
isAnnotationHit(it, point, aspectRatio, activeToolThickness)
|
||||||
}
|
}
|
||||||
if (toRemove.isNotEmpty()) {
|
if (toRemove.isNotEmpty()) {
|
||||||
val batch =
|
val batch =
|
||||||
|
|
@ -4405,6 +4406,7 @@ fun PdfViewerScreen(
|
||||||
onHighlightUpdate = onHighlightUpdate,
|
onHighlightUpdate = onHighlightUpdate,
|
||||||
onHighlightDelete = onHighlightDelete,
|
onHighlightDelete = onHighlightDelete,
|
||||||
onTts = { pageIdx, charIdx -> startTtsWithPermissionCheck(pageIdx, charIdx) },
|
onTts = { pageIdx, charIdx -> startTtsWithPermissionCheck(pageIdx, charIdx) },
|
||||||
|
activeToolThickness = currentStrokeWidthState,
|
||||||
onTwoFingerSwipe = { direction ->
|
onTwoFingerSwipe = { direction ->
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
val targetPage =
|
val targetPage =
|
||||||
|
|
@ -4632,7 +4634,7 @@ fun PdfViewerScreen(
|
||||||
val aspectRatio = pageAspectRatios.getOrElse(pageIndex) { 1f }
|
val aspectRatio = pageAspectRatios.getOrElse(pageIndex) { 1f }
|
||||||
val existing = allAnnotations[pageIndex] ?: emptyList()
|
val existing = allAnnotations[pageIndex] ?: emptyList()
|
||||||
val toRemove = existing.filter {
|
val toRemove = existing.filter {
|
||||||
isAnnotationHit(it, point, aspectRatio)
|
isAnnotationHit(it, point, aspectRatio, activeToolThickness)
|
||||||
}
|
}
|
||||||
if (toRemove.isNotEmpty()) {
|
if (toRemove.isNotEmpty()) {
|
||||||
val batch =
|
val batch =
|
||||||
|
|
@ -4670,7 +4672,7 @@ fun PdfViewerScreen(
|
||||||
val aspectRatio = pageAspectRatios.getOrElse(pageIndex) { 1f }
|
val aspectRatio = pageAspectRatios.getOrElse(pageIndex) { 1f }
|
||||||
val existing = allAnnotations[pageIndex] ?: emptyList()
|
val existing = allAnnotations[pageIndex] ?: emptyList()
|
||||||
val toRemove = existing.filter {
|
val toRemove = existing.filter {
|
||||||
isAnnotationHit(it, point, aspectRatio)
|
isAnnotationHit(it, point, aspectRatio, activeToolThickness)
|
||||||
}
|
}
|
||||||
if (toRemove.isNotEmpty()) {
|
if (toRemove.isNotEmpty()) {
|
||||||
val batch =
|
val batch =
|
||||||
|
|
@ -4737,6 +4739,7 @@ fun PdfViewerScreen(
|
||||||
onHighlightUpdate = onHighlightUpdate,
|
onHighlightUpdate = onHighlightUpdate,
|
||||||
onHighlightDelete = onHighlightDelete,
|
onHighlightDelete = onHighlightDelete,
|
||||||
onTts = { pageIdx, charIdx -> startTtsWithPermissionCheck(pageIdx, charIdx) },
|
onTts = { pageIdx, charIdx -> startTtsWithPermissionCheck(pageIdx, charIdx) },
|
||||||
|
activeToolThickness = currentStrokeWidthState,
|
||||||
onLinkClicked = onLinkClickedStable,
|
onLinkClicked = onLinkClickedStable,
|
||||||
onInternalLinkClicked = onInternalLinkNavStable,
|
onInternalLinkClicked = onInternalLinkNavStable,
|
||||||
bookmarks = bookmarksHolder,
|
bookmarks = bookmarksHolder,
|
||||||
|
|
@ -6386,19 +6389,20 @@ fun PdfViewerScreen(
|
||||||
activePenColor = dockPenColor,
|
activePenColor = dockPenColor,
|
||||||
activeHighlighterColor = dockHighlighterColor,
|
activeHighlighterColor = dockHighlighterColor,
|
||||||
lastPenTool = lastPenTool,
|
lastPenTool = lastPenTool,
|
||||||
|
lastHighlighterTool = lastHighlighterTool,
|
||||||
isStylusOnlyMode = isStylusOnlyMode,
|
isStylusOnlyMode = isStylusOnlyMode,
|
||||||
onToggleStylusOnlyMode = {
|
onToggleStylusOnlyMode = {
|
||||||
isStylusOnlyMode = !isStylusOnlyMode
|
isStylusOnlyMode = !isStylusOnlyMode
|
||||||
saveStylusOnlyMode(context, isStylusOnlyMode)
|
saveStylusOnlyMode(context, isStylusOnlyMode)
|
||||||
},
|
},
|
||||||
onToolClick = { clickedTool ->
|
onToolClick = { clickedTool ->
|
||||||
if (clickedTool == InkType.ERASER || clickedTool == InkType.TEXT) {
|
if (clickedTool == InkType.TEXT) {
|
||||||
annotationSettingsRepo.updateSelectedTool(
|
annotationSettingsRepo.updateSelectedTool(
|
||||||
clickedTool
|
clickedTool
|
||||||
)
|
)
|
||||||
showToolSettings = false
|
showToolSettings = false
|
||||||
} else if (selectedTool == clickedTool) {
|
} else if (selectedTool == clickedTool) {
|
||||||
if (clickedTool == InkType.PEN || clickedTool == InkType.FOUNTAIN_PEN || clickedTool == InkType.PENCIL || clickedTool == InkType.HIGHLIGHTER || clickedTool == InkType.HIGHLIGHTER_ROUND) {
|
if (clickedTool == InkType.PEN || clickedTool == InkType.FOUNTAIN_PEN || clickedTool == InkType.PENCIL || clickedTool == InkType.HIGHLIGHTER || clickedTool == InkType.HIGHLIGHTER_ROUND || clickedTool == InkType.ERASER) {
|
||||||
showToolSettings = !showToolSettings
|
showToolSettings = !showToolSettings
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,7 @@ fun ToolSettingsPopup(
|
||||||
onSnapToggle: (Boolean) -> Unit = {}
|
onSnapToggle: (Boolean) -> Unit = {}
|
||||||
) {
|
) {
|
||||||
val isHighlighter = selectedTool == InkType.HIGHLIGHTER || selectedTool == InkType.HIGHLIGHTER_ROUND
|
val isHighlighter = selectedTool == InkType.HIGHLIGHTER || selectedTool == InkType.HIGHLIGHTER_ROUND
|
||||||
|
val isEraser = selectedTool == InkType.ERASER
|
||||||
|
|
||||||
val activeColor = when (selectedTool) {
|
val activeColor = when (selectedTool) {
|
||||||
InkType.FOUNTAIN_PEN -> fountainPenColor
|
InkType.FOUNTAIN_PEN -> fountainPenColor
|
||||||
|
|
@ -117,6 +118,7 @@ fun ToolSettingsPopup(
|
||||||
InkType.PENCIL -> pencilColor
|
InkType.PENCIL -> pencilColor
|
||||||
InkType.HIGHLIGHTER -> highlighterColor
|
InkType.HIGHLIGHTER -> highlighterColor
|
||||||
InkType.HIGHLIGHTER_ROUND -> highlighterRoundColor
|
InkType.HIGHLIGHTER_ROUND -> highlighterRoundColor
|
||||||
|
InkType.ERASER -> Color.White
|
||||||
else -> markerColor
|
else -> markerColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,8 +132,11 @@ fun ToolSettingsPopup(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Thickness settings
|
val thicknessRange = when {
|
||||||
val thicknessRange = if (isHighlighter) 0.01f..0.06f else 0.001f..0.015f
|
isHighlighter -> 0.01f..0.06f
|
||||||
|
isEraser -> 0.01f..0.1f
|
||||||
|
else -> 0.001f..0.015f
|
||||||
|
}
|
||||||
@Suppress("UnusedExpression") if (isHighlighter) 0.005f else 0.001f
|
@Suppress("UnusedExpression") if (isHighlighter) 0.005f else 0.001f
|
||||||
|
|
||||||
var showColorPicker by remember { mutableStateOf(false) }
|
var showColorPicker by remember { mutableStateOf(false) }
|
||||||
|
|
@ -164,65 +169,92 @@ fun ToolSettingsPopup(
|
||||||
modifier = Modifier.padding(20.dp),
|
modifier = Modifier.padding(20.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Box(
|
if (isEraser) {
|
||||||
modifier = Modifier
|
Box(
|
||||||
.fillMaxWidth()
|
modifier = Modifier
|
||||||
.height(125.dp),
|
.fillMaxWidth()
|
||||||
contentAlignment = Alignment.BottomCenter
|
.height(125.dp),
|
||||||
) {
|
contentAlignment = Alignment.Center
|
||||||
Row(
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(28.dp),
|
|
||||||
verticalAlignment = Alignment.Bottom
|
|
||||||
) {
|
) {
|
||||||
if (isHighlighter) {
|
val radiusDp = (activeToolThickness * 1000).coerceIn(10f, 100f).dp
|
||||||
PenItem(
|
Box(
|
||||||
type = PenType.HIGHLIGHTER,
|
modifier = Modifier.size(radiusDp),
|
||||||
forcedInkType = InkType.HIGHLIGHTER,
|
contentAlignment = Alignment.Center
|
||||||
color = highlighterColor.copy(alpha = 1f),
|
) {
|
||||||
inkColor = highlighterColor,
|
Canvas(modifier = Modifier.fillMaxSize()) {
|
||||||
isSelected = selectedTool == InkType.HIGHLIGHTER,
|
drawCircle(
|
||||||
strokeWidth = activeToolThickness,
|
color = Color.White.copy(alpha = 0.3f),
|
||||||
onClick = { onToolTypeChanged(InkType.HIGHLIGHTER) },
|
radius = size.width / 2
|
||||||
isSnappingEnabled = isHighlighterSnapEnabled
|
)
|
||||||
)
|
drawCircle(
|
||||||
|
color = Color.White,
|
||||||
|
radius = size.width / 2,
|
||||||
|
style = Stroke(width = 2.dp.toPx())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(125.dp),
|
||||||
|
contentAlignment = Alignment.BottomCenter
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(28.dp),
|
||||||
|
verticalAlignment = Alignment.Bottom
|
||||||
|
) {
|
||||||
|
if (isHighlighter) {
|
||||||
|
PenItem(
|
||||||
|
type = PenType.HIGHLIGHTER,
|
||||||
|
forcedInkType = InkType.HIGHLIGHTER,
|
||||||
|
color = highlighterColor.copy(alpha = 1f),
|
||||||
|
inkColor = highlighterColor,
|
||||||
|
isSelected = selectedTool == InkType.HIGHLIGHTER,
|
||||||
|
strokeWidth = activeToolThickness,
|
||||||
|
onClick = { onToolTypeChanged(InkType.HIGHLIGHTER) },
|
||||||
|
isSnappingEnabled = isHighlighterSnapEnabled
|
||||||
|
)
|
||||||
|
|
||||||
PenItem(
|
PenItem(
|
||||||
type = PenType.HIGHLIGHTER_ROUND,
|
type = PenType.HIGHLIGHTER_ROUND,
|
||||||
forcedInkType = InkType.HIGHLIGHTER_ROUND,
|
forcedInkType = InkType.HIGHLIGHTER_ROUND,
|
||||||
color = highlighterRoundColor.copy(alpha = 1f),
|
color = highlighterRoundColor.copy(alpha = 1f),
|
||||||
inkColor = highlighterRoundColor,
|
inkColor = highlighterRoundColor,
|
||||||
isSelected = selectedTool == InkType.HIGHLIGHTER_ROUND,
|
isSelected = selectedTool == InkType.HIGHLIGHTER_ROUND,
|
||||||
strokeWidth = activeToolThickness,
|
strokeWidth = activeToolThickness,
|
||||||
onClick = { onToolTypeChanged(InkType.HIGHLIGHTER_ROUND) },
|
onClick = { onToolTypeChanged(InkType.HIGHLIGHTER_ROUND) },
|
||||||
isSnappingEnabled = isHighlighterSnapEnabled
|
isSnappingEnabled = isHighlighterSnapEnabled
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
PenItem(
|
PenItem(
|
||||||
type = PenType.FOUNTAIN_PEN,
|
type = PenType.FOUNTAIN_PEN,
|
||||||
forcedInkType = InkType.FOUNTAIN_PEN,
|
forcedInkType = InkType.FOUNTAIN_PEN,
|
||||||
color = fountainPenColor,
|
color = fountainPenColor,
|
||||||
isSelected = selectedTool == InkType.FOUNTAIN_PEN,
|
isSelected = selectedTool == InkType.FOUNTAIN_PEN,
|
||||||
strokeWidth = activeToolThickness,
|
strokeWidth = activeToolThickness,
|
||||||
onClick = { onToolTypeChanged(InkType.FOUNTAIN_PEN) }
|
onClick = { onToolTypeChanged(InkType.FOUNTAIN_PEN) }
|
||||||
)
|
)
|
||||||
|
|
||||||
PenItem(
|
PenItem(
|
||||||
type = PenType.MARKER,
|
type = PenType.MARKER,
|
||||||
forcedInkType = InkType.PEN,
|
forcedInkType = InkType.PEN,
|
||||||
color = markerColor,
|
color = markerColor,
|
||||||
isSelected = selectedTool == InkType.PEN,
|
isSelected = selectedTool == InkType.PEN,
|
||||||
strokeWidth = activeToolThickness,
|
strokeWidth = activeToolThickness,
|
||||||
onClick = { onToolTypeChanged(InkType.PEN) }
|
onClick = { onToolTypeChanged(InkType.PEN) }
|
||||||
)
|
)
|
||||||
|
|
||||||
PenItem(
|
PenItem(
|
||||||
type = PenType.PENCIL,
|
type = PenType.PENCIL,
|
||||||
forcedInkType = InkType.PENCIL,
|
forcedInkType = InkType.PENCIL,
|
||||||
color = pencilColor,
|
color = pencilColor,
|
||||||
isSelected = selectedTool == InkType.PENCIL,
|
isSelected = selectedTool == InkType.PENCIL,
|
||||||
strokeWidth = activeToolThickness,
|
strokeWidth = activeToolThickness,
|
||||||
onClick = { onToolTypeChanged(InkType.PENCIL) }
|
onClick = { onToolTypeChanged(InkType.PENCIL) }
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -262,7 +294,7 @@ fun ToolSettingsPopup(
|
||||||
valueRange = thicknessRange, isOpacity = false,
|
valueRange = thicknessRange, isOpacity = false,
|
||||||
trackColor = Color(0xFF424242),
|
trackColor = Color(0xFF424242),
|
||||||
thumbColor = Color(0xFF757575),
|
thumbColor = Color(0xFF757575),
|
||||||
activeColor = activeColor
|
activeColor = if (isEraser) Color.White else activeColor
|
||||||
)
|
)
|
||||||
|
|
||||||
// Darkness (Opacity) Slider for Highlighters
|
// Darkness (Opacity) Slider for Highlighters
|
||||||
|
|
@ -281,80 +313,82 @@ fun ToolSettingsPopup(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(Modifier.height(16.dp)) // Reduced spacing
|
if (!isEraser) {
|
||||||
|
Spacer(Modifier.height(16.dp)) // Reduced spacing
|
||||||
|
|
||||||
// --- Color Palette ---
|
// --- Color Palette ---
|
||||||
Row(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
activePalette.take(6).forEachIndexed { index, color ->
|
Row(
|
||||||
val isSelected = index == selectedPaletteIndex
|
modifier = Modifier.weight(1f),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
activePalette.take(6).forEachIndexed { index, color ->
|
||||||
|
val isSelected = index == selectedPaletteIndex
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(circleSize)
|
.size(circleSize)
|
||||||
.testTag("Palette_Item_$index")
|
.testTag("Palette_Item_$index")
|
||||||
.pointerInput(color) {
|
.pointerInput(color) {
|
||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
onTap = {
|
onTap = {
|
||||||
currentOnColorChanged(color)
|
currentOnColorChanged(color)
|
||||||
},
|
},
|
||||||
onLongPress = {
|
onLongPress = {
|
||||||
colorPickerSlotIndex = index
|
colorPickerSlotIndex = index
|
||||||
showColorPicker = true
|
showColorPicker = true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Canvas(modifier = Modifier.fillMaxSize()) {
|
Canvas(modifier = Modifier.fillMaxSize()) {
|
||||||
drawCircle(color = color.copy(alpha = 1f))
|
drawCircle(color = color.copy(alpha = 1f))
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
drawCircle(
|
drawCircle(
|
||||||
color = Color.White,
|
color = Color.White,
|
||||||
radius = size.minDimension / 2,
|
radius = size.minDimension / 2,
|
||||||
style = Stroke(width = 2.dp.toPx())
|
style = Stroke(width = 2.dp.toPx())
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(Modifier.width(16.dp))
|
Spacer(Modifier.width(16.dp))
|
||||||
|
|
||||||
// Divider
|
// Divider
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(1.dp)
|
.width(1.dp)
|
||||||
.height(circleSize)
|
.height(circleSize)
|
||||||
.background(Color.White.copy(alpha = 0.15f))
|
.background(Color.White.copy(alpha = 0.15f))
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(Modifier.width(16.dp))
|
Spacer(Modifier.width(16.dp))
|
||||||
|
|
||||||
// Spectrum / Color Wheel Button
|
// Spectrum / Color Wheel Button
|
||||||
val rainbowColors = listOf(
|
val rainbowColors = listOf(
|
||||||
Color.Red, Color.Magenta, Color.Blue, Color.Cyan, Color.Green, Color.Yellow, Color.Red
|
Color.Red, Color.Magenta, Color.Blue, Color.Cyan, Color.Green, Color.Yellow, Color.Red
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(circleSize)
|
.size(circleSize)
|
||||||
.clip(CircleShape)
|
.clip(CircleShape)
|
||||||
.background(Brush.sweepGradient(rainbowColors))
|
.background(Brush.sweepGradient(rainbowColors))
|
||||||
.clickable {
|
.clickable {
|
||||||
if (selectedPaletteIndex != -1) {
|
if (selectedPaletteIndex != -1) {
|
||||||
colorPickerSlotIndex = selectedPaletteIndex
|
colorPickerSlotIndex = selectedPaletteIndex
|
||||||
showColorPicker = true
|
showColorPicker = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
) {}
|
||||||
) {}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ data class TextStyleConfig(
|
||||||
data class AnnotationToolSettings(
|
data class AnnotationToolSettings(
|
||||||
val selectedToolName: String = "PEN",
|
val selectedToolName: String = "PEN",
|
||||||
val lastActivePenType: String = "PEN",
|
val lastActivePenType: String = "PEN",
|
||||||
|
val lastActiveHighlighterType: String = "HIGHLIGHTER",
|
||||||
val toolConfigs: Map<String, ToolConfig> = emptyMap(),
|
val toolConfigs: Map<String, ToolConfig> = emptyMap(),
|
||||||
val penPaletteArgb: List<Int> = listOf(
|
val penPaletteArgb: List<Int> = listOf(
|
||||||
android.graphics.Color.BLACK,
|
android.graphics.Color.BLACK,
|
||||||
|
|
@ -101,6 +102,12 @@ data class AnnotationToolSettings(
|
||||||
|
|
||||||
fun getPenPalette(): List<Color> = penPaletteArgb.map { Color(it) }
|
fun getPenPalette(): List<Color> = penPaletteArgb.map { Color(it) }
|
||||||
fun getHighlighterPalette(): List<Color> = highlighterPaletteArgb.map { Color(it) }
|
fun getHighlighterPalette(): List<Color> = highlighterPaletteArgb.map { Color(it) }
|
||||||
|
|
||||||
|
fun getLastHighlighterTool(): InkType = try {
|
||||||
|
InkType.valueOf(lastActiveHighlighterType)
|
||||||
|
} catch (_: Exception) {
|
||||||
|
InkType.HIGHLIGHTER
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AnnotationSettingsRepository(context: Context) {
|
class AnnotationSettingsRepository(context: Context) {
|
||||||
|
|
@ -154,6 +161,8 @@ class AnnotationSettingsRepository(context: Context) {
|
||||||
|
|
||||||
if (tool == InkType.PEN || tool == InkType.FOUNTAIN_PEN || tool == InkType.PENCIL) {
|
if (tool == InkType.PEN || tool == InkType.FOUNTAIN_PEN || tool == InkType.PENCIL) {
|
||||||
currentSettings = currentSettings.copy(lastActivePenType = tool.name)
|
currentSettings = currentSettings.copy(lastActivePenType = tool.name)
|
||||||
|
} else if (tool == InkType.HIGHLIGHTER || tool == InkType.HIGHLIGHTER_ROUND) {
|
||||||
|
currentSettings = currentSettings.copy(lastActiveHighlighterType = tool.name) // ADD THIS
|
||||||
}
|
}
|
||||||
|
|
||||||
saveSettings(currentSettings)
|
saveSettings(currentSettings)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue