change param from code: how to disable gui?

Oh, does the paramWidget consumes the event, and so doesn’t pass it to the child…

If I get time, I’ll take a better look at this at the weekend, but right now I don’t think this is going to work for params that your module does not own, unless you want to try to reparent them in the tree…

edit: if I were trying to make this work, my next step would be debugging, I would want to see what methods are being called when and what events are generated and handled by the different widgets… I would hope that would point me in the right direction

replace paramWidget->addChild with paramWidget->parent->addChild would be my next guess

To replace a widget, you must remove it from it’s parent’s list of children.

That’s true but op doesnt want to replace it rather wants to place another widget atop it in the parent z order.

Right - child widgets are normally drawn in order, from first added to last since addChild appends. This is the default for Rack widgets. Children added later draw on top of prior children. A widget can control whether it paints under or on top of its children by overriding draw, and changing where it calls its base class draw relative to any drawing that it does.

A widget can draw children in any order it wants to by overriding draw and never calling the base class draw.

Draw order is distinct from input handling. Input events are more complicated due to the recursive dispatch of events, setting the target, etc. I wish the Rack docs went into more detail on the design and protocols for input event handling.

Yeah notice the number of times I said “I think” and “maybe” :slight_smile:

Surge does some tricky stuff to get the modulation overlays but I wouldn’t have figured it out without reading the code and stopping in the debugger

I think a parent add child and a widget that implements all the methods either a consume or blank will do it. Maybe.

Just to add a little note that might help some readers. TransparentWidget is not called that because it is visually transparent. Transparent in this case only means that mouse clicks pass through it as though it wasn’t there.

If you want to block mouse clicks, you could use an OpaqueWidget and ensure that it doesn’t draw anything. That would be visibly transparent, but would prevent mouse events getting to any widgets that were behind it.

This is how I always did on Rack v1 (if I remember correctly), but in fact it doesn’t work:

struct UnclickableLayerOpaque : OpaqueWidget {
	UnclickableLayerOpaque(Vec size, Vec pos = {0.0f, 0.0f}) {
		box.size = size;
		box.pos = pos;
	}

	void draw(const DrawArgs &args) override {
		// background
		nvgBeginPath(args.vg);
		nvgRect(args.vg, 0, 0, box.size.x, box.size.y);
		nvgFillColor(args.vg, nvgRGBA(255, 0, 0, 128));
		nvgFill(args.vg);
		nvgClosePath(args.vg);
	};
};

ParamWidget *paramWidget = getParam(16);
paramWidget->addChild(new UnclickableLayerOpaque(paramWidget->box.size));

I can still move the knob (even if I see the semi-transparent red layer above the knob). Removing the draw() function, nothing change, its the same (aside I won’t see the red layer, obviously). Am I doing it wrong? That would be the easiest way to accomplish what I need…

Well, this seems to works:

ParamWidget *paramWidget = getParam(16);
paramWidget->parent->addChild(new UnclickableLayer(paramWidget->box.size, paramWidget->box.pos));

BUT: since I need to add/remove it dynamically, remove it seems a PAIN: in fact, if later I remove the child, it will remove ALL the children (so, also the param :cry:) Which I don’t want.

Can’t remove a single child singularly?

Sure there’s a remove child method which returns you the pointer you need to free

So I would keep the weak pointer to your widget as a member then later search for the knob again find its parent search for the weak pointer remove it so you own it and delete it if found or set to null if not found

I don’t see this function? I can only see removeChild (void) which delete all the children of the input node (which one of it will be the param).

So the code you would write would be

When you add

Mywid = new invisible

Cover = find param(16)

If cover and cover parent Cover parent add mywid

When you remove

Cover = find Param 16

If cover and cover parent and cover has widget(mywid) { cover remove child mywid; delete mywid: }

Mywid = null

I wish the iPhone keyboard had backticks - lol

Yeah, adding the opaqueWidget as a child of the widget you want to disable is the wrong thing to do.

I was expecting you to add the opaqueWidget to the parent, in front (z-order) of the widget that you want to disable (which as you say, works).

You could simply change the size of that opaqueWidget whenever you want to enable/disable the knob. (change it between knobWidget->size and (0,0))

2 Likes

Sorry, but I don’t get your point. removeChild will remove all the children of the child I’ll remove (in this case, the parent or every widget, so It remove everything).

Did you mean implement my own removeChild? Damn, this is huge: need to manage lot of operations/event and such…

Yes, adding works. Removing it seems tricky… how would you do?

RemoveChild gives a pointer to it, so enumerate it’s children and reinject them into the parent. Make sure to remove them from your wrapper as you go so that they don’t get destroyed when you delete your widget.

??? Its void…

Bad memory on my part, then.

To remove it, you have to have a pointer to it, so the principle is the same. You have to add the re-parented children back.

It takes a widget argument - I linked the code above

For completion here’s the implementation. It just deletes one widget

Check everything first like parent and parent contains