G4P Mouseover Event, mainly for tooltips

Hi,

I’m wanting to add tool tips to assorted text, labels and possibly buttons. Not apparent in processing and G4P specifically. Main requirement would be for a “mouseover” events generated for these objects. Then imagine the tooltips might start to be a possibility. IE tooltip pops up after x milli-seconds on mouseover event.

Is this a possibility with the G4P library?
or
A work around that isn’t mouseX and mouseY. Plenty of references to that approach. That approach works fine for projects graphical in nature, not so much for a screen full of labels and text boxes.

To put the need in context I’m writing a bit of software that generates batch and script (OS dependent) files for towards a dozen target embedded projects to support Unit testing. There are quite a number of labels, and text boxes that describe installation directories for the toolchains and utilities. In order to make it easier for a new user to get up and running want to be able to intuitively lead the user through the maze of installation dependencies.

Hence the mouseover and tooltip question and why mouseX, mouseY would be a struggle.

Any thoughts?

Many Thanks
Stefan

G4P does not support tooltips because I didn’t think of it when I created G4P. There has never been sufficient interest in having tooltips for me to add it as a feature. In fact you are the first person to ask about tooltips in G4P’s since its launch in March 2009.

It seems to me that the real problem is because the UI is cluttered because you are using lots of controls to guide and get info from the user. I suggest that you look at using the GGroup control - this allows you to group controls by purpose and then control their appearance with a single instruction to the group e.g. fade-out, fade-in, make invisible etc.

G4P comes with a GGroup example. I suggest you play with this to see if you can make use of it in your project.

2 Likes

Hi Peter,
Thanks for the feedback. BTW love your work. Had a play with Groups. Makes sense in some ways but starts to miss the point of what I’m trying to do. Agree what I’ve done is cluttered, but with the tool flow for assorted modes, it does makes sense for the user to get a feel for the overall picture.

Basically user selects the mode from “Select mode” panel on the left, then the column on the right has checkboxes to show which installations are required for that mode. Then the button “Test Installation” checks the status of the assorted tools/toolchains and highlights in green on success, red on failure. Simply run the assorted tools/toolchains with --version or as required to determine status.

Yes it is cluttered, but there is logic to the madness. Peoples can get a quick overview of what works, and what is still needed. They only need to install the binaries for the mode they care about. Gui gets auto populated for new toolchains/tools based on a JSON file. And a separate JSON for all installation directories for all users based on USERDOMAIN. Hence the JSON index spinner request a few weeks back. Wanted to use some construct of tool tips to steer peoples in the right directions. Right mouse click opens a file explorer to select an installation directory. Left mouseclick to directly edit text boxes. Wanted mouseover to give hints as to the URL that might have the relevant binaries.

I’m in the camp with processing that uses processing to get simple GUI stuff working. Not a Java bod, although processing and your library has taught me enough to be dangerous. Possibly not good :slight_smile: Enough that I use IntelliJ and Eclipse for the projects. Your library is so graphically clean and intuitive that it just feels right.

I’m having a crack at adding a tooltips feature for my own purposes to your library. More miss than hit at the moment, but I can see it starting to take shape. This would be less than ideal as would need to update with new source code releases. Understand the interactions are possibly complex and don’t want to foist something on your efforts that have a negative impact.

If I get this going are you happy to vet it for possible inclusion with your library? No offence take if you tell me to go away.

Many Thanks
Stefan

That is a serious challenge. :smile:

In principle I have no issues but in practice this is not so easy because I end up having to maintain the code. In 2010 I was approached by the creators of another (very nice) library wanting to add some ‘cool’ sliders to make their library examples more aesthetically pleasing. I agreed because they would be writing all the code. Unfortunately the slider code did not follow the same event handling pattern used by my other controls, it was slightly buggy and did not work cleanly and I ended up rewriting most of the code myself. Not a complete loss because the new code became the GCustomSlider control :smile:

I have been considering a changing how to G4P manages events but been put off by the amount of work involved. If I decide to go ahead with it I could add tooltips.

Hi Peter,

Know this is a very belated response to an old question, but it is same topic. I get where your coming from; re including third party contribution to libraries, but I’ve needed this tooltip functionality a few times in the intervening period.

Not going to inflict my hacks onto the community (and your KISS library) but I’ve had a crack at the starting’s of the tooltips. Hoping I can do it as a source code patch to any new versions you might release. I know, a bit messy, but assuming I write it cleanly, there is no reason a patch couldn’t be used. Assuming there isn’t a major restructuring of the codebase. Naturally if you feel it’s a fit, your free to use it but that isn’t an expectation.

The basics work, although as I learn more about the workings of your library I recognize I need to follow your underlying philosophy a bit more. Eg Color Schemes, possibly others.

Currently I use MouseEvent.Move in my GToolTextTip and start a GTimer based on currSpot being >=0. Any other MouseEvent cancels the timer. On timeout of the Timer the tooltip gets displayed with the alhpa channel being clearly transparent (to make it obvious it is a tooltip) for as long as the mouse is over the control. Any other mouse action stops the timer and the tooltip disappears. There are a couple of things I have to fix but the basics work.

Looks like this

The Tooltips are reasonably abstracted away from other source files other than a constructor to optionally use the tooltips. ATM I’ve only added the functionality to the GButton which calls a Tooltip constructor if one optionally needs a tooltip. However that is only the GButton, hardly universal; although it is the one aspect that has driven me to following through.

Question what might be the ideal source file to allow this optional use of a tooltip that might be a bit more universal? Constructor wise is really the only one, as the tooltip otherwise is pretty much stand alone.

Thanks
Stefan

G4P has evolved since its release in 2009 and the source code has gone through

  • 3 major revisions as Processing went from V2 to V4
  • major revision when Processing started using OpenGL for P3D
  • massive increase in the number of G4P controls available since first release

so has lost some of its cleanness / clarity which make adding to it a bit of a challenge even for me.

A very good question but I think that there is an easier way to do this.

So what I am going to do is describe how I would approach adding a tooltip feature to G4P. What follows might seem a bit disjointed but I am typing as things come to me. Here we go

Step 1
Knowing what I do about G4P I would ask “Is there a control that could be repurposed to use as a tooltip?”. If you think about it, what is the difference between a label and a tooltip? Not a lot really :grinning:

Step 2
Create a GTooltip class and copy all the code from the GLabel class into it. Change all GLabel references to GTooltip. (dropped the ‘text’ bit from the name because it will also support icons).
Test the class by simply creating GTooltip objects.
We do not use GLabel directly because we will want to add additional functionality to the GTooltip class but that can wait for now.
Since it is likely that the tooltip must be aware of the control it belongs too we can add some new fields to the GTooltip class

protected GAbstractControl owner = null; // reference to the control that owns this tooltip
protected long tiptime = 0;   // current time when the tip is made visible

Step 3
There are several ways we could create and associate a GTooltip with another G4P control. For instance the user could instantiate a GTooltip object then add it to the G4P control object but that is rather verbose and more complicated for the G4P user than it should.
A simple solution is to have a control create its own tooltip when required. So we start with the GAbstractControl class add a new field -

protected tip = null; // reference to the tooltip for this control

Step 4*
This is the key to the whole thing we are going to add three methods to GAbstractControl, the first two control the visibility of the tool tip

protected void showTooltip(){
    if(tip != null) {
        tip.setVisible(true);
        tip.tiptime = System.currentTimeMillis();
    }
}

protected void hideTooltip(){
    if(tip != null) {
        tip.setVisible(false);
        tip.tiptime = 0;
    }
}

These will be used later but are useful in that they will help prevent NPEs.

The third method is the key and I only show an outline as additional parameters are needed to set the tooltip position relative to the control (usually they are shown adjacent to the control but we must make sure they don’t go outside the display area).

public void setTooltip("tip text", ...){      // ... variable(s) to determine relative position to control
    if(tip != null) return; // Can only use this method once for this control
    float tpX, tpY, tpW, tpH; // tooltip poistion
    // set the values in tpX, tpY, tpW and tpW based on current position of 'this' control
    // and parameters passed in the function header.
    tip = new GTooltip(winApp, "tip text", tpX, tpY, tPW, tpH);   // create the tooltip
    tip.owner = this;   // set the tooltip owner to this control
    hideTooltip();// Hide the tooltip until needed
}

Step 5
Now we need to hide the tooltip after a certain amount of time has elapsed we can do this in the GTooltip draw method like this

public void draw(){
    if(!visible) return;
    if(System.currentTimeMillis() - tiptime > 2000) { // hide after 2 seconds
        visible = false;
        tiptime = 0;
        return;
    }
    // rest of draw method code
}

Step 6
That’s just about it except to make the tooltip visible in the first place. To do that we need to be able to detect whether the mouse has moved over and moved off the control. We start by adding a new attribute to GAbstractControl

	protected int lastSpot = -1;

Now we need to modify the mouseEvent method for each control class. Using GButton as an example we have

