π
<-

GUI toolkit under development

C, C++, ASM...

GUI toolkit under development

Hello,

I am currently in the process of developing a toolkit for making GUI-based applications in C++ using both Ndless and SDL.
This project, done on my free time, is initially for my own needs and is focused on mitigating the lack of GUI toolkit, but while coding it, I realize it may help other developers.

The root of the project is coming from Vogtinator's pyWrite, with now major changes and additions. I use this opportunity to thank him very much cause I learnt a lot while reading his code .

This is far from being finished (if a version number is required, I would says I am currently at 0.2beta ), but if there is an interest, I can push the development bit further than what I just actually need and hence make something more "generic".

This is how it looks like right now :

Many things are still done by hand (by instance the positioning of widgets, but it can be improved significantly by additional work of mine).

The following window is achieved just by coding this :

Code: Select all
    // Creation of the application    WidgetApplication *MyApp = new WidgetApplication();    MyApp->setbackgroundpicture( "/documents/Widget/002.bmp.tns" ); // with a wallpaper cause it's cool !!!    // this is the window frame    WindowWidget *window = new WindowWidget( "This is a Window", 20, 30, 250, 150, nullptr );    // in which we add widgets by connecting to the window as a parent-child relationship    InputWidget *input = new InputWidget( "Test 2", 25, 60, 240, 15, window );    input->setcontent( "Hello World !!! This is the best widget I have ever seen in my Life !!!");    ButtonWidget *button = new ButtonWidget( "Active Button", 30, 150, 110, 15, window );    ButtonWidget *button2 = new ButtonWidget( "Disabled Button", 150, 150, 110, 15, window );    button2->disable();    CheckBoxWidget * check1 = new CheckBoxWidget ("Checkbox Square tick", 25, 85, 200, 12, window );    check1->settype( Square_Tick );    CheckBoxWidget * check2 = new CheckBoxWidget ("Checkbox Cross tick", 25, 105, 200, 12, window );    check2->settype( Cross_Tick );    CheckBoxWidget * check3 = new CheckBoxWidget ("Checkbox unchecked", 25, 125, 200, 12, window );    check3->settype( Cross_Tick );    // when it's done we connect the window to the application    MyApp->addchild( window );    while (!done)    {        // we check is something is happening with the mouse or the keyboard (this is spread hierarchically to childrens)        MyApp->logic();        // Here is the loop for detecting keypressed and exit if needed        // and we render (this is also cascaded to childrens widgets)        MyApp->render();    }

It has some good things inside (I think ), such as triggered functions from the widget (if connected by the adequate call) when it is clicked/released/hovered. No need to say we can also just get the properties of the different widgets by using usual getters/setters functions/methods.

What I would like to add in the coming revisions :
- some more widgets (label, radiobuttons, frame, combobox, sliders, multiline inputbox, ...)
- create a simple system for automatic positioning of the widget (using default relative calculations and positioning in "transparent" grid containers)
- move / fold / unfold / expand / shrink windows
- ... many other things (but not to compete with GTK/KDE/Wxwidgets toolkits )

And of course some demonstration programs to check whether everything is working properly...

Let me know your thoughts and if a public release could be beneficial to some of you.

Cheers

Sly
Developing the GUI Toolkit for nSpire
see current revision here : https://github.com/SlyVTT/Widget-for-TI-NSpire

SlyVTTProgrammeur

Niveau 8: ER (Espèce Rare: nerd)
Level up: 21.5%

Posts: 65
Images: 0
Joined: 19 Jan 2021, 09:41
Gender:
Calculator(s):

Re: GUI toolkit under development

Hello,

Some good improvements have been done to the toolkit:
- Horizontal and Vertical grid containers with automatic positioning are available
- Frame widgets have been added
- some bugs have been corrected (I guess some are still here, it takes time to detect them all ... so please feel free to report them)

I uploaded the source code and the tns file her : http://ti-pla.net/a2704117 for ones interested in testing and giving feedbacks.

This is a screenshot of the current revision :

Still a quite long road to reach the end, but it is quite useable for most of the applications.

This is a Widget toolkit for making GUI on NSpire

The development is not so advanded but one already use this toolkit to make applications.
Already existing and useable widgets are :

labels / input / sliders / buttons / minibuttons / window / frame / ContainerH and ContainerV

Attached is a small example :

Touch pad to control the cursor (like a mouse) and click
esc to exit
Ctrl + . (capture) takes a screenshot

