Jump to content

Tabset with image in tab instead of text


Vikash

Recommended Posts

I am following below example to create Tabset. 
I want to show image in tab instead of text like "Page 1", "Page 2".  Please suggest how to show image in Tab instead of Text. 
	// Create the Tabset
	wi.g.width = 200; wi.g.height = 200; wi.g.x = 10, wi.g.y = 10;
	ghTabset = gwinTabsetCreate(0, &wi, GWIN_TABSET_BORDER);
	ghPage1 = gwinTabsetAddTab(ghTabset, "Page 1", FALSE);
	ghPage2 = gwinTabsetAddTab(ghTabset, "Page 2", FALSE);
	ghPage3 = gwinTabsetAddTab(ghTabset, "Page 3", FALSE);
Link to comment
Share on other sites

Hello & Welcome to the µGFX community!

You can customize the look'n'feel of any widget to match your needs. The easy approach here is to implement a custom drawing/rendering function for the existing widget. This means that you keep using the existing tabset widget behavior and you only change the way it is being rendered.
There is a full example in the documentation showing how to add an icon to a pushbutton widget. The process will be the same for the tabset: https://wiki.ugfx.io/index.php/Creating_a_custom_rendering_routine

You can use the void* parameter to pass in anything you like such as an images array or a complete custom type.
This should cover any scenario where you are happy with the existing behavior but want more control over the visual look.

In case that you also want to have different behavior, you can implement your own widget: https://wiki.ugfx.io/index.php/Creating_a_widget

Link to comment
Share on other sites

Thank you for your prompt reply.

I tried with gwinSetCustomDraw, but image is not getting displayed over Tab instead of text. 

Also, as I have set NULL in text name like gwinTabsetAddTab(ghTabset, NULL, FALSE);  Tabset is not displaying any text but Image is also not getting displayed and Tab width is now shrinked.  Please suggest.

void
tap_page_image_renderer(GWidgetObject* obj, void* p)
{
    const auto img = (gImage *)p;
    int16_t imgX = obj->g.x + (obj->g.width - img->width) / 2;
    int16_t imgY = obj->g.y + (obj->g.height - img->height) / 2;

    gdispGImageDraw(obj->g.display, img, imgX, imgY, -1, -1, 0, 0);
}

 
static void createWidgets(void)
{
    GWidgetInit    wi; 

// Prepare the images
    gdispImageOpenFile(&_home_img, "settings.gif");


    // Apply some default values for GWIN
    gwinWidgetClearInit(&wi);
    wi.g.show = TRUE;
 
    // Create the Tabset
    wi.g.width = 200; wi.g.height = 200; wi.g.x = 10, wi.g.y = 10;
    ghTabset = gwinTabsetCreate(0, &wi, GWIN_TABSET_BORDER);
    ghPage1 = gwinTabsetAddTab(ghTabset, NULL, FALSE);
    gwinSetCustomDraw(ghPage1, tap_page_image_renderer, (void*)&_home_img);
    
    ghPage2 = gwinTabsetAddTab(ghTabset, NULL, FALSE);
    gwinSetCustomDraw(ghPage2, tap_page_image_renderer, (void*)&_home_img);
    
    ghPage3 = gwinTabsetAddTab(ghTabset, NULL, FALSE);
    gwinSetCustomDraw(ghPage3, tap_page_image_renderer, (void*)&_home_img);

Link to comment
Share on other sites

I just had a closer look at this. In case of anything inheriting from the container class, the custom draw is only responsible for the client area of the container which explains why this didn't work out for you.

The proper way of doing this would be to implement a custom widget to facilitate your needs as demonstrated by the documentation and various existing widgets (there are also two examples in the downloads section).
If you prefer a quick'n'dirty solution you could change the current drawtabs() implementation to render the tabs with images instead. You might be sneaky with some weak pointers here.

Long term, the best approach would be to create a custom VMT for the Tabset and having a function pointer in there for the non-client-area drawing.

Link to comment
Share on other sites

Hi Joel, Thank you looking this out. 

I tried creating custom VMT for the Tabset based on example of statusbar.  But its not working.  I am attaching here my gwin_custom_tabset.h file and  gwin_custom_tabset.c file, main.c file.

Please confirm if I missed something.  How we can achieve this?  Also, what should be the corresponding implementation of customTabsetAddTab(...)

gwin_custom_tabset.h gwin_custom_tabset.cpp

main.c

Edited by Vikash
added main.c file
Link to comment
Share on other sites

I come up with this customTabsetAddTab(...)

#include "gwin_custom_tabset.h"

GHandle customTabsetAddTab(GHandle gh, gdispImage* icon) {
    // Verify that the handle is a custom tabset
    if (gh->vmt != (gwinVMT*)&tabsetVMT)
        return 0;

    CustomTabsetObject* to = (CustomTabsetObject*)gh;
    GHandle tabHandle;

    // Check if the number of tabs exceeds the maximum
    if (to->tabset.nTabs >= MAX_TABS)
        return 0; // Maximum number of tabs reached, cannot add more

    // Create a new tab
    tabHandle = gwinTabAdd(gh, "Tab", GWIN_TABHEIGHT, GWIN_TABHEIGHT, gTrue);

    // Set the tab's user pointer to store the icon
    gwinSetUserData(tabHandle, icon);

    // Add the icon to the custom tabset object
    to->icons[to->tabset.nTabs - 1] = icon;

    // Return the handle to the new tab
    return tabHandle;
}

Edited by Vikash
added customTabsetAddTab(...)
Link to comment
Share on other sites

The code attachments you provided don't seem to compile and seem generally incomplete.
We'll gladly help wherever we can but we can't do guess work. Please provide a minimal example and explain what "does not work".

I'd recommend you to either implement a custom widget from scratch (there is documentation on that as well as the aforementioned examples) or to copy the existing tabset and modifying it as needed.
Your last post seems to go the right direction :)

Link to comment
Share on other sites

  • 2 weeks later...

Hi Joel, Thank you.  As per your suggestion we copied the existing tabset and modified it to show icons on Tab with this we are able to show icons on Tab. 

Attaching here working code. 

We need help in below:

1.  In Tabs icons as well as text is showing up, if we try to remove the tab text, tab width is getting reduced. Please suggest how to make tab width constant.

2.  We try to just show the icons, but it is not working.

3.  Also, we are not able to align icons to the center of each tab, it is always showing at the top left corner of tab.

software.zip

Link to comment
Share on other sites

I had a quick look between meetings and I think you're on the right track :)

All three of your questions are basically answered the same way: You're essentially creating a custom widget which means that you have full control over all of these aspects. Unless I am missing something, everything is happening inside your gwin_custom_tabset.c implementation. It sounds silly but "just go through it and remove what you don't need".

The first thing I'd recommend doing is remove all unused code (eg. stuff that is just there to make it play nicely with other built-in widgets (which isn't relevant when you create your custom widget). Notable that would be:

  • gwin_custTabsetDraw_image() (lines 579 to 613)
  • The true branch of GWIN_FLAT_STYLING (lines 403 to 429)

 

On 01/09/2023 at 16:35, Vikash said:

1.  In Tabs icons as well as text is showing up, if we try to remove the tab text, tab width is getting reduced. Please suggest how to make tab width constant.

Given that you're basically creating a custom widget you have full control over these aspects.
Have a look at the FixTabSizePos()

 

On 01/09/2023 at 16:35, Vikash said:

2.  We try to just show the icons, but it is not working.

Can you explain what "not working" means? I guess that it's just a side effect of the existing tabset widget using the text width to size the tabs. Once you remove all the tab text logic (as you don't need that) you'll most likely manually size the tabs which will make this issue go away.
Hint: Currently logic calls gdispGetStringWidth() at line 517. You want to replace that with something that suits you after you removed the tab texts.

 

On 01/09/2023 at 16:35, Vikash said:

3.  Also, we are not able to align icons to the center of each tab, it is always showing at the top left corner of tab.

You've correctly added the function calls to render the icons via gdispGImageDraw(). To align the icons, just modify the x, y, width and height parameters of that function call.

 

I hope that helps!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...