element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Embedded and Microcontrollers
  • Technologies
  • More
Embedded and Microcontrollers
Blog STM32H7B3I - TouchGFX Application Framework: MVP and the ModelListener
  • Blog
  • Forum
  • Documents
  • Quiz
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Embedded and Microcontrollers to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 22 Aug 2020 4:12 PM Date Created
  • Views 4588 views
  • Likes 2 likes
  • Comments 4 comments
  • stm32h7b3i
  • rt
  • stm32h7b3i-dk
Related
Recommended

STM32H7B3I - TouchGFX Application Framework: MVP and the ModelListener

Jan Cumps
Jan Cumps
22 Aug 2020

I'm selected for the STM32H7B3I-DK -  DISCOVERY KIT road test.

I'm working on a touch screen GUI for my electronic load.

I'm going to review the ModelListener today. A software component that takes care that your business logic (electronic lab instrument in my case) does not need to know what screen is active, and what it displays.

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

video: capture in the simulator. This is no longer a mock GUI but a real GUI with a mock SCPI instrument.

 

I've reviewed the Model-View-Presenter framework before.

I focused there on using RTOS queues to exchange data and commands between GUI and backend. And how the main objects in the MVP work together.

The goal of that post was to show abstraction between backend and GUI. Backend is an electronic load that knows how to act as an electronic load.

Front end is specialised in displaying things and taking user input. It does not know anything about constant current, ADCs, DACs, electronics...

The only GUI class and backend class that talk together are the SCPI client (representing the instrument) and the TouchGFX Model class (representing the gateway with the backend).

 

image

Image: Model does not know each screen but knows the backend. Backend knows nothing about the GUI at all. It receives and sends messages.

 

A rich GUI can have a number of screens. And we want to prevent that the TouchGFX business level gateway, the Model, has to know each screen, or what each screen needs.

That's why they introduced the ModelListener.

I'll talk about the c++ part soon. Let's first discuss the goal.

A Model gets messages from the backend. The backend informs the Model about the measured current, measured voltage, temperature, ...

The Model will want to pass that info on to the screen. But not all screens want the same info. And not all screens want it in the same form.

We want to avoid that the Model needs to know what the screen wants, and what it doesn't need. No logic in the Model based on the active screen, if at all possible.

Now c++:

The ModelListener is a base class for each screen that gladly takes any message from the Model, and does nothing with it.

It silently takes the message and returns control back to the Model. Not interested.

 

class ModelListener
{
public:

    virtual void scpi_idn(const char* data) {}
    virtual void scpi_function(const char* data) {}and 

};

 

If you have a screen that is not interested when the Model receives the instrument's SCPI ID, it will gladly be ignored. The virtual function is empty and the message dies silently.

c++ optimisers make this efficient. Not a lot overhead is burned if your screen isn't interested.

 

But each TouchGFX Presenter class inherits from ModelListener. There's a Presenter class generated (and associated) for each screen you design. It's the backbone of the screen.

That means that you can choose if you ignore a message, or act on it, in the Presenter class of your screen.

If you aren't interested in changing the active screen when a SCPI ID arrives, you do nothing in the Presenter for that screen.

If you want to do something - my start screen wants to display the ID as part of the init sequence - you implement the listener method.

 

image

image: one Model, one ModelListener. Each screen has a tied (tight) pair of Presenter and View

 

You tell the compiler you're fair game in the header file:

 

class MainPresenter : public Presenter, public ModelListener
{
public:

    void scpi_idn(const char* data);

};

 

... and pick up the signal in the implementation of that class:

 

void MainPresenter::scpi_idn(const char* data) {
  view.status(data);
}

 

In my implementation, the Presenter (tightly coupled to the graphic screen - represented by a View class in TouchGFX) knows that when a ID arrives, the screen want to update it's status.

If needed, the presenter can massage the data so that it's in a good format for the View. In our case, no massaging is needed.

We just send the data to the View. The View will update the right GUI widget(s) and redraw what needs to be redrawn.

 

void MainView::status(const char* data) {
  Unicode::strncpy(txtStatusBuffer, data, TXTSTATUS_SIZE);
  txtStatus.invalidate();
}

 

In essence, the whole organisation is a decision engine without IFs and CASEs. As a screen, you tell the compiler you want to receive a notification by implementing it.

For the c++ fanboys (like me).

 

Related Posts
First Experience with CubeIDE
Create a TouchGFX Project with support for the Designer, CubeIDE and Debugger - Pt 1: Screen Works
Create a TouchGFX Project with support for the Designer, CubeIDE and Debugger - Pt 2: Touch Works
TouchGFX Simple Example: react on a button click
USB, freeRTOS ,Task Notifications and Interrupts
the Development Kit STMod+ Connector and Using UART2
TouchGFX Application Framework: Model, View, Presentation, Message Queue
TouchGFX Application Framework: A Mock GUI - Show Statuses, Switch Screens
TouchGFX Application Framework: MVP and the ModelListener
Write a CubeIDE MX application: Hardware Cryptography with DMA
Attachments:
MyApplication_1_20200823.zip
  • Sign in to reply

Top Comments

  • Jan Cumps
    Jan Cumps over 5 years ago +1
    demo of the interface in its current state: www.youtube.com/watch
  • Jan Cumps
    Jan Cumps over 5 years ago

    For my own reference later (I need these conversions): From Ascii / Unicode / UTF8 tricks:

      touchgfx::Unicode::snprintf(currentConnectedWifi.password, 64, "%s", password);
      touchgfx::Unicode::snprintf(currentConnectedWifi.wifi.ssid, 32, "%s", wifiAccessPoints[id].ssid);
      touchgfx::Unicode::snprintf(currentConnectedWifi.wifi.encryption, 30, "%s", wifiAccessPoints[id].encryption);
      currentConnectedWifi.wifi.signalStrength = wifiAccessPoints[id].signalStrength;
      
      touchgfx::Unicode::toUTF8(password, password_ascii, 64);
      touchgfx::Unicode::toUTF8(wifiAccessPoints[id].ssid, ssid_ascii, 32);
      touchgfx::Unicode::toUTF8(wifiAccessPoints[id].encryption, encryption_ascii, 30);

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • DAB
    DAB over 5 years ago in reply to Jan Cumps

    Good job Jan.

     

    DAB

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 5 years ago

    demo of the interface in its current state:

     

    You don't have permission to edit metadata of this video.
    Edit media
    x
    image
    Upload Preview
    image

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 5 years ago

    There is a reason to design this mechanism between the single Model class and all screens.

    It's a 1-to-n relation, and you don't want to put all those "if screen 1 then", "if screen 2 then" forks in the model.

    It has one duty: be the mediator between the LCD and the backend. It should not have to deal with screen layout, flow, actions.

     

    The other way doesn't need the same abstraction, because there's only one Model. And the screens are allowed to know the model.

    That's why the ModelListener deals with any message coming from the Model, going to he screens.

    But when the screens want to ask the Model something, there's no compelling reason for abstraction. The single Model has the duty to deal with Backend requests. And the screens should be able to just invoke those functions.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube