Closed watkyn closed 4 years ago
Analysis from @ty-wilson:
I took some time to look into this, but I am not sure it will be possible to accomplish with the current UI. Basically the Save/Upload buttons cannot be updated dynamically depending with the contents of Applications.
First, the app list is managed by an NSArrayController (executablesAC) with only specific attributes that can be accessed, for example 'ExecutablesAC.canRemove'. I couldn't find a way to add an attribute, and I assume that is why it the current build they bound them to 'canRemove' since that simulates whether an item is in the list (but not very well).
Second, to get around that I tried updating the existing IBOutlet for the save/upload buttons when items are added or removed from the app list, but this is also problematic: When the '-' button is clicked, it can only call one action, and is already bound to executablesAC.remove. If we change that to a custom IBAction within a controller, it somewhat works and we can use the model directly to remove an item (model.selectedExecutables.remove). However the issue then becomes that we cannot tell which item is selected to be removed.
So at that point, I was able to build a version where it "works" as desired, but when you click '-' it always removes the first item in the list. I seem to be running into memory issues when trying to access exeutablesAC.selectedIndex to tell which item is highlighted. I assume that is executablesAC is managed by the UI, but not really sure on that. As the 'selectedIndex' is contained by the executablesAC and not stored elsewhere, I am thinking it won't be possible to create a custom action, without some sort of memory management added.
I think we need one of the following:
add a custom bool attribute to NSArrayController so we can tell when it is empty and bind the buttons to that attribute create a way to access the selectedIndex of the current array within executablesAC so we can remove that app and update the buttons simultaneously, using some sort of memory management function to rebuild the app list to not be bound to an NSArrayController and instead build a customizable controller I don't see that 1 or 3 are realistic, 2 seems possible but is outside of my abilities currently, and might be more changes than we want for such a simple issue.
This is actually easier done than the analysis by @ty-wilson would indicate.
TLDR: change the Enabled binding away from the NSArrayController, and instead use the "PPPC Utility" object with a Model Key Path of model.selectedExecutables.@count
Explanation
The NSArrayController that handles the left-most table of applications has its contents bound to the PPPC Utility
object's Model Key Path of model.selectedExecutables
. That means we can use that same binding for the Save and Upload buttons enabled state to get direct access to the list of executables.
We just need to add .@count
on the end of the Model Key Path. When the count of objects in the array is zero, that zero is treated as a boolean false, which is perfect for our Enabled binding (we want it disabled when there are zero objects in the array). When the count of objects is more than zero, that positive integer is treated as a boolean true, which will enable the button.
Apple Developer page on Key Value Coding > Using Collection Operators
Key Value Coding is super powerful, but it's also hidden away in the views (the storyboard in this case) so it's not very discoverable.
Thanks @macblazer for your help with that binding, I made that change and submitted it as a pull request
If there are applications in the sidebar, we should not disable the save and upload buttons.
Change the logic to only disable the buttons when there are no applications in the list.