Skip to content

Use assets for custom html frame and dialog icons#6005

Open
Baaaaaz wants to merge 4 commits into
RPTools:developfrom
Baaaaaz:feature/4018-custom-icons-for-html-frames-and-dialogs
Open

Use assets for custom html frame and dialog icons#6005
Baaaaaz wants to merge 4 commits into
RPTools:developfrom
Baaaaaz:feature/4018-custom-icons-for-html-frames-and-dialogs

Conversation

@Baaaaaz

@Baaaaaz Baaaaaz commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Identify the Bug or Feature request

closes #4018

Description of the Change

Icons for DIALOG, DIALOG5, FRAME, FRAME5(and theirhtml.*` variants) can now be set by:

  1. the frame/dialog property icon=asset://...;
  2. in HTML using the <link rel="icon" type="..." href="asset://..."> (requires all three attribute to be present).
  3. by the functions setFrameIcon() or setDialogIcon() without having to do a full frame/dialog refresh. However, if the frame/dialog is subsequently refreshed the icon will change to whatever has been specified according to methods 1 and 2 above.

Code changes:

  • HTMLFrameFactory -> handling of the new icon parameter and new getScaledImageIcon method.
  • HTMLActionEvent -> new ChangeIconActionEvent class.
  • HTMLPane and HTMLWebViewManager -> additional handling of <link rel="icon" type tags and attributes.
  • HTMLFrame and HTMLDialog -> manage updating the icon.

Possible Drawbacks

  • If setting via the HTML <link> tag, the property icon is set first (or set the default current icon if the property icon is not set), then the <link> tag icon is set. The icon may flicker as it needs to wait for the HTML content to load first. This flicker is similar to if setting the frame/dialog title via the <title> tag. Had a go a cracking this, but was getting no where fast and I persevered for as long I could.

Documentation Notes

New functions:

setFrameIcon(frameName, assetId)
frameName - the name of the frame
assetId - the asset ID. If blank (i.e. "" will reset the frame icon to the default)

ditto for dialogs

Enhanced functions:

getFrameProperties(): now returns an icon key with the assigned asset.
frame/frame5/dialog/dialog5/html.frame/html.frame5/html.dialog/html.dialog5 can now take an assetid for the icon parameter.

Release Notes

  • frame and dialog icons can now be customized to an image image.

This change is Reviewable

@github-actions github-actions Bot added the feature Adding functionality that adds value label Jul 9, 2026
@Baaaaaz

Baaaaaz commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Some MTScript to have a play with toggling frame/dialog icons:

[h: vMacroArgs = macro.args]
[h, if (vMacroArgs == ""), code: {
	<!-- First run -->
	[h: doPropertyIcon = 0]
	[h: doLinkIcon = 0]
	[h: vMacroArgs = "{}"]
} ; {
	<!-- Subsequent runs via macrolinks -->
	[h: doPropertyIcon = json.get(vMacroArgs, "doPropertyIcon")]
	[h: doLinkIcon = json.get(vMacroArgs, "doLinkIcon")]
}]

[h: assert(listCount(getSelected())==1, "You must first select one and only one token")]

[h: macroLinkTogglePropertyIcon = macroLink("Toggle All Property Icons !" + doPropertyIcon + " (uses selected token image)", getMacroName()+"@"+getMacroLocation(), "all", json.set(vMacroArgs, "doPropertyIcon", 1-doPropertyIcon, "doLinkIcon", doLinkIcon))]
[h: macroLinkToggleLinkIcon = macroLink("Toggle All HTML Link Icons !" + doLinkIcon + " (uses selected token portrait)", getMacroName()+"@"+getMacroLocation(), "all", json.set(vMacroArgs,  "doPropertyIcon", doPropertyIcon, "doLinkIcon", 1-doLinkIcon))]

[h: vTokenImage = getTokenImage("", getSelected())]
[h: vTokenPortrait = getTokenPortrait("", getSelected())]

[h: vHtmlTypes = "FRAME5,FRAME,DIALOG5,DIALOG"]
[h: frameNameSuffix = ""]
[h: isTemp = 1]

[h: vProperty = strFormat("temporary=%s;", isTemp)]
[h, if(doPropertyIcon): vProperty = vProperty + strFormat("icon=%s; ", vTokenImage)]
[h, if(doLinkIcon): vHtmlHead = strFormat('<head><link rel="icon" type="image/x-icon" href="%{vTokenPortrait}"></head>') ; vHtmlHead = '']

[r, forEach(iHtmlType, vHtmlTypes), code: {
	[r: execMacro( strFormat('[%{iHtmlType}("%{iHtmlType}%{frameNameSuffix}", "%{vProperty}"): { %{vHtmlHead} <body>%{macroLinkTogglePropertyIcon}<br><br>%{macroLinkToggleLinkIcon}<hr>N.B. a link icon will override a propery set icon</body>}]'))]
}]

<h1>Frames</h1>
[r, forEach(iHtmlType, vHtmlTypes, "<br>"), code: {
	<pre>[r: json.indent(getFrameProperties(iHtmlType+frameNameSuffix))]</pre>
}]

@kwvanderlinde

Copy link
Copy Markdown
Collaborator

Nice to see this being picked up! I like that HTML tags can be used to do this.

One general concern I have developed in the few years since opening the FR is that not all of "features" will keep working right if/when we tighten up the asset cache so that loaded assets need to be part of the campaign. One case I remember where this is a "no" is global macros that use assets as icons. I don't know what the answer would be for frames & dialogs. Not that it's really new for them, as they can already load assets in <img> tags and the like. Related to that is #5279 for scoping frames to campaign, as that should side-step the issue.

Anyhow, I don't think anything needs to change in this PR regarding that point. I just wanted to make sure it's something we think about, and maybe we'll have to rethink a couple things in the future.

Comment on lines +343 to +345
ImageIcon imageIcon = new ImageIcon(RessourceManager.getImage(Images.BROKEN));
byte[] imageBytes = asset.getData();
if (imageBytes != null && imageBytes.length > 0) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should check that the asset is an image with asset.getType()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added an asset type check.

} catch (IOException | ExecutionException | InterruptedException e) {
// Do nothing
}
} else if (rel.toString().equalsIgnoreCase("icon")) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rel could be null so need to check that it isn't first

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think that is already covered by the checks done at the parent nested level on line 308?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Adding functionality that adds value

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Custom icons for HTML frames

3 participants