public void mouseEvent(MouseEvent event){
    if(!visible || !enabled || !available) return;
	
    calcTransformedOrigin(winApp.mouseX, winApp.mouseY);
    currSpot = whichHotSpot(ox, oy);

change it to something like

public void mouseEvent(MouseEvent event){
    if(!visible || !enabled || !available) return;

    calcTransformedOrigin(winApp.mouseX, winApp.mouseY);
    currSpot = whichHotSpot(ox, oy);

        // New code to detect mouse enter and mouse enter control
	if(currSpot > 0 && currSpot != lastSpot) {
		showTooltip();
		lastSpot = currSpot;
	}
	else if(lastSpot >= 0 && currSpot < 0) {
		hideTooltip();
		lastSpot = -1;
	}
	lastSpot = currSpot;
    
    // Continue with existing code

Step 7
Pick a control e.g. GButton and change the mouseEvent method as shown. Test the tooltip thoroughly to make sure it works as expected debugging the code as necessary. When satisfied that all is well then change the mouseEvent code in the other controls that might need tooltips.

Final words - This is all off the top of my head and there is still a lot of coding and testing to do to get it right. Hope this helps :grinning:

1 Like

Hi Peter,

Thanks for your thoughts. More than I expected.

Guess people are more visually literate than myself but commercial software that heavily relies on buttons of a graphical nature with little to no tooltips annoys me. Even a button with a one word description on that button can give rise to a bad user experience. One can get used to a GUI, visually based (or simple text) button if there is an initial clue as to what it is and does.

I’ve seen the changes though the three significant versions of G4P and the nicest part is your discipline in keeping the code base clean. Didn’t realize the latest G4P was using JDK16 until I tried building your library. More about processing than G4P. Inevitable that will change as Processing moves forward. Patching becomes a slippery slope but at least following your underlining philosophy might make it possible.

I’ll fix my code so it “functions”; pulling in especially the Color Schemes so I have a reference point. Then massage that across to your suggestions. Liking the adding to abstract control but need to figure out how that works.

Your right, there is very little difference between a label and a tooltip. The one thing that is different (but its only a variation on the theme of a label) is the fact that it visually needs to be “clearly” a tooltip and not another control element. Hence my rounded rectangle, use of the alpha channel and use of a dropshadow to hint at it being a temporary floating element. Think I used a GTextField or something like that as the starting point but possibly merit in using the GLabel.

Anyway thanks for your input, I’ll massage it into submission. I’ll send you a link once its at a point I’m happy with.

Cheers
Stefan

2 Likes

This afternoon I decided to have a go myself using the steps shown in my last post. I soon discovered several errors in the post :frowning_face: but I did say it was off the top of my head. :innocent:

Anyway I have corrected the post based on my programming efforts so far. :grinning:

Based on the 7 steps I now have a basic working tooltip class. I have decided to continue and incorporate this feature into G4P. There is still a lot of design decisions to make, also a lot of coding and testing to perform but the basic logic appears to be sound.

One of the design decisions to be made will be the visual appearance of the tooltip, whether it is based on the current color scheme or has a unique appearance based on it’s own scheme. :thinking:

1 Like

Hi Peter,

Sorry; intent wasn’t to prod you into action at all. Was happy to muddle along, but grateful you can see merit.

I have no doubt the addition will be a huge improvement to user experience for things needing GUI controls. Certainly a dozen or so of mine would benefit, even your GUI Builder tool with a tooltip on the graphical buttons would be a beneficiary.

Aside some tools I’ve developed for CI with Jenkins, most of my efforts are to control or display data from embedded micro controllers. Work for a quantum computing lab in an engineering role supporting research experiments. Becomes difficult to convey intent of a control element to my target audience when there are any number of factors that need to be controlled/managed with only a bit of text on a control. They are clued up girls and guys, but how I think about things and the way they might think about the same thing can be at odds. This becomes a game changer.

Not sure how the Tooltips might look and still being in keeping with your current GUI elements. Variation on the theme of your colour schemes would make sense but needs to be visually temporary. Adding drop shadows and rounded corners certainly gives clues as to the temporary nature of the tooltip but it is a diversion from your “out of the box experience” graphical elements wise. Consistency across all your widgets is one of the great points about your library but maybe a tootip is enough of a functional difference to make an allowance for a difference to be considered.

Below is what I used, can’t claim credit for the snippet but long since lost the original source other than I bashed it into submission to work with JDK16. After posting the snippet I noticed there are some flaws in the code IE “(int)(w * (10/64));” would probably end up as Zero… No matter you get the idea.

“w” and “h” worked out from Font Size and length of string.
“shadowOffset” constant 8
Margins are about the extra space either side and above/below the tooltiptext

The rest probably makes sense.

void drawBalloon(int x, int y, int w, int h)
{
    this.w = w;
    this.h = h;
    rectWidthMargin = (int)(w * (10/64));
    rectHeightMargin = (int)(h * (10/64));
    int rounding = (int)(h / 5);
    this.applet.strokeWeight(2);
    this.applet.stroke(0,0,0,alpha_tool_tip/20);
    this.applet.fill(0,0,0,alpha_tool_tip/4);
    roundedRect(x + shadowOffset + 2,y + shadowOffset + 2,w + rectWidthMargin,h + rectHeightMargin, rounding);
    this.applet.stroke(255,255,255,alpha_tool_tip);
    this.applet.fill(80, 150, 0, alpha_tool_tip);
    roundedRect(x, y, w + rectWidthMargin, h + rectHeightMargin, rounding);
}

/***
 * A method to produce a rounded rectangle.
 **/
void roundedRect(int left, int top, int width, int height, int roundness)
{
    this.applet.beginShape();
    this.applet.vertex(left + roundness, top);
    this.applet.vertex(left + width - roundness, top);
    this.applet.bezierVertex(left + width - roundness, top,
            left + width, top,
            left + width, top + roundness);

    this.applet.vertex(left + width, top + roundness);
    this.applet.vertex(left + width, top + height - roundness);
    this.applet.bezierVertex(left + width, top + height - roundness,
            left + width, top + height,
            left + width - roundness, top + height);

    this.applet.vertex(left + width - roundness, top + height);
    this.applet.vertex(left + roundness, top + height);
    this.applet.bezierVertex(left + roundness, top + height,
            left, top + height,
            left, top + height - roundness);

    this.applet.vertex(left, top + height - roundness);
    this.applet.vertex(left, top + roundness);
    this.applet.bezierVertex(left, top + roundness,
            left, top,
            left + roundness, top);
    this.applet.endShape();
}

More than happy to test any of your efforts and thanks.

Stefan

2 Likes
    rectWidthMargin  = (int) (10 / 64. * w);
    rectHeightMargin = (int) (10 / 64. * h);
1 Like

if I didn’t want to do it no amount of prodding from you, or anyone else would make a difference :grinning: but I agree that tooltips would enhance G4P so it’s worth the effort.

GUI Builder uses Java Swing for its interface and the toolbar buttons have had tooltips as long as I remember LOL.

Consistency is certainly important which is why G4P has several pre-defined color schemes. If the tooltip was to have its own unique color scheme then it must work visually with all the other colour schemes. Personally I am undecided yet but will start with the standard G4P colour schemes.

In all my libraries I have tried to predict user expectations in terms of functionality and useability and to a large extent I have been successful I will do the same for this project. Since tooltips have been around for a very long time users would expect G4P tooltips to behave similarly.

The next design decision is related to size and placement. For instance a tooltip is associated with a particular control so should appear near that control but be entirely visible and not extend over the window borders.

So still a long way to go but the journey will be challenging and fun. :grinning:

1 Like

Here is the first challenge.

Few people realise that any G4P control can be rotated an arbitrary angle. In this picture the button has been rotated by 22.5 degrees but the tooltip hasn’t.

Screenshot 2023-06-22 at 11.38.38

For me this raises some issues

  • the tip become more visually distant from the button
  • it looks ‘untidy’
  • need to prevent the tooltip being hidden by the button

So if the control is rotated should the tooltip also be rotated?

2 Likes

Hi Peter,

Just had a quick look at the GUI Builder, no tooltips pop up!! Think I have the latest.

You’ve definitely been successful in predictable user experience outcomes. Pretty certain that is the main reason so many people use your library.

Can see the dilemma posed by rotated controls. Pretty much everything I’ve ever done has been orthogonal so not an issue with that. You raise a valid point though.

The sorts of commercial GUIs that have “rotated” controls, typically they would be irregular shaped controls around a central point. Akin to remote controls or a series of buttons that might describe a joystick control. The user would still be looking at the GUI in the X/Y orientation so maybe it is valid to keep the orthogonal orientation for the tooltip but float the tool tool tip over the centre of the control in the rotated instance. Edge of screen would need to be central to the Y axis of the control but an X offset by the width of the Tooltip text. So the relevance of the tooltip to the control is apparent. But orthogonally placed controls have the tooltip justified either left or right of the control depending on which half the screen they are placed.

Relevance to the tooltip will probably be apparent to a fair degree, given one has floated the mouse pointer over the control for an extended period anyway. Tooltip doesn’t hinder user GUI interactions either functionally or visually unless the user isn’t sure of the intention of the control. Which case they will be floating over the object for a while and some feedback to the user is better than none.

Just thoughts, thinking how I might expect a tool tip to work in the two circumstances. Can see that it might be a better design decision to have one shoe fitting all circumstance, weather orthogonal or rotated. Having the tooltip display one way for rotated and another for orthogonal might be messy and unpredictable. User experience wise wise though I can see there might be a valid reason to make a distinction between the two.

Feeling is the tooltip should look different to other control elements and shouldn’t be opaque as that will hinder the user reading other objects that might be around and under the tooltip popup.

Stefan

The latest version is 4.4.2 released 5th Nov 2022 and here is the text area tool tip :wink:

It always happens that when I start to add functionality to one of my libraries, it highlights problems with the existing code and that’s what happened today. The issue is that the much of the code in GTextIconBase should have been in GTextBase but wasn’t due to poor OO design and laziness on my part. So I have spent some hours today fixing that and making sure the changes hasn’t affected other controls that inherit from these classes.

So things are going well in that I now have a GToolTip class that correctly inherits from GTextBase and I can create working toot tips for the GButton class. It will be easy to extend this to other controls - less than 8 lines of code for each control class.

I have decided that the tool tip will rotate with the control while maintaining the same relative angular position and this has been implemented. To be honest I included rotated controls on a whim because I could and it seemed a fun thing to do. :grinning:

At the moment the tool tip becomes visible when the mouse moves over the control and invisible after 2 seconds or when the mouse moves off the control whichever comes first. There will be an option for the user to set the show time interval for all tool tips.

The next 2 priorities are

  1. tool tip placement. In the picture the tool tip is south-east of the button. The user will want to select their own placement position so I have to decide on how to implement that e.g. free form or choosing from a range of preset positions
  2. I have added code to allow the user to define a default font for tool tips but still have to decide on what other customisation methods to implement.

I am not too worried about the code for the tool tip visual as it only requires changes to the updateBuffer method so can easily be changed very rapidly but I will try your suggestions out and see what it looks like. Although semi-transparent backgrounds can be nice care must be taken because you want to maintain text clarity no matter what the background,

I am sure there will be other problems along the way but they shouldn’t be big ones.

All suggestions / ideas are welcome so keep them coming.

1 Like

Maybe add some option to disable that inherited behavior?
I’m not so sure every1 likes to read rotated tooltips.

Hi Peter,

GUI Builder 4.4.1 didn’t, 4.4.2 does. Accounts for why I didn’t see it. Was my main reason for not using the Builder. That and my visual literacy, no slight on your efforts. Might have a bit of a play.

Very aware of how easy it is to make a hash of code. Takes a lot of thought to land on an architecture that works intuitively, then the discipline to keep to that underlying premise, along with the willingness to recognize when a change needs to happen. That’s not even considering a library that many people use.

Like the idea of it being an option to rotate or not rotate the tool tip.

Placement wise the position would need to alter depending on which side of the screen (XAxis), how close to the bottom (Y Axis). But extrapolating your south-east comment maybe that alters depending on which quadrant the tooltip (or maybe the control) is on. That would be reasonably intuitive.

Multiline tooltip might also be a consideration. The joy of not being able to predict what a user might want…

image

Yay, fixed up my offset bug you highlighted. Shows multi line.

Stefan

1 Like

@GoToLoop and @myupctoys thanks for your thoughts and I agree that an option to rotate / not rotate the tool tip with the control is a good idea so will give users the option.

I plan to give the user a variety of options when deciding on the placement but have decided to leave it to the user to make sure it fully displays within the window.

Since the GToolTip class was originally based on GLabel it already supports multi-line text :smile:

1 Like

I now have a fully working version of G4P (V4.3.9) with a tool tips feature. The video below shows two Processing sketches

  1. using G4P standard tool tips (out of the box variety). Each tip requires a single statement to create it :grinning:
  2. a user defined version that was fully created in the Processing IDE. This custom version is a simple animation but could be adapted by a user to meet their specific needs.

BTW he default tip orientation is horizontal but can be changed so it rotates with the control.

Both of these sketches will be included as library examples.

Any comments or thoughts are welcome.

2 Likes

Hi Peter,

That’s cool. Seems to work as advertised. Can see you’re using the GSchemes which retains the look and feel of the library.

Few things I’m wondering about but like to throw it at a few of my assorted programs to give feedback.

Cheers
Stefan

Just announced the release of G4P V4.3.9 with tool tips. It is also available in sourceforge

1 Like