8 Replies Latest reply: May 23, 2012 11:54 AM by Don McKee RSS

    Checkbox visual out of sync with property value.  Work-around?

    Don McKee

      I'd like to be able to override a checkbox with code similar to this:

       

      f:checkbox {

          title = "Some Title",

          value = bind { key = 'someProperty',

              transform = function(value, fromModel)

                  if not fromModel then

                      if not userReallyWantsToDoThis() then

                          value = not value

                      end

                  end

                 

                  return value

              end,

          },

          checked_value = true,

          unchecked_value = false,

      }

       

      This works so far as setting the bound property goes, but the visual representation doesn't change if the transform is perfomed (e.g. if the incoming and outgoing "transform" values differ).  So, even if the user changed his mind, it still looks like the override didn't happen (i.e. the box is still checked/unchecked as the case may be).

       

      Has anyone else seen this behavior?  Any work-arounds?  BTW, this is on LR 3.6 -- I haven't tried any others.

       

      -Don

        • 1. Re: Checkbox visual out of sync with property value.  Work-around?
          areohbee Community Member

          Remove the clause that confines the behavior to "not fromModel", i.e.

           

                transform = function(value, fromModel)

                      if not userReallyWantsToDoThis() then

                          value = not value

                      end

                     

                      return value

                  end

           

           

          Should work.

          • 2. Re: Checkbox visual out of sync with property value.  Work-around?
            Don McKee Community Member

            The "not fromModel" clause is needed to distinguish between a user "click" and, say, the initialization of the checkbox by Lightroom.  But, that's neither here nor there -- the transform function is only invoked once per mouse-click.

             

            As an aside, before implementing this functionality in the transform function (where it belongs, I think), I had tried doing the same thing using code in a property observer to do the override.  However, when I used that mechanism I had the exact opposite problem: the UI checkbox looked the way I expected it to, but the property value (in the plug-in's preferences table) didn't "stick".

             

            -Don

            • 3. Re: Checkbox visual out of sync with property value.  Work-around?
              areohbee Community Member

              I'm not sure what to say - I've never had this trouble.

               

              But make sure you check for errors in userReallyWantsToDoThis(). e.g. pcall or function-context handler.

              • 4. Re: Checkbox visual out of sync with property value.  Work-around?
                Don McKee Community Member

                According to my instrumentation (trace, debug -- not shown in above code snippet), everything is completing cleanly.  My userReallyWantsToDoThis() just pops a confirm() dialog and returns true if 'OK' was pressed, false if 'Cancel'.  Should all be very simple stuff. 

                 

                -Don

                • 5. Re: Checkbox visual out of sync with property value.  Work-around?
                  johnrellis CommunityMVP

                  I couldn't get your approach to work either.  But I was able to use a property-table observer to make it work:

                   

                   

                  local Require = require 'Require'.path ("../common")
                  local Debug = require 'Debug'
                  require 'strict'
                  
                  local LrBinding = import 'LrBinding' 
                  local LrDialogs = import 'LrDialogs' 
                  local LrFunctionContext = import 'LrFunctionContext' 
                  local LrRecursionGuard = import 'LrRecursionGuard'
                  local LrView = import 'LrView' 
                  
                  local bind = LrView.bind 
                  local f = LrView.osFactory()
                  local recursionGuard = LrRecursionGuard ("check")
                  
                  local function userReallyWantsToDoThis (prop, key, newValue)
                      recursionGuard:performWithGuard (function ()
                          if "ok" == LrDialogs.confirm ("Do you want to do this?") then
                              prop.check = newValue
                          else
                              prop.check = not prop.check
                              end
                          end)
                      end
                  
                  LrFunctionContext.callWithContext ("", function (context) 
                      local prop = LrBinding.makePropertyTable (context) 
                      prop.check = false
                      prop:addObserver ("check", userReallyWantsToDoThis)
                      LrDialogs.presentModalDialog {title = "Test",  
                          contents = f:column {bind_to_object = prop, 
                              f:checkbox {title = "Some Title",
                                  checked_value = true, unchecked_value = false,
                                  value = bind {key = "check"}}}}
                      end)
                  
                  
                  • 6. Re: Checkbox visual out of sync with property value.  Work-around?
                    Don McKee Community Member

                    Thanks for looking at this, John.  Your solution is pretty much what I started with.  All looked like it was going peachy until I reloaded my plug-in, then the value was back to the pre-override state.  Weird, but (I swear!) true.  I'm trying to do this in the plug-in manager dialog, against the plug-in's preferences table (if it makes a difference).

                     

                    -Don

                    • 7. Re: Checkbox visual out of sync with property value.  Work-around?
                      Matt Dawson Community Member

                      [[Apologies if anyone has seen this response previously. Responded by email and it appears that never made it through to the forums.]]

                       

                      Hi Don,

                       

                      I was trying to work out the logic behind this. Let me know whether you agree with the reasoning here.

                       

                      The value is being bound to propertyTable.someProperty. Every time this property's value changes it then executes all observers including the transform function to convert the value into the value needed by the checkbox.

                       

                      In your original transform function it was synchronously resetting that exact same bound value to a different value. There are only two ways I think that situation can be handled:

                      1) when you set the property value from within the transform function, recursively call all observers (and thus the transform function) again before setting the value

                      2) suspend all observers for the property value during the transform function to avoid getting into a recursive loop

                      Looks like the team have gone with option 2) here.

                       

                      So to me this behaviour makes sense as otherwise it would be difficult to impossible to commit the property table processing with a consistent state.

                       

                      If above holds true it is possible that you don't even need the sleep() call in your async task. Setting the property value from within the async task might be enough to allow the original property table observer to commit the value in a consistent state. If the sleep() proves necessary then people who make extensive use of async tasks will need to be very careful when setting property table entries, lest they encounter intermittent issues where observers don't fire because of this very situation.

                       

                      Did that make sense?

                       

                      Matt

                      • 8. Re: Checkbox visual out of sync with property value.  Work-around?
                        Don McKee Community Member

                        Hi Matt,

                         

                        I suspect your post didn't appear because I deleted the post you were replying to.  Sorry about that. 

                         

                        Anyway, after I posted that I had success setting the property in an async task, further testing proved the results were inconsistent.  I don't remember the specifics now -- I just know that I couldn't trust the behavior to provide consistent results, so I tossed the code, and my post.

                         

                        Perhaps I'll revisit this later, but for now I'm just popping a warning when the user changes the setting (and popping another warning if he decides to change it back -- yuck).  At least this way, what you see is what you'll get.

                         

                        Thanks for looking into this.

                         

                        -Don