Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

renderers placed in _rendererPool in VirtualLayout are not aware of Toolkit.pixelsPerRem change #529

Open
NipponSunrise opened this issue Jun 15, 2023 · 6 comments

Comments

@NipponSunrise
Copy link

To scale an application I'd prefer to use Toolkit.pixelsPerRem instead of scaleX and scaleY for some reasons. When Toolkit.pixelsPerRem value is changed, renderers placed in _rendererPool in VirtualLayout are not aware of that change, so when they back on stage they are displayed incorrectly.

From my point of view, suggested solution would be adding instance.invalidateComponent(InvalidationFlags.ALL, true); call to VirtualLayout.getRenderer:

	private function getRenderer(cls:Class<ItemRenderer>, index:Int):ItemRenderer {
		var instance:ItemRenderer = null;
		var comp:IVirtualContainer = cast(_component, IVirtualContainer);
		if (comp.virtual == true) {
			for (i in 0..._rendererPool.length) {
				var renderer = _rendererPool[i];
				if (isOfType(renderer, cls)) {
					_rendererPool.splice(i, 1);
					instance = renderer;
					instance.invalidateComponent(InvalidationFlags.ALL, true);
					break;
				}
			}
		}
		......
		......
		......
@ianharrigan
Copy link
Member

Is there any chance of a test / repro? Id like to understand exactly whats going on.

Cheers,
Ian

@NipponSunrise
Copy link
Author

Repro is hard to provide at the moment. See screenshot Screenshot_20230615_115736_Samsung Internet

@ianharrigan
Copy link
Member

what does your renderer look like? I'll try and reproduce this end.

Cheers,
Ian

@NipponSunrise
Copy link
Author

NipponSunrise commented Jun 15, 2023

what does your renderer look like? I'll try and reproduce this end.

Cheers, Ian

<?xml version="1.0" encoding="utf-8" ?>

<CustomListItemRenderer styleName="lobbyTableListRow" layoutName="horizontal" width="100%" padding="0">

    <box id="col1" verticalAlign="center">
        <TablesListRowPlayersView id="players" width="100%" />
    </box>

    <box styleName="divider" height="100%" /> 

    <box id="col2" verticalAlign="center">
        <label id="stake" width="100%" horizontalAlign="center" textAlign="center" /> 
    </box>

    <box styleName="divider" height="100%" />

    <box id="col3" verticalAlign="center">
        <TablesListRowGameSpeedView id="gameSpeed" width="100%" />
    </box>

    <box styleName="divider" height="100%" />

    <box id="col4" verticalAlign="center" width="100%">
        <label id="tableNumber" width="100%" horizontalAlign="center" textAlign="center" /> 
    </box>

    <box id="extraCol" />
</CustomListItemRenderer>
class CustomListItemRenderer extends ItemRenderer {
	public var isInactive:Bool = false;

	public function new() {
		super();
		autoRegisterInteractiveEvents = false;
		addEventListener(openfl.events.MouseEvent.RELEASE_OUTSIDE, _onItemMouseReleasedOutside);
	}

	override private function _onItemMouseOver(e:MouseEvent) {
		if (!e.touchEvent && !isInactive && !hasClass(":hover")) {
			addClass(":hover");
		}
	}

	private var mouseDownTimestamp:Float = 0;

	override private function _onItemMouseDown(e:MouseEvent) {
		mouseDownTimestamp = Timer.stamp();
		if (!isInactive && !hasClass(":down")) {
			addClass(":down");			
		}
	}

	override private function _onItemMouseOut(e:MouseEvent) {
		removeClasses([":down", ":hover", ":click"]);
	}

	override private function _onItemMouseUp(e:MouseEvent) {
		if (e.touchEvent) {
			var clickEventStamp = Timer.stamp();
			if (clickEventStamp - mouseDownTimestamp > 400.millis().toSeconds()) {
				// long touches are being filtered
				removeClasses([":down", ":hover", ":click"]);
				e.cancel();
				return;
			}
		}

		if (isInactive) {
			removeClasses([":down", ":hover", ":click"]);
			e.cancel();
			return;
		}

		removeClasses([":down", ":hover"], false);
		addClass(":click");
		Timer.delay(() -> removeClass(":click"), 160.millis());

		super.onItemClick(e);
	}

	private function _onItemMouseReleasedOutside(e:Dynamic) {
		removeClasses([":down", ":hover", ":click"]);
	}

	override private function validateComponentData() {
		onDataChanged(_data);
	}

	override private function onPointerEventsMouseOver(e:MouseEvent) {}

	override private function onPointerEventsMouseDown(e:MouseEvent) {}

	override private function onPointerEventsMouseOut(e:MouseEvent) {}

	override private function onPointerEventsMouseUp(e:MouseEvent) {}
}

@NipponSunrise
Copy link
Author

what does your renderer look like? I'll try and reproduce this end.

Cheers, Ian

Well, that's pretty logical. Renderers that have been removed from the stage and are in the pool are not invalidated by stage events. Therefore, it is necessary to validate them when they return to the stage. On the other hand, I don't understand why they don't get validated "automatically" (I mean on another layer of abstraction, like in "Component") when they are returned to the stage via addComponent.

@ianharrigan
Copy link
Member

So, ive had a little look, and i think you are right, i think that when a component is added to another component that child should probably be invalidating itself... i think what happens is the "isReady" flag is true on the child (which is correct) which means it skips a bunch of invalidation stuff. That should probably always invalidate the child.

Ive actually noticed something else while playing with this: http://haxeui.org/builder/?32b1ae05

You'll notice that when you hit "Set 1", nothing at all happens, but i would expect that the square doubles in size. So Ill take a look at that... to the original issue, if you change these lines:

https://github.com/haxeui/haxeui-core/blob/master/haxe/ui/core/Component.hx#L400-L402

to:

        if (_componentReady) {
            if (!child.isReady) {
                child.ready();
            } else {
                child.invalidateComponent();
            }
        }

Does it fix that issue?

Cheers,
Ian

PS: whats the app, it looks interesting :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants