Forum Discussion

Photovor's avatar
Photovor
Visitor
9 years ago

Using registry values inside dialog?

So I'm using the new ScreenGraph APIs, and I'm showing a keyboarddialog, and I want to pre-set the text (and then save any changed text) from the registry. Any anyone provide an example of how I would do that?

My keyboard dialog looks like this:
function showdialog()
    keyboarddialog = createObject("roSGNode", "KeyboardDialog")
    keyboarddialog.backgroundUri = "pkg:/images/rsgde_dlg_bg_hd.9.png"
    keyboarddialog.buttons=["Save","Cancel"]
    keyboarddialog.title = "Enter Location ID"
    keyboarddialog.text = ScreenID
    m.top.dialog = keyboarddialog
end function


ScreenID would be blank on the first time this dialog appeared, but would then be set to the text that they entered from this screen every time after. I need this to persist in the registry.

7 Replies

  • Generally, I store my registry data as an roAssociative array formatted as a single JSON string.

    I read the registry on startup in Main(), storing what I need in global data.

    When I need to write to the registry from within a Scene, I use a Task node.

    Here's an example function to read, called from within Main():

    function getConfig() as Object
       config = {}
       registrySection = CreateObject("roRegistrySection", "MyChannel")
       configString = registrySection.Read("config")
       if configString = ""
           print "getConfig. No config registry info found"
       else
           config = ParseJson(configString)
           if Type(config) <> "roAssociativeArray"
               print "getConfig. Expecting roAssociativeArray, found: "; Type(config)
               config = {}
           end if
       end if
       return config
    end function

    Here's  the code in components/TaskRegistry.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <component name="TaskRegistry" extends="Task">
     <script type="text/brightscript" uri="pkg:/components/TaskRegistry.brs" />
     <interface>
       <field id="write" type="assocarray" />
     </interface>
    </component>

    and in components/TaskRegistry.brs

    sub init()
       m.top.functionName = "taskRun"
    end sub

    sub taskRun()
       registrySection = CreateObject("roRegistrySection", "MyChannel")
       if Type(m.top.write) <> "roAssociativeArray"
           print "TaskRegistry.brs. taskRun(). m.top.write expecting roAssociativeArray, found: "; Type(m.top.write)
       else
           value = FormatJson(m.top.write)
           if value = ""
               print "TaskRegistry.brs. taskRun(). FormatJson error"
           else
               if not registrySection.Write("config", value)
                   print "TaskRegistry.brs. taskRun(). roRegistrySection Write error"
               else if not registrySection.Flush()
                   print "TaskRegistry.brs. taskRun(). roRegistrySection Flush error"
               end if
           end if
       end if
    end sub

    To use TaskRegistry, include the following in your Scene's component:

    <TaskRegistry id="taskRegistry" />

    and write to the registry using the following code:

    ' Code in init() '
    m.taskRegistryNode = m.top.findNode("taskRegistry")

    ' Code in event-handler '
    config =  {
             key1: 42
             key2: "Forty Two"
             key3: ["blah", "blah"]
             }
    m.taskRegistryNode.write = config
    m.taskRegistryNode.control = "RUN"
  • Thank you belltown, that's exactly what I needed. Been trying to hack this together for a while now, since there are no good examples or documentation on how to do this effectively.
  • I'm still having a slight issue with accessing the config array from my screengraph screen.

    In main() I do this:
    sub Main()
        m.config = getConfig()
        showChannelSGScreen()
    end sub

    function getConfig() as Object
        print "Getting Registry Values"
        config = {}
        registrySection = CreateObject("roRegistrySection", "CampusSignage")
        configString = registrySection.Read("config")
        if configString = ""
            print "getConfig. No config registry info found"
        else
            config = ParseJson(configString)
            if Type(config) <> "roAssociativeArray"
                print "getConfig. Expecting roAssociativeArray, found: "; Type(config)
                config = {}
            end if
        end if
        return config
    end function

     And that gets my config as a global, but I can't access that inside my Screen.
  • In Main(), you need to gain access to the Global Node, which is a global super-node that's global to everything in the entire Scene Graph Application (https://sdkdocs.roku.com/display/sdkdoc/Scene+Graph+Data+Scoping). You can call your Main's Global Node reference anything you like. Roku documentation uses "m.global" (which defines a property in the BrightScript global associative array -- which is only accessible from the Main thread). Personally, I just use a local variable called "g" in Main().


    screen = CreateObject("roSGScreen")
    .
    .
    m.global = screen.getGlobalNode()

    Then you need to create a field (or fields) in the Global Node for your config data:


    m.global.addField("config", "assocarray", false)

    Then you need to assign your config object to the config field you created in the Global Node:


    m.global.config = getConfig()

    In your Scene code, you can reference fields in the Global Node like so (Note that the use of "m.global" in a Scene, versus in Main(), is required; you can't call it something else):


    print "global config: "; m.global.config
  • btpoole's avatar
    btpoole
    Channel Surfer
    "belltown" wrote:
    In Main(), you need to gain access to the Global Node, which is a global super-node that's global to everything in the entire Scene Graph Application (https://sdkdocs.roku.com/display/sdkdoc/Scene+Graph+Data+Scoping). You can call your Main's Global Node reference anything you like. Roku documentation uses "m.global" (which defines a property in the BrightScript global associative array -- which is only accessible from the Main thread). Personally, I just use a local variable called "g" in Main().


    screen = CreateObject("roSGScreen")
    .
    .
    m.global = screen.getGlobalNode()

    Then you need to create a field (or fields) in the Global Node for your config data:


    m.global.addField("config", "assocarray", false)

    Then you need to assign your config object to the config field you created in the Global Node:


    m.global.config = getConfig()

    In your Scene code, you can reference fields in the Global Node like so (Note that the use of "m.global" in a Scene, versus in Main(), is required; you can't call it something else):


    print "global config: "; m.global.config


    belltown thanks so much for the example. Using your code was great for my app but I do have a question. I am trying to delete one of the elements of the config as follows
    m.global.config.delete("mylist")
    print m.global.config

    When I do the above the print still shows the "mylist" as being part of the config. Is there something missing? Thanks for any help
  • btpoole's avatar
    btpoole
    Channel Surfer
    "belltown" wrote:
    "btpoole" wrote:
    belltown thanks so much for the example. Using your code was great for my app but I do have a question. I am trying to delete one of the elements of the config as follows
    m.global.config.delete("mylist")
    print m.global.config

    When I do the above the print still shows the "mylist" as being part of the config. Is there something missing? Thanks for any help

    Try:


    m.global.config.removeField("mylist")

    See https://sdkdocs.roku.com/display/sdkdoc/ifSGNodeField#ifSGNodeField-removeField(fieldNameasString)asBoolean

    I see my mistake. I was only removing or deleting the mylist from global but not really deleting it from the registry section it was stored in, so each time app started it was getting it from the registry. Thanks again for the code.