As it is often required to know the pixel width of text outside of draw functions the task is to move the GetStringFramebufferWidth() function (https://github.com/apertus-open-source-cinema/AXIOM-Remote/blob/dev/Firmware/UI/Painter/Painter.cpp#L536) into the Utils Class (https://github.com/apertus-open-source-cinema/AXIOM-Remote/blob/dev/Firmware/Utils.h)
Hello, I started looking into this.
Due to my lack of familiarity with the codebase, I have a few questions:
When moving GetStringFramebufferWidth() out of IPainter,
the font to use for the calculations has to be added as an additional parameter.
Should this be done using GFXfont or enum class Font?
Currently, GFXfont is only used internally in Painter.
So my thinking was that it would be good to keep it that way,
and instead allow other code to pick a font with enum class Font,
just like how SetFont() currently works.
If so, _fontList could be moved out of Painter to be accessible to GetStringFramebufferWidth() too.
The next thing I was wondering about is the status of namespace utils.
Currently, only one of the utils is inside the namespace, the rest are in the global one.
Are all the utils eventually going to be moved into the namespace?
Well then, great :)
My question about namespace utils still remains though, is the plan to move all the utility functions into it,
or is there some rationale behind whether a function ends up there or in the global one?
Utils was used to move some general stuff, but we had no time to review the architecture again, as we were trying to fix some things after GSoC2020 and discovered problems. Feel free to propose or add improvements. We can discuss anytime.
@sebastian , @BAndiT1983 I am really sorry, I called this task complete (i thought it was), I have not been confident enought to raise proper pull request, that I should have done way earlier, and I would be been having this discussion earlier, instead of jumping to another task. Please help me devise the right approach in this regard.
My understanding and Approach
- Painter - Only Responsible for populating framebuffer.
- Utilities - Group of different functions used to assist object(s), hence we are using namespace, instead of class (since we don't need encapsulation or abstraction)
Since, current font that is selected ,setting the font (or changing) and calculating text width does not involve manipulating framebuffer directly, so they should not be placed in painter.
What I thought is a good approach, setfont() , textwidth(), current font selected, height of current font all involves FontSettings.
so instead of placing it in utils, we have an class of CharacterFormat.h (or FontSettings.h or TextSettings.h), which involves setting the fontstyle, selecting fontsize, and other Character formatting related methods and attributes that we might add or need in firmware, in future.
- like all normal User interfaces, if we'll give option to change fontsize in settings of remote to user, then CharacterFormat.h class might be the right way.
- Since current font and current font height is only variables that is needed in other objects of the firmware (and these variables do not belong to any class yet), and since they are current font size and style belong more to character formatting, so placing these variables (or settings) in painter would not align with Single Responsibility Principle(SRP)
- We can have a class for global variables in firmware, that involves variables that are needed in various objects of the firmware, (unlike global settings because it stores variables involved in data abstraction of axiom remote not just firmware), but again these variables are being manipulated by other objects and currently we don't have a class or namespace for global variables, because we didn't need that (since variables are organized, as they always belong to some object according to their usage or properties)
- Font manager could help, but why is current font needed elsewhere than painter? Who uses it and for which reason?
- Are you sure that current font is not belonging to some class? Was under impression that it belonged to painter before.
- Font size changes won't be done by user, don't see a necessity there
- We would like to avoid global variables, as they are very error-prone as everybody can rewrite values from anywhere and break application logic, but we have CentralDB which is a hybrid solution, so we can react to value changes
- current font, and current font height, changes according to SetFont(). In painter we need current font height, while drawing text on screen, only. But the thing is, If we look at Numeric Value Screen , Image Button, Push Button, Toggle Button, Parameter List Screen, they also require the current font's height, and when whenever we set/change the font, the current font and hence current font height changes. So, I thought the sole purpose of current font and and its dimension (height) is not just drawing text on screen, but also in calculation of other objects of firmware, infact current font and its dimension(s) is more needed outside painter, same as GetTextWidth() .
- I don't think providing option to change font size might be needed either ,(no other camera GUI's have this I checked). Was just saying in terms of advantages Font Manager might offer, if we ever need something like that.
- I couldn't agree more. Global variables are not needed ("Abstractions should not depend upon details. Details should depend upon abstractions." - SOLID). But as you said, all the attributes pair's in CebtralDb (or global variables) involves observing changes by subject, which then dispatches those changes to observer that registered for those changes. So, placing current font dimension or font selected would not belong here, I thought.
Hence, I proposed and want to discuss the possiblity of FontManager.h, Since yesterday, I saw the logic of why and how things are organized the way they are in AXIOM Remote Firmware, the complexity of structure, the design (previous remote version was more functional oriented, and this is object oriented, hence I have wondered how to cameup with structure so organized) but reading SOILD principle gave me some thinking capacity in this direction.
I see there might be some confusion about the SetFont() usage. The purpose is not to allow a user to select the general size of fonts used in the remote (like operating systems let you set larger fonts that are easier to read for all software). The purpose is to allow drawing headers in a larger font than normal menu text for example.
Sorry, my English is rather bad, I was saying that for FontManager object, not SetFont() method. But as I have realized and after discussion I am sure, this feature was and is something, that is not needed, in axiom remote. But rest of the points still stand for FontManager .