Generated Gui

Hi all,

I’m coding a SysEx Manager for Renoise and during the development I ran into a couple of issues. It’s my first time coding in Lua, so I’m hoping the reason I can’t find a (better) solution to these items is because of my ignorance :)

  • Tabs
    I couldn’t find a nice way of implementing tabs. What I want is for each device (synth) to have a separate (full) page of sysex dumps in the GUI with a tab associated to it. The way I currently implemented it is with a switch. The switch can be extended to add new devices. The only case I can’t cover with the switch is the case of a single device (since a switch requires at least two).
    Since the list of sysex dumps has a “request” and a “send” button for each entry, and the list of sysex dumps differs per device I have to redraw the GUI when switching ‘tabs’. To effectuate the redraw, I have to close the current window from the code and reopen it from the Renoise application API. It’s not pretty, but it works. Is there a better way to do this?

  • Generated buttons
    The ‘request’ and ‘send’ buttons are generated in a for loop for each sysex dump in the list. When I receive sysex data I need to be able to access those buttons from the sysex callback function. I guess the only way to do this is by using an ID. Assigning the loop counter of the for loop that generates the buttons to the ID of each button, gives nicely different IDs for each button. My question is: how can I access generated IDs? Typing vb.views. to access an ID does not allow me to use variables in this reference. So how is this done?

Thanks :)

Xeryc / Inque

Have you taken a look at the “Example Tool GUI” tool in the XRNX starter pack? If not, please check it out. This tool demonstrates all of the available ViewBuilder controls, how to properly construct them, how to dynamically generate them (and correctly handle the IDs), how to dynamically toggle the visibility of controls and update the GUI without closing/reopening it, etc.

For your tabs, you could perhaps add each page of tab content to its own container such as a vb:column, then you could dynamically toggle the visibility of each container as you switch from tab to tab. Once you’ve toggled the visibility, you can call vb.views.dialog_content:resize() to refresh the GUI (where “dialog_content” refers to your instance of the dialog object itself).

For your button IDs, you should do something like:

  
vb:button {  
 id = "send_" .. tostring(loop_index),  
 text = "Send " .. tostring(loop_index)  
}  
  

Then you should have no problems accessing this via: vb.views.send_1, vb.views.send_2, etc.

You’ve seen this, right?

http://tools.renoise.com/tools/sysex-librarian

Hi dblue,

thanks for the quick response! I have studied the “Example Tool GUI” quite a bit, but could not find answers for the issues I’m trying to resolve.
Using the visibility property is an excellent suggestion. I should define a maximum number of sysex dumps that can be shown at the same time (that determines how many fields and buttons I should create upfront), refill/relabel those fields and buttons with the content for a specific tab (/ device), add a way to scroll up/down through the list and hide (if any) the unused fields and buttons. That way I don’t have to create new objects while the dialog is already being shown by Renoise. So that issue is resolved. Although out of curiosity I would like to know if it is possible to redraw an open dialog based on new dialog_content without simply closing it and opening a new one.

I know how the generate IDs. The problem I have with the IDs of generated objects is that it seems that you cannot use variable-defined strings in the references to those objects.
So using your example: a reference to button with ID = “send_1” is, as you said, “vb.views.send_1”. The ID was generated while the for loop was run. But the reference “vb.views.send_1” has to be typed out completely and it seems I cannot do something like:

  
-- user defines a button_index, say 3  
button_index = 3  
  
-- reference to this run-time determined button_index:  
vb.views.send_(("%s"):format(button_index)) ...  
  

Is there a way to do this other than:

  
if button_index == 1 then  
 vb.views.send_1 ...   
elseif button_index == 2 then  
 vb.views.send_2 ...  
elseif button_index == 3 then  
 vb.views_send_3 ...  
end  
  

Kind regards,

Xeryc

Hi Conner_Bw,

I’m aware of the SysEx-Librarian yes. A nice tool, but not exactly what I’m looking for.

The tool I’m writing looks (at the moment) like this:

2915 Screen Shot 2012-01-28 at 12.31.52 AM.png

The idea is to have for each of my synthesizers all sysex dumps for a particular song available in the tool window. The sysex dumps have a (patch) name and in the second field their sysex data (placeholder data in picture atm), along with two buttons.
When I have finished creating a patch on one of the synths, I simply have to:

  • open tool
  • press “Request” (short for request single edit buffer dump)

to store that patch in my tool. That way I don’t have to keep overwriting patches in the internal memory of my synths. It’s always quite an annoyance finding a crappy patch to overwrite :)
When I want to re-use a patch for a particular song, I can simply “Send” it to my synth from the tool sysex list. That way it’s super fast and convenient.

The tool will automatically store all sysex data in a predefined file.

It’s all still work in progress… but slowly I’m getting there. Also thanks to you guys :)

Cheers!

Xeryc

In Lua, pretty much everything is a bloody table :)

So, in many cases where you see something like “vb.views.send_1”, the dot notation is really just shorthand for accessing properties within a table.

The following examples are all valid ways of accessing the same object:

  
vb.views.send_1  
vb.views["send_1"]  
vb.views["send_" .. tostring(1)]  
vb["views"]["send_1"]  
vb["views"]["send_" .. tostring(1)]  
  

:)

Another popular method is that you simply have a custom array/table full of indexed references to all the objects you want to work with.

For example:

  
local buttons = table.create()  
  
-- create some buttons  
table.insert(buttons, vb:button { text = "button 1" })  
table.insert(buttons, vb:button { text = "button 2" })  
table.insert(buttons, vb:button { text = "button 3" })  
  
-- access a button by index  
buttons[2].text = "this is the second button"  
  

Thanks a lot dblue! You’ve been a great help. :)