Html5: cannot stop icons resizing

Hi folks,

I’m a Haxe noob using HaxeUI html5 to build the GUI for a new personal project, and I cannot stop the generated JS from resizing my icons. I want to display them at actual size: 256x256

The project is here: GitHub - osullivj/BizDeck: StreamDeck RPA core

There’s a load of C# stuff in there for the server. Here’s a cut down Hx only version of the code that demonstrates the bug: BizDeckIconSizeBug.zip - Google Drive

There are two TableViews embedded in a TabView. Once of the TableViews has the icon column. MainView.hx and main-view.xml reproduced below. Any and all tips gratefully recved!

Thanks
John

<vbox id="bd_top_vbox" style="padding: 5px;" width="100%" height="100%" styleName="default-background">
	<style>
	.bd_icon_box {
		width:256;
		height:256;
	}
	</style>
	<!--  top tabview -->
    <tabview id="bd_main_tabview" width="100%" height="100%">
        <box text="Buttons" id="bd_buttons_box" width="100%" height="100%">
			<spacer height="5%" />
			<tableview id="bd_buttons_tableview" virtual="true" width="100%" height="100%">
				<header width="100%">
					<column id="bd_index" text="Index" width="40%"/>
					<column id="bd_name" text="Name" width="40%"/>
					<column id="bd_icon" text="Icon" width="20%"/>
				</header>
				<item-renderer verticalAlign="center">
					<label id="bd_index" horizontalAlign="center" />
				</item-renderer>
				<item-renderer verticalAlign="center">
					<label id="bd_name" horizontalAlign="center" />
				</item-renderer>
				<item-renderer verticalAlign="center">
					<box style="width:256;height:256" styleName="bd_icon_box">
						<image id="bd_icon"/>
					</box>
				</item-renderer>
			</tableview>
		</box>		
		<box text="Config" id="bd_config_box" width="100%" height="100%">
			<spacer height="5%" />
			<tableview id="bd_config_tableview" virtual="true" width="100%" height="100%">
				<header width="100%">
					<column id="bd_setting" text="Setting" width="40%"/>
					<column id="bd_value" text="Value" width="60%"/>
				</header>				
			</tableview>
		</box>
    </tabview>
</vbox>

package ;

import haxe.Serializer;
import haxe.ui.containers.VBox;
import haxe.ui.containers.Box;
import haxe.ui.containers.TableView;
import haxe.ui.containers.TabView;
import haxe.ui.components.Image;
import haxe.ui.data.ArrayDataSource;
import haxe.ui.events.MouseEvent;
import haxe.ui.events.UIEvent;
import js.html.WebSocket;
import js.Browser;


class BizDeckWebSocket {
	public var websock:WebSocket;
	public var connected:Bool;
	public var mainview:MainView;
	
	public function new(mv:MainView) {
		this.mainview = mv;
		this.connected = false;
		this.websock = new WebSocket(mv.websock_url, "json");
		this.websock.onopen = function() {
			trace("ws.conn");
		};	
		this.websock.onmessage = function(e) {
			trace("ws.recv: " + e.data);
			var obj = haxe.Json.parse(e.data);
			switch obj.Type {
				case "connected":
					this.connected = true;
				case "config": {
					this.mainview.on_config(obj.Data);
					this.mainview.rightsize_icons();
				}
			}
		};
		this.websock.onclose = function() {
			trace("ws.disconn");
			this.connected = false;
			this.websock = null;
		};
	}
}

@:build(haxe.ui.ComponentBuilder.build("main-view.xml"))
class MainView extends VBox {
	var websock:BizDeckWebSocket;
	public var websock_url:String;
	private var config_data_source:ArrayDataSource<Dynamic>;
	private var buttons_data_source:ArrayDataSource<Dynamic>;
	
    public function new() {
        super();
		// API has rendered in the browser, so open a client
		// websock back to the embedio server
		var port = js.Browser.document.location.port;
		this.websock_url = "ws://localhost:" + port + "/ws";
		this.websock = new BizDeckWebSocket(this);
	}
	
	public function rightsize_icons() {
		var btn_tv:TableView = this.findComponent("bd_buttons_tableview");
		var box_list:Array<Box> = this.findComponents("bd_icon_box", Box);
		trace("mv.rightsize_icons: " + box_list.length);		
		for (box in box_list) {
			trace("mv.rightsize_icons: " + Serializer.run(box));
		}
	}
	
	public function on_config(config:Dynamic) {
		// yes, we're splitting the contents of config.json
		// across two TableViews. Refactor needed....
		var cfg_tv:TableView = this.findComponent("bd_config_tableview");
		var btn_tv:TableView = this.findComponent("bd_buttons_tableview");
		config_data_source = new ArrayDataSource<Dynamic>();
		buttons_data_source = new ArrayDataSource<Dynamic>();		
		// clear table contents: false means don't clear headers
		cfg_tv.clearContents(false);
		btn_tv.clearContents(false);
		var cfg:haxe.DynamicAccess<Dynamic> = config;
		for (key in cfg.keys()) {
			var val:Any = cfg.get(key);
			if (key == "BizDeckConfig") {
				var subcfg:haxe.DynamicAccess<Dynamic> = val;
				for (subkey in subcfg.keys()) {
					var subval:Any = subcfg.get(subkey);
					if (subkey=="ButtonMap") {
						var button_list:haxe.DynamicAccess<Dynamic> = subval;
						for (btn_defn in button_list) {
							var btn_row:Any = {bd_index:btn_defn.ButtonIndex,
										bd_name:btn_defn.Name,
										bd_icon:btn_defn.ButtonImagePath};
							buttons_data_source.add(btn_row);
							trace("mv.on_config: btn_row=" + btn_row);
						}
					}
					else {
						config_data_source.add({bd_setting:key+"."+subkey, bd_value:subval});
					}
				}
			}
			else {
				// NB setting and value in the jobj match the
				// element IDs in main-view.xml
				var cfg_row:Any = {bd_setting:key, bd_value:val};
				trace("mv.on_config: cfg_row=" + cfg_row);
				config_data_source.add(cfg_row);
			}
		}
		cfg_tv.dataSource = config_data_source;
		btn_tv.dataSource = buttons_data_source;
	}
}

Sorry about the messy code formatting - cannot seem to find a button on the editor that let’s me see the markdown or structured text directly…

I fixed the styling, you can just use backticks:

'''
code here
'''

where ’ is `

So im not 100% sure i understand, are you saying you want to NOT use the .bd_icon_box style?

When i run your app i get:

Is that not right?

EDIT: Oh… and welcome! :slight_smile:

Ian: thanks! bd_icon_box style was an attempt at stopping the icons being resized to fit. Basically I’m trying to stop resizing for the icons, and have tried elements and attributes in the xml, as well as searching for any way I can get hold of the HxImage in the .hx code. So far, no luck…

So just to understand fully, you dont want to force them to be 256x256 and want to let them be the orginal size? If i remove the css, i get:

Ie, the first is the wrong size… this feels like a bug, presumably because the image loads a little slower and then doesnt update the parent layout (its a hunch). Is this the behaviour you get?

Also, what version of haxeui are you using? If you are using the haxelib release (1.5.0) you certainly want to move to git versions… 1.5.0 is like 8 months out of date or something at this point - im going to make a new release soon (hopefully this weekend), but until then, i would use git versions of haxeui + whatever backend.

Cheers,
Ian

OK, i can see the problem: its because you are using a virtualized tableview (virtual=true), what is happening is its trying to do some calculations (for the virtualization) and by that time, the image hasnt loaded. So it thinks the row size is 0 (well, 0 + padding), a quick fix is to just not use virtualization, another fix might be to preload all your images using a module.xml (i havent tested that).

Longer term, ill fix this and somehow let virtual layouts that “something has changed”

Any reason you wanted to use virtualized tables? How many rows / columns were you expecting - if you are using haxeui-html5 (which you appear to be), you can also get pretty hefty speed ups with -D rapid_text_metrics (its experimental, but i use it often)

Cheers,
Ian

1 Like

Ian,

I used this Q on dynamic tables as boilerplate: Dynamic TableView - #7 by DominikGrebien

So the use of virtual is a carry over from that code. I assumed it was necessary for dynamically providing the data. In MainView.hx you can see the websock code that recieves the data and invokes a callback to convert json to an ArrayDataSource, which is then supplied to the TableView.dataSource. In the zip of cut down code the data is supplied as in the main-view.xml. So I know the columns up front, but not how many rows of data there will be. I’ll try removing the virtual attribute, though I’m not sure what a “virtual” table is. Does it mean the table is dynamic, and we don’t know the data up front?

Thanks
John

The icons are 256x256 PNGs, cos that’s what works with Elgato’s StreamDeck. I just want to display them at that resolution.

Ian,

So I tried removing the virtual attribute entirely, as well as virtual=“false”; no change in behaviour.

I also tried getting the latest haxeui-core from github. I moved it into HaxeToolkit\haxe\lib\haxeui-core as 1,6,0 and changed .current to point to 1.6.0. Lots of compile errors, and the build logged use of 1,5,0 anyway. I also tried using -L on the build cmd line with the git options described here: Compiler Usage - Haxe - The Cross-platform Toolkit No luck with that either. I’ll keep my fingers crossed for your new release. Plenty of other none Hx issue to fix!

Thanks
John

So, “virtualization” on the context of TableView / ListView means it can have many millions of items with little to no performance degradation because it only creates as many item renderers as can be visible (well, +1 for giving the illusion of scrolling). In essence a virtual table scrolls the data, not the contents.

It does come with some caveats / limitations though, like the items having to be equal height (and, the bug you have found).

For the most part, if you dont need millions (or 100s or thousands of items) and arent getting any perf issues, then i would just remove it - if you do start getting perf issues, then try -D rapid_text_metrics or virtualization.

Cheers,
Ian

there is no version 1.6… i meant use the git version from github:

haxelib git haxeui-core https://github.com/haxeui/haxeui-core
haxelib git haxeui-html5 https://github.com/haxeui/haxeui-html5

Something else must be up with your env then, it certainly fixes it. Maybe vscode compiler cache (if you are using it), restart vscode, or use the terminal just to confirm.

Finally got back on to this, and wanted to record the fix. I’ve upgraded to the 22 Apr 1.6.0 haxeui-core and haxeui-html5 releases. The fix was to explicitly set height and width attributes in the XML as pixels for the item-renderers. I could not get CSS fragments to work, nor style=“height:50px;width:50px”. Using a styleName on the renderers, then searching with findComponents didn’t work. Though I find that findComponent does work. Maybe because it defaults to using XML ID attribute, which seems to pass through to the generated HTML elements ID attr. styleName setting don’t seem to pass through. Nor do CSS fragments, either in global or as style=“” attrs. Working XML layout below.

I should also note that the msedge and chrome debuggers highlight the generated HTML img elements with same id attribute values as an error. I guess that’s not such a problem unless one wants to mix and match with eg jQuery.

Thanks
John

<vbox id="bd_top_vbox" style="padding: 5px;" width="100%" height="100%" styleName="default-background">
	<!--  top tabview -->
    <tabview id="bd_main_tabview" width="100%" height="100%">
        <box text="Buttons" id="bd_buttons_box" width="100%" height="100%">
			<spacer height="5%" />
			<tableview id="bd_buttons_tableview" width="100%" height="100%">
				<header width="100%">
					<column id="bd_index" text="Index" width="40%" height="32"/>
					<column id="bd_name" text="Name" width="40%" height="32"/>
					<column id="bd_icon" text="Icon" width="20%" height="32"/>
				</header>
				<item-renderer verticalAlign="center" height="50">
					<label id="bd_index" horizontalAlign="center" />
				</item-renderer>
				<item-renderer verticalAlign="center" height="50">
					<label id="bd_name" horizontalAlign="center" />
				</item-renderer>
				<item-renderer verticalAlign="center" height="50" width="50">
					<image height="50" width="50" id="bd_icon"/>
				</item-renderer>
			</tableview>
		</box>		
		<box text="Config" id="bd_config_box" width="100%" height="100%">
			<spacer height="5%" />
			<tableview id="bd_config_tableview" width="100%" height="100%">
				<header width="100%">
					<column id="bd_setting" text="Setting" width="40%"/>
					<column id="bd_value" text="Value" width="60%"/>
				</header>				
			</tableview>
		</box>
    </tabview>
</vbox>
1 Like