Is there a component to make the collapsible panes in HISE?
-
@d-healey Do you mean, by making a chain reaction by listening to surrounding components state or something similar?
-
you can dynamically resize a panel, so in this case you would have a top part of the panel be a place where you click to collapse/expand.
just enable all callbacks, check for mouse y and if it's within your height limit, either expand it or collapse it, then call repaint and update the graphics.
like David said, broadcasters are helpful here because if you have multiple in a column, you'll need to update the Y position of other panels as well. If you have a broadcaster, you can just add a function that does this for each panel that you add, letting you have a dynamic system that you can move between projects or update by easily adding or removing these panels.
-
@aaronventure Right! That all makes sense. I'll just have to force myself to use the broadcaster then (I went through David's tutorial but I haven't used it in my workflow yet).
-
The whole system is just three parts.
- Create the broadcaster itself and get its reference into a const
- Decide what you're attaching it to, if anything (if attached, it will trigger automatically, which requires a specific constructor in step 1, which is done automatically if you go through the wizard). In this case you can try attaching it to the component property change (in this case height). If not, you can call it manually from the mouse callbacks of panels.
- Add functions (listeners) that will execute when it triggers
-
@aaronventure Thanks :) Working on it now.
-
Here's a quick little example with two panels and a button.
HiseSnippet 1042.3ocsV0saaaCElxIJH1aYXEXWsqHztwYHKURyMwqcAMyNNaFqI0nNKn.CcELTzVDQhTPhNMtE4IX2rGoc4dL1CvtXuAcGperkmcShM13EB57G4m9zgmyoWrjxRRjwHiZmMNhgL9Xy9iEJ+19Dt.08HjwVlWP6QDrfyXIJTqwQjjDlGxvXsuW6hQ00Qoq+9osHADAkMUEBctjSYOiGxUS016vejGDbLwicFOrj2MNrKUJZKCji.3rloMJhPujLjcJQ6VESzOPR7QFeoomSCmAMoj8Z5zvkRcatu62rOkQFLfsmyi1uQyAMFPn1tHiM53wUx39Jhhk.aZKo2399x2HxNfy4I7KBXZAGTe3jyTiZ6yC75UvMIHjw58lxTqkwTel4IbO9D8SYrOM0.dZDkIMiJ2FjbVBHYTBRqmAoGX1mFyiTSsnwyGY1UnXw.kvlAJY9hp7WqY1VBdHT6FRtjcbLHLIh56YauCFdr8SpU6gOD2JVR7njDvL1iMfK3JtTTC9yknvWQhwWPeAKg+VF9.bGwPtfsKMlAeqkBr96r3dVOFaU3q0NXKR7vDP2OaQkgQRAfFs1qHAiXVu5F3zKbdWhRQn9mIaW334Zmpa0ZjRIEN5vrzncZ.ddS7EnlHVrZ7y3.RD.VrRStSi5MbOku9k7ufHsErKnYvHAU+cVmK7XWuCdBF2AmhvseWspwL0nXQlL9fCvN3mhaXaieL1019I0tYYIP2kgAc+vTXT9W7GfNcmmOy4HNKYgryLjq68gccWY1s.7yyyPJI9qxzlStKOjt9+N3TFHvpXOvRwoRE64h5aWCbt1M0v+aSCFrPa5qjwxf..wKxrt1Y7sEXcwnvKXwEHsvQnVwrEf139U.hlUgnjiRQWH284Qrb4ikAd5BK52mubEJuDC71O08HhhnqfkqaZ9Fn6H1UPOir5YUMOhkboRFA65jenHCSUp0OIuZW18dD2SGPdQ.z0SZr76AGNdhve91CSHWw5J5EyRXJcYPTocdyrcdqh5n5bhzMdSyrKBk1WXMtrPZ9MnXi+HWgOiOzWCWiew.g3JVXQyspa7qu5yeu1moZcKqdYvjaJllbpKFS+lwciouP8sKBSEpQy2uA5zI8FEPTy19SOXPtAHkbldN59JhDtZb4AGVhdh12ZOw6KDefYOth5uXLVYAXDRV++.i4SRrkYGXzEpZJ.W273WtpiMbGG+KjiTbwvSHpXNj3Xd5nv9vuZJCNcAjNknSNpnSAyjs0xZFnOS3kJ7dXkazQKajazovHJjPikullUHROqxloZ.LIRmkqp4IZYrCJs3TYdNDFc50T5ra0bA5tpA90qZfMV0.ezpF3dqZf6upA17tCTOY62MRICyt1fPmzqSZ0bCiNBBjAllsh9Gci.ghA
The first broadcaster is attached to the button's value, and when it changes it updates panel1's width.
The second broadcaster is attached to panel1's width and when it changes it updates panel2's width and x position.
-
On a side note here I may have found a bug, or I am scripting something wrong:
I am doing a factory method for 2 panels and the header of is deriving it's name from a unique "name" argument, but the second panel name is overwriting the first one:
Content.makeFrontInterface(10000, 700); const Panel1 = createCollapsiblePanel("Panel1", [100, 100, 800, 200], 15, 2) const Panel2 = createCollapsiblePanel("Why is this overwriting the first name??", [100, 300, 800, 200], 15, 2) inline function createCollapsiblePanel(name, area, headerSize, margins) { local panel = Content.addPanel(name,0,0); Content.setPropertiesFromJSON(name, { "x": area[0], "y": area[1], "width": area[2], "height": area[3], "borderRadius": 0.0, "allowCallbacks": "All Callbacks", "opaque": true, "visible": true }); // Set the initial state to expanded panel.data.isExpanded = true; // mouse callback panel.setMouseCallback(function[area, headerSize](event) { var a = this.getLocalBounds(0); var clickHeaderArea = [a[0], a[1], a[2], headerSize]; // set the expanded state data if (event.clicked && event.y <= headerSize) { this.data.isExpanded = !this.data.isExpanded; } if (event.clicked && this.data.isExpanded) { // Expand the panel this.set("height", area[3]); this.repaint(); } else if (event.clicked && !this.data.isExpanded) { // Collapse the panel this.set("height", headerSize); this.repaint(); } }); // paint routine panel.setPaintRoutine(function[name, headerSize, margins](g) { var a = this.getLocalBounds(0); // fill main content area g.setColour(Colours.grey); g.fillRect( [a[0] + margins, a[1] + headerSize, a[2] - margins * 2, a[3] - headerSize -margins ]); // draw text on header g.setColour(Colours.white); g.setFont("Oxygen", headerSize * 0.8); var textArea = [ a[0], a[1], a[2], headerSize, ]; g.drawAlignedText(name, textArea, "centred"); }); };
I'm not sure how "name" is not a unique argument for each paint routine.
-
@VirtualVirgin
What do you mean by overwriting? When I load your script I see two panels created.Oh I see the UI is massive, I needed to scroll along. You might want to reduce that a lot, I don't know anyone with a 10000px wide monitor.
-
@VirtualVirgin Ok the issue is that you are passing in the arguments to the paint routine as lambda values. Instead you should set them as properties of the panel, so the name is the panel's ID or its text, for the headerSize and margin you could make use of the borderSize and borderRadius properties, or just store them within the panel's data object.
-
@d-healey said in Is there a component to make the collapsible panes in HISE?:
@VirtualVirgin
What do you mean by overwriting? When I load your script I see two panels created.Oh I see the UI is massive, I needed to scroll along. You might want to reduce that a lot, I don't know anyone with a 10000px wide monitor.
HAHAHA! Sorry, just an extra "0" by mistake.
-
@d-healey said in Is there a component to make the collapsible panes in HISE?:
@VirtualVirgin Ok the issue is that you are passing in the arguments to the paint routine as lambda values. Instead you should set them as properties of the panel, so the name is the panel's ID or its text, for the headerSize and margin you could make use of the borderSize and borderRadius properties, or just store them within the panel's data object.
So what is a "lambda value"? When I look that up I get a metric for heat conductivity.
Why does the inline function treat the name as unique for when creating the component ID (you can see the component names in the component list are unique) but not for the header text?
Also, why is the "area" argument input seen as unique (the panels are created in different positions), but the headerSize is not (if I change the headerSize of panel2 it changes both)?
I will store all of the relevant data to the panels, but just curious about this disambiguation principle of the variables involved.
-
@VirtualVirgin A lambda value in this context is an outside local variable that you are passing into a function that doesn't otherwise accept additional arguments. Christoph explains a little more about it here.
For the most part I avoid them and use other methods to pass data into functions, in the case of panel's you should always keep the data self contained within the panel's data object.
There are a few occasions when I've found lambdas useful, like passing values in message boxes to be used in the user's response which is asynchronous.
@VirtualVirgin said in Is there a component to make the collapsible panes in HISE?:
Why does the inline function treat the name as unique for when creating the component ID
At that point you are passing the value into the inline function. But when you get to the regular function of the paint routine some magic has happened and the value is treated differently - not sure of the exact reason, but something to do with it not being a local variable probably.
@VirtualVirgin said in Is there a component to make the collapsible panes in HISE?:
Also, why is the "area" argument input seen as unique (the panels are created in different positions), but the headerSize is not (if I change the headerSize of panel2 it changes both)?
The area isn't being passed into the paint routine and although you're passing it into the mouse callback it isn't used there. So it's the same issue as the name, you're passing in the headerSize as a lambda.
Correction, area is used in the mouse callback, but only on click and it's the same value for both panels - I suspect you will hit the same issue if you use different heights.
-
@d-healey Thanks but I'm still confused.
Here I store the "name" argument in panel.data.text,
then I use that later to draw the text and I am still getting the disambiguation problem.Also, I changed the header size to unique values for each panel and the mouseCallback definitely treats the lambdas as unique values for the 2 panels.
Content.makeFrontInterface(1000, 700); const Panel1 = createCollapsiblePanel("Panel1", [100, 100, 500, 100], 15, 2) const Panel2 = createCollapsiblePanel("Why is this overwriting the first name??", [100, 300, 800, 200], 90, 2) inline function createCollapsiblePanel(name, area, headerSize, margins) { local panel = Content.addPanel(name,0,0); Content.setPropertiesFromJSON(name, { "x": area[0], "y": area[1], "width": area[2], "height": area[3], "borderRadius": 0.0, "allowCallbacks": "All Callbacks", "opaque": true, "visible": true }); panel.data.text = name; // Set the initial state to expanded panel.data.isExpanded = true; // mouse callback panel.setMouseCallback(function[area, headerSize](event) { var a = this.getLocalBounds(0); var clickHeaderArea = [a[0], a[1], a[2], headerSize]; // set the expanded state data if (event.clicked && event.y <= headerSize) { this.data.isExpanded = !this.data.isExpanded; } if (event.clicked && this.data.isExpanded) { // Expand the panel this.set("height", area[3]); this.repaint(); } else if (event.clicked && !this.data.isExpanded) { // Collapse the panel this.set("height", headerSize); this.repaint(); } }); // paint routine panel.setPaintRoutine(function[panel, headerSize, margins](g) { var a = this.getLocalBounds(0); // fill main content area g.setColour(Colours.grey); g.fillRect( [a[0] + margins, a[1] + headerSize, a[2] - margins * 2, a[3] - headerSize -margins ]); var text = panel.data.text; // draw text on header g.setColour(Colours.white); g.setFont("Oxygen", headerSize * 0.75); var textArea = [ a[0], a[1], a[2], headerSize, ]; g.drawAlignedText(text, textArea, "centred"); }); };
-
@VirtualVirgin You need to use
this.data.text
-
@d-healey said in Is there a component to make the collapsible panes in HISE?:
@VirtualVirgin You need to use
this.data.text
Sorry, just caught that before you wrote back!!
Your responses are lightning fast...