FeathersUI : Customizing label for a particular Alert box

The message is showing a scrollbar beneath it, that shifts the text one side.
I am using a global Alert style having label width of 450px for other Alert boxes.
But I want some exceptions for this feedback Alert.

Screen Shot 2022-10-12 at 2.51.27 PM

To customize the label of another alert box to show feedback within 300px I am using following code:
But it seems messageLabelFactory() is never called.


alert_Al =  Alert.show("Time: " + timerLabel.text  +"\n Clicks: " + clickNum_Int,"Great Job!", ["Play Again"]);
    			 	alert_Al.width = 400;
    			 	alert_Al.messageLabelFactory = () -> {
    				var message = new Label();
    				var tf = new TextFormat("_sans", 35, 0x000000,false,false,false, null,null,TextFormatAlign.CENTER );
			 		message.width = 300;
					message.wordWrap = true;
 				    message.textFormat = tf ;
      				return message;
				};

Hi,

If you look into Alert code for createMessageLabel, right after it creates the label using messageLabelFactory :

if (this.messageLabel.variant == null) {
	this.messageLabel.variant = this.customMessageLabelVariant != null ? this.customMessageLabelVariant : Alert.CHILD_VARIANT_MESSAGE_LABEL;
}

My understanding is you should set message.variant in your code and either set the Label properties in the theme, or just have an empty function for that variant name in your theme so that you can define everything like you are doing now without having the theme overriding your values.

The default theme sets the maxWidth on the Alert’s background skin to keep the Alert from getting too wide. That’s why the Alert enables scrolling when you change the Label’s width to be larger. The Label has become wider than the Alert is allowed to be.

You should be able to set the width or maxWidth of the Alert to override this behavior. Alternatively, you could provide the Alert with a custom background skin that has a larger maxWidth.

By the way, the default theme passes HorizontalLayout to the Alert, and HorizontalLayoutData with percentWidth set to 100.0 to the Label. This allows the label to fill the Alert automatically, no matter what the Alert’s width happens to be. If you are providing a custom Label, it would probably be a good idea to keep using HorizontalLayoutData in this way.

As long as the theme exclusively sets properties on the component that are marked with @:style metadata, it can’t override anything that you’ve already set outside of the theme.

The main things that you might think can be set inside the theme (but shouldn’t) are properties like width, height, minWidth, minHeight, maxWidth, and maxHeight. Those aren’t styles. Instead, the theme should set them on the display objects that are passed to the component’s skin properties (for most components, that’s usually backgroundSkin).

button.width = 150.0; // try to avoid inside the theme

var bg = new RectangleSkin(SolidColor(0x999999));
bg.width = 150.0; // recommended
button.backgroundSkin = bg;

I’m not sure I understand that correctly :

  • he has a messageLabelFactory that creates a 300px wide label
  • after calling that function, Alert looks at the label’s variant, since it’s null it sets it to either customMessageLabelVariant or Alert.CHILD_VARIANT_MESSAGE_LABEL
  • the label gets styled through the Alert style he has, which he said sets the label width to 450px and the label that was 300px is now 450px no ?

Oh I think I get it : it won’t happen with @:style properties but width/height etc aren’t @:style properties so width can be overriden (even though setting width in theme is not recommended).

What I suggested would only work if he has a style for Alert.CHILD_VARIANT_MESSAGE_LABEL, if he sets the label’s width in an Alert style it won’t work (or it will depend on the order styling functions are executed).

That’s not how I would do it, but I thought in his context it’s something that would work without needing many changes.

I missed this part when I first read through this thread.

Does your theme set messageLabelFactory too? A factory for a sub-component is another thing that isn’t considered a style, so you should avoid providing a factory in a theme. Instead, to customize a sub-component in a theme, you should use a custom variant. For the Alert’s Label, you’d want to set customMessageLabelVariant on the Alert.

styleProvider.setStyleFunction(Alert, null /* or a variant */, function(alert:Alert):Void {
	alert.customMessageLabelVariant = "my-custom-alert-label";
	// set more alert styles...
});

styleProvider.setStyleFunction(Label, "my-custom-alert-label", function(label:label):Void {
	// set label styles...
});

But I have two Alerts. Most of their styles are same. Except two. The alert-width and label-width inside.
The Feathers-Ui manual says that to make style changes in specific Alert, I need to use factory method for that particular instance of Alert.

Here is my custom-theme I use for all Alerts.
But how should I make some exceptions to one of the Alerts I am using?

I see you are talking about setting a custom variant. But where will I specify this variant for the Alert instance I want to make changes to?

import feathers.controls.ButtonState;
import feathers.themes.ClassVariantTheme;
import openfl.text.*;
import openfl.display.GradientType;
import feathers.skins.RectangleSkin;
import feathers.controls.*;

class CustomTheme extends ClassVariantTheme {
 	public function new() {
		super();

	 
		// custom themes may provide their own unique variants
		styleProvider.setStyleFunction(Label, Alert.CHILD_VARIANT_MESSAGE_LABEL, setAlert_MessageLabel_Styles);

		styleProvider.setStyleFunction(Header,Alert.CHILD_VARIANT_HEADER,setAlert_Header_Styles);

		styleProvider.setStyleFunction( Button, ButtonBar.CHILD_VARIANT_BUTTON,setButtonBar_Button_Styles);
	}

 	function setAlert_Header_Styles(header:Header):Void 
 	{

			var header_tf = new TextFormat("_sans", 40, 0x000000,true,false,true, null,null,TextFormatAlign.CENTER );
			//var header = new Header();
			header.textFormat= header_tf; 
			var skin = new RectangleSkin();
			skin.border = SolidColor(1.0, 0x999999);
			skin.fill = SolidColor(0xcccccc);
			skin.width = 16.0;
			skin.height = 16.0;
			header.backgroundSkin = skin;
		 
	}

	function setAlert_MessageLabel_Styles(label:Label):Void 
	{
      
 		var logoFormat = new TextFormat("_sans", 35, 0x000000,false,false,false, null,null,TextFormatAlign.CENTER );
 		label.width = 450.0;
		label.wordWrap = true;
	    label.textFormat = logoFormat ;
 		 
		 
	}

	function setButtonBar_Button_Styles(button:Button):Void {
      
			var rs:RectangleSkin  = new RectangleSkin(SolidColor(0xFFFFFF), SolidColor(2.0, 0x000000));
			rs.cornerRadius = 10.0;
			button.backgroundSkin = rs ;
			button.paddingTop=10;
			button.paddingLeft=10;
			button.paddingRight=10;
			button.paddingBottom=10;
		button.textFormat = new TextFormat("Helvetica", 45, 0x3c3c3c);
	 
	}

}

You can set the Alert’s variant property. Probably the best place to do it is a custom alertFactory passed to Alert.show().

alert_Al =  Alert.show("Time: " + timerLabel.text  +"\n Clicks: " + clickNum_Int,"Great Job!", ["Play Again"], null, () -> {
	var alert = new Alert();
	alert.variant = "custom-variant"
	return alert;
});

Technically, you could probably set it on the Alert instance returned by Alert.show(), but that’s a bit less efficient because the Alert will be styled once, have its styles cleared, and then be styled a second time with the variant styles. But here’s how you would do that:

alert_Al =  Alert.show("Time: " + timerLabel.text  +"\n Clicks: " + clickNum_Int,"Great Job!", ["Play Again"]);
alert_Al.variant = "custom-variant";

Ok. Thanks. Will try this and let you know if I encounter any issue.