Skip to content
Snippets Groups Projects
Commit c9f182eb authored by Elvin Holst's avatar Elvin Holst Committed by Dennis Abrikossov
Browse files

Fix loop block drag behaviour to ensure loop begin/end are draggable and come in correct order

parent 850e6fa9
No related branches found
No related tags found
4 merge requests!18Merging dev into main,!17Merge Dev into main,!16Sprint 1 done, mergin to main,!5Fix loop block drag behaviour to ensure loop begin/end are draggable and come in correct order
......@@ -38,8 +38,8 @@ error: failed to push some refs to 'https://github.com/eliasjlara/PUM-04.git'
This is a safety precaution to keep bugs and non-approved code from the most important branch, the main one! To start coding on a ticket, you can follow these steps as a guide:
#### Steps on your local machine
1. Check that you're on the main branch using `git branch`, if you're not, do `git checkout main`.
2. Pull the latest changes from main using `git pull`.
1. Check that you're on the Development branch using `git branch`, if you're not, do `git checkout Development`.
2. Pull the latest changes from Development using `git pull`.
3. Create a branch with a name relating to the ticket name using `git checkout -b <good-name>`.
4. Implement your changes on this branch.
5. When ready, push your changes following standard procedure:
......@@ -66,10 +66,10 @@ Navigate over to the link in the message, or if this isn't the first time you pu
2. You should now be directed to a page that looks like this: <img width="1065" alt="Update README md #10" src="https://github.com/eliasjlara/PUM-04/assets/94451739/169fc8a6-ec10-4fd4-94ba-7da0d680f1ca">
Congratulations, you have now created a PR! This is where all updates added to the branch will be shown. If you continue working on the branch, for example if you forgot a bug, each commit will be shown on the timeline, creating a simple way to keep track of everything that has happened. Also, notice the big red crosses, don't be alarmed, we will take care of this in the next step.
3. Before we can merge this pull request we first need someone else to look at it, this is the safety precaution previously mentioned. To request a review from someone you either click on the cogwheel that belongs to the reviewers tab on the to right of the page, and choose a specific person to review the PR. The easiest way however would probably just be to send the link in discord and ask for a review.
4. Once the PR is reviewed and approved, you can now go ahead and merge the PR into main!
4. Once the PR is reviewed and approved, you can now go ahead and merge the PR into Development!
5. After merging you might be given an option to delete the branch, I would recommend that you do it to keep branches clean but this is up to you.
Wow, your code feature is now real since it's implemented on main 🥳🎉. This should be it for someone who is developing, if someone asked you to review a PR, check out the ["Approve a pull request" section](#approve-a-pull-request).
Wow, your code feature is now real since it's implemented on Development 🥳🎉. This should be it for someone who is developing, if someone asked you to review a PR, check out the ["Approve a pull request" section](#approve-a-pull-request).
---
......@@ -82,12 +82,12 @@ TODO: Write the rest about our iterative development
### Approve a pull request
So, someone has asked you to review a pull request... well, don't worry. Here is a guide on how to do it step by step.
1. First off, reviewing a pr isn't anything special, you simply want to check that all the code that the author wants to merge into main looks good. The simplest way to check is using the `Files changed` tab on the pr page. When actually checking the code, there is no specific way to do this so go ahead and do it in what ever way is best for you, BUT, be thorough, we don't want any errors in main just because you approved the pull request without looking!
1. First off, reviewing a pr isn't anything special, you simply want to check that all the code that the author wants to merge into Development looks good. The simplest way to check is using the `Files changed` tab on the pr page. When actually checking the code, there is no specific way to do this so go ahead and do it in what ever way is best for you, BUT, be thorough, we don't want any errors in Development just because you approved the pull request without looking!
2. If there are any comments you want to add:
- The simplest way to add a comment is to click the line where you have a comment and then simply write the comment and post it.
- After the author of the pull request has changed or answered your comments, and it now looks good to you, press the `resolve conversation` button to "remove" the comment.
3. When the pr looks good. Head over to the `Files changed` tab again and press the `Review changes` button, select `Approve` and then submit the review.
4. The pr should now be reviewed and the author can merge it into main.
4. The pr should now be reviewed and the author can merge it into Development.
<br/>
......
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
</set>
</option>
</component>
</project>
\ No newline at end of file
......@@ -683,6 +683,7 @@ fun UserButtons(
else
{
// Execute next action
if((curr - 1) < actionsInSequenceBar.size)
{
// Sends action to ROS
......@@ -700,6 +701,7 @@ fun UserButtons(
// If loop start encountered
if (action.name == "LOOP START")
{
println("IN loop Start")
if (!isLooping)
{
loopCounter = (action.data.value).toInt()
......@@ -810,8 +812,9 @@ private fun addActionToSequenceBar(action: BaseAction, actionsInSequenceBar: Mut
if (action.name == "LOOP") {
// For LOOP, add LOOP START and LOOP END together
val loopStart = SpecialAction(id = 2, name = "LOOP START", isActive = mutableStateOf(true), isReorderable = false, data = mutableStateOf("1"), icon = mutableStateOf(Icons.Outlined.Repeat), cardColor = mutableStateOf(specialActionColor), duration = 5.0f)
val loopEnd = SpecialAction(id = 2, name = "LOOP END", isActive = mutableStateOf(true), isReorderable = false, data = mutableStateOf(""), icon = mutableStateOf(Icons.Outlined.Repeat), cardColor = mutableStateOf(specialActionColor), duration = 1.0f)
// TODO: LOOP setting action settings are defind in two seperet areas HERE and in ActionsData.kt
val loopStart = SpecialAction(id = 2, name = "LOOP START", isActive = mutableStateOf(true), isReorderable = true, data = mutableStateOf("1"), icon = mutableStateOf(Icons.Outlined.Repeat), cardColor = mutableStateOf(specialActionColor), duration = 5.0f)
val loopEnd = SpecialAction(id = 2, name = "LOOP END", isActive = mutableStateOf(true), isReorderable = true, data = mutableStateOf(""), icon = mutableStateOf(Icons.Outlined.Repeat), cardColor = mutableStateOf(specialActionColor), duration = 1.0f)
val copiedLoopStart = loopStart.copy(data = mutableStateOf(loopStart.data.value), icon = mutableStateOf(loopStart.icon.value))
val copiedLoopEnd = loopEnd.copy(data = mutableStateOf(loopEnd.data.value), icon = mutableStateOf(loopEnd.icon.value))
......
......@@ -16,7 +16,6 @@ val moveActionColor = Color(0xff6c779c) // Color for move actions
val specialActionColor = Color(0xff435159) // Color for special actions
val activeColor = Color(0xFF5B7A8C) // Color indicating an active state
val inActiveColor = Color(0xff8A8A8A) // Color indicating an inactive state
/**
* Represents the base attributes of an action.
*
......
......@@ -33,7 +33,6 @@ import androidx.compose.runtime.key
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
......@@ -64,7 +63,6 @@ import com.example.aida.popups.PopupLoop
import androidx.compose.ui.platform.LocalContext
import com.example.aida.viewmodels.MainViewModel
import java.util.Locale
/**
* Displays a horizontal "sequence bar" where users can arrange and configure actions.
*
......@@ -222,6 +220,8 @@ fun SequenceBar(
.zIndex(2f)
)
// Reorderable row of actions
// Allows drag-and-drop reordering if items permit it.
ReorderableRow(
......@@ -235,13 +235,17 @@ fun SequenceBar(
horizontalArrangement = Arrangement.spacedBy(12 .dp),
list = actionsInSequenceBar.toList(),
onSettle = { fromIndex, toIndex ->
val fromItem = actionsInSequenceBar[fromIndex]
// Only reorder if the action allows reordering
if (fromItem.isReorderable) {
actionsInSequenceBar.add(toIndex, actionsInSequenceBar.removeAt(fromIndex))
} else {
println("Action is not reorderable, no action taken.")
if (fromIndex in actionsInSequenceBar.indices && toIndex in actionsInSequenceBar.indices) {
val fromItem = actionsInSequenceBar[fromIndex]
// Only reorder if the action allows reordering
if (fromItem.isReorderable) {
actionsInSequenceBar.add(
toIndex,
actionsInSequenceBar.removeAt(fromIndex)
)
}else {
Log.e("SequenceBar, onSettle", "Error: fromIndex or to Index out of bounds in onSettle.")
}
}
},
onMove = {
......@@ -279,6 +283,7 @@ fun SequenceBar(
index - 1,
actionsInSequenceBar.removeAt(index)
)
true
} else {
false
......@@ -293,6 +298,7 @@ fun SequenceBar(
index + 1,
actionsInSequenceBar.removeAt(index)
)
true
} else {
false
......@@ -434,8 +440,6 @@ fun SequenceBar(
textAlign = TextAlign.Center,
fontWeight = FontWeight.Bold,
)
}
}
// If this is a special action (except LOOP END), show a settings button to open popup
......@@ -491,6 +495,8 @@ fun SequenceBar(
}
}
}
sortLoopButtons(actionsInSequenceBar)
}
/**
......@@ -591,7 +597,7 @@ fun TimeLine()
.fillMaxHeight()
.width(160.dp)
.background(Color(0x4D099D0B))
) {}
)
}
}
......@@ -718,5 +724,55 @@ fun DurationCountdown(
}
/**
* Sorts the sequence to ensure that loop ends don't occur before their corresponding loop begin.
*
* @param actionsInSequenceBar A mutable list (state) of actions to sort.
*/
private fun sortLoopButtons(actionsInSequenceBar: SnapshotStateList<BaseAction>) {
var loopBeginIndex = 0 // Current left index
var loopEndIndex = actionsInSequenceBar.size - 1 // Current right index
var counterBegin = 0 // Keeps track of loop starts encountered
var counterEnd = 0 // Keeps track of loop ends encountered
// Keep 2 indices, iterate from both ends until they reach eachother
while (loopBeginIndex < loopEndIndex) {
if (actionsInSequenceBar[loopBeginIndex].name == "LOOP END" && actionsInSequenceBar[loopEndIndex].name == "LOOP START") {
if (counterBegin == 0 && counterEnd == 0) {
// Encountered a loop begin and corresponding end in incorrect order, swap them
// TODO: Check why add does not do the expected effect
val temp = actionsInSequenceBar[loopBeginIndex]
actionsInSequenceBar[loopBeginIndex] = actionsInSequenceBar[loopEndIndex]
actionsInSequenceBar[loopEndIndex] = temp
}
if (counterBegin != 0) {
loopBeginIndex++
counterBegin--
}
if (counterEnd != 0) {
loopEndIndex--
counterEnd--
}
}
// If the left index has encountered a loop end, stay there, otherwise keep going
if (actionsInSequenceBar[loopBeginIndex].name != "LOOP END") {
// If the left index is on a loop begin, increment the loop begin counter
if (actionsInSequenceBar[loopBeginIndex].name == "LOOP START")
counterBegin++
loopBeginIndex++
}
// If the right index has encountered a loop start, stay there, otherwise keep going
if (actionsInSequenceBar[loopEndIndex].name != "LOOP START") {
// If the right index is on a loop end, increment the loop begin counter
if (actionsInSequenceBar[loopEndIndex].name == "LOOP END")
counterEnd++
loopEndIndex--
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment