We strongly encourage users to use Package manager for sharing their code on Libstock website, because it boosts your efficiency and leaves the end user with no room for error. [more info]
Rating:
Author: VCC
Last Updated: 2022-04-21
Package Version: 2.0.0.1
Category: TFT
Downloaded: 888 times
Not followed.
License: GNU Library or "Lesser" General Public License (LGPL) (License History)
DynTFT is a set of visual components, inspired by Delphi's VCL. These components are compilable by mikroPascal, Delphi and FreePascal, allowing faster designing and debugging of the UI part of an application. The API features a runtime component registration, to make sure that users won't have to deal with internal handling of mouse/touch events.
Do you want to subscribe in order to receive notifications regarding "DynTFT" changes.
Do you want to unsubscribe in order to stop receiving notifications regarding "DynTFT" changes.
Do you want to report abuse regarding "DynTFT".
DOWNLOAD LINK | RELATED COMPILER | CONTAINS |
---|---|---|
1650520214_dyntft_mikropascal_pic32.zip [8.99MB] | mikroPascal PRO for PIC32 |
|
For creating/editing DynTFT UIs, see DynTFT Code Generator.
For creating/editing DynTFT color themes, see DynTFT Color Theme Generator.
Already available DynTFT color themes
Version v2.0.0.1:
- Added double click support (an external timer is required to set the DynTFTGetTickCount global variable with the current "tick time" in [ms]).
- The DynTFTItems component can display cropped text, to avoid overdrawing the ScrollBox from a ListBox.
- The DynTFTItems component can display custom icons for every item (see Unsized example: D2006 and FP).
Version: 1.4.3.1
Fixed a drawing issue on DynTFTScrollBar when both Min and Max were greater than 0.
Version 1.4.2.1
New feature: Added support for MouseClick event.
Version 1.4.0.0
New feature: RTTI and binary encoded components (more info in DynTFTBaseDrawing.pas)
UIs can be stored on external media and loaded at run-time
See provided 480x272_RTTI example
See also DynTFTCodeGen's documentation https://libstock.mikroe.com/projects/view/2905/dyntftcodegen
DynTFT is a set of visual components, inspired by Delphi's VCL. These components are compilable by mikroPascal, Delphi and FreePascal, allowing faster designing and debugging of the UI part of an application. The API features a runtime component registration, to make sure that users won't have to deal with internal handling of mouse/touch events, and no hardcoded list of component types has to be maintained. DynTFT components use dynamic memory allocation, allowing them to be created and destroyed at runtime. Users can write their own custom UI simulators, building upon the provided templates. Compiler differencies are handled by the means of using compiler directives. Although the code was tested on PIC32 and PIC24, it might work on other architectures as well.
There is no 8-bit support.
DynTFT library example on custom board with PIC32MX250F128D and Spartan6 FPGA
Watch on YouTubeFeatures / Advantages:
- The code can be compiled in mikroPascal, Delphi and FreePascal.
- All components are created in RAM memory, allowing to be destroyed when no longer needed. For example, a button can create a scroll bar, set the event handlers, then destroy itself.
- A template high-level simulator is provided, so users can design and simulate their own GUI on desktop. Much of the code will work the same on microcontroller.
- DynTFT allows faster design of the GUI, by simulating it on PC instead of flashing the microcontroller at every change.
- DynTFT allows debugging application logic of some non-GUI applications, by creating a debugging GUI and simulating application parts (e.g. state machines).
- Using the same memory manager on desktop as on microcontroller, memory addresses are more predictable, making bugs easier to reproduce.
- Using the simulator, various use cases which lead to out of memory, can be identified before verifying the application on microcontroller.
- Access violations are easier to debug on desktop than on microcontroller.
- New components can be added as plugins (component type registration at run time).
- When compiled for desktop (Delphi or FreePascal), the "constructors" raise exceptions if creating unregistered components.
- Components can be used hierarchically, e.g. a listbox contains items and a scroll bar. The scroll bar contains two arrow buttons and a dragging panel. etc.
- Mouse and touch events are handled in the same way.
- Some of the repaint events are handled internally, without user intervention, e.g. showing/hiding or enabling/disabling a component.
- Various events are internally propagated from subcomponents to parent components, for a proper handling on all levels.
- At the expense of one additional pointer / component and a bit of processing, the internal structure (simple linked list) is isolated from visual components.
- Components are organized in screens (each screen has a linked list of components) and multiple screens can be active at the same time.
- Only active screens can process events. Screens can be activated/deactivated from any event handler.
- Components have focus support. It will be needed when implementing keyboard support.
- Multiple components can be destroyed from a single "destructor" if they are allocated one after the other (range of components). This is useful when a component has multiple subcomponents.
- When a component is destroyed, it repaints the area, which can be a screen, a parent component or other unrelated components.
- If some projects require custom component properties or event handlers, they can be defined in an .inc file and enabled from project-level definition.
Limitations / Disadvantages (version independent):
- Compiler directives have to be used at every piece of code which contains event handler assignments, in order to make the code work on all compilers.
- Creating new components, requires extra care at defining component structures, because pointers to event handlers, must be Word or DWord aligned, depending on architecture.
- Although components can be structurally inherited, access to base component properties must be done by specifying them as part of the hierarchy, e.g.: DerivedComp^.BaseTypeComp^.BaseProps.Left := 30;
- The amount of allocated memory may be different between 32-bit and 16-bit architectures.
- OnMouseMove events are triggered only when mouse button is down. This is to make both touch and mouse events work the same.
- FreePascal projects must be configured to compile in Delphi mode. This would be an issue if parts of a FreePascal project must be compiled in default (FreePascal) mode.
- A lot of typecasting has to be done, because components are simple structures not classes.
- All components use absolute coordinates (Left / Top), regardless of their parents.
Limitations / Disadvantages (in current version):
- There is no automatic event triggering on value change (e.g. OnTextChange, OnPositionChage, OnAddItem), except for ScrollBar. Calls to Repaint have to be manually added when updating properties.
- Listboxes can't display partial items. Empty space will be displayed at the end of a listbox.
- Scrollbar dragging buttons are not resized based on scroll page length.
- Can't set focus to a component from another's component handlers and properly clearing the current focused component.
- Assigning event handlers must be done in two ways each time, using compiler directives. Function pointers are not compatible across compilers.
- Limited support for Z order (there is a "BringToFront" procedure). In case of overlapped components, the one which is created before the other(s), will process the events.
- A page control does not have pages. It provides the same functionality as a radio group.
- Clicking on a component, outside of a ComboBox, to close the ComboBox, does not allow the event to be handled by pressed component.
- Text or Caption properties of components which implement them, have fixed length.
- ListBoxes, RadioGroups and PageControls use fixed-size arrays to store pointers to their elements. These sizes can be changed from external constants.
- The Edit component does not have text selection support.
- Scrollbars do not have fast scroll support (i.e. scrolling by clicking between buttons). Because of this, a ComboBox will be closed if clicking its ScrollBar between buttons.
- RadioButtons do not work outside RadioGroups. There would be not a much of a benefit to implement this.
- Some components lack useful features, like autoarrange items in RadioGroup or PageControl. For now, each item must be manually positioned.
- A PageControl can't scroll tab buttons if they take more space than displayable.
- Moving a component across a screen, requires manual repainting. There is however a procedure which can repaint all components from a given area.
- Components cannot be moved from one "screen" to another (from one parent to another), on run time. However, this can be implemented.
- A ComboBox drops down by default. It must be configured manually to drop up (or elsewhere) if there is no enough space below it.
- Screen color is not fully implemented. Applications will have to draw a screen-sized rectangle at startup. Destroying/hiding components will repaint the screen with assigned screen color.
Known issues / other info:
- Clicking on an editbox does not always place the caret properly.
- Some of the provided examples contain hardcoded paths. Because of that, all the three folders, DynTFT, DynTFTDocs and DynTFTSim, must be extracted in D:\, so the paths would be D:\DynTFT, D:\DynTFTDocs and D:\DynTFTSim .
Areas that might change:
- The Items, RadioGroup and PageControl components should allow dynamic creation/deletion of their elements. At the moment they used a fixed-size array to store elements.
- Various constants may be moved to external constants (like array lengths).
- Some datatypes, compiler directives and functions/procedures may be renamed.
- Adding (important) features, on complex components may lead to various changes in subcomponents, like enabling internal event handlers. This will cause the code to grow.
- Other stuff as a result of bug fixing.
Buttons, arrow buttons and a panel. mikromedia for PIC24EP. mikromedia for PIC32MX7
View full imageCheckBoxes, ListBoxes and ScrollBars. mikromedia for PIC24EP. mikromedia for PIC32MX7
View full imageLabels and RadioGroups. mikromedia for PIC24EP. mikromedia for PIC32MX7
View full imageEditbox and VirtualKeyboard. mikromedia for PIC24EP. mikromedia for PIC32MX7
View full imageListBoxes, ComboBoxes and Labels. mikromedia for PIC24EP. mikromedia for PIC32MX7
View full imageFAQ:
- Where is the documentation?
In work.
- What is the purpose of the DynTFT simulator?
Since the DynTFT library/infrastructure is pretty complex, it was designed to be compilable both for microcontroller and desktop. The desktop application is the simulator.
Users are adviced to test as many application features as possible by writing this kind of code, because debugging on the microcontroller would be more difficult.
Each application should have its own derived simulator (derived from provided template), with its custom features.
- How do I start using DynTFT?
Start by modifying provided examples. Some files should always be shared between Delphi/FreePascal and mikroPascal projects, like: DynTFTGUI.pas, DynTFTGUIObjects.pas, DynTFTHandlers.pas and some .inc files (e.g. DynTFTColorTheme.inc)
Each .pas file should have an equivalent .mpas file, which includes the former.
- What if there are type/var/func/proc name collisions between DynTFT and the user application?
Most variables, functions and procedures are prefixed with DynTFT to avoid such collisions. Not sure what to do with the remaining ones.
- Some components do not work as expected. How do I know if it's a bug?
For starters, see "Limitations / Disadvantages" sections. Indeed some components have incomplete implementation. Others work in a particular way by design. And.. yes, there may be bugs in some components.
- How do I change the font?
Define DynTFTFontSupport compiler directive at project level, and assign font constants to ActiveFont property of components which support text.
- How do I create my own custom component?
At first, identify if your component requires existing components as subcomponents or not. Then, look at how existing components are created. They follow a template.
Each component should have its own unit and implement a set of functions/procedures like: Draw<CompName>, <CompName>_Create, <CompName>_Destroy, <CompName>_DestroyAndPaint, Register<CompName>Events and Get<CompName>Type.
You can start by copy-pasting an existing unit. Then, rename everything to match your component. Do not use the DynTFT name, because it might collide with some future implementation of the same component from the DynTFT library.
Pay extra attention at complex components (those which use subcomponents), because subcomponents data types are available in your code and typecasting to them instead of the main component, may lead to problems.
- No automated regression tests?
No, not at this time. The whole thing started as a hobby experiment. It was not designed with automated testing in mind.
Again, time will tell when and if there will be tests. Indeed, they would be very useful when implementing features and fixing bugs.
- How much is this library expected to grow and in what direction?
New components should be added, but new featues of the infrastructure should not go too far. This is because the code may already be too big for a microcontroller application.
Fancy/exotic features should be placed under compiler directives, to keep the code small in most cases.
- How do I change the visual appearance of the provided components?
At the moment, only the colors can be changed, by providing new .inc files with color constants. Other visual aspects can't be changed. Fonts can be changed with some limitations, see above.
If more than colors must be changed, then new custom components must be created.
- How do I use the generic "constructor" and "destructor"?
There is a generic "constructor" and a generic "destructor", which can be called by knowing the component registration number only.
They can be used to create and destroy all components, regardless their type. This requires enabling the RTTIREG project-level definition.
Calling the generic "constructor" and "destructor" also requires knowing in advance the order of the registered components. Their types are index-based.
A small description about how they work can be found in DynTFTBaseDrawing.pas, at the implementation of DynTFTComponent_CreateFromReg "constructor". DynTFTCodeGen can already generate RTTI instructions.
- Why the 16-bit architecture requires less memory than a 32-bit one?
Some data types contain architecture-dependent structures and can be better packed in 16-bit architectures.
Since the simulator reports the memory usage for 32-bit, the 16-bit one should not be a concern.
- Why components are "stored" in isolated linked lists?
This is by design, to support non-visual components, which do not contain properties like Left, Top, Width, Height etc, so allocation would not be user's job.
At the moment, the infrastructure does not support non-visual components, so all of them must contain the BaseProps field in their structure.
Because of this, the component data type "registry" reserves type 0 for screens and negative values for non-visual components. All the others use positive values, in the order they are registered.
Another reason was to isolate the linked lists from user code, to make memory corruption a bit "safer". Thus, each item of a list, points to a component instance.
If some components require usage of these lists, they should do it with extra care.
Another benefit of the linked lists, is the ability to create big complex components, without keeping a separate pointer to each of their subcomponent. For example, the VirtualKeyboard stores only two pointers, to the first and to the last created keys. Thus, all the keys can be "range destroyed" in one call.
- Some components do not implement all internal event handlers. Why is that?
At the moment, this to reduce code size. If other complex components will be created, some internal event handlers may have to be implemented as well. This will increase code size of unrelated applications.
- There are many compiler directives. Which is which?
There are four types
1. Those which enable/disable code across compilers, i.e. "IsMCU" and "IsDesktop"
2. Those which define bitness, i.e. "AppArch32" and AppArch16.
3. Those which enable/disable features, e.g. "RTTIREG" or "ComponentsHaveName".
4. Those which control if user code should be included/linked into DynTFT units, like data types, other units, component properties, colors and color themes etc.
The first two types are automatically handled. The others should be project-level defined. Since documentation is not ready, you must look at the code to understand what should be defined and where to include user code.
- Why so much typecasting?
The main reason is because datatypes are partially the same and can be overlapped in memory. Some typecasting is required by the language rules themselves. Others, to avoid warnings/errors.
Anyway, handle this with extra care, if using custom component "properties" on generic data types. You should always know what a pointer points to.
Most (if not) all typecasting involves the TPtrRec data type, to avoid compiler warnings. Normally, this would not be required because this data type is simply the type of pointer, i.e. Word or DWord.
- Why having a wrapper over TFT library?
Not all applications use TFT compatabile displays, so the DynTFTUtils library allows user code to be included. It was much more practical to wrap each TFT call, than using compiler directives each time.
Troubleshooting:
- Why the microcontroller keeps resetting either on application startup or on handling some event?
Make sure all used components are registered in RegisterAllComponentsEvents procedure from DynTFTGUI.pas. The simulator should tell you about this. If it doesn't, make sure the Delphi/FreePascal and mikroPascal apps are using the same files.
- Why some/all components do not handle events at all?
Make sure the screen they belong to, is active. See SetScreenActivity procedure from DynTFTGUI.pas. Screens can be activated/deactivated when needed.
- The simulator's log turns pink (red was to hard to read) and an exception/error is mentioned.
You should debug that application and not deploy it in that state to microcontroller. It won't be easy to debug it on microcontroller.
Some debugging features are available in simulator only. Make sure the application works as expected on simulator.
- mikroPascal debugger won't step into the .pas units, because they are included with {$I} in .mpas files.
This is a debugger limitation and if you really want to enter those units with debugger, copy-paste their contents into the required .mpas files.
As soon as the problem is solved, switch back to "include .pas" mode. This is to avoid the need to keep files (.pas and .mpas) in sync.
Also, make sure each mikroPascal project will share the files with a Delphi/FreePascal project. Do not share GUI files between projects. This will lead to a mess.
Components: Button, ArrowButton, Panel, CheckBox, ScrollBar, ListBox, Label, RadioGroup, PageControl, Edit, VirtualKeyboard, ComboBox
View full image