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,
|
||||
canRedo: Boolean,
|
||||
lastPenTool: InkType,
|
||||
lastHighlighterTool: InkType = InkType.HIGHLIGHTER,
|
||||
modifier: Modifier = Modifier,
|
||||
isSticky: Boolean = false,
|
||||
isMinimized: Boolean,
|
||||
|
|
@ -180,7 +181,15 @@ fun AnnotationDock(
|
|||
description = "Pen",
|
||||
size = buttonSize,
|
||||
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
|
||||
|
|
@ -195,7 +204,7 @@ fun AnnotationDock(
|
|||
onClick = {
|
||||
if (!isMinimized) {
|
||||
if (selectedTool != InkType.HIGHLIGHTER && selectedTool != InkType.HIGHLIGHTER_ROUND) {
|
||||
onToolClick(InkType.HIGHLIGHTER)
|
||||
onToolClick(lastHighlighterTool)
|
||||
} else {
|
||||
onToolClick(selectedTool)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -438,6 +438,7 @@ internal fun PdfPageComposable(
|
|||
onHighlightUpdate: (String, PdfHighlightColor) -> Unit = { _,_ -> },
|
||||
onHighlightDelete: (String) -> Unit = {},
|
||||
onTts: (Int, Int) -> Unit = { _, _ -> },
|
||||
activeToolThickness: Float = 0f
|
||||
) {
|
||||
val pdfDocumentItem = pdfDocument.item
|
||||
var bitmapState by remember { mutableStateOf(PdfThumbnailCache.get(pageIndex)) }
|
||||
|
|
@ -3775,6 +3776,7 @@ internal fun PdfPageComposable(
|
|||
isEditMode = isEditMode,
|
||||
selectedTool = selectedTool,
|
||||
eraserPosition = eraserPosition,
|
||||
activeToolThickness = activeToolThickness,
|
||||
richTextController = richTextController,
|
||||
textBoxes = textBoxes,
|
||||
selectedTextBoxId = selectedTextBoxId,
|
||||
|
|
@ -4516,6 +4518,8 @@ private fun PdfPageRenderer(
|
|||
onHighlightUpdate: (String, PdfHighlightColor) -> Unit,
|
||||
onHighlightDelete: (String) -> Unit,
|
||||
onTts: (Int, Int) -> Unit,
|
||||
activeToolThickness: Float
|
||||
|
||||
) {
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
Box(
|
||||
|
|
@ -4704,7 +4708,11 @@ private fun PdfPageRenderer(
|
|||
|
||||
if (isEditMode && selectedTool == InkType.ERASER && eraserPosition != null) {
|
||||
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(
|
||||
color = Color.White.copy(alpha = 0.3f),
|
||||
|
|
|
|||
|
|
@ -231,6 +231,7 @@ internal fun PdfVerticalReader(
|
|||
onHighlightUpdate: (String, PdfHighlightColor) -> Unit = { _,_ -> },
|
||||
onHighlightDelete: (String) -> Unit = {},
|
||||
onTts: (Int, Int) -> Unit = { _, _ -> },
|
||||
activeToolThickness: Float = 0f
|
||||
) {
|
||||
SideEffect { Timber.tag("PdfDrawPerf").v("LIST: PdfVerticalReader Recomposing.") }
|
||||
var globalEraserPosition by remember { mutableStateOf<Offset?>(null) }
|
||||
|
|
@ -1512,6 +1513,7 @@ internal fun PdfVerticalReader(
|
|||
onHighlightUpdate = onHighlightUpdate,
|
||||
onHighlightDelete = onHighlightDelete,
|
||||
onTts = onTts,
|
||||
activeToolThickness = activeToolThickness,
|
||||
onTextBoxDragStart = { box, localTopLeft, touchOffset ->
|
||||
val currentZoom = zoomAnimatable.value
|
||||
val panX = panXAnimatable.value
|
||||
|
|
@ -1911,7 +1913,11 @@ internal fun PdfVerticalReader(
|
|||
if (isEditMode && selectedTool == InkType.ERASER && globalEraserPosition != null) {
|
||||
Canvas(modifier = Modifier.fillMaxSize()) {
|
||||
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)
|
||||
|
||||
|
|
|
|||
|
|
@ -1374,8 +1374,9 @@ fun PdfViewerScreen(
|
|||
val selectedTool = toolSettings.getActiveTool()
|
||||
|
||||
val lastPenTool = toolSettings.getLastPenTool()
|
||||
val lastHighlighterTool = toolSettings.getLastHighlighterTool()
|
||||
val dockPenColor = toolSettings.getToolColor(lastPenTool)
|
||||
val dockHighlighterColor = toolSettings.getToolColor(InkType.HIGHLIGHTER)
|
||||
val dockHighlighterColor = toolSettings.getToolColor(lastHighlighterTool)
|
||||
|
||||
val activeToolColor = toolSettings.getToolColor(selectedTool)
|
||||
val activeToolThickness = toolSettings.getToolThickness(selectedTool)
|
||||
|
|
@ -2714,7 +2715,7 @@ fun PdfViewerScreen(
|
|||
annotation: PdfAnnotation,
|
||||
hitPoint: PdfPoint,
|
||||
pageAspectRatio: Float,
|
||||
threshold: Float = 0.025f
|
||||
threshold: Float
|
||||
): Boolean {
|
||||
if (annotation.points.isEmpty()) return false
|
||||
|
||||
|
|
@ -4242,7 +4243,7 @@ fun PdfViewerScreen(
|
|||
val aspectRatio = pageAspectRatios.getOrElse(pageIndex) { 1f }
|
||||
val existing = allAnnotations[pageIndex] ?: emptyList()
|
||||
val toRemove = existing.filter {
|
||||
isAnnotationHit(it, point, aspectRatio)
|
||||
isAnnotationHit(it, point, aspectRatio, activeToolThickness)
|
||||
}
|
||||
if (toRemove.isNotEmpty()) {
|
||||
val batch =
|
||||
|
|
@ -4289,7 +4290,7 @@ fun PdfViewerScreen(
|
|||
val aspectRatio = pageAspectRatios.getOrElse(pageIndex) { 1f }
|
||||
val existing = allAnnotations[pageIndex] ?: emptyList()
|
||||
val toRemove = existing.filter {
|
||||
isAnnotationHit(it, point, aspectRatio)
|
||||
isAnnotationHit(it, point, aspectRatio, activeToolThickness)
|
||||
}
|
||||
if (toRemove.isNotEmpty()) {
|
||||
val batch =
|
||||
|
|
@ -4405,6 +4406,7 @@ fun PdfViewerScreen(
|
|||
onHighlightUpdate = onHighlightUpdate,
|
||||
onHighlightDelete = onHighlightDelete,
|
||||
onTts = { pageIdx, charIdx -> startTtsWithPermissionCheck(pageIdx, charIdx) },
|
||||
activeToolThickness = currentStrokeWidthState,
|
||||
onTwoFingerSwipe = { direction ->
|
||||
coroutineScope.launch {
|
||||
val targetPage =
|
||||
|
|
@ -4632,7 +4634,7 @@ fun PdfViewerScreen(
|
|||
val aspectRatio = pageAspectRatios.getOrElse(pageIndex) { 1f }
|
||||
val existing = allAnnotations[pageIndex] ?: emptyList()
|
||||
val toRemove = existing.filter {
|
||||
isAnnotationHit(it, point, aspectRatio)
|
||||
isAnnotationHit(it, point, aspectRatio, activeToolThickness)
|
||||
}
|
||||
if (toRemove.isNotEmpty()) {
|
||||
val batch =
|
||||
|
|
@ -4670,7 +4672,7 @@ fun PdfViewerScreen(
|
|||
val aspectRatio = pageAspectRatios.getOrElse(pageIndex) { 1f }
|
||||
val existing = allAnnotations[pageIndex] ?: emptyList()
|
||||
val toRemove = existing.filter {
|
||||
isAnnotationHit(it, point, aspectRatio)
|
||||
isAnnotationHit(it, point, aspectRatio, activeToolThickness)
|
||||
}
|
||||
if (toRemove.isNotEmpty()) {
|
||||
val batch =
|
||||
|
|
@ -4737,6 +4739,7 @@ fun PdfViewerScreen(
|
|||
onHighlightUpdate = onHighlightUpdate,
|
||||
onHighlightDelete = onHighlightDelete,
|
||||
onTts = { pageIdx, charIdx -> startTtsWithPermissionCheck(pageIdx, charIdx) },
|
||||
activeToolThickness = currentStrokeWidthState,
|
||||
onLinkClicked = onLinkClickedStable,
|
||||
onInternalLinkClicked = onInternalLinkNavStable,
|
||||
bookmarks = bookmarksHolder,
|
||||
|
|
@ -6386,19 +6389,20 @@ fun PdfViewerScreen(
|
|||
activePenColor = dockPenColor,
|
||||
activeHighlighterColor = dockHighlighterColor,
|
||||
lastPenTool = lastPenTool,
|
||||
lastHighlighterTool = lastHighlighterTool,
|
||||
isStylusOnlyMode = isStylusOnlyMode,
|
||||
onToggleStylusOnlyMode = {
|
||||
isStylusOnlyMode = !isStylusOnlyMode
|
||||
saveStylusOnlyMode(context, isStylusOnlyMode)
|
||||
},
|
||||
onToolClick = { clickedTool ->
|
||||
if (clickedTool == InkType.ERASER || clickedTool == InkType.TEXT) {
|
||||
if (clickedTool == InkType.TEXT) {
|
||||
annotationSettingsRepo.updateSelectedTool(
|
||||
clickedTool
|
||||
)
|
||||
showToolSettings = false
|
||||
} 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
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ fun ToolSettingsPopup(
|
|||
onSnapToggle: (Boolean) -> Unit = {}
|
||||
) {
|
||||
val isHighlighter = selectedTool == InkType.HIGHLIGHTER || selectedTool == InkType.HIGHLIGHTER_ROUND
|
||||
val isEraser = selectedTool == InkType.ERASER
|
||||
|
||||
val activeColor = when (selectedTool) {
|
||||
InkType.FOUNTAIN_PEN -> fountainPenColor
|
||||
|
|
@ -117,6 +118,7 @@ fun ToolSettingsPopup(
|
|||
InkType.PENCIL -> pencilColor
|
||||
InkType.HIGHLIGHTER -> highlighterColor
|
||||
InkType.HIGHLIGHTER_ROUND -> highlighterRoundColor
|
||||
InkType.ERASER -> Color.White
|
||||
else -> markerColor
|
||||
}
|
||||
|
||||
|
|
@ -130,8 +132,11 @@ fun ToolSettingsPopup(
|
|||
}
|
||||
}
|
||||
|
||||
// Thickness settings
|
||||
val thicknessRange = if (isHighlighter) 0.01f..0.06f else 0.001f..0.015f
|
||||
val thicknessRange = when {
|
||||
isHighlighter -> 0.01f..0.06f
|
||||
isEraser -> 0.01f..0.1f
|
||||
else -> 0.001f..0.015f
|
||||
}
|
||||
@Suppress("UnusedExpression") if (isHighlighter) 0.005f else 0.001f
|
||||
|
||||
var showColorPicker by remember { mutableStateOf(false) }
|
||||
|
|
@ -164,6 +169,32 @@ fun ToolSettingsPopup(
|
|||
modifier = Modifier.padding(20.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
if (isEraser) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(125.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
val radiusDp = (activeToolThickness * 1000).coerceIn(10f, 100f).dp
|
||||
Box(
|
||||
modifier = Modifier.size(radiusDp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Canvas(modifier = Modifier.fillMaxSize()) {
|
||||
drawCircle(
|
||||
color = Color.White.copy(alpha = 0.3f),
|
||||
radius = size.width / 2
|
||||
)
|
||||
drawCircle(
|
||||
color = Color.White,
|
||||
radius = size.width / 2,
|
||||
style = Stroke(width = 2.dp.toPx())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
@ -226,6 +257,7 @@ fun ToolSettingsPopup(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(Modifier.height(16.dp))
|
||||
|
||||
|
|
@ -262,7 +294,7 @@ fun ToolSettingsPopup(
|
|||
valueRange = thicknessRange, isOpacity = false,
|
||||
trackColor = Color(0xFF424242),
|
||||
thumbColor = Color(0xFF757575),
|
||||
activeColor = activeColor
|
||||
activeColor = if (isEraser) Color.White else activeColor
|
||||
)
|
||||
|
||||
// Darkness (Opacity) Slider for Highlighters
|
||||
|
|
@ -281,6 +313,7 @@ fun ToolSettingsPopup(
|
|||
)
|
||||
}
|
||||
|
||||
if (!isEraser) {
|
||||
Spacer(Modifier.height(16.dp)) // Reduced spacing
|
||||
|
||||
// --- Color Palette ---
|
||||
|
|
@ -358,6 +391,7 @@ fun ToolSettingsPopup(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showColorPicker && colorPickerSlotIndex != -1) {
|
||||
val initialColor = activePalette.getOrElse(colorPickerSlotIndex) { Color.Black }
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ data class TextStyleConfig(
|
|||
data class AnnotationToolSettings(
|
||||
val selectedToolName: String = "PEN",
|
||||
val lastActivePenType: String = "PEN",
|
||||
val lastActiveHighlighterType: String = "HIGHLIGHTER",
|
||||
val toolConfigs: Map<String, ToolConfig> = emptyMap(),
|
||||
val penPaletteArgb: List<Int> = listOf(
|
||||
android.graphics.Color.BLACK,
|
||||
|
|
@ -101,6 +102,12 @@ data class AnnotationToolSettings(
|
|||
|
||||
fun getPenPalette(): List<Color> = penPaletteArgb.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) {
|
||||
|
|
@ -154,6 +161,8 @@ class AnnotationSettingsRepository(context: Context) {
|
|||
|
||||
if (tool == InkType.PEN || tool == InkType.FOUNTAIN_PEN || tool == InkType.PENCIL) {
|
||||
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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue