00:00
00:00
Newgrounds Background Image Theme

Patrick8008 just joined the crew!

We need you on the team, too.

Support Newgrounds and get tons of perks for just $2.99!

Create a Free Account and then..

Become a Supporter!

Indirect call vs. exposed function

368 Views | 6 Replies
New Topic Respond to this Topic

Not sure what to call the title, but the question goes as such:

I have a class Tooltip that displays a tooltip at a given x and y coordinate and a message to go along with it. Because the tooltip can be displayed anywhere on the desktop, the coordinates have to be converted to the Screen coordinates and then the function has to be called. It's a static-initialized/singleton since there should be only one Tooltip at a time, and also because it should be accessible from all locations (which I figure shouldn't be too harmful since it's more or less a passive class that doesn't change global state)

Since all the code to display the tooltip (converting to screen coordinates, etc.) is the same, I figure it would be easier to create a manager class ToolTipMessageManager that stores all the messages for each object in a Dictionary, and the displayTooltip() is defined within it to display the tooltip at a given location (which it converts to screen coordinates). It's worth noting that this manager class is not static, and each class should have an instance of this class.

(This class does not automatically register event listeners, though, so the class that uses tooltips should add listeners for it. I figured this was because tooltips could appear in a number of ways, not just through mouse / key input, so the TTMM class is more akin to a Dictionary + a function to display a tooltip at a given Screen location)

Now, I have a bunch of classes PanelA, PanelB, PanelC,...PanelN. All the Panel classes that use tooltips (not all do) have the interface IUsesTooltip, with a displayTooltip(evt:MouseEvent) function defined within. What I do is at runtime, I go through all the panelA...N instances, and see if they implement IUsesTooltip, and if so, then I add an event listener to display a tooltip on mouseover the target.

It works fine, but I wonder if I'm making a few design mistakes here. I have a few options in front of me:

* Keep it the same. Each panel that wants to implement a tooltip can implement a displayTooltip(evt:MouseEvent) function, and either let the manager do the displaying, or display it themselves. The problem is that the displayTooltip function becomes public, and it shouldn't be, really (there aren't any protected interfaces in AS3 sadly.)

* Gut the manager class and make it a singleton as well. Whenever an object is added to the manager class, e.g. ToolTipMessageManager.set(object, "message") then I add a listener to that object (internally), and have the tooltip display every time the object is hovered over. This way, there's no (imo unnecessarily) public displayToolTip(evt:MouseEvent) function in each class that uses tooltips, nor any IUsesToolTip interface either.

* Any other option?


Slint approves of me! | "This is Newgrounds.com, not Disney.com" - WadeFulp

"Sit look rub panda" - Alan Davies

BBS Signature

Response to Indirect call vs. exposed function 2017-08-25 12:27:08


At 8/25/17 02:34 AM, Gimmick wrote: * Any other option?

I like the second option. Though, could you make it so that each Panel implements the interface, but the ones that don't actually have tooltips have empty displayTooltip() functions?

I mainly don't like the idea of checking for the interface at runtime. Second to that, the second option is cleaner to me, as long as the text doesn't change. If it does change, like if the tooltip is "Deals N damage" for an upgradeable weapon, you could use a function to piece that together or put some custom markers in your string, which is what I do, "Deals [[damage]] damage."

Response to Indirect call vs. exposed function 2017-08-25 12:48:28


At 8/25/17 12:27 PM, MSGhero wrote:
At 8/25/17 02:34 AM, Gimmick wrote: * Any other option?
I like the second option. Though, could you make it so that each Panel implements the interface, but the ones that don't actually have tooltips have empty displayTooltip() functions?

I can. However, that still doesn't solve the problem of any class being able to call displayTooltip() by passing in a fake event. It doesn't cause any harm (except possibly spoofing tooltips), but it looks rather ugly to have a public listener, imo.

I mainly don't like the idea of checking for the interface at runtime. Second to that, the second option is cleaner to me, as long as the text doesn't change. If it does change, like if the tooltip is "Deals N damage" for an upgradeable weapon, you could use a function to piece that together or put some custom markers in your string, which is what I do, "Deals [[damage]] damage."

It doesn't, or it shouldn't, at least. The function will still map a message to an object in the same way it did before. Some tooltips may be affected, but I could work around that by calling the function directly and bypassing the manager class. The custom markers is a good idea! It would be handy indeed for localization, if I ever plan to support that.


Slint approves of me! | "This is Newgrounds.com, not Disney.com" - WadeFulp

"Sit look rub panda" - Alan Davies

BBS Signature

Personally I'd say instead of going through the trouble of creating an interface and implementing in everything and dictionaries just create a string tooltip on anything you need a tooltip on have it call some logic like on rollover.

import flash.events.MouseEvent;

function ro(event:MouseEvent):void {
	trace(event.target.name);
	if(event.target.hasOwnProperty("tooltip"))
		trace(event.target["tooltip"]);
}

addEventListener(MouseEvent.MOUSE_OVER, ro);

Do that on the root and you don't even have to think twice about anything, it either has a tooltip string or it doesn't. heck you could make tool tips some object and just pass them to the tootipManager class on rollover.

you could also make the tool tip go away on rollout. If you rollover something with a tooltip it will just pop back up.

Perhaps my solution isn't very elegant but it will do the trick. Also I'm lazy...

Response to Indirect call vs. exposed function 2017-08-27 06:44:47


At 8/27/17 12:55 AM, JoSilver wrote: Personally I'd say instead of going through the trouble of creating an interface and implementing in everything and dictionaries just create a string tooltip on anything you need a tooltip on have it call some logic like on rollover.

[code]

This would only work if the target was a MovieClip or some dynamic class; Sprite doesn't support that, nor do other non-dynamic InteractiveObjects.


Slint approves of me! | "This is Newgrounds.com, not Disney.com" - WadeFulp

"Sit look rub panda" - Alan Davies

BBS Signature

At 8/27/17 06:44 AM, Gimmick wrote: This would only work if the target was a MovieClip or some dynamic class; Sprite doesn't support that, nor do other non-dynamic InteractiveObjects.

bummer. However just doing the check for the tooltip field on objects will save you having from have to use put all your classes in a dictionary. Again the benefit is it either has a tooltip or it doesn't. No need to maintain some other structure or interfaces.

Response to Indirect call vs. exposed function 2017-08-27 19:21:02


Just use a hash table. Or in place modifications to your array, though you'll have to set some special values aside.


∀x (∃e (e ∈ x ∧ ∀x ¬(x ∈ e)) ∨ ∃y ¬∃e (e ∈ x ∧ ¬∃z (z ∈ y ∧ z ∈ e ∧ ∀x ¬((x ∈ y ∧ x ∈ e) ∧ ¬(x = z)))))