Skip to main content
Inspiring
July 11, 2025
Answered

SDK: inside a modal dialog how to create a mine slideshow

  • July 11, 2025
  • 1 reply
  • 329 views

After uploading images to a API web service I get a stream of information back.

I want to create a modal dialog where the information processed by the API is shown.
So there needs to be:

  1. a text area where the information text returned is updated as more info is returned.
  2. I want the currently processed image shown, but in time, this image should be refreshed by the next image being processed.

 

Receiving streaming information seems to be difficult, I want to implement pagination in the API and call from the Lightroom SDK this API every x seconds.

 

Questions:

 

  1. Is there a way to keep on adding information to a modal dialog?
    Probably the solution with f:scrolled_view with adding rows could work, but this requires the refresh the dialog at an interval and is not nice
  2. Is there a way to show the image being processed along the text area from bullit 1.
    And the image should be changed as the API returns information of a different image.
    So somekind of slideshow in the modal dialog
  3. Any other ideas?
Correct answer johnrellis

"a text area where the information text returned is updated as more info is returned."

 

Thinking about this a little more, you could use a multi-line f:static_text() or an f:simple_list() bound to a property that gets dynamically updated as new info is returned. The problem with this approach is that there is no way to scroll the control to the end.  For example, with a f:simple_list(), if you set the selection to the last item, the control won't scroll to show that item.  Here's the example above, expanded to include a dynamically updated simple_list():

local LrApplication = import "LrApplication"
local LrBinding = import "LrBinding"
local LrDialogs = import "LrDialogs"
local LrFunctionContext = import "LrFunctionContext"
local LrTasks = import "LrTasks"
local LrView = import "LrView"

local bind = LrView.bind
local catalog = LrApplication.activeCatalog ()
local f = LrView.osFactory ()

LrFunctionContext.postAsyncTaskWithContext("", function(context)
    local photos = catalog:getMultipleSelectedOrAllPhotos ()
    local prop = LrBinding.makePropertyTable (context)
    prop.items = {}

    LrTasks.startAsyncTask (function ()
        local n = 1
        while true do 
            local i = math.mod (n - 1, #photos) + 1
            prop.caption = photos [i]:getFormattedMetadata "fileName"
            prop.photo = photos [i]
            table.insert (prop.items, {title = "Cycle " .. n, value = n})
            prop.items = prop.items
            prop.value = {n}
            LrTasks.sleep (1)
            if not photos then break end 
            n = n + 1
            end
        end)

    local contents = f:column {bind_to_object = prop,
        f:static_text {title = bind "caption", width_in_chars = 25},
        f:catalog_photo {photo = bind "photo"},
        f:simple_list {items = bind "items", value = bind "value"}}

    LrDialogs.presentModalDialog {title = 'Demo', contents = contents}
    photos = nil 
    end)

1 reply

johnrellis
Legend
July 11, 2025

"Is there a way to keep on adding information to a modal dialog?
Probably the solution with f:scrolled_view with adding rows could work, but this requires the refresh the dialog at an interval and is not nice"

 

I think redisplaying the dialog via LrDialogs.stopModalWithResult() (as we discussed a while ago) is the only option. In the last many years with faster computers, the flicker isn't bad -- my Any Vision plugin's Prompt > New window uses it to let the user add new actions, which consist of many controlls that get added to an f:scrollled_view().

 

"uploading images to a API web service ... Is there a way to show the image being processed"

 

Assuming the photos are in the catalog, use f:catalog_photo(), binding the property "photo" to the image being processed. Here's a sample script showing how to change the photo dynamically:

 

--[[----------------------------------------------------------------------------
------------------------------------------------------------------------------]]

local LrApplication = import "LrApplication"
local LrBinding = import "LrBinding"
local LrDialogs = import "LrDialogs"
local LrFunctionContext = import "LrFunctionContext"
local LrTasks = import "LrTasks"
local LrView = import "LrView"

local bind = LrView.bind
local catalog = LrApplication.activeCatalog ()
local f = LrView.osFactory ()

LrFunctionContext.postAsyncTaskWithContext("", function(context)
    local photos = catalog:getMultipleSelectedOrAllPhotos ()
    local prop = LrBinding.makePropertyTable (context)

    LrTasks.startAsyncTask (function ()
        local i = 1
        while true do 
            prop.caption = photos [i]:getFormattedMetadata "fileName"
            prop.photo = photos [i]
            LrTasks.sleep (1)
            if not photos then break end 
            i = math.mod (i, #photos) + 1
            end
        end)

    local contents = f:column {bind_to_object = prop,
        f:static_text {title = bind "caption", width_in_chars = 25},
        f:catalog_photo {photo = bind "photo"}}

    LrDialogs.presentModalDialog {title = 'Demo', contents = contents}
    photos = nil 
    end)
johnrellis
johnrellisCorrect answer
Legend
July 11, 2025

"a text area where the information text returned is updated as more info is returned."

 

Thinking about this a little more, you could use a multi-line f:static_text() or an f:simple_list() bound to a property that gets dynamically updated as new info is returned. The problem with this approach is that there is no way to scroll the control to the end.  For example, with a f:simple_list(), if you set the selection to the last item, the control won't scroll to show that item.  Here's the example above, expanded to include a dynamically updated simple_list():

local LrApplication = import "LrApplication"
local LrBinding = import "LrBinding"
local LrDialogs = import "LrDialogs"
local LrFunctionContext = import "LrFunctionContext"
local LrTasks = import "LrTasks"
local LrView = import "LrView"

local bind = LrView.bind
local catalog = LrApplication.activeCatalog ()
local f = LrView.osFactory ()

LrFunctionContext.postAsyncTaskWithContext("", function(context)
    local photos = catalog:getMultipleSelectedOrAllPhotos ()
    local prop = LrBinding.makePropertyTable (context)
    prop.items = {}

    LrTasks.startAsyncTask (function ()
        local n = 1
        while true do 
            local i = math.mod (n - 1, #photos) + 1
            prop.caption = photos [i]:getFormattedMetadata "fileName"
            prop.photo = photos [i]
            table.insert (prop.items, {title = "Cycle " .. n, value = n})
            prop.items = prop.items
            prop.value = {n}
            LrTasks.sleep (1)
            if not photos then break end 
            n = n + 1
            end
        end)

    local contents = f:column {bind_to_object = prop,
        f:static_text {title = bind "caption", width_in_chars = 25},
        f:catalog_photo {photo = bind "photo"},
        f:simple_list {items = bind "items", value = bind "value"}}

    LrDialogs.presentModalDialog {title = 'Demo', contents = contents}
    photos = nil 
    end)
Inspiring
July 11, 2025

Wow John, thanks!

Fortunately, HI, human intelligence, still surpasses AI.
I tried several, but none came with a good solution and often the code was broken.