Jump to content

How I'm using Studio


Recommended Posts

When I saw uGFX and Studio for first time, Studio was just a example maker, i.e. you should start project in Studio, place widgets, see preview, generate code and.. that's all. If you need to shift some widget, change font or do something like this, you cannot, because you will lost all changes you made to sources. It is acceptable if you have small project and can do it manually by changing source code, but if your project is more complicated (like mine) or you want something special from uGFX (like me).. you simple cannot.

Thanks to Tectu, he implemented some changes to Studio, so we can use Studio in all development process now! Mine process was more complicated at start, but I will describe below how I do this now.

First of all, Studio can generate code for you. Lets see what we will get after code generation:

  • functions that creates all windows for you (CreatePage*() in gui.c)
  • guiShowPage() that will show selected window for you
  • guiCreate() that will load all fonts and images, init defaults, create all pages and show default page (window)
  • guiEventLoop() as example of events main loop
  • main_sample.c as example of your main.c
  • gfxconf.h with defines you selected in Studio
  • header files with color styles, files and other resources

You can take all these files and use in your project as is, but you can't change anything in output directory, because you will lost all your changes if you will re-generate source with Studio. So, I selected other way, I will use code generated by Studio, but with some modifications:

  • main_sample.c not used
  • I'm using more than one image per widget, to show status of hardware to user by icons
  • guiCreate() copied from gui.c to my own application with little modifications, I'm not using supplied one (because I need specific startup with touch panel re-calibration by holding a key at start, and similar things)

So, I need every resource to be defined as extern, CreatePage*() function as non-static and so on. Ok, lets accept this challenge!

First, now we can generate header files with additional images, place them somewhere outside of output folder and set additional files in Settings->GFILE->Additional files. All these file will be included into romfs_files.h (but will not defined as variables).

Second, we can use now post-generation script that will be called each time you pressed hammer icon in Studio just after all files were generated. You can do this by adding script to Settings->Generator->Scripts. You can use (or not) script for preview and for build actions. I wrote my own Perl script for post-build action.

What is does:

  • scans gui.c for handlers names like ah<something>_X or ah<something>_X_Y and converts them into array variables, like GHandle ahButton_dt[5] or GHandle ahLabel_mem[5][4], also adding them as extern into gui.h
  • scans romfs_files.h for images, and adds them into gui.c as variables and to gui.h as extern variables (note again, additoinal files not defined as variables, so I should get them from this file)
  • converts all CreatePage*() functions to non-static, to be called from my own main.c
  • scans for fonts and also put them as extern into gui.h
  • defines all widget styles as extern
  • adds some custom defines into gfxconf.h, like GFX_USE_OS_CHIBIOS, GINPUT_TOUCH_USER_CALIBRATION_SAVE, GDISP_NEED_PIXELREAD, GFILE_MAX_GFILES and so on
  • rewrites LoadMouseCalibration() definition as __weak (I'm using my own function).

Note again, that I'm using my own version of guiCreate(), so I should have access to all fonts, images, widgetstyles and other resources from my own main.c. If you satisfied with default created guiCreate(), you can use sources as is, without using script at all (or make your own, depending on your needs).

Now we can add window, some widget, add/change font or shift our labels, then press hammer icon in Studio, then compile and run our modified GUI in hardware just in couple of clicks! 

More important, we can use Studio in any step of our development, we can add some windows or widgets later, we can change everything even after firmware was finished. We are not limited by 'design GUI -> generate files -> develop firmware' sequence anymore!

Link to comment
Share on other sites

I just copied guiCreate() that uses gdispImageOpenFile() to open images. Studio places additional files to romfs_files.h, but not declares variables to use these additional files. To place another one file into my firmware I do:

  • place button somewhere in window
  • assign new image file to it
  • generate code in Studio
  • copy generated .h file from rsc to my ../files folder
  • add its name into "Additional files" section in Studio
  • copy generated line with new file and gdispImageOpenFile() from gui.c to my main.c
  • remove temporary button with its image
  • re-generate code again
  • use this new file in my firmware to replace another button's image (when, for example, I want to show user that recording was turned on)

Using variables collected from romfs_files.h and defining them as extern in gui.c/gui.h allows me to keep all image variables in one place, and keep them intact (in fact, re-generate each time by prepare script) when re-generating code by Studio. So, I have only one place where all my files located on disk, and only one place where files are defined in sources and so on.

I think it will be nice to add possibility to Studio to assign more than one image file some widgets (not touching uGFX code, but associate these files in Studio project with widget, just creating additional image variables and gdispImageOpenFile() calls). It will allow get 'spare' images for widgets if user wanted to replace images at runtime and it will delete all widget's images automatically if such widget will be deleted from Studio project.

Link to comment
Share on other sites

Those additional files can be opened using gfileOpen() so there is no need to mark them extern. romfs_files.h is supposed to contain the structures and file information for the ROMFS file system (which is accessed using gfileOpen() or gdispImageOpenFile()). It is not meant to be a way to memory address arbitrary objects. The internal elements in ROMFS should never be accessed directly as it is entirely possible that the implementation of ROMFS may change in future. The items put into romfs_files.h are supposed to be accessed using the GFILE api.

As an example, in future we may compress data put into romfs_files.h with the GFILE api decompressing that data automatically during read operations This is actually on my TODO list (although near the bottom) as it could save significant amounts of ROM/code space in the final application. In such a situation accessing the ROMFS objects directly using extern would not lead to usable data.

Link to comment
Share on other sites

I just decided to keep all files to be opened same way, with same type of variables and so on.

Note that I'm telling about gdispImage type variables, generated by Studio for gui.c internal usage. It generates such variables for images that used in GUI, but not for additional ones (what I can understand, it do not knows what inside of such files, maybe not image at all). But I know for sure that I have only images there, so I made such hack for me.

If you will make compressing, I still will define new gdispImage variables for additional files, and they still can be opened with:

gdispImageOpenFile(<my generated gdispImage variable>, <ROMFS pathname>)

I just take filename from romfs_files.h, change dashes to underscores and this is my new variable name. I add this variable into gui.c and into gui.h as extern, to be used in my main.c, just to keep all gdispImage variables definitions in one place (inside gui.c/gui.h).

Sorry, if I misunderstood something.

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...