-
-
Notifications
You must be signed in to change notification settings - Fork 28
Add Smart Lasso Selection feature #158
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,9 @@ | ||
| package com.ethran.notable.editor | ||
|
|
||
| import android.content.Context | ||
| import android.util.Log | ||
| import androidx.compose.ui.geometry.Offset | ||
| import com.ethran.notable.TAG | ||
| import io.shipbook.shipbooksdk.Log | ||
| import com.ethran.notable.data.datastore.GlobalAppSettings | ||
| import com.ethran.notable.editor.state.EditorState | ||
| import com.ethran.notable.editor.state.History | ||
|
|
@@ -146,6 +146,9 @@ class EditorControlTower( | |
| } | ||
|
|
||
| fun deleteSelection() { | ||
| // Clear pending smart lasso data since user has committed to the selection action | ||
| clearPendingSmartLassoData() | ||
|
|
||
| val operationList = state.selectionState.deleteSelection(page) | ||
| history.addOperationsToHistory(operationList) | ||
| state.isDrawing = true | ||
|
|
@@ -166,19 +169,28 @@ class EditorControlTower( | |
| } | ||
|
|
||
| fun duplicateSelection() { | ||
| // Clear pending smart lasso data since user has committed to the selection action | ||
| clearPendingSmartLassoData() | ||
|
|
||
| // finish ongoing movement | ||
| applySelectionDisplace() | ||
| state.selectionState.duplicateSelection() | ||
|
|
||
| } | ||
|
|
||
| fun cutSelectionToClipboard(context: Context) { | ||
| // Clear pending smart lasso data since user has committed to the selection action | ||
| clearPendingSmartLassoData() | ||
|
|
||
| state.clipboard = state.selectionState.selectionToClipboard(page.scroll, context) | ||
| deleteSelection() | ||
| showHint("Content cut to clipboard", scope) | ||
| } | ||
|
|
||
| fun copySelectionToClipboard(context: Context) { | ||
| // Clear pending smart lasso data since user has committed to the selection action | ||
| clearPendingSmartLassoData() | ||
|
|
||
| state.clipboard = state.selectionState.selectionToClipboard(page.scroll, context) | ||
| } | ||
|
|
||
|
|
@@ -230,5 +242,71 @@ class EditorControlTower( | |
|
|
||
| showHint("Pasted content from clipboard", scope) | ||
| } | ||
|
|
||
| /** | ||
| * Clears all pending smart lasso data when user commits to a selection action | ||
| */ | ||
| private fun clearPendingSmartLassoData() { | ||
| state.selectionState.pendingSmartLassoStroke = null | ||
| state.selectionState.pendingSmartLassoPen = null | ||
| state.selectionState.pendingSmartLassoStrokeSize = null | ||
| state.selectionState.pendingSmartLassoColor = null | ||
| } | ||
|
|
||
| /** | ||
| * Dismisses the current selection. If the selection was from smart lasso, | ||
| * draws the original stroke with its original pen settings instead. | ||
| */ | ||
| fun dismissSelection() { | ||
| val pendingStroke = state.selectionState.pendingSmartLassoStroke | ||
| val pendingPen = state.selectionState.pendingSmartLassoPen | ||
| val pendingStrokeSize = state.selectionState.pendingSmartLassoStrokeSize | ||
| val pendingColor = state.selectionState.pendingSmartLassoColor | ||
|
|
||
| if (pendingStroke != null && pendingPen != null && pendingStrokeSize != null && pendingColor != null) { | ||
| Log.i("SmartLasso", "User dismissed smart lasso selection, drawing the original stroke with original pen settings") | ||
| // User dismissed without using the panel, so draw the original stroke with original settings | ||
| // Save the pending data before reset clears it | ||
| val strokeToDrawCopy = pendingStroke.toList() | ||
| val penCopy = pendingPen | ||
| val strokeSizeCopy = pendingStrokeSize | ||
| val colorCopy = pendingColor | ||
|
|
||
| // Reset the selection | ||
| state.selectionState.reset() | ||
|
|
||
| // Now draw the pending stroke with its original pen settings | ||
| val strokeHistoryBatch = mutableListOf<String>() | ||
| com.ethran.notable.editor.utils.handleDraw( | ||
| page, | ||
| strokeHistoryBatch, | ||
| strokeSizeCopy, | ||
| colorCopy, | ||
| penCopy, | ||
| strokeToDrawCopy | ||
| ) | ||
|
|
||
| // Add to history | ||
| if (strokeHistoryBatch.isNotEmpty()) { | ||
| history.addOperationsToHistory( | ||
| operations = listOf( | ||
| Operation.DeleteStroke(strokeHistoryBatch) | ||
| ) | ||
| ) | ||
| } | ||
|
|
||
| state.isDrawing = true | ||
|
|
||
| // Refresh UI | ||
| scope.launch { | ||
| DrawCanvas.refreshUi.emit(Unit) | ||
| } | ||
|
Comment on lines
+267
to
+303
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should be moved to separate funtion
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, it should be done as new operation list in History(pageView: PageView), private var uncommittedOperations: OperationList = mutableListOf()And there should be functions: (There probably are better names for them) See also branch |
||
| } else { | ||
| // Normal selection dismissal | ||
| applySelectionDisplace() | ||
| state.selectionState.reset() | ||
| state.isDrawing = true | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,9 +14,11 @@ import androidx.core.graphics.createBitmap | |
| import com.ethran.notable.TAG | ||
| import com.ethran.notable.data.db.Image | ||
| import com.ethran.notable.data.db.Stroke | ||
| import com.ethran.notable.data.db.StrokePoint | ||
| import com.ethran.notable.data.model.SimplePointF | ||
| import com.ethran.notable.editor.PageView | ||
| import com.ethran.notable.editor.drawing.drawImage | ||
| import com.ethran.notable.editor.utils.Pen | ||
| import com.ethran.notable.editor.utils.imageBoundsInt | ||
| import com.ethran.notable.editor.utils.offsetImage | ||
| import com.ethran.notable.editor.utils.offsetStroke | ||
|
|
@@ -35,6 +37,13 @@ class SelectionState { | |
| var selectedStrokes by mutableStateOf<List<Stroke>?>(null) | ||
| var selectedImages by mutableStateOf<List<Image>?>(null) | ||
|
|
||
| // Smart lasso: stores the original stroke data if selection was made via smart lasso | ||
| // This allows fallback to drawing the stroke if user dismisses without using the panel | ||
| var pendingSmartLassoStroke by mutableStateOf<List<StrokePoint>?>(null) | ||
| var pendingSmartLassoPen by mutableStateOf<Pen?>(null) | ||
| var pendingSmartLassoStrokeSize by mutableStateOf<Float?>(null) | ||
| var pendingSmartLassoColor by mutableStateOf<Int?>(null) | ||
|
Comment on lines
+40
to
+45
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not the place for those, see other comments. |
||
|
|
||
| // TODO: Bitmap should be change, if scale changes. | ||
| var selectedBitmap by mutableStateOf<Bitmap?>(null) | ||
|
|
||
|
|
@@ -53,6 +62,10 @@ class SelectionState { | |
| selectionStartOffset = null | ||
| selectionDisplaceOffset = null | ||
| placementMode = null | ||
| pendingSmartLassoStroke = null | ||
| pendingSmartLassoPen = null | ||
| pendingSmartLassoStrokeSize = null | ||
| pendingSmartLassoColor = null | ||
| setAnimationMode(false) | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to check I really want to enable it. Having it set to false makes sure that I know exact state of app config. For now this PR should not make this change.