Most TFT displays is built for either landscape or portrait orientation. That is, the display will have a fixed starting point where the first pixel value received from the TFT controller is placed, and a fixed direction in which the following pixels are placed. Some displays are configurable in terms of this but that is not necessarily the case. In order to support both landscape and portrait orientation for user interfaces, TouchGFX has a built-in mechanism for rotating the UI such that e.g. a portrait UI can be realized on a display that natively runs in landscape mode. This rotation is applied at no performance cost so rendering times are not increased if your UI design does not match the native orientation of the display.
In order to achieve this, TouchGFX must be informed of what the native orientation of the display itself is. This is done in the BoardConfiguration, where the hardware abstraction layer is informed of the width and height of the display in pixels. If the width is larger than the height, the native orientation is inferred to be landscape. If the user interface you are implementing has the same display orientation as your actual TFT display has, nothing special needs to be done since the default behavior is to match the orientation of the display itself. If, however, your UI is e.g. portrait and your display is landscape, you need explicitly change orientation at runtime by calling the function
//Switch to portrait mode.
HAL::getInstance()->setDisplayOrientation(ORIENTATION_PORTRAIT);
If your entire application uses the same orientation throughout, it is easiest to change the display orientation before the GUI task starts so you do not have to worry about it in your views. If your application supports both, please see Dynamic Switching at Runtime (supporting both orientations).
The necessary coordinate transformations take place behind the scenes. The width and height of the root Container of your view, touch input coordinates, and widget coordinates are all expressed in the coordinate space denoted by your chosen display orientation for the user interface. As such, there is really only one thing an application developer needs to be concerned with regarding display orientation, and that relates to bitmaps and is described in the following section.
Graphics Data in a Non-Native User Interface Orientation If the orientation of your user interface is different from the native orientation of the TFT display, all graphics data must be generated with a specific flag. This will cause the binary pixel data to be represented in a different format on the target, which is what allows TouchGFX to render a rotated display without performance overhead. When configuring your project it is therefore necessary to know whether UI orientation differs from the native orientation. If that is the case, modify the config/gcc/app.mk
to specify the following:
screen_orientation := -rotate90
And likewise for config/msvc/Application.props if using Visual Studio to generate assets:
<RotateImage90>true</RotateImage90>
To summarize, the rotate90 flag must be applied to your asset generation if one of the following is true:
- Your application is in portrait mode and the display is natively in landscape mode, or
- Your application is in landscape mode and the display is natively in portrait mode.
Rotating the canvas in the Designer
In version 4.9.3 of TouchGFX Designer, changing the orientation of the canvas is done manually. Assuming a default landscape project with the resolution of 800 x 480 pixels
In the designer, click on the button named "Browse Code" and locate the .touchgfx and open with a text editor. Change the resolution settings, by swapping the values of Width and Height
From: "Resolution": { "Width": 800, "Height": 480 }
To: "Resolution": { "Width": 480, "Height": 800 }
Go back to the designer window and click "OK" to reload the project, the canvas should now be rotated 90 degrees.
Setting up the simulator
To let the simulator reflect the rotated orientation the following changes have to be made to simulator/main.cpp
Switch SIM_WIDTH and SIM_HEIGHT in the method touchgfx_generic_init so
touchgfx_generic_init<HALSDL2>(dma, lcd, tc, SIM_WIDTH, SIM_HEIGHT, 0, 0);
becomes
touchgfx_generic_init<HALSDL2>(dma, lcd, tc, SIM_HEIGHT, SIM_WIDTH, 0, 0);
In the next line, add the following line to inform HAL layer of the orientation of the assets.
//Switch to portrait mode.
HAL::getInstance()->setDisplayOrientation(ORIENTATION_PORTRAIT);
Dynamic Switching at Runtime (supporting both orientations)
This subsection only applies in the case where your application must be able to dynamically switch between portrait and landscape mode at runtime, for instance if the device is equipped with an accelerometer to detect rotation change. If both orientations are to be supported, then the bitmaps that are to be displayed in the orientation matching the native display orientation must be generated without rotation, whereas the bitmaps to display in the non-native orientation must be generated with the -rotate90 option. In order to achieve this, the TouchGFX asset generation mechanism has built in support for a per-bitmap setting of rotation instead of the global -rotate flags. Therefore, when having both orientations present, set the screen_orientation variable to an empty string (or -rotate0). We then need to override this setting for the bitmaps in non-native orientation, e.g. portrait bitmaps on a native landscape display. TouchGFX has a naming convention regarding bitmaps which means that the orientation can be overridden from the global setting by including “.90.” in the file name, such that for instance a bitmap called
icon.90.png will be generated with the -rotate90 switch automatically.
Performing the Switch
Because the root container of your view must be changed to the new dimensions when switching orientation, it is necessary to perform a screen transition after switching orientation. This transition can either be to a different view/presenter, or to the same view/presenter as being currently displayed. For instance:
#include <gui/common/FrontendApplication.hpp>
#include <touchgfx/hal/HAL.hpp>
void MyView::performOrientationChange(DisplayOrientation orientation)
{
HAL::getInstance()->setDisplayOrientation(orientation); //set new orientation
static_cast<FrontendApplication*>(Application::getInstance())->gotoMyScreen(); //switch screen (to the same screen we are currently displaying).
}
Whether or not to reuse the same screen for both orientations or to create landscape and portrait versions of a screen primarily depends on the amount of differences between the two. Usually it is only widget coordinates and bitmap IDs that differ, and therefore it is easier to use the same view/presenter and simply testing for current orientation in the setupScreen function, like this:
void MyView::setupScreen()
{
bg.setXY(0, 0);
if (HAL::getInstance()->getDisplayOrientation() == ORIENTATION_LANDSCAPE)
{
bg.setBItmap(BITMAP_BG_ID);
icon.setBitmap(BITMAP_ICON_ID);
icon.setXY(200, 20);
}
else //Portrait
{
bg.setBItmap(BITMAP_BG_90_ID);
icon.setBitmap(BITMAP_ICON_90_ID);
icon.setXY(40, 30);
}
add(bg);
add(icon);
}
Note: In the example above, the native orientation is
landscape
which means that the bitmaps used in portrait mode have been suffixed with .90. as mentioned earlier.