Widgets.tns, 001.bmp.tns and 002.bmp.tns must be in a root based directory called 'Widget'.

Tested only on nSpire CX II-T CAS, not sure if it work correcly on other nSpire devices.

Source code is available for ones who can be interested.

Revision is 0.3beta.

Cheers

Sly
Developing the GUI Toolkit for nSpire
see current revision here : https://github.com/SlyVTT/Widget-for-TI-NSpire

SlyVTTProgrammeur

Niveau 8: ER (Espèce Rare: nerd)
Level up: 21.5%

Posts: 65
Images: 0
Joined: 19 Jan 2021, 09:41
Gender:
Calculator(s):

Re: GUI toolkit under development

Hi,

Well, congrats, it sure looks nice, good job!

Niveau 16: CC2 (Commandeur des Calculatrices)
Level up: 57.1%

Posts: 13312
Images: 1093
Joined: 01 Jun 2007, 00:00
Location: France
Gender:
Calculator(s):
Class: (ingénieur)

Re: GUI toolkit under development

For whom may be interested, the new window (in comparison to the first message) and all widgets' behavior is just achieved in only few lines of code:

Code: Select all
    WindowWidget *window2 = new WindowWidget( "This is a Window", 50, 20, 250, 100, nullptr );    // not that all the positions and dimensions are arbitrary set to 1    ContainerVWidget *containerv = new ContainerVWidget( "container", 1, 1, 1, 1, window2 );    ContainerHWidget *containerh = new ContainerHWidget( "container", 1, 1, 1, 1, containerv );    ContainerHWidget *containerh2 = new ContainerHWidget( "container", 1, 1, 1, 1, containerv );    LabelWidget *labelA = new LabelWidget( "This is automatic positioning", 1, 1, 1, 1, containerv );    ButtonWidget *buttonB = new ButtonWidget( "Hide window", 1, 1, 1, 1, containerh );    ButtonWidget *buttonC = new ButtonWidget( "Show Window", 1, 1, 1, 1, containerh );    ButtonWidget *buttonD = new ButtonWidget( "Disable window", 1, 1, 1, 1, containerh2 );    ButtonWidget *buttonE = new ButtonWidget( "Enable Window", 1, 1, 1, 1, containerh2 );    ButtonWidget *buttonF = new ButtonWidget( "Quit", 1, 1, 1, 1, containerv );    containerv->addtocontainer( labelA );    containerh->addtocontainer( buttonB );    containerh->addtocontainer( buttonC );    containerv->addtocontainer( containerh );    containerh2->addtocontainer( buttonD );    containerh2->addtocontainer( buttonE );    containerv->addtocontainer( containerh2 );    containerv->addtocontainer( buttonF );    // the adust method of containers (vertical and horizontal makes the magic !!    containerv->adjust();    containerh->adjust();    containerh2->adjust();    // and once agai we attach the window to the application    MyApp->addchild( window2 );    // we render and play the logic of the toolkit    while (!done)    {        MyApp->logic();        SDL_Event event;        while (SDL_PollEvent(&event))        {            switch (event.type)            {                case SDL_QUIT:                    done = true;                    break;                case SDL_KEYDOWN:                {                    if (event.key.keysym.sym == SDLK_ESCAPE) done = true;                    break;                }            }        }        // the logic behind the buttons click (easy way, not using triggered pointer function)        // window is the object define in the first message of this post        if (buttonB->ispressed()) window->setinvisible();        if (buttonC->ispressed()) window->setvisible();        if (buttonD->ispressed()) window->disable();        if (buttonE->ispressed()) window->enable();        if (buttonF->ispressed()) done=true;        MyApp->render();    }    return 0;
Developing the GUI Toolkit for nSpire
see current revision here : https://github.com/SlyVTT/Widget-for-TI-NSpire

SlyVTTProgrammeur

Niveau 8: ER (Espèce Rare: nerd)
Level up: 21.5%

Posts: 65
Images: 0
Joined: 19 Jan 2021, 09:41
Gender:
Calculator(s):

Re: GUI toolkit under development

Looks really nice, good job !

Ti64CLi++Modo

Niveau 16: CC2 (Commandeur des Calculatrices)
Level up: 10.5%

Posts: 3386
Images: 75
Joined: 04 Jul 2014, 14:40
Location: Clermont-Ferrand 63
Gender:
Calculator(s):
Class: MP
GitHub: Ti64CLi

Re: GUI toolkit under development

Thanks Both, appreciated...

I forgot to mention that a clear documentation would be mandatory

Sly
Developing the GUI Toolkit for nSpire
see current revision here : https://github.com/SlyVTT/Widget-for-TI-NSpire

SlyVTTProgrammeur

Niveau 8: ER (Espèce Rare: nerd)
Level up: 21.5%

Posts: 65
Images: 0
Joined: 19 Jan 2021, 09:41
Gender:
Calculator(s):

Re: GUI toolkit under development

Nice, good job!

The root of the project is coming from Vogtinator's pyWrite, with now major changes and additions. I use this opportunity to thank him very much cause I learnt a lot while reading his code .

Oh dear - I hope you didn't pick up any of the examples on what not do to, at least outside of the restricted environment here...
The main logic/render loop for instance is mainly for games where you want high FPS anyway (though those usually wait for VSync), but not really for UIs where constant rendering just keeps the CPU busy and wastes power. This could be improved by adding support for timer events and waiting for an event before doing the next logic/render iteration.

I see that you got rid of using different tasks for dialogs, which is a good step in the right direction. That was mostly to circumvent the primitive event handling system, which basically did almost everything in custom logic methods. If you want to know how to do it the right (or at least less wrong), I suggest to look at how Qt Widgets work at a higher level.

- some bugs have been corrected (I guess some are still here, it takes time to detect them all ... so please feel free to report them)

I had a quick try and noticed that the Widgets.tns example is 1.2MiB large, is there an image embedded?

It seems like widgets also react to input if another window is on top. You could fix that by only notifying the window the cursor is on in WidgetApplication::logic, or implementing "enter"/"leave"/"focus"/"unfocus" events and handling that in the windows themselves.

The Makefile appears to hardcode a path on your development system: /home/sylvain/SharedFolder/SharedFolder/, so currently it won't build on other systems.

Here's a suggestion on how to significantly improve the appearance of the UI without much work: Font drawing with glyphs of varying width! I'm not sure what you're currently using for font drawing, but you could switch over to use something like FreeType (more complex, but can load arbitrary fonts and even draw with subpixel rendering) or something using prerendered bitmaps with width info, like pyWrite's font.cpp.

Niveau 8: ER (Espèce Rare: nerd)
Level up: 71.9%

Posts: 177
Joined: 29 Mar 2014, 15:55
Gender:
Calculator(s):

Re: GUI toolkit under development

Hi Vogtinator,

At present it uses the render()/logic() from your widget, but you are right, it makes the CPU busy all the time. This is far from being optimum, it would be much better to check the mouse movement (let's call this a mouse as it serves as a mouse), mouse clicks or keyboard strokes to initiate a "logic" and "render" round and check if something has to happen (or not), this is planed for later revisions. The current architecture of the toolkit should make this change quite easy. It just means creating a kind of keyboard events handler, adjust the mouse task to also support events and branch this to the right functions.

Your concept of 'Dialogs' has been removed, such as one of ContainerWidget. The Widget class has been boosted and contains both children and parent pointers to cascade the methods. It also permits (this is under development) to automatically position widgets relatively to others. As of today, this is done only by ContainerHWidget and ContainerVWidget objects throught their method 'adjust()'.

The TNS is very large and to be frank I am really surprised and do not understand why. It would be so easy if an image would be embedded, but sadly that is not the case. I think this is coming from static linking to both SDL and SDL_Image libraries, but I cannot confirm. It would be much better if we could have dynamic linking. Especially cause I develop this toolkit with the aim of rewriting all my routines, so if each is 1.2Mb, it will drastically reduce what can be done.

The window (in fact all the widgets) contains a enabled/visible properties that can be used to stop the logic() or render() methods respectively and cascade to children widgets. In the example, there is a button to enable the window in the background and one to disable and two others for making it visible/invisible. Making in disabled renders the window titlebar in grayish instead of blue. I think i can quite easily mix this properties with the focus/unfocus concept. I have also to find a way of switching the order of windows (for example background window moving to foreground when clicked). Need to put some brain juice on this by working on the <Vector> collections in the WidgetApplication class.

Font drawing is really a pain with nSDL... set of routines and even if it was not so fun to re-code routines for font management, I will have to do cause it is done in such a way with "nSDL" functions that you cannot change the color of the font (if you want to draw string in white and in red for example, you have to load two different fonts with nSDLLoadFont ..., one with RGB(255,255,255) adn the second with RGB(255,0,0), so not so practical). I do not know yet if the best is to code something from scratch or use the SDL_TTF library. The second options is very attractive but I am afraid of the final size of the executable if I add one more library ...

I can fix very easily the makefile. This folder is not the build target, it is just a place where I copy the TNS after building to save time (and clicks) for copying to my calculator cause I am a lazy guy

Really appreciate your feedback, and I agree with all the points. But as you can see, there are still a lot of thing to code/correct/improve.

Will work on all this for next revisions.

Thanks

Sly
Developing the GUI Toolkit for nSpire
see current revision here : https://github.com/SlyVTT/Widget-for-TI-NSpire

SlyVTTProgrammeur

Niveau 8: ER (Espèce Rare: nerd)
Level up: 21.5%

Posts: 65
Images: 0
Joined: 19 Jan 2021, 09:41
Gender:
Calculator(s):

Re: GUI toolkit under development

Maybe interesting for some coders,

I spent some time on trying to understand why the size of the TNS file was so big, and I have been able to reduce it from 1250kib to 550kib just by removing <fstream> in the included files.
I also removed all non essential included files, making the code much more clean (so it worth the job )

I got one single function that took 700kib just for verifying if one file exists or not.

Formerly it was coded as follows :

Code: Select all
#include <fstream>bool is_existing( const std::string & file ){    std::ifstream fichier( file.c_str() );    return !fichier.fail();}

and it is now replace with the following code :

Code: Select all
#include <sys/stat.h>bool is_existing( const std::string & file ){    struct stat buffer;       return (stat (file.c_str(), &buffer) == 0);  }

which weight 700kib less in the final executable !!!

The gain is really impressive ... I will think twice before adding some std classes in my code. When coding for PC, it is not so important, but with "only" 100Mib of disk space on embedded device, each byte counts

Now I can focus on more interesting stuff

Cheers

Sly
Developing the GUI Toolkit for nSpire
see current revision here : https://github.com/SlyVTT/Widget-for-TI-NSpire

SlyVTTProgrammeur

Niveau 8: ER (Espèce Rare: nerd)
Level up: 21.5%

Posts: 65
Images: 0
Joined: 19 Jan 2021, 09:41
Gender:
Calculator(s):

Re: GUI toolkit under development

All,

the revision 0.4 is done, with majors improvements, but unfortunately not so visible as it is more linked to the internal parts of the routines and of the toolkit.

I created a GitHub here https://github.com/SlyVTT/Widget-for-TI-NSpire where sources can be found as well as a compiled version. It can also be downloaded here: https://tiplanet.org/modules/archives/download.php?id=2706263

Among the new things :
- the Application class is now able to manage
multiple desktop
(we can switch by using 'CTRL+<--' and 'CTRL+-->' to switch between the desktop, each being fully autonomous, with own properties such as wallpaper/background color ....
- each widget (by instance windows) can be assigned to one given desktop, and at render time, non visible desktop are "paused".
- now
rendering and widget internal logic is activated base on keyboard/mouse events
(and hence saving a lot of time). This is not based on interrupt or like, don't know if this can be done on NSpire (would be very interested)
- the
focus/unfocus is now correctly implemented
, last revision was buggy and I discovered afterward that I was not able to manage two inputboxes. Now it is corrected and works as it should.
- a
keyboard and mouse handlers

For build,
Makefile is corrected
and should work correctly, all 'personal" folders have been removed.

Next step will be
that are needed and still missing AND the
font management
cause current one is too limited.
And I plan to publish a first
actual application using the toolkit
to demonstrate what we can do when using it ...

Always open to comments and feedbacks (and also bug reports).

Regards

Sly
Developing the GUI Toolkit for nSpire
see current revision here : https://github.com/SlyVTT/Widget-for-TI-NSpire

SlyVTTProgrammeur

Niveau 8: ER (Espèce Rare: nerd)
Level up: 21.5%

Posts: 65
Images: 0
Joined: 19 Jan 2021, 09:41
Gender:
Calculator(s):

Next

Who is online

Users browsing this forum: No registered users and 6 guests

-
Search
-
Social
-
Featured topics
1234
-
For more contests, prizes, reviews, helping us pay the server and domains...

Discover the the advantages of a donor account !

-
Stats.
511 utilisateurs:
>485 invités
>18 membres
>8 robots
Record simultané (sur 6 mois):
6892 utilisateurs (le 07/06/2017)

-
Other interesting websites
Texas Instruments Education
Global | France
(English / Français)
Banque de programmes TI
ticalc.org
(English)
La communauté TI-82
tout82.free.fr
(Français)