9 Replies Latest reply on Aug 10, 2014 3:23 PM by areohbee

    Overlay information in a dialog?

    KlausBusse Level 1

      I would like to create a plugin that shows the AF area of an selected image (gathered from EXIF MakerNotes).

       

      As it seems close to impossible to overlay such information directly in the LR-Interface, I'm thinking of opening a dialog with the image and overlay the AF area(s).

       

      Is this possible in a dialog, or should I rather go for a WebExport?

       

      Thanks a million

       

      Klaus

        • 1. Re: Overlay information in a dialog?
          areohbee Level 5

          Good idea. Luc Renambot started a plugin to do this, but never finished it (or never released it anyway). I've been assuming he would, but it's been years now. I'm glad somebody else is taking the initiative - it's a plugin that "needs" to be done .

           

          But yes, you most definitely can overlay information using place argument when you create view items.

           

          See child layout properties in API doc (LrView).

           

          Note: consider using a non-modal dialog box, which automatically displays focus info whenever the user selects a different target photo. You could even have a multi-photo aggragate view. - that way user would not need to re-invoke the plugin for each photo he/she wants to inspect.

           

          Rob

          • 2. Re: Overlay information in a dialog?
            KlausBusse Level 1

            Hi Rob,

             

            Thanks for your answer… after a while I finally start to tackle that again… I have a few issues with the non-modal dialog box (on a Mac, LR 5.6):

             

            As soon as I click beside the dialog, it moves to the background, which makes that rather useless. I need to resort to the windows list to get it back into front.  Is this a known issue or am I ding something wrong? I'm using

            local args = {title = "Show AF Area", contents = dialogcontents};
            local result = LrDialogs.presentFloatingDialog( _PLUGIN, args)-- invoke dialog box

            to call the dialog.

            Generally it would be much nicer if we could place LRViews in the Metadata pane, however to my understanding this is yet impossible, correct?

             

            Then I'm struggling to find out, when the user is selecting another image, so I could update the information in the dialog dialog…

             

            Best regards

             

            Klaus

             

            P.S.: Any word on how to access the photo's metaData filled by your great ExifMeta plugin?

            • 3. Re: Overlay information in a dialog?
              KlausBusse Level 1

              KlausBusse wrote:

               

              P.S.: Any word on how to access the photo's metaData filled by your great ExifMeta plugin?

              Meanwhile I solved that one…

               

              LrFunctionContext.postAsyncTaskWithContext( 'Olympus AF', function( context )

              ...

              afText = photo:getPropertyForPlugin( 'com.robcole.lightroom.ExifMeta', 'Olympus_AFAreas')
              • 4. Re: Overlay information in a dialog?
                areohbee Level 5

                Thanks Klaus ,

                 

                KlausBusse wrote:


                fText = photo:getPropertyForPlugin( 'com.robcole.lightroom.ExifMeta', 'Olympus_AFAreas')

                Great. And also:

                 

                allPluginMetadata = photo:getRawMetadata( 'customMetadata' ) -- you have to iterate through all to pick out the part(s) you want.. (read the api doc..).

                • 5. Re: Overlay information in a dialog?
                  areohbee Level 5

                  Hi Klaus,

                   

                  KlausBusse wrote:

                   

                  As soon as I click beside the dialog, it moves to the background

                  There is a callback for bringing to the front (see api doc), but also: make sure you pass save_frame=... in the args, so user can position outside Lr main window.

                   

                  KlausBusse wrote:

                   

                  Generally it would be much nicer if we could place LRViews in the Metadata pane, however to my understanding this is yet impossible, correct?

                  Correct.

                   

                  |> "when the user is selecting another image"

                   

                  You have to have an async task which constantly polls target photo - and make sure you stop the task when plugin is reloaded etc. otherwise multiple tasks will accumulate - it's tricky - you need a shutdown module, and a cleanup handler. shutdown detects plugin reload, and cleanup handler makes sure the task stops in case of error etc.

                   

                  Shutdown module - LrShutdownPlugin in Info.lua (should have been called LrPluginReload, since it's only invoked when plugin is reloaded, NOT when Lr is shutdown, or when plugin is first loaded..). Often only needs to be one line - set a global boolean value to true, e.g. "_G.pluginReloaded=true".

                   

                  Cleanup handler - see api doc for LrFunctionContext.

                   

                  Task:

                  LrFunctionContext.postAsyncTaskWithContext( "Target photo change detector", function( context )
                  
                       local killTask
                  
                       context:addCleanupHandler( function( s, m )
                  
                            killTask = true
                  
                       end )
                  
                       local lastTarget
                  
                       while not killTask and not pluginReloaded do
                  
                            local target = catalog:getTargetPhoto()
                  
                            if target ~= lastTarget then
                  
                                lastTarget = target
                  
                                local worked, didntWork = LrTasks.pcall( processChangedTarget, target ) --  process new target, but errors should not kill the task, since they can easily occur if user deletes target photo in mid-processing..
                                if didntWork then
                                    debugLog( didntWork ) -- debug..
                                end
                  
                            else
                  
                                LrTasks.sleep( .1 )
                  
                            end
                  
                       end
                  
                  end )

                  *** Also, the task must stop when the floating dialog box is closed! (not shown).

                  *** Also, the task must stop when the floating dialog box is closed! (not shown).


                  • 6. Re: Overlay information in a dialog?
                    KlausBusse Level 1

                    First thanks for pointing me to the API docs… I had overlooked a number of the parameters, among others the selectionChangeObserver, which should address the selection change issue. Any hint what I would need to do to actually change the dialog content?

                     

                    How do I access the UI elements of my dialog after it's been presented?

                     

                    The toFront call from the onShow callback documentation is a bit weird, is this the call I would have to call from windowWillClose… didn't work for me, though I admit that my Lua skills still need a lot of development… or would I have to do something entirely different to keep the dialog in front?

                    My concern is that this doesn't work on the Mac at all, because the dialog is opened as a normal "Document Window". In OS X parlance a floating dialog should open as a "Panel", which would keep it automatically in front until the user closes it explicitly, and would not move into background when the user works in an underlaying window. As a "Document Window" it behaves completely according to standards, which moves it to the back as soon as the user clicks in the main interface.


                    Thanks a lot for your patience, it's appreciated


                    Klaus

                    • 7. Re: Overlay information in a dialog?
                      areohbee Level 5

                      KlausBusse wrote:

                       

                      First thanks for pointing me to the API docs… I had overlooked a number of the parameters, among others the selectionChangeObserver, which should address the selection change issue.

                      You're welcome Klaus. Unfortunately, selection-change-observer is of no use for detecting changes to (most-selected) target photo, it is only invoked when target photos change (note the 's'), i.e. the set of target photos - thus the reason for the sample code I posted.

                       

                      KlausBusse wrote:

                       

                      Any hint what I would need to do to actually change the dialog content?

                      Not sure what you mean. But the answer in general is: bind UI elements to properties of an observable table.

                       

                      KlausBusse wrote:

                       

                      How do I access the UI elements of my dialog after it's been presented?

                      Depends. For most things you can simply set those observable properties that the UI is bound to (and set change observers..), but also, you can name the UI elements (make them separate lua variables).

                       

                      KlausBusse wrote:

                       

                      The toFront call from the onShow callback documentation is a bit weird, is this the call I would have to call from windowWillClose… didn't work for me, though I admit that my Lua skills still need a lot of development… or would I have to do something entirely different to keep the dialog in front?

                      I know of know good way to keep your dialog box on top. Long-term/persistent floating dialogs are best used by people with multiple monitors.

                       

                      When you call "toFront" it brings the dialog box to the front alright, but also gives it focus, which means you can't keep it on top else user can not use Lightroom.

                       

                      It's useful for some cases (when something has happened and you know your dialog should consequently have focus), but it is NOT possible to do what you are trying to do (have it stay above Lr main window, even as user is using Lr proper), or at least I never figured out how (and I did try).

                       

                      R

                      • 8. Re: Overlay information in a dialog?
                        KlausBusse Level 1

                        Rob Cole wrote:

                        You're welcome Klaus. Unfortunately, selection-change-observer is of no use for detecting changes to (most-selected) target photo, it is only invoked when target photos change (note the 's'), i.e. the set of target photos - thus the reason for the sample code I posted.

                        Actually I'm not yet looking for changes in the target photo – I will have to do in a later step to catch edge cases like a user who is cropping an image. Right now I'm happy if I get a changing selection. This works so far, however, the function seems to be called in a blocking context, which means that it doesn't work for accessing the Metadata. Right now the code here looks like this:

                         

                        function selectionChanged()

                          catalog = LrApplication.activeCatalog()

                          _G.myLogger:trace(catalog)

                          photo = catalog:getTargetPhoto()

                          _G.myLogger:trace(photo)

                          aftext = refreshMetadata(photo)

                          _G.myLogger:trace(aftext)

                          _G.myLogger:type(aftext)

                          return photo, aftext

                        end

                         

                        function  userChangedSelection()

                          _G.myLogger:trace('UserChangedSelection' )

                          photo, aftext = selectionChanged()

                        end

                         

                        The logger gets the changing selection, but refreshMetadata is not successfully called.

                         

                        function refreshMetadata ( photo )

                          return photo:getPropertyForPlugin( 'com.robcole.lightroom.ExifMeta', 'Olympus_AFAreas')

                        end

                         

                        selectionChanged() works fine when called during the dialog setup. I think that I must somehow run that task in an unblocking way, but haven't found out yet how to do that correctly.

                         

                        Rob Cole wrote:

                        Not sure what you mean. But the answer in general is: bind UI elements to properties of an observable table.

                        KlausBusse wrote:

                        How do I access the UI elements of my dialog after it's been presented?

                        Depends. For most things you can simply set those observable properties that the UI is bound to (and set change observers..), but also, you can name the UI elements (make them separate lua variables).

                         

                         

                        I still struggling to get my head around that binding concept – any idea how that compares to KVO, or any helpful pointers about that concept in general? I'm sure that I'm missing some basic understanding here. I'm a seasoned Objective-C developer, Lua is new to me…

                         

                        Rob Cole wrote:

                        I know of no good way to keep your dialog box on top. Long-term/persistent floating dialogs are best used by people with multiple monitors.

                        It's useful for some cases (when something has happened and you know your dialog should consequently have focus), but it is NOT possible to do what you are trying to do (have it stay above Lr main window, even as user is using Lr proper), or at least I never figured out how (and I did try).

                        IMO this is a quite limiting implementation of that floating dialog in the SDK… it basically limits its use to Multi-Scree scenarios or the always on top scenario you have described :-/  Well, let's hope that Adobe makes some progress on this front, currently we've to live with it.

                        Which of course raises the next question: How to identify if the dialog is already open… and then bring the existing dialog to the top instead of creating a new one.

                         

                        So many questions, you are earning a lot of Karma points here…

                         

                        THANKS!

                         

                        Klaus

                        • 9. Re: Overlay information in a dialog?
                          areohbee Level 5

                          There are TONS of examples of all this stuff in all of my plugins which come with source code here:

                           

                          robcole.com - Products & Services

                           

                          And also be sure to pour over the programmer's guide (pdf doc), as well as the api doc (html) in the SDK.

                           

                          KlausBusse wrote:

                           

                          Rob Cole wrote:

                          You're welcome Klaus. Unfortunately, selection-change-observer is of no use for detecting changes to (most-selected) target photo, it is only invoked when target photos change (note the 's'), i.e. the set of target photos - thus the reason for the sample code I posted.

                          Actually I'm not yet looking for changes in the target photo – I will have to do in a later step to catch edge cases like a user who is cropping an image. Right now I'm happy if I get a changing selection. This works so far, however, the function seems to be called in a blocking context, which means that it doesn't work for accessing the Metadata. Right now the code here looks like this:

                           

                          function selectionChanged()

                            catalog = LrApplication.activeCatalog()

                            _G.myLogger:trace(catalog)

                            photo = catalog:getTargetPhoto()

                            _G.myLogger:trace(photo)

                            aftext = refreshMetadata(photo)

                            _G.myLogger:trace(aftext)

                            _G.myLogger:type(aftext)

                            return photo, aftext

                          end

                           

                          function  userChangedSelection()

                            _G.myLogger:trace('UserChangedSelection' )

                            photo, aftext = selectionChanged()

                          end

                           

                          The logger gets the changing selection, but refreshMetadata is not successfully called.

                           

                          function refreshMetadata ( photo )

                            return photo:getPropertyForPlugin( 'com.robcole.lightroom.ExifMeta', 'Olympus_AFAreas')

                          end

                           

                          selectionChanged() works fine when called during the dialog setup. I think that I must somehow run that task in an unblocking way, but haven't found out yet how to do that correctly.

                           

                          You need to put the contents of the selectionChanged function in an async task, e.g.

                          LrFunctionContext.postAsyncTaskWithContext( "selection-changed", function( context )

                              -- same contents as currently in selectionChanged function.

                          end )

                           

                          *** But note: you may need to handle the potential for recursion, which could happen if this task hasn't finished when the user's (or plugin initiated..) next selection begins.

                           

                           

                          KlausBusse wrote:

                          Rob Cole wrote:

                          Not sure what you mean. But the answer in general is: bind UI elements to properties of an observable table.

                          KlausBusse wrote:

                          How do I access the UI elements of my dialog after it's been presented?

                          Depends. For most things you can simply set those observable properties that the UI is bound to (and set change observers..), but also, you can name the UI elements (make them separate lua variables).

                           

                           

                          I still struggling to get my head around that binding concept – any idea how that compares to KVO, or any helpful pointers about that concept in general? I'm sure that I'm missing some basic understanding here. I'm a seasoned Objective-C developer, Lua is new to me…

                           

                           

                          I wrote some info about it (Home | Lightroom Plugin Development Project | Assembla), but it's standard lua plugin UI stuff, i.e. you can read examples and docs and experiment.. - not sure what to say in general..

                           

                           

                          KlausBusse wrote:

                           

                          Rob Cole wrote:

                          I know of no good way to keep your dialog box on top. Long-term/persistent floating dialogs are best used by people with multiple monitors.

                          It's useful for some cases (when something has happened and you know your dialog should consequently have focus), but it is NOT possible to do what you are trying to do (have it stay above Lr main window, even as user is using Lr proper), or at least I never figured out how (and I did try).

                          IMO this is a quite limiting implementation of that floating dialog in the SDK… it basically limits its use to Multi-Scree scenarios or the always on top scenario you have described :-/  Well, let's hope that Adobe makes some progress on this front, currently we've to live with it.

                          Which of course raises the next question: How to identify if the dialog is already open… and then bring the existing dialog to the top instead of creating a new one.

                           

                          So many questions, you are earning a lot of Karma points here…

                           

                          THANKS!

                           

                          Klaus

                           

                          Agreed - in order to keep a non-modal dialog on top, it essentially becomes a modal dialog!

                           

                          You're welcome and good luck..

                           

                          R