Problem with a toggle button in a Toolbar


#1

Hi,

I have some trouble with setting up a toggle ToolbarButton inside a Toolbar.

I have successfully set-up a toolbar with various icons. The ToolbarItemFactory creates the ToolbarItemComponents, the commands are well triggered either via keyboard short-cuts or by clicking on the icons.

Now I want to add a toggle ToolbarButton. I simply use the other constructor of the ToolbarButton, giving two images instead of one.

Whenever I receive the related command, I manually switch the toggle state via the ToolbarItemComponent.setToggleState method to make it show the right image. Well, nothing happens. It stays on the “off” state.

Via the debugger, I can see that the “lastToggleState” is well set to true in the setToggleState method, a repaint is called, but if I click again on my icon, the “lastToggleState” is still set to false.

What am I doing wrong?

Second strange thing, is it normal that the only way to get a reference on the ToolbarButton is via the Toolbar.getItemComponent(index) method? Is there no way to make a search with the ID? I know it is probably because there can be several instances of the icon, but it seems rather fragile to use an index.

Thanks.

Julien.


#2

Hi Julien,

Have you tried calling setClickingTogglesState (true) on your ToolbarButton when you create it? This should make it behave like a normal ToggleButton.

Yes, searching with the ID wouldn’t be very useful as you can have multiple instances of a ToolbarItemComponent all using the same ID so the index is the best way to return an item from the Toolbar.

Ed


#3

Thanks for your reply.

Yes, I already tried this setClickingTogglesState method. However, it doesn’t work, it triggers a Juce assertion because I also use a Command Invoker linked to this button. Here is the comment related to the assertion:

// if you’ve got clickTogglesState turned on, you shouldn’t also connect the button
// up to be a command invoker. Instead, your command handler must flip the state of whatever
// it is that this button represents, and the button will update its state to reflect this
// in the applicationCommandListChanged() method.

So just like the comment tells me, I perform the switch myself via the setToggleState. But nothing happens…


#4

Using setToggleState should work fine. Can you post your code where you perform the switch?

Ed


#5

Well, the problem is that it’s pretty straightforward.

In my ToolbarItemFactory, I declare my Button (which is a “record on/off” button):

ToolbarItemComponent* MainToolbarItemFactory::createItem(int itemId)
{
	...
	case CommandIDGlobal::toggleRecord:
	{
		ToolbarButton* toolbarButton = new ToolbarButton(itemId, translate("Toggles the record mode"),
			Drawable::createFromImageData(BinaryData::IconRecordOff_png, BinaryData::IconRecordOff_pngSize),
			Drawable::createFromImageData(BinaryData::IconRecordOn_png, BinaryData::IconRecordOn_pngSize));
			
		toolbarButton->setCommandToTrigger(&applicationCommandManager, CommandIDGlobal::toggleRecord, true);
		//toolbarButton->setClickingTogglesState(true); // If set, Juce assertion fails!
		
		return toolbarButton;
	}
}

Then, another class is declared as an ApplicationCommandTarget to receive the command. The command is well triggered when clicking on the button.

bool MainContentComponent::perform(const InvocationInfo& info)
{
	...
	case CommandIDGlobal::toggleRecord:
		...
		recordItem->setToggleState(newState, NotificationType::dontSendNotification);
		break;
}

The “newState” is well managed (my internal value is correctly managed). As a test, if I force it to true, it does not work either. Like I posted above, by debugging the call to setToggleState, I can see that the previous value (false) is replaced by the new value (true) and that the display is triggered. Yet, nothing happened. Was a Toolbar designed to hold a Toggle Button?

Thanks,
Julien.


#6

Hi Julien,

I’ve just been taking a look at this and the code in your perform function should just flip the state variable “newState” that is represented by your toggle button and shouldn’t call setToggleState directly. The actual setting of the button state is handled internally using the ApplicationCommandInfo::isTicked flag so in your getCommandInfo method you should set the isTicked flag on or off based on the value of “newState”.

Hope this helps,
Ed


#7

Wow, this is working! I would have never thought it was meant to work like that.

Thanks a lot for your excellent support! I really appreciate this.

Julien.