Sei sulla pagina 1di 96

Prism

Prism Runtime Framework


Runtime Framework
Developers Guide
Prism Runtime Framework Release 3.x.x

May 2011
August 2011

Prism v3.4.x
Copyright 2010-2011

Blue Water Embedded Inc. All rights reserved.

Copyright 2011

Blue Water Embedded, Inc. All Rights Reserved


Developers Guide

Copyright 2010-2011

Blue Water Embedded, Inc.


3847 Pine Grove Ave
Suite A

Fort Gratiot, MI 48059


PH: (810) 987-3002
FAX: (810) 987-3151

info@bwembedded.com

No part of the document may be reproduced in any form without the express written
consent of Blue Water Embedded, Inc

All rights reserved.

Prism, Prism Micro, Prism Insight, Prism Micro Insight, and Prism Runtime Framework
are trademarks of Blue Water Embedded, Inc.

Page 2 Blue Water Embedded, Inc.


Developers Guide

Revision History
Date Revision Change By
8/17/2011 7 Event Recorder/Playback, Panel Push/Pop Stack Reset JC
8/3/2011 6 Improved macro functionality detailed RN
6/13/2011 5 Chapter 10 added KM
5/30/2011 4 Modernized Look&Feel for Insight added JC
5/11/2011 3 Graphics Data Pipeline and diagrams added. KM
3/25/2011 2 Event table update KM
11/18/2010 1 TOC added JC
7/16/2010 Initial Release

Blue Water Embedded, Inc. Page 3


Developers Guide

Table of Contents
Developers Guide ....................................................................................................... 1
Revision History ........................................................................................................... 3
FORWARD .................................................................................................................. 7
The Prism Documentation Set ..................................................................................... 8
What exactly is Prism, and why is it written using C++? .............................................. 9
Why C++? .................................................................................................................. 10
1 GETTING STARTED ............................................................................................. 11
1.1 Installing and Building the Prism Runtime Framework ..................................... 11
1.1.1 Installing Prism .......................................................................................... 11
1.1.2 Building the Prism Runtime Framework..................................................... 11
1.2 Prism File Description ...................................................................................... 12
1.3 Memory Footprint ............................................................................................. 21
1.4 Paint Engines ................................................................................................... 21
1.5 Additional Drivers ............................................................................................. 24
1.6 Pre-configured Make/Project files .................................................................... 24
2 DEFINITIONS ........................................................................................................ 25
2.1 Terms and Data Types..................................................................................... 25
2.2 Panels and Widgets and Utility classes............................................................ 25
2.3 Parent Child Sibling .................................................................................... 25
2.4 Fundamental Data Types ................................................................................. 26
2.5 Naming Conventions ........................................................................................ 27
2.6 pm_bitmap_t .................................................................................................... 28
2.7 Pm_Brush ........................................................................................................ 28
2.8 pm_canvas_t .................................................................................................... 31
2.9 pm_event_t ...................................................................................................... 32
2.10 pm_font_t ...................................................................................................... 33
2.11 pm_point_t .................................................................................................... 34
2.12 Pm_Region ................................................................................................... 35
2.13 Pm_Snapshot ............................................................................................... 37
3 THE EXECUTION MODEL .................................................................................... 39
3.1 Runtime Execution Model ................................................................................ 39
3.2 Framework Overview ....................................................................................... 39

Page 4 Blue Water Embedded, Inc.


Developers Guide

3.3 Program Startup ............................................................................................... 42


3.4 Prism Standalone Operation ............................................................................ 43
4 THE SCREEN MANAGER ..................................................................................... 44
4.1 Pm_Screen_Manager ...................................................................................... 44
4.1.1 Key features and functions of Pm_Screen_Manager ................................ 44
4.2 Mouse and Touch Screen Input Handling ........................................................ 45
5 THE EVENT MANAGER ........................................................................................ 47
5.1 Pm_Event_Manager ........................................................................................ 47
5.1.1 Key features and functions of Pm_Event_Manager................................... 47
5.1.2 pm_event_t ................................................................................................ 48
5.2 Sending Events ................................................................................................ 48
5.3 Event Flow and Routing ................................................................................... 48
5.4 Prism Pre-defined System Events.................................................................... 49
5.5 System Event List ............................................................................................ 49
5.6 Child Event Notifications .................................................................................. 53
5.7 Event Handlers................................................................................................. 53
5.8 Example Event Handler ................................................................................... 55
5.9 User Defined Events ........................................................................................ 56
5.10 Event Record and Playback.......................................................................... 56
6 THE TIMER MANAGER ......................................................................................... 58
6.1 Pm_Timer_Manager ........................................................................................ 58
7 THE RESOURCE MANAGER................................................................................ 60
7.1 Pm_Resource_Manager .................................................................................. 60
7.1.1 Resource IDs ............................................................................................. 61
7.1.2 Registering Resources .............................................................................. 61
7.2 Themes and Skin-ability ................................................................................... 61
7.3 Retrieving Resource Pointers........................................................................... 62
8 THE PAINT ENGINE.............................................................................................. 63
8.1 Pm_Paint_Engine ............................................................................................ 63
8.2 Pm_HiColor_Sim_Engine ................................................................................ 63
8.3 Screen Coordinates ......................................................................................... 65
8.4 Graphics Controllers ........................................................................................ 65

Blue Water Embedded, Inc. Page 5


Developers Guide

8.5 The Graphics Data Pipeline ............................................................................. 66


8.5.1 Double Buffering ........................................................................................ 66
8.5.2 Multiple Canvases ..................................................................................... 67
8.5.3 Graphics Pipeline Diagrams ...................................................................... 67
8.6 Writing your own Hardware Specific Driver Class ............................................ 71
9 RUNNING ON YOUR DESKTOP........................................................................... 72
9.1 DESKTOP SIMULATION ................................................................................. 72
9.2 Paint Engines for Desktop Operation ............................................................... 72
9.3 Operating System Integration files for Desktop Operation ............................... 73
9.4 Screen Size ...................................................................................................... 73
10 The Pm_Framework Class .................................................................................. 74
10.1 APIs for Painting ........................................................................................... 75
11 ALL ABOUT WIDGETS ....................................................................................... 77
11.1 Using Pm_Widget ......................................................................................... 77
11.2 Pm_Widget Overview ................................................................................... 77
11.3 Pm_Widget Members ................................................................................... 78
12 PROGRAMMING EXAMPLES ............................................................................ 84
12.1 Determining the position of an object ............................................................ 84
12.2 Creating and displaying Panels and Widgets................................................ 84
12.3 Unlinking and Destroying Objects ................................................................. 85
12.4 Finding an objects children .......................................................................... 86
12.5 Reserved Widget Ids..................................................................................... 86
12.6 Using Widget Ids to identify panels and widgets ........................................... 87
12.7 Using Event Tables ....................................................................................... 88
12.8 Overriding the Paint() function ...................................................................... 90
12.9 Screen transitions and navigation example .................................................. 93
12.10 Persistent Panels .......................................................................................... 95

Page 6 Blue Water Embedded, Inc.


Developers Guide

FORWARD
The personnel at Blue Water Embedded thank you for choosing the Prism family of
embedded graphical interface development tools. We believe Prism is the most robust,
best supported, and easiest to use graphical interface software package available today
at any cost.

The developers at Blue Water Embedded have been working in the embedded graphics
industry for nearly 14 years, and have worked on thousands of applications and unique
products. We have been involved in developing consumer electronics, office
equipment, desktop applications, military devices, and medical instrumentation to name
a few of the types of projects in which we have participated.

The engineering staff at Blue Water Embedded wants your project to be successful, and
we sincerely want to assist you in accomplishing this goal. Never hesitate to ask us
questions or make suggestions which will help us to improve our software.

Blue Water Embedded also welcomes the opportunity to assist in your product
development at any level. We can provide training, porting and customization services,
or complete turnkey application development. Contact our sales department if you
would like to learn more about any of these services.

For technical support, we prefer you email your questions to


support@bwembedded.com. Please provide as much detail as possible so we can fully
understand the problem and provide detailed answers. Example code and screen shots
are always the best way to communicate what you are trying to do and the result you
are seeing.

For urgent matters, you can always call us directly at (810) 987-3002 and ask for
technical support. The Prism Runtime Framework and Prism Insight support personnel
are the same software engineers who developed the software, so we are confident you
will get timely and accurate answers to your questions!

Blue Water Embedded, Inc. Page 7


Developers Guide

The Prism Documentation Set


The Prism documentation set includes the following references and guides:

The Prism Evaluation Kit- This document is a brief introduction to Prism which shows
you how to launch the Prism Insight application, run sample example applications, and
how to generate a UI application on your desktop.

The Prism Runtime Framework Developers Guide (this manual) - This is a detailed
description of the Prism Runtime Framework; what is does, how it does it, and what you
need to know to use the software to your best advantage.

The Prism Runtime Framework API Reference Manual- This manual documents every
class and public function of the Prism Runtime Framework. This manual will be very
helpful when you begin using the Prism API directly in your application software.

The Prism Insight Users Guide- This manual documents how to use the Prism Insight
application to change your framework settings, create UI screen designs, manage and
edit strings, and generate system resource files among a host of other capabilities.

All of these manuals are provided in electronic (PDF) formats. Prism is living software
product, and as such is constantly being enhanced, updated, improved, and revised.
These revisions include updates to the manuals and related documentation. For this
reason your manuals may not always match with 100% accuracy the contents and
function of the Prism Runtime Framework. We try to keep these discrepancies to a
minimum and insure no large modification to the framework is released without a
matching update to the documentation set.

All users of the Prism software are allowed to update their electronic documentation set
as often as desired. The latest PDF manuals are always available for download at the
following URL:

http://www.bwembedded.com/SecureManual/prismman.php

Contact us to get the latest username and password to download the manuals.

Page 8 Blue Water Embedded, Inc.


Developers Guide

What exactly is Prism, and why is it


written using C++?
Prism is a software package designed to simplify the task of creating an advanced
Graphical User Interface. Prism includes three key components:

The Prism Runtime Framework

This is the Prism software library, which implements a very stable runtime environment
for managing your user interface application, and provides a complete customizable
widget set you can use and build on to provide the UI input and output elements needed
by your product user.

The Prism Insight and Prism Micro Insight applications

These are the design and prototyping desktop applications which can be run in nearly
any Windows or Linux/X11 desktop. Prism Insight was designed and written to make it
very easy to create the screens or panels which will comprise your user interface. You
can visually design and layout your screens, and Prism Insight tool generates the
required source code and data structures (in normal, human readable form!) that are
required to actually implement your UI design on your target system.

The support and training by Blue Water Embedded personnel

The Blue Water Embedded, Inc. team is dedicated to providing best in class technical
support to our customers. Your product's success is our success. With a license
purchase, 90 days of technical support is included from the date you purchase and
receive (usually via ftp download links) the software. With valid support contracts,
technical support includes phone support during normal business hours, email support
and software updates.

Blue Water Embedded offers a two-day Prism training class which can be held at our
facility or yours. Many times we find prospects have a basic understanding of what a
GUI entails. Blue Water Embedded has developed a program to help you apply Prism
Insight and the Prism library and maximize the benefits of the software. Contact a sales
team member to learn more and schedule a training class today.

Blue Water Embedded, Inc. Page 9


Developers Guide

Why C++?
Prism is written in C++ because the authors believe this is a natural language for
implementing a UI framework and widget set. We do not use some of the more
advanced features of C++ such as Exceptions, Templates, or Runtime Type
Identification. We use C with Classes, which in the end means if you are a proficient
C programmer you will have absolutely no problem using the Prism Runtime Framework
effectively.

One advantage of using the C++ language is there are fewer API function names for
you to learn. We use the same function name to accomplish common tasks such as
assigning colors or fonts for every Prism class. This reduces the learning curve and
helps you become proficient with the framework API very quickly. This manual will
explain everything you need to know to use Prism effectively, whether you are primarily
a C language developer or if you have several years experience with C++, C#, or other
languages.

A common concern among developers of safety critical devices is the C++ memory
allocation operator new and potential heap fragmentation. Prism utilizes several
strategies to overcome this concern, including providing its own operating specific
versions of the new and delete operators, and strategies to completely eliminate post-
boot heap allocations are also supported. Whatever your requirements, Prism is
designed to function correctly in high level of concern devices.

Page 10 Blue Water Embedded, Inc.


Developers Guide

1 GETTING STARTED
1.1 Installing and Building the Prism Runtime Framework

1.1.1 Installing Prism


Getting started to use Prism is easy by simply extracting the Prism.zip or Prism.tar
archives to your selected location. If you are installing on a Windows desktop PC, you
might also need to run the vcredist_x86.exe, which is found in your root Prism folder
after you extract the Prism archive. Vcredist_x86.exe is a Microsoft installer that
provides the Windows runtime libraries compatible with the MS 2005 compiler suite,
which is used to build the Prism Insight application for Windows platforms.

Your distribution may contain specific instructions regarding the folder into which Prism
should be installed. This matters only for specific RTOS integrations, to insure the
provided make/project files can correctly locate the RTOS specific header files.

1.1.2 Building the Prism Runtime Framework


The software package contains of a large number of C++ source files which are
normally compiled and archived by a compiler specific librarian to produce a library
archive. You will then link this library archive during your build process to produce your
final binary image.

Your Prism distribution normally includes makefiles or project files specific to your
designated toolchain. We support a wide variety of toolchains and build environments,
so if you do not find a project file for your specific tools please notify Blue Water
Embedded.

When the library is configured, it includes a header file prism_settings.h. The header
file is found in prism\include\prism_settings.h and is automatically generated by Prism
Insight and should not be modified manually. To change your prism_settings.h file, you
should run the Prism Insight application and run through the various settings screens to
turn on and off the options your target requires, then use the Generate Prism Settings
command to update your prism_settings.h header file.

Depending on your desktop environment preference, when you first install the Prism
software, the prism_settings.h header file is configured to build the Prism library for
either the Win32 or X11. Whenever possible, this file is also pre-configured for your
target RTOS and hardware. You can reconfigure the library at any time to build for your
intended target. It is important to remember whenever you update your

Blue Water Embedded, Inc. Page 11


Developers Guide

prism_settings.h header file; you need to re-build the Prism library in addition to your
application files.

1.2 Prism File Description


This chapter describes each of the library source files and their contents. Several of the
source files are optional and only included if required for your target system. The last
section of this chapter describes the pre-configured library make files which are
included in your Prism distribution.

The Prism source files are located in the \prism\source folder and sub-folders, and the
matching Prism header files are located in the \prism\include folder and sub-folders.
The sub-folders contain drivers and operating system integration files specific to various
hardware platforms and operating systems. Your installation package includes only
those drivers and operating system integration files required for your specified target.

After installation your directory structure should look similar to this:

The build directory contains project and makefiles for your compiler and operating
system, along with project files for building the Panels and/or X11 desktop simulation
environments.

Page 12 Blue Water Embedded, Inc.


Developers Guide

The docs directory contains the Prism documentation set.

The examples directory contains several pre-built example applications configured to


build and run in the desktop simulation environment.

The fonts directory contains free TrueType fonts you can use as part of your
application.

The include directory contains your Prism header files. The root \include directory
contains all of the header files of the core Prism Runtime Framework. The sub-
directories within this folder contain header files for specific graphics hardware drivers,
keyboard drivers, mouse drivers, and touch drivers. The specific set of drivers included
in your distribution will vary depending on your selected target hardware.

The rtos sub-directory contains header files specific to your Prism/RTOS combination.
Prism implements a thin abstraction layer to isolate RTOS requirements from the core
library files.

The Insight directory contains the Prism Insight application and related example project
files.

The source directory contains the Prism core library files and related drivers. The
\source directory structure is a mirror of the \include directory structure.

The core Framework source and header files, in alphabetical order, include:

prism_anim_prompt.cpp / .h

These files declare the Pm_Animated_Prompt widget class and define the matching
implementation.

prism_big5_map.cpp / .h

These optional files declare the Chinese Big 5 character encoding to Unicode mapping
tables.

prism_bitmap_prompt.cpp / .h

These files declare the Pm_Bmp_Prompt widget class and define the matching
implementation.

prism_bmp_btn.cpp / .h

Blue Water Embedded, Inc. Page 13


Developers Guide

These files declare the Pm_Bmp_Btn widget class and define the matching
implementation.

prism_bmp_dec_btn.cpp / .h

These files declare the Pm_Bmp_Decorated_Btn widget class and define the matching
implementation.

prism_bmp_rotate.cpp / .h

These files define the Pm_Bitmap_Rotator class used for runtime rotation of bitmaps
and text.

prism_brush.cpp / .h

These files define the Pm_Brush class, which is used for most painting operations.

prism_button.cpp / .h

These files define the base Pm_Btn class, which is a base class for most other button
widget types.

prism_dec_panel.cpp / .h

These files define the Pm_Decorated_Panel class, which is a panel class supporting
several pre-defined decorations such as Pm_Title_Bar and Pm_Status_Bar.

prism_drop_box.cpp / .h

These files declare the optional Pm_Drop_Box widget class and define the matching
implementation.

prism_event_mgr.cpp / .h

These files declare the Pm_Event_Manager framework class and define the matching
implementation.

prism_exclusive_btn.cpp / .h

These files declare the Pm_Exclusive_Btn widget class and define the matching
implementation.

prism_file_wrapper.cpp /.h

Page 14 Blue Water Embedded, Inc.


Developers Guide

These files declare the optional Pm_File class and define the matching implementation.
Pm_File is a filesystem abstraction class implemented within Prism to insure operating
system portability related to filesystem APIs.

prism_framework.cpp / .h

These files declare and implement the Pm_Framework class, which is a class for
organizing and granting access to the Prism Runtime Framework components.

prism_graphic_reader.cpp / .h

These files declare the optional Pm_Graphic_Reader base class, which defines the
APIs for runtime decode and conversion of various graphics file types.

prism_group.cpp / .h

These files declare the Pm_Group widget class and define the matching
implementation. Pm_Group is a simple container class used to visually and logically
group collections of child widgets.

prism_help_btn.cpp / .h

These files declare the Pm_Help_Btn widget class and define the matching
implementation.

prism_icon.cpp / .h

These files declare the Pm_Icon widget class and define the matching implementation.
The Pm_Icon class is a simple graphic display widget.

prism_icon_btn.cpp / .h

These files declare the Pm_Icon_Btn widget class and define the matching
implementation.

prism_input_device.cpp / .h

These files declare the common API used for all Prism input device drivers and define
generic implementations for common functions.

prism_jpg_reader.cpp / .h

Blue Water Embedded, Inc. Page 15


Developers Guide

These optional files declare and implement the Pm_Jpg_Reader class, which is used
for runtime decode and conversion of JPG format graphic files.

prism_list.cpp /.h

These files declare the Pm_List, Pm_Vert_List, and Pm_Horz_List panel types and the
matching implementations.

prism_math.cpp /.h

These files declare various utilities functions for Sin, Cos, Min, Max, and related
functions.

prism_menu.cpp / .h

These optional files declare the Pm_Menu panel, Pm_Menu_Bar widget, and
Pm_Menu_Btn widget classes and their matching implementations.

prism_ml_popup.cpp / .h

These files declare the Pm_ML_Popup_Panel panel class and define the matching
implementation.

prism_ml_prompt.cpp / .h

These files declare the Pm_ML_Prompt widget class and define the matching
implementation.

prism_ml_text_btn.cpp / .h

These files declare the PM_ML_Text_Btn widget class and define the matching
implementation.

prism_ml_text_input.cpp / .h

These files declare the Pm_ML_Text_Input widget class and define the matching
implementation.

prism_paint_engine.cpp / .h

These files declare the base Pm_Paint_Engine paint class and define the matching
implementation. Pm_Paint_Engine defines the painting API used by all widgets and
panels and the application level software. Pm_Paint_Engine provides the entry point for
all primitive painting functions, and performs required checks and validation of input

Page 16 Blue Water Embedded, Inc.


Developers Guide

parameters. In most cases Pm_Paint_Engine then passes the request to a low-level


paint driver for final implementation.

prism_paint_gradient.cpp / .h

These optional files declare the Pm_Gradient class and define the matching
implementation. Pm_Gradient painting engine, which is used to dynamically create
gradient fills for various widget and panel types.

prism_panel.cpp / .h

These files declare the Pm_Panel panel class and define the matching implementation.

prism_password.cpp / .h

These optional files declare the Pm_Password text input widget and define the
matching implementation.

prism_png_reader.cpp / .h

These optional files declare the Pm_Png_Reader class and its implementation. The
Pm_Png_Reader class is used for runtime decoding and conversion of PNG format
image files. This class is not required for correct operation of the framework.

prism_point.h

This file declares the pm_point_t data type and defines the matching implementation.

prism_popup.cpp / .h

These files declare the Pm_Popup_Panel panel class and define the matching
implementation.

prism_progress_bar.cpp / .h

These files declare the Pm_Progress_Bar widget class and define the matching
implementation.

prism_progress_panel.cpp / .h

These files declare the Pm_Progress_Panel panel class and define the matching
implementation.

Blue Water Embedded, Inc. Page 17


Developers Guide

prism_prompt.cpp / .h

These files declare the Pm_Prompt text display widget and define the matching
implementation.

prism_region.cpp / .h

These files declare the Pm_Region class and define the matching implementation.

prism_res_file.h

This optional file defines the format of a Prism binary resource file.

prism_resource_mgr.cpp / .h

These files declare the Pm_Resource_Manager framework class and define the
matching implementation.

prism_screen_mgr.cpp /.h

These files declare the Pm_Screen_Manager framework class and define the matching
implementation.

prism_scroll.cpp / .h

These optional files declare the Pm_Scroll, Pm_VScroll, and Pm_HScroll widget
classes and define the matching implementations.

prism_shadow_btn.cpp / .h

These files declare the Pm_Shadow_Btn widget class and define the matching
implementation.

prism_slider.cpp / .h

These files declare the Pm_Slider widget class and define the matching implementation.

prism_snapshot.cpp / .h

This file declares the Pm_Snapshot class and defines the matching implementation.

prism_spin_btn.cpp / .h

These files declare the Pm_Spin_Btn class and the matching implementation.

Page 18 Blue Water Embedded, Inc.


Developers Guide

prism_sprite.cpp / .h

These files declare the Pm_Sprite class and related data structures and
implementation.

prism_startup.cpp

This file contains the Prism startup function named PrismAppStart. This function
creates each of the Prism Runtime Framework core components and prepares the
Prism runtime environment for use by the application.

prism_status.h

This header file defines the available widget status flags.

prism_status_bar.cpp / .h

These files declare the Pm_Status_Bar widget class and matching implementation.

prism_std_int.h

This file declares the Prism basic data types, including the C99 data types.

prism_string_lib.h

This file declares the Prism string handling functions for various character encoding
methods.

prism_tab_panel.cpp / .h

These optional files declare the Pm_Tab_Panel panel class and matching
implementation.

prism_text_input.cpp / .h

These files declare the basic single-line text input widget and matching implementation.

prism_text_widget.cpp / .h

These files declare the base Pm_Text_Widget class and matching implementation.

prism_timer_mgr.cpp / .h

Blue Water Embedded, Inc. Page 19


Developers Guide

These files declare the Pm_Timer_Manager framework class and matching


implementation.

prism_title_bar.cpp / .h

These optional files declare the Pm_Title_Bar widget and matching implementation.

prism_tool_bar.cpp / .h

These optional files declare the Pm_Tool_Bar and Pm_Button_Group classes and their
corresponding implementation.

prism_tree_view.cpp / .h

These files declare the Pm_Tree_Node widget and Pm_Tree_View panel classes and
their implementations.

prism_txt_icon_btn.cpp / .h

These files declare the Pm_Text_Icon_Btn widget class and define the matching
implementation.

prism_virtual_list.cpp / .h

These files declare the Pm_Virtual_List panel class and define the matching
implementation.

prism_vprompt.cpp / .h

These files declare the Pm_VPrompt widget class and define the matching
implementation.

prism_widget.cpp / .h

These files declare the base Pm_Widget class, which is used as the base class for all
displaying widget and panel types.

prism_zip.cpp / .h

These files declare the Pm_Zip and Pm_Unzip utility functions and their matching
implementations.

Page 20 Blue Water Embedded, Inc.


Developers Guide

1.3 Memory Footprint

The code size of the Prism framework changes based on which features and
components you choose to include. Also remember most linkers will not include
components that are not referenced.

Prism provides detailed configuration settings to allow you to trim features you are not
using. For example, if you do not need desktop style TitleBar widgets for your panels,
you can turn this feature off in the configuration settings. You can do the same for
many optional features, such as scroll bars, filesystem dependent components, and
runtime image decompression components.

When asked for a rule of thumb, we have observed linker map files that range from
40Kbytes for Prism Micro to nearly 200Kbytes for Prism with all features enabled using
the ARM mode (32 bit instruction set) build for an ARM9 processor. Similar code size
can be expected for other targets.

The ROM footprint of Prism Micro can be very low, less than 40 KBytes. We are
commonly running entire applications within the 256 KBytes internal flash of Cortex M3
devices. Of course you must sacrifice some capabilities to make the footprint small,
and Prism Micro allows you to remove features like scroll bars and other widgets with
ease.

As for RAM, Prism can run with a 4 KByte stack. The amount of heap required is always
a difficult question to answer because it depends heavily on the application
organization. A realistic minimum heap size might be 16 KBytes. If Prism is running on
a CPU with an external LCD driver and external graphics RAM, we can do all drawing
directly into that external graphics RAM. This is common for example with an external
controller made by companies like ILITEK or Solomon Systech, where the graphics
RAM is actually incorporated within the LCD display. The performance and capabilities
are not as good with this type of system, but the RAM requirements are minimal.

If the application wants to do animations, sprites, and runtime image decoders, of


course it will need far larger memory, maybe even several Mega-Bytes depending on
the requirements.

1.4 Paint Engines

In addition to the core framework source files listed above, you will need to include a
Prism Paint Engine specific to your hardware in your framework build. We will discuss

Blue Water Embedded, Inc. Page 21


Developers Guide

the Paint Engine classes in much more detail in a later chapter, however to enable you
to build a working Prism library we need to introduce the files and class hierarchy here.

The Pm_Paint_Engine class serves as a base class for painting and related API
functions. Pm_Paint_Engine provides a thin layer of abstraction between the Prism
widgets and the underlying hardware, allowing Prism to be easily ported to new
hardware targets.

Derived from the Pm_Paint_Engine base are classes providing a common set of
functions supporting each color depth and color format. Derived from these color-
format-specific engines are actual hardware specific engines that are optimized to utilize
your target hardware to the fullest extent. The following diagram illustrates the C++
derivation or hierarchy of the paint engine classes for a general target:

Prism Paint Engine Base


(prism_paint_engine.cpp)

Derived From

Prism Color Format Specific Engine


(ex: prism_pe_base_xxbpp.cpp)

Derived From

Hardware Specific Paint Engine


(ex: Prism_pe_atmel.cpp)

Configures and Renders to

Physical Display

Your Prism distribution includes at a minimum the desktop platform specific painting
engine and usually at least one additional engine specific to your hardware.

Page 22 Blue Water Embedded, Inc.


Developers Guide

The base Pm_Paint_Engine source files are included the Prism core, and they always
need to be included in every build of the Prism Runtime Framework. This class is not
specific to your hardware or color depth. The files comprising the base
Pm_Paint_Engine class include:

prism_paint_engine.cpp Core painting functions


prism_paint_lines.cpp - Line, Polyline, PatternLine, and Rectangle functions

The color-format specific derivations of the base painting class are contained in the
drivers\graphics sub-directory. You will need to include at least one of these mid-level
paint engines in your library build. Choose the filename that matches the color depth of
your target system. For example, if your target will run using 16-bpp (bit-per-pixel) color
format, choose the prism_pe_base_16bpp. If your target will run at 24-bpp, include the
prism_pe_base_24bpp.cpp file in your library build.

Finally, you will need to include the hardware-level driver specific to your target
platform. For the Panels simulation environment, the driver is named
prism_pe_panels_xxx where xxx is the desired color depth. For Linux/X11, the driver
is named prism_pe_x11_xxx where again xxx is the color depth of the desired
simulation environment.

The filename for your target hardware should be intuitive based on the CPU / graphics
controller name.

For example, to build the Prism Runtime Framework for 16-bpp color depth for the
Microsoft Windows desktop, you would include in your Prism build:

\drivers\graphics\prism_pe_base_16bpp.cpp - This is the 16-bit base painting engine.

\drivers\graphics\prism_pe_windows_16bpp.cpp - This is the paint engine for your


desktop, which is derived from the 16-bpp base class.

As a second example, to build the Prism Runtime Framework for 16-bpp color depth for
the Atmel AT91SAM9M10 target hardware, you would include in your Prism build:

\drivers\graphics\prism_pe_base_16bpp.cpp - This is the 16-bit base painting engine.

\drivers\graphics\prism_pe_atmel_9m10_16bpp.cpp - This is the paint engine for your


target hardware, which is derived from the 16-bpp base class.

Blue Water Embedded, Inc. Page 23


Developers Guide

1.5 Additional Drivers

Additional drivers are provided with Prism for keyboard/keypad and mouse. Drivers for
touch input devices are available for a nominal fee. The specific drivers provided will
vary depending on your selection of target hardware and operating system.

1.6 Pre-configured Make/Project files

The \prism\build directory contains multiple project files and makefiles for building the
Prism Runtime Framework using a variety of tools, operating systems, and target
controllers. Your Prism distribution should include a makefile or project file for building
the Prism Runtime Frame for your desktop environment, and an additional build file to
be used for your target environment. Simply scan the \prism\build directory to find the
build files provided in your distribution.

Page 24 Blue Water Embedded, Inc.


Developers Guide

2 DEFINITIONS

2.1 Terms and Data Types

This chapter describes some terminology you will need to learn in order to understand
the Prism Runtime Framework API and execution environment, and introduces the data
type names that are used to pass and return parameters within the Prism API.

2.2 Panels and Widgets and Utility classes

It is sometimes convenient to divide the Prism classes into several groups: the Panel
classes, the Widget classes, the Managers, and the Utility classes.

Widgets are graphical objects like buttons and scroll bars. Widgets are derived at some
point from the Pm_Widget class. Widgets can paint themselves, can receive events,
and have common set of member functions and variables.

Panels are objects derived at some point from the Pm_Panel class. Panels are
generally used as background containers to which you might add other Panels and
widgets. Panels are also derived from the Pm_Widget class, and therefore panels can
also paint themselves and receive events. Panels are a superset of the Pm_Widget
members and functions.

The Managers are overseers of the executing UI application. The mangers include the
Pm_Event_Manager and Pm_Resource_Manager, among others. The managers are
what compose the Framework portion of the Prism Runtime Framework. They are not
visible (with the exception of the Pm_Screen_Manager), but they are essential to the
capabilities of the runtime environment.

Utility classes are neither panels nor widgets. Utility classes refer to classes such as the
runtime image readers, or the Pm_Brush class. These classes are not derived from
Pm_Widget and do not directly participate in the UI by painting themselves, however
they are still critically important to the final working system.

2.3 Parent Child Sibling

These terms refer to the relationship between the Panels and widgets which compose
your user interface implementation. The Prism API allows you to link one object to
Blue Water Embedded, Inc. Page 25
Developers Guide

another, after which the objects will operate together. For example, if you link a
Pm_Button widget to a Pm_Panel widget, the Pm_Panel is from that point referred to as
the Parent of the button. If the panel is moved, the button will automatically move with
it. If the Parent is scrolled, the button will scroll up or down or left or right within the
panel client area. The Panel is the parent object, and the button is the child object.

You can link any type of object to any other type of object, meaning that an object does
not have to be Panel to be a parent or a button to be a child. You could link a Panel to
become a child of a Button. Prism imposes no restrictions on what type of objects may
be used as parents or children, and imposes no limits on the nesting level of your parent
child child linkage. You can, at any time, unlink or link any object to any other.

If you link multiple buttons to a common parent panel, the buttons are said to be
siblings. Any set of objects which share a common parent are termed siblings.

An object can and often is both a parent and a child at the same time. For example,
you might create a background panel, and add to this panel several child panels, and
add to the child panels several other widgets. So the middle-level panels are children of
the background, but parents of the inner widgets. This is normal and very common in
Prism software development.

2.4 Fundamental Data Types

This section describes fundamental data types used in Prism. Prism uses simple 8, 16,
and 32 bit data storage types, and more complex types for passing information such as
color, position, bitmap and font data. Prism utilizes the C99 data types as the basis for
all other user-defined types, which will make the most basic types immediately
recognizable for those users who are familiar with the basic C99 defined data type
definitions.

int8_t signed 8-bit value

uint8_t unsigned 8-bit value

int16_t signed 16-bit value

uint16_t unsigned 16-bit value

int32_t signed 32 bit value

uint32_t unsigned 32 bit value

pm_int_t signed native int (16 or 32 bit)

Page 26 Blue Water Embedded, Inc.


Developers Guide

pm_uint_t unsigned native int (16 or 32 bit)

pm_char_t U16 encoded character type

pm_bool_t boolean type true/false type

pm_color_t color storage type, size dependent on color format

2.5 Naming Conventions

Prism class names are always preceded with Pm_, and each word of the class name
is separated by an underscore. The first letter of each work is capitalized, as in
Pm_Screen_Manager, Pm_Widget, and Pm_Panel.

Prism structures and other user-defined types are always lowercase, with an
underscore between words, and followed by _t indicating this is a data type.
Examples are pm_point_t, pm_color_t, and pm_font_t.

Class member variables are always prefixed with lowercase m, as in mSize and
mFont. Pointer variable names are always prefixed with lowercase p as in pFont and
pData. Member pointers are prefixed with both m and p as in mpFont and mpData.

Variable names and API function names always use a capital letter for each word of the
variable name of function name. Examples of API function names are AssignFont(),
Link(), MoveFocusTo(), etc. Example member variable names include mpVScroll,
mpFont, mSize, etc.

There are a large number of style flags, event types, status flags, and various other
enumerations and definitions you will need to become familiar with when you begin
writing custom painting functions or creating your own derived widgets. We try to be
consistent and precise in our naming conventions to make this learning process as
short as possible.

The Prism event names always begin with PM_EVENT_.

The Prism color indexes always begin with PM_CI_

The Prism style flags always begin with PM_. The style flags are enumerated in the
header file for the base class that defines them.

Blue Water Embedded, Inc. Page 27


Developers Guide

2.6 pm_bitmap_t

pm_bitmap_t is a structure that contains the information required by the Prism paint
engines to render a bitmap to the graphics buffer. The bitmap structure defines the data
format, color depth, compression type, bitmap size, and contains a pointer to the actual
bitmap data array.

Several variations within each color format for endian-ness and color channel order are
supported. Prism bitmaps may optionally be compressed and may have an alpha
channel.

pm_bitmap_t data structures are usually created by Prism Insight and saved in your
resource file(s); however, they can also be created dynamically by the runtime image
readers or by other means as well. When you use pm_bitmap_t data created by the
Prism Insight application, you will refer to those bitmaps using Bitmap IDs, which are
linked to pm_bitmap_t data structures by the Pm_Resource_Manager.

The pm_bitmap_t structure is defined as:

struct pm_bitmap_t
{
uint8_t *pStart;
uint32_t TransColor;
uint16_t Width;
uint16_t Height;
uint8_t BitsPix;
uint8_t Flags;
};

The Flags field contains color format modifiers recognized by the paint engine, and
indicated whether the bitmap uses compression. The BitsPix field indicates how many
bits of data are required to encode one pixel color. The Width and Height fields indicate
the image dimensions. The TransColor field is only used of the image does not include
an alpha channel but does encode transparency. The pStart field is a pointer to the
actual bitmap data.

2.7 Pm_Brush

class Pm_Brush
{
friend class Pm_Paint_Engine;

public:
Pm_Brush();

Page 28 Blue Water Embedded, Inc.


Developers Guide

Pm_Brush(pm_color_t _LineColor,
pm_color_t _FillColor,
pm_int_t BStyle = PBS_NO_ALIAS,
pm_int_t _LineWidth = 1,
const pm_font_t *_pFont = NULL);

~Pm_Brush();

void Set(pm_color_t _LineColor,


pm_color_t _FillColor,
pm_int_t BStyle = PBS_NO_ALIAS,
pm_int_t _LineWidth = 1)
{
LineColor = _LineColor;
FillColor = _FillColor;
Style = BStyle;
Width = _LineWidth;
}

pm_bitmap_t *pBitmap;
const pm_font_t *pFont;

uint32_t Pattern;

pm_int_t Width;
pm_int_t Style;

pm_color_t LineColor;
pm_color_t FillColor;
};

A Pm_Brush is used to pass color and font data to the painting API functions. A
Pm_Brush contains the LineColor, FillColor, Pattern, Width, and Style for each paint
operation. The Pm_Brush class is defined as shown:

LineColor is the color used for paint the outline of rectangles, the line color for lines, and
the text foreground color for text..

FillColor is the color value used to fill rectangles, polygons, etc. The FillColor is only
used if the brush style includes PBS_SOLID_FILL.

Pattern is used only for painting pattern lines, and defines the LineColor/ FillColor
pattern to be used for painting a pattern line.

Width is the brush width. This defines the border width for any outlined object such as a
rectangle or circle.

Style defines the Brush style flags. These flags include:

Blue Water Embedded, Inc. Page 29


Developers Guide

PBS_NO_ALIAS

This flag is applied to line, circle, and all arc painting. This flag indicates that no ant-
aliasing should occur. This is faster than anti-aliasing but also produces a more jagged
painting appearance.

PBS_SOLID_FILL

This style flag indicates that the painted shape will be filled with the FillColor. In the
case of text, this style indicates that the text background will be filled rather than
transparent.

PBS_BMP_FILL

This style flag indicates that the painted shape will be filled with a user-supplied bitmap.

PBS_TRUE_ALIAS

This flag is applied to line, circle, and related arc painting and also to text painting. This
flag indicates that the painting should be anti-aliased to an unknown or varying
background color. This means that the painting engine will read the background color as
it paints each pixel and perform anti-aliasing with the actually background color value.
This is slower than no alias or simple alias, but produces the best looking results over a
varying background such as when painting over a background bitmap.

PBS_ROUNDED

This flag is applied only when painting wide lines. This flag indicates the line ends
should be capped with a round endpoint.

PBS_CENTER_LINE

This flag indicates when painting a wide line or wide outline, the outline should be
centered around the passed pixel coordinates. The alternative, if this flag is not set, is
the passed pixel coordinates define the outer edge of the wide line, and the outline is
painted inward.

PBS_PATTERN

This flag is applied only to line painting, and indicates the line should be painted in an
on-off pattern as defined by the Brush.Pattern parameter.

The Brush.pBitmap field allows the caller to pass a bitmap used for bitmap fill of the
painted shape.

Page 30 Blue Water Embedded, Inc.


Developers Guide

2.8 pm_canvas_t

A canvas is a memory region into which a Pm_Paint_Engine can paint. An application


can create any number of canvases for painting, and there are several different canvas
types. A canvas might be directly linked to a hardware frame buffer
(PM_CANVAS_TYPE_HARDWARE) or it might be an offscreen painting area that only
the application references (PM_CANVAS_TYPE_SIMPLE).

The pm_canvas_t data structure is shown below:

struct pm_canvas_t
{
pm_color_t **pScanPointers;
pm_portal_t *pPortal;
pm_bitmap_t *pMap;
Pm_Widget *pNotify;
pm_canvas_t *pNext;
pm_canvas_t *pPrev;

Pm_Region Invalid;

pm_int_t Id;
pm_int_t Alpha;
pm_uint_t Type;
pm_int_t PaintCount;
pm_int_t HardwareLayer;

pm_int_t PaintOffsetX;
pm_int_t PaintOffsetY;
pm_int_t DisplayOffsetX;
pm_int_t DisplayOffsetY;
};

Applications do not normally directly modify any of the pm_canvas_t data fields. These
fields are managed by Pm_Paint_Engine. Applications simply create canvases, open
canvases, paint on canvases, and close them. The Pm_Paint_Engine manages the
display of canvases and overlay of different canvas types on the background frame
buffer.

Blue Water Embedded, Inc. Page 31


Developers Guide

2.9 pm_event_t
pm_event_t is used to pass incoming event information to receiving widgets and panels.
The pm_event_t structure is shown (in reduced form) below:

struct pm_event_t
{
public:

pm_event_t();
pm_event_t(uint16_t Val) ;
pm_event_t(Pm_Widget *Target, uint16_t Val);

Pm_Widget *pSource;
Pm_Widget *pTarget;
uint16_t Type;
uint16_t Param;

union
{
void *pData;

Pm_Region Region;
pm_point_t Point;
int32_t Payload[2];

int32_t User_int32[2];
uint32_t User_uint32[2];
int16_t User_int16[4];
uint16_t User_uint16[4];
uint8_t User_uint8[8];
};
};

For events generated by Prism widgets, the pSource parameter always points to the
event originator. The Type field identifies the event type, which defines the event and
defines which of the data fields within the event, if any, are utilized.

Events will be described in more detail in the chapter which describes


Pm_Event_Manager.

Page 32 Blue Water Embedded, Inc.


Developers Guide

2.10 pm_font_t

A pm_font_t is a data structure that provides the information required by the Prism pain
engine to render text to the graphics buffer. Prism fonts contain the information to
define the font character widths, baseline, and character range of each font. Prism
fonts can be linked together to support large fonts containing multiple code pages.

The pm_font_t data structure is defined as:

struct pm_font_t
{
uint8_t Type;
uint8_t Ascent;
uint8_t Descent;
uint8_t CharHeight;
uint8_t PreSpace;
uint8_t PostSpace;
uint8_t LineHeight;
uint16_t BytesPerLine;
uint16_t FirstChar;
uint16_t LastChar;
uint16_t *pOffsets;
pm_font_t *pNextPage;
uint8_t *pData;
};

The font Type indicates how the font data is encoded. This field is utilized by the
painting engine to properly paint the font characters. The font Ascent and Descent
indicate the Ascent and Descent of the font, in pixels, from the font baseline.

The CharHeight field indicates the total height of the font in pixels.

The PreSpace and PostSpace fields indicate the amount of whitespace to allow before
and after each line of text in a multi-line text widget.

The BytesPerLine, FirstChar, and LastChar fields are used to by the Pm_Paint_Engine
to properly locate the data for a particular character within the font data block.

The pOffsets and pData fields point to a character offset and character data tables,
respectively. The pNextPage is used for multi-page fonts, where a single font may have
multiple character pages.

Blue Water Embedded, Inc. Page 33


Developers Guide

2.11 pm_point_t

This is a simple x,y coordinate structure. In Prism, x, y position is always relative to the
top-left corner of the screen and the top-left pixel is always pixel address 0,0. Pixel y
values increase as you move from top to bottom on the display screen. This convention
is opposite of the standard Cartesian coordinate system, but is a common practice in
graphics programming.

pm_point_t is defined as:

struct pm_point_t
{
void Set(pm_int_t InX, pm_int_t InY)
{
x = (int16_t) InX;
y = (int16_t) InY;
}

pm_bool_t operator != (const pm_point_t &InPoint) const


{
if (x != InPoint.x || y != InPoint.y)
{
return TRUE;
}
return FALSE;
}
pm_bool_t operator == (const pm_point_t &InPoint) const
{
if (x == InPoint.x && y == InPoint.y)
{
return TRUE;
}
return FALSE;
}
pm_point_t operator +(const pm_point_t &Point) const
{
pm_point_t NewPt;
NewPt.Set(x + Point.x, y + Point.y);
return NewPt;
}

pm_point_t operator -(const pm_point_t &Point) const


{
pm_point_t NewPt;
NewPt.Set(x - Point.x, y - Point.y);
return NewPt;
}

int16_t x;
int16_t y;
};

Page 34 Blue Water Embedded, Inc.


Developers Guide

2.12 Pm_Region

Prism uses rectangular screen areas to define an objects limits and which areas of the
screen the object painting will be clipped within. Its also very common when writing
custom Paint function to need to work with regions on the screen. For this reason the
Pm_Region class is defined to simply doing math and logical operations with screen
regions.

Pm_Region is defined as:

Blue Water Embedded, Inc. Page 35


Developers Guide

struct Pm_Region
{
void Set(pm_point_t UpperLeft, pm_point_t BottomRight)
{
Left = UpperLeft.x;
Top = UpperLeft.y;
Right = BottomRight.x;
Bottom = BottomRight.y;
}

void Set(pm_int_t xLeft, pm_int_t yTop,


pm_int_t xRight, pm_int_t yBottom)
{
Left = (int16_t) xLeft;
Top = (int16_t) yTop;
Right = (int16_t) xRight;
Bottom = (int16_t) yBottom;
}

Pm_Region operator ++(int);


Pm_Region operator += (int x);
Pm_Region operator --(int);
Pm_Region operator -= (int x);

Pm_Region operator &=(const Pm_Region &Other);


Pm_Region operator &(const Pm_Region &Size) const;
Pm_Region operator |= (const Pm_Region &Other);
Pm_Region operator ^= (const Pm_Region &Size);
pm_bool_t operator != (const Pm_Region &Size) const;
pm_bool_t operator == (const Pm_Region &Size) const;

pm_bool_t Contains(pm_point_t Test) const;


pm_bool_t Contains(pm_int_t x, pm_int_t y) const;
pm_bool_t Contains(const Pm_Region &Size) const;

pm_int_t Height(void) const { return (Bottom - Top + 1);}


pm_bool_t Overlap(const Pm_Region &Size) const;

void MoveTo(pm_int_t x, pm_int_t y);


void Shift(pm_int_t xShift, pm_int_t yShift);
pm_int_t Width(void) const {return (Right - Left + 1);}

int16_t Left;
int16_t Top;
int16_t Right;
int16_t Bottom;
};

Page 36 Blue Water Embedded, Inc.


Developers Guide

2.13 Pm_Snapshot

The Pm_Snapshot structure is used internally by Prism when painting a mouse cursor
in software, without a dedicated hardware mouse support. In this case, Prism must
save the pixels in the area beneath the mouse position before drawing the mouse
bitmap. The saved area is then restored when the mouse cursor is moved and the
process repeats.

The Pm_Snapshot structure can also be used by application to copy and move
rectangular area of pixel about on the screen.

The Pm_Paint_Engine class also has optional functions to create a snapshot of any
screen area at runtime and save this snapshot as a MS Panels formatted bitmap image.
This capability can be useful for creating screen shots for automated testing or for
marketing materials.

class Pm_Snapshot
{
public:
Pm_Snapshot(void)
{
mRegion.Set(0, 0, 0, 0);
mBitmap.pData = 0;
mValid = FALSE;
mDataSize = 0;
}

~Pm_Snapshot()
{
if (mBitmap.pData)
{
delete mBitmap.pData;
}
}

int32_t DataSize(void) {return mDataSize;}

Pm_Region &Pos(void) {return mRegion;}


pm_point_t Point(void);

void SetPos(Pm_Region &Region)


{
mRegion = Region;
mBitmap.Width = (uint16_t) Region.Width();
mBitmap.Height = (uint16_t) Region.Height();
}

pm_bool_t IsValid(void) const {return mValid;}

Blue Water Embedded, Inc. Page 37


Developers Guide

void MoveTo(pm_int_t Left, pm_int_t Top);

void SetValid(pm_bool_t Valid) {mValid = Valid;}


void SetDataSize(int32_t Size);

void Reset(void);
void Shift(pm_int_t xShift, pm_int_t yShift)
{mRegion.Shift(xShift, yShift);}

pm_bitmap_t *Bitmap(void) {return &mBitmap;}

private:

Pm_Region mRegion;
pm_bitmap_t mBitmap;
int32_t mDataSize;
pm_bool_t mValid;
};

Page 38 Blue Water Embedded, Inc.


Developers Guide

3 THE EXECUTION MODEL

3.1 Runtime Execution Model

This chapter provides an overview of the Prism runtime framework and describes how
the various high-level components interact to support and bring structure to your user
interface application. We will introduce the framework components at a high level view,
and the leave the details of each class implementation to the following chapters.

Prism can be run in a standalone model or in a multitasking environment. Since the


multitasking environment is by far the most common, we will describe things using the
multitasking view of the system. The system actually becomes simpler in some
respects if you are running Prism under the standalone model.

In the multitasking model, input drivers and any system task can directly interact with
Prism using the Prism API and event manager. In the standalone model, input devices
are usually polled by the Prism loop and only the Prism loop can send and receive
events.

3.2 Framework Overview

The components of Prism which control the execution of the GUI application are
Pm_Framework, Pm_Animation_Manager, Pm_Data_Manager, Pm_Event_Manager,
Pm_Paint_Engine, Pm_Resource_Manager, Pm_Screen_Manager, and
Pm_Timer_Manager. These components are all implemented as C++ classes that are
instantiated when the function PrismInitialize is called, usually during system startup.
The PrismInitialize function is called near the start of the PrismTask for most operating
system integrations.

If you are familiar with common desktop UI programming systems such as Microsoft
MFC programming, you will quickly understand the Prism execution model because it is
modeled after these desktop environments in terms of being event driven and is also
similar as to how objects invalidate themselves to signal the Screen Manager they need
to be repainted.

The class Pm_Framework is composed entirely of static functions for assigning and
retrieving pointers to instances of the remaining framework components.
Pm_Framework provides convenient methods to allow any porting of the application
level software to invoke the Prism API, regardless of whether that software is

Blue Water Embedded, Inc. Page 39


Developers Guide

considered part of the UI software or whether that software is executing withing the
scope of a Prism widget class.

Pm_Screen_Manager keeps track of the visible UI elements, where they are located,
and the status of each. Pm_Screen_Manager decides where to direct input events
such as touch screen or keypad events, and makes sure that those events are
processed by the correct panels and widgets. Pm_Screen_Manager also provided a
mechanism for user-defined event types to be handled by a user-define event
processing function. Finally, Pm_Screen_Manager keeps track of which parts of the
visible screen need to be re-painted, and invoked the required panel and widget
painting functions to refresh the screen as needed.

Pm_Event_Manager provides an API for sending and receiving system and user-
defined event types. Events are what drive your user interface; events make widgets do
things and cause screen changes. The Pm_Event_Manager implementation is often
highly specific to the underlying operating system details, but this dependence is hidden
from the application level software. To the Prism application, the Pm_Event_Manager
API is all that is visible and all that is needed to send and receive all event types.
Pm_Event_Manager may be responsible for managing multiple Event Queues,
depending on how many UI threads are executing simultaneously.

Pm_Event_Manger also blocks the Prism task(s) when no events are available for
processing. This is how Prism suspends itself when the UI is idle. Pm_Event_Manager
will automatically wake up and resume the Prism thread when an input event is
received. Exactly how this wakeup occurs is unique to each operating system
integration, but to the application developer the key point is that Prism automatically
suspends or blocks when the UI is idle, and the Pm_Event_Manager forms the main
execution loop. Applications must always return from Event handlers and painting
functions and not block within those functions.

Pm_Paint_Engine provides the API definition by which all panels and widgets paint
themselves. While not part of the framework execution loop, the Pm_Paint_Engine is
vital to maintaining portability in your application across different hardware platforms
and is there counted as part of the runtime framework.

Pm_Resource_Manager installs and grants access to the application resources.


Application resources can include any combination of fonts, colors, bitmaps, screen
construction/transition data, and strings in either binary, source, or XML formats.

Pm_Timer_Manager provides a simple interface for low-resolution timing operations.


Prism timers are all driven by one low-level RTOS timer.

Page 40 Blue Water Embedded, Inc.


Developers Guide

The following is a simple visual model of the operating Prism Runtime Framework:

Touch Driver Keypad Driver

Pm_Event_Manager

Event
Timer Driver Queue
Event
Event
Queue
Queue

Pm_Timer_Manager
System
Resources
Pm_Screen_Manager

Pm_Resource_Manager

Pm_Widget
Pm_Panel Pm_Widget
Pm_Widget

Pm_Paint_Engine Base

Hardware Specific Engine

Display Device

Blue Water Embedded, Inc. Page 41


Developers Guide

Examining this diagram and working from top to bottom:

Input devices drivers such as touch input or keypad input drivers send events into
Pm_Event_Manager. Pm_Timers may also be active and sending events into
Pm_Event_Manager.

Pm_Timer_Manager starts and stop timers as directed by the application software, and
receives input from the RTOS timer driver to generate PM_TIMEOUT events.

Pm_Event_Manager maintains one event queue for each UI task, which may be only
one task. Pm_Event_Manager passes events to Pm_Screen_Manager for routing to the
correct object.

Pm_Screen_Manager sends events to the UI objects for processing. The UI objects,


which are some assortment of Pm_Panel and Pm_Widget objects, invalidate
themselves if they need to refresh the screen.

Pm_Resource_Manager loads resources and prepares them for use by the application.
The application widgets query the resource manager when they paint themselves to
obtain color, bitmap, font, and string resources.

The Panels and Widgets utilize the Pm_Paint_Engine API to render themselves on the
screen. The Pm_Paint_Engine derived graphics drivers do the final rendering to the
display hardware.

3.3 Program Startup


The low-level startup of your system software is not affected by running Prism. If you
are running with an RTOS, then you will need to have at least one task configured to
run the Prism framework. There are RTOS integration notes provided for each
supported RTOS to detail any special considerations needed for your system.

Once the Prism task is started, the function named PrismInitialize (), found in the file
named prism_startup.cpp, is called to create each of the Prism Runtime Framework
components. Once PrismInitialize() returns, a user-supplied function named
PrismAppStart is called to initialize the user interface.

PrismAppStart() is defined by the application. You can create as much or as little as


you desire in this function. The Prism Insight application program will create a default
PrismAppStart function for you in the source module that has the Startup Module
option selected.

Page 42 Blue Water Embedded, Inc.


Developers Guide

PrismAppStart() should create the initial screen(s), link those screens to


Pm_Screen_Manager, and return. Do not enter a while(1) type loop in your
PrismAppStart function

PrismAppStart usually loads the resource required by the application into the
Pm_Resource_Manager, waits for input devices to be ready, and then creates the intial
screen(s) to be displayed. The Prism Insight tool will generate your PrismAppStart
function for you if desired.

The exact Prism startup sequence may vary from one operating system to another;
however, from the application perspective the startup is always the same regardless of
the target platform and operating system. PrismAppStart is the application UI software
entry point, and this is where you create the first screen(s) to be displayed.

After calling PrismAppStart(), the Prism startup code calls a member function of the
Pm_Screen_Manager named Execute(). The execute function begins retrieving
events from the Pm_Event_Manager and sending them to your Prism panels and
widgets for processing. This is the Prism Event Loop, and it runs forever. On a
multitasking system, the Prism Event Loop automatically blocks or suspends when the
Pm_Event_Manager indicates there are not events needing to be processed.

3.4 Prism Standalone Operation


If you are running Prism in a standalone environment, the startup operation and
execution are very similar to the multitasking version, with the exception Prism has no
mechanism to suspend its thread of execution when running in a standalone
environment. Therefore in a standalone environment Prism calls a second user-
supplied function named PrismIdleCallback() when the Pm_Event_Manager has no
events to process.

PrismIdleCallback is a callback function that allows you to perform other processing


outside of the Prism thread. In a single-threaded standalone system, the program
execution basically becomes a super-loop where individual program segments are
generally run in order, one after another, until you loop back to the start. The
PrismIdleCallback function is the hook to allow you to branch off to the other parts of
your application when Prism is idle.

It is important your PrismIdleCallback function returns to allow Prism to continue running


and checking for new events!

PrismIdleCallback is only required when running in a standalone (i.e. no RTOS)


environment.

Blue Water Embedded, Inc. Page 43


Developers Guide

4 THE SCREEN MANAGER

4.1 Pm_Screen_Manager

Pm_Screen_Manager is a background panel, to which you link the other panels and
widgets you want to have visible on the display device. Pm_Screen_Manager is
derived from Pm_Panel, so really Pm_Screen_Manager is just another Pm_Panel to
which we have added some additional functions for keeping track of which object has
input focus and to which object input events should be directed.

We will describe the terms Link and Unlink as they are used in Prism programming in
full detail in a later chapter, but for an introduction you need to understand the Prism
keeps tracks of all of your panels and widgets using simple doubly linked lists. When
you link a panel or widget to Pm_Screen_Manager, this panel or widget becomes a
child of Pm_Screen_Manager, and also (by default) becomes visible. When you Unlink
a panel or widget, that object has no parent and is no longer visible.

In general, your application programming, at least as far as determining what is


displayed to the end user, will involve creating panels, linking them to
Pm_Screen_Manager, navigating from one panel to another, and possibly destroying
panels when they are no longer required.

Pm_Screen_Manager provides the main execution loop of you application. During


system startup, after calling your PrismAppStart() function, the initialization and startup
code calls a function named Pm_Screen_Manager::Execute(). The Execute() function
begins checking for incoming events, and blocks the Prism thread of execution when no
input events are available. This yields control of the microprocessor to other system
threads.

4.1.1 Key features and functions of Pm_Screen_Manager

Pm_Screen_Manager is derived from Pm_Panel, and is always the background panel


responsible for painting the screen background. When and if you remove your
application panels from the display, the Pm_Screen_Manager repaints the background.
Therefore to change the screen background color you would assign a new color to the
Pm_Screen_Manager.

Pm_Screen_Manager also keeps track of which panel and widget has input focus. This
concept is mainly used for keyboard or keypad input, but can be used with a touch
screen or mouse as well. When keyboard or keypad input events arrive,

Page 44 Blue Water Embedded, Inc.


Developers Guide

Pm_Screen_Manager directs them to the correct child widget by keeping track of which
widget has input focus.

Pm_Screen_Manger does portal management, meaning Pm_Screen_Manager keeps


track of which areas of the screen are visible to which panels. This is needed when
panels become stacked or overlapping, and it prevents a panel in the background from
painting over a panel in the foreground.

Pm_Screen_Manager maintains global color and style settings for various widget types
such as Pm_Button, Pm_Scroll, Pm_Title, and Pm_Menu. This makes it easy for your
application to change the default appearance of all buttons or or scroll bars, simply by
modifying these settings within Pm_Screen_Manager.

Pm_Screen_Manager keeps track of objects and regions that have been invalidated.
When the Pm_Event_Manager discovers no events are available for processing, the
Pm_Screen_Manager is invoked to efficiently repaint those objects and screen regions
that need to be refreshed.

When the #define PRISM_SCREEN_STACK_DEPTH is defined in the prism_settings.h


file, Pm_Screen_Manager implements a Panel Stack, which is a simple mechanism to
save and retrieve panels from the display. The panel stack can be used to allow nested
menu systems to easily dive into a sub-menu and return back up the menu tree. Nested
menus might be invoked from different paths, and using the panel stack the nested
menu does not need to know which path was used to get to the current state. When the
nested menu or panel is ready to close, it simply pops the most recent panel from the
panel stack to return to the previous state. The panel stack is accessed via the functions
PanelPop(), PanelPush(), and PanelStackReset().

4.2 Mouse and Touch Screen Input Handling

Pm_Screen_Manager handles the routing of Mouse and/or touch screen input events to
the various widgets on the screen. Mouse and Touch input drivers send events into the
Pm_Event_Manager that encode the pixel coordinates of the mouse or touch event.
Pm_Screen_Manager searches for the topmost visible and selectable widget that lies
beneath the indicated coordinates, and routes the input event to that object.

Base mouse and touch input event types include:

PM_EVENT_PEN_DRAG- Sent for touch or mouse drag, when the left mouse
button is clicked or the screen is touched.

Blue Water Embedded, Inc. Page 45


Developers Guide

PM_EVENT_PEN_MOVE- Sent only for mouse movement, when no button is


clicked.

PM_EVENT_PENDOWN- Sent when the mouse or touch screen transitions to the


pen down or clicked state.

PM_EVENT_PENUP- Sent when the mouse or touch screen transitions to the


pen up or unclicked state.

Additional touch screen input events are defined to support capacitive touch screens
that can generate multi-touch input and input gestures. These additional events are
enabled when the configuration value PRISM_FLICK_GESTURE_SUPPORT is
defined. The additional event types include:

PM_EVENT_CANVAS_CHANGE
PM_EVENT_ST_PAN_U
PM_EVENT_ST_PAN_DOWN
PM_EVENT_ST_PAN_LEFT
PM_EVENT_ST_PAN_RIGHT
PM_EVENT_ST_ROTATE_CW
PM_EVENT_ST_ROTATE_CCW
PM_EVENT_MT_PAN_UP
PM_EVENT_MT_PAN_DOWN
PM_EVENT_MT_PAN_LEFT
PM_EVENT_MT_PAN_RIGHT
PM_EVENT_ZOOM_IN
PM_EVENT_ZOOM_OUT

Page 46 Blue Water Embedded, Inc.


Developers Guide

5 THE EVENT MANAGER

5.1 Pm_Event_Manager
Pm_Event_Manager maintains any number of FIFO event queues, and provides API
functions for sending events into these queues. Pm_Event_Manager also prevents
input events from being posted into the event queue when the screen is not stable,
meaning that input events are lock-out when a screen transition is occurring.

Events are sent to Pm_Event_Manager by Input devices such as mouse or keypad, by


Prism itself, by the Prism timer service, or an event by other tasks in the multitasking
system. Pm_Event_Manager is always implemented in a thread-safe mannor to allow
Prism to run in a multitasking environment with other tasks posting events to the
Pm_Event_Manager that will be processed by the Prism thread.

Pm_Event_Manager also provides services for creating new event queues and for
removing unwanted events after a widget has been removed or destroyed.

5.1.1 Key features and functions of Pm_Event_Manager


Maintains a queue of events for each Prism thread. A new queue is created when the
Pm_Panel::Execute() API function is called from within a thread or task that does not
already have an event queue. The Execute() function works as a continuous event
processing loop, and when any thread calls the Pm_Panel::Execute function that thread
effectively becomes a Prism UI thread.

Events are placed in the event queue by calling the PostHead() and PostTail() API
functions. PostHead() places an event at the head of the queue (first to be processed),
while PostTail() places an event at the tail of the queue (last to be processed).

Events are always copied into the event queue to protect against posting events that
are dynamically allocated in stack (i.e. automatic event structures) or heap space.

When the event queue is empty, Pm_Event_Manager blocks the executing thread until
a new event arrives. The specific mechanisms for this vary from one operating system
to another.

Prevents user input and child event notifications via the InputProtect() API function.
This prevents spurious input during screen transition / animation sequences.

Blue Water Embedded, Inc. Page 47


Developers Guide

5.1.2 pm_event_t
Prism defines its own pm_event_t data format. The Prism event format never changes
from one operating system to another or when running on the desktop vs. running on
your target. When running with a real-time operating system, Prism implements each of
the event queues maintained by Pm_Event_Manager by utilizing the underlying
operating system services. To your application level software, it always appears simply
as Prism events running through the Pm_Event_Manager, regardless of the underlying
implementation. This helps to make your application software completely portable
across operating systems.

5.2 Sending Events


Creating and sending events through Pm_Event_Manager requires only that the
application software create a pm_event_t structure, initialize the required data fields,
and call the Pm_Event_Manager::PostHead or Pm_Event_Manager::PostTail functions
to send the event. The PostTail function is preferred so that events are processed in the
order they are generated, unless there is a known reason for prioritizing an event over
all others.

This is a typical event creating and posting sequence:

void MySendFunction(uint16_t EventType, uint16_t Param)


{
pm_event_t NewEvent;

NewEvent.Type = EventType;
NewEvent.pTarget = NULL;
NewEvent.Param = Param;
Pm_Framework::EventManager()->PostTail(NewEvent);
}

5.3 Event Flow and Routing

Events can be intentially routed to specific widgets or panels by initializing the


pm_event_t.pTarget member variable with the address of the Pm_Widget derived
object. When the pTarget field is not NULL, this takes priority over any other event
routing algorithms.

Routing by initializing the Event.pTarget field is not recommended for targets that are
not statically allocated. There is no method for Prism to verify that an Event.pTarget
pointer is valid, therefore routing an Event to an object that might be deleted before the
event is delivered could cause a system failure by invalid pointer reference.

Page 48 Blue Water Embedded, Inc.


Developers Guide

If you initialize the Event.pTarget field with a pointer to an object, your application
should try to insure that the object is not deleted before the event is processed. To
handle this situation, Pm_Event_Manager provides a Purge() API function that is called
automatically whenever any Prism widget is destroyed using the Pm_Widget::Destroy
function. The purpose of the Purge function is to locate any events in the event queue
that have pTarget fields that are not NULL, and detect if the event is directed to a widget
that is being destroyed (or any child of a widget being destroyed).

5.4 Prism Pre-defined System Events

There are a set of events that Prism automatically generates and sends to notify panels
and widgets of changes in system status. For example, events are sent to notify a
widget that it has become visible, or has obtained inpu t focus, or that the active system
language has changed.

The Prism widgets have event handlers defined to handle these pre-defined system
events, or at least the events that they need to catch and take action on. It is also
possible for your application to catch system events and it is quote common to do so. If
you define a handler for a system event by making a corresponding entry in your event
table (we will talk more about event tables in the Pm_Widget chapter), it is important
that you pass the event to your base class in addition to taking whatever action you
want to add. If you do not pass system events to your base class, you effectively
prevent Prism from seeing the event, and unpredictable results may occur.

5.5 System Event List


The following is listing of the most common Prism system event types and their
meanings.

PM_EVENT_RESIZE

This event can be sent to force an object to resize itself. The Event.Region field should
contain the new desired position and size of the target object.

PM_EVENT_CLOSE

This event can be sent to a Pm_Panel derived object to cause the object to Destroy
itself.

PM_EVENT_HIDE

Blue Water Embedded, Inc. Page 49


Developers Guide

This event is sent to an object whenever that object is Unlinked or hidden. This event
tells the object that it is about to become invisible. Often Panels or other widgets take
specific actions, such as stopping running timers, when they are no longer visible.

PM_EVENT_SHOW

This event is sent to an object whenever it is made visible. This event allows the object
to do any preparations for display that were not done in the object constructor, or
perform actions that need to be completed each time the object is re-displayed.

PM_EVENT_PEN_DRAG

This event is sent when the mouse/touch device pen is down and moving. The
Event.Point field contains the mouse/touch pen position in pixels. These events are
caught by moveable objects such as sliders and scroll bars, and can also be caught by
the application software.

PM_EVENT_PEN_MOVE

This event is sent when a mouse device is moved, but no button is clicked. Note that
this event type cannot be generated for touch input, since there is no input available
when the touch screen is not in the pen down state.

PM_EVENT_PENDOWN

This event is sent when the mouse or touch input device changes state from pen up (or
no mouse button) to pen down (or left mouse button clicked).

PM_EVENT_PENUP

This event is sent when the mouse or touch input device changes state from down (or
clicked) to up (or not clicked), as in the left mouse button is release or the touch screen
pen is raised.

PM_EVENT_PAINT

This event can be sent to force an object invalidate and repaint itself.

PM_EVENT_GAINED_FOCUS

Pm_Screen_Manager sends this event to objects when they gain keypad input focus.
Objects may draw themselves differently when they have input focus to give the user a
visual queue as to which object is currently active.

Page 50 Blue Water Embedded, Inc.


Developers Guide

PM_EVENT_LOST_FOCUS
Pm_Screen_Manager sends this event to all objects that were previously members of
the branch of the display tree that has now lost input focus.

PM_EVENT_NEW_LANGUAGE

This event is broadcast to all visible widgets when the active language is changed by
calling the Pm_Resource_Manager::SetCurrentLanguage() API function. The purpose
of this event is to allow all text objects which have a stringId to lookup their new string
value, in other words this event causes all text displayed on the screen to be translated
to the active language.

PM_EVENT_MOUSE_OVER

This event is supported only for mouse input devices. This event is sent when the
mouse pointer enters the mSize bounding region of an object. Many Prism objects
draw themselves in a unique fashion when the mouse hovers over the object.

PM_EVENT_MOUSE_NOTOVER

This event is supported only for mouse input devices. This event is sent when the
mouse pointer leaves the mSize bounding region of an object.

PM_EVENT_TERMINATE

This event can be sent into Prism to terminate the event loop and execution thread of
the target Pm_Screen_Manager.

PM_EVENT_PARENTSIZED

This event is sent by Pm_Panel to inform child widgets that the parent Panel has been
resized. Often child widgets will resize or relocate themselves based on the Parent
panel size.

PM_EVENT_VSCROLL

This event is sent by child Pm_VScroll widgets to cause the parent Panel to scroll
vertically. The application software can also send this event to force a panel to scroll
the contents of the client area.

PM_EVENT_HSCROLL

Blue Water Embedded, Inc. Page 51


Developers Guide

This event is sent by child Pm_HScroll widgets to cause the parent Panel to scroll
horizontally. The application software can also send this event to force a panel to scroll
the contents of the client area.

PM_EVENT_TIMEOUT

This event is sent when a user-defined timer expires. The Event.Param holds the timer
Id, which allows an object to have multiple simultaneous timers running.

PM_EVENT_KEYPAD_PUSH

This event is sent by a keypad/keyboard input device when a key is pushed.

PM_EVENT_KEYPAD_RELEASE

This event is sent by a keypad/keyboard input device when a key is released.

PM_EVENT_SLIDER_MOVE

This event is sent by Pm_Slider widgets to inform the parent that the slider value has
been changed. The Event.Param holds the slider Id, and the Event.Payload[0] holds
the new slider value.

PM_EVENT_CLOSING

Pm_Popup_Panel and Pm_ML_Popup_Panel send this event to the panel owner, if


any, to notify the owner that the popup panel is closing. The popup owner and popup
parent do not have to be the same object.

PM_EVENT_PAINT_NOTIFY

This event can be sent to a designated target to notify the target when a canvas has
been updated. This is useful for applications which are configured to have some off-
screen objects painting to a non-visible canvas, and then allow a visible object to
display the resulting canvas bitmap on a visible display.

PM_EVENT_NEW_RESOURCES

This event is sent by Pm_Resource_Manager when a new resource table is installed.


All objects that utilize resources update and repaint themselves when this event is
received.

PM_EVENT_CANVAS_CHANGE

Page 52 Blue Water Embedded, Inc.


Developers Guide

This event is sent by a parent Pm_Panel to all of the panels child widgets when the
parent panels painting canvas is changed. This re-assigns the active canvas of all of
the panels child widgets, to insure they are painting to the same canvas as the parent.

5.6 Child Event Notifications


Child Event Notifications events are simply a range of Event.Type values which encode
the child widget ID and the notification type within the Event.Type field. Child event
notifications are the most common type of event you will be concerned with when
writing your UI software. These are the event types that you will need to define event
handers (described in the next section) for.

Child Event Notifications are send by your panel children to the parent panel. You then
program your UI application by catching these events as they are generated by your
child widgets and acting on them. Maybe event types contain other information in the
event payload, such as scroll position, button ID value, or the sender of the event.

These Event.Type values are actually encoded with the child object ID and the event
type the child object is generating. Prism provides a macro to make this Event.Type
encoding transparent and self-documenting in your application software. The macro is
named PM_CEN, which stands for Prism Child Event Notification. We will provide an
example of using the PM_CEN macro in the following section.

5.7 Event Handlers

As events are retrieved from the Prism event queue(s), Pm_Screen_Manager


determines the target for each event and calls that target objects Notify member
function, passing a reference to the event as a parameter to Notify().

The Notify() function traverses an Event Table for that object, seeking an entry in the
event table which matches the event type received. If a match is found, the event table
specifies an Event Handler function to be called for that event. If not match is found for
the Event.Type, the event is by default passed to the target objects parent.

Event Handler tables are generally defined by the Prism Insight application, but they
can also be defined by you or more often extended by you to add additional events you
might be interested in. You can add new entries to the event table created by Prism
Insight as long as you do not work within the delimited area of the table.

Event Handler Tables are arrays of pm_event_table_entry records. Each record looks
like this:

Blue Water Embedded, Inc. Page 53


Developers Guide

typedef struct {
uint32_t EventType;
pm_int_t (Pm_Widget::*Handler) (const pm_event_t &Event);
} pm_event_table_entry;

Each record is simply the event type we are interested in handling, and a pointer to the
function which will be called if and when that event arrives. The Event Handler Table
always ends with a NULL record terminator, meaning that the last entry is always
EventType = 0 and a NULL function pointer. This terminates the array.

Event handler functions must have the following signature:

pm_int_t MyClass::MyEventHandler(const pm_event_t &Event)

The following is a simple example of how an Event Handler Table might be defined and
coded for a fictional panel class named MyPanel, which has buttons with ID values
IDB_BUTTON_GO and IDB_BUTTON_STOP.

////////////////////////////////////////////////////////////////////////////
// First, the Event Handler Table is defined:

pm_event_table_entry MyPanel_Event_Table[] = {

{PM_EVENT_SHOW, PM_EVENT_HANDLER(&MyPanel::OnEventShow)},

{PM_CEN(MyPanel::IDB_BUTTON_GO, PM_EVENT_CLICKED),
PM_EVENT_HANDLER(&MyPanel::OnEventGoClicked)},

{PM_CEN(MyPanel::IDB_BUTTON_STOP, PM_EVENT_CLICKED),
PM_EVENT_HANDLER(&MyPanel:OnEventStopClicked)},
{0, NULL}
};

The first entry above is a system event handler, PM_EVENT_SHOW. This means
every time MyPanel is displayed, we want the PmPanel::OnEventShow function to be
called.

The next two entries are CEN (Child Event Notification) handlers. These handlers
specify the Event.Type by using the PM_CEN macro, and again the function to be
called if and when these events arrive.

These event tables and event handler functions will usually be created for you by Prism
Insight, and all you need to do is fill in the contents of the event handler function(s).
However, it is useful to understand the inner workings and be able to create and modify
your own event tables.

Page 54 Blue Water Embedded, Inc.


Developers Guide

The API reference manual specifies the exact event types supported by each type of
Prism widget.

5.8 Example Event Handler

Event handlers should always follow a basic structure. First of all, event handler
functions return a pm_int_t value. This value returned is nearly always 0, because non-
zero return values have special significance. A non-zero return value indicates that the
event handler is signaling the termination of a modal execution loop, and desires to
return the Event Handler return value to the caller of the Execute() function. In most
cases, Event Handlers do not want to trigger the termination of the Execute() function
and they therefore return the value 0.

Event handler for pre-defined system events should always pass the event to the
objects base class to allow Prism to see and act on the event. This is an example of an
event handler for the PM_EVENT_SHOW system event:

pm_int_t MyPanel::OnEventShow(const pm_event_t &Event)


{
Pm_Panel::OnEventShow(Event); // call base class

// turn myself red (for example!)

SetColor(PM_CI_NORMAL, CID_RED);
return 0;
}

In the above example, we first called the base class event handler. If you do not know
of an exact event handler for the event type you are processing, you can always call the
base class Notify function by default. Directly invoking the correct event handler of the
base class is more efficient, but not critical.

There is nothing magical about the function name OnEventShow. The Prism
developers try to use function names that indicate the type of event the function is
designed to handle, but you can use any names or convention you like for naming your
event handler functions. All that matters is the function signature matches what is
shown above.

Blue Water Embedded, Inc. Page 55


Developers Guide

5.9 User Defined Events

Aside from the pre-defined system event types described in the previous sections,
Prism also supports the application defining, sending, and handling events with custom
or application defined meanings.

User defined events are distinguished by the Event.Type field, which is above the value
of FIRST_APP_EVENT for user defined event types. User-defined events are never
caught or interpreted by the Prism framework, so the payload of these events is
completely at the discretion of the application. The exception to this is the Event.pTarget
field, which can still be used (with caution!) to direct an event to a particular object.

5.10 Event Record and Playback

Prism includes mechanisms to allow an application to record and playback input events,
effectively creating user-input macros. This is useful in creating standalone demos (no
user-interaction required), UI testing, etc. Event recorded can be saved in either XML
format (intended for use on targets with a filesystem) or C data array format (to allow
compiling the macro data directly into the application).

The macro record and macro playback code are optional and can be enabled using the
defines PRISM_MACRO_RECORDER and PRISM_MACRO_PLAYBACK, which are
produced by Prism Insight in your prism_settings.h header file when you enable these
options.

The macro record and playback feature is most commonly utilized as follows:

1) The application is built and run as a desktop executable.

2) The macro recorder is enabled, and a macro file generated to exercise


some screen flow(s) within the application.

3) The macro file is save to the host computer filesystem.

4) Moving to the target, the macro data is either compiled as a data array
within the application, or it is read from the target filesystem.

5) The macro playback function is invoked, and the target begins to self
drive without any user input.

Page 56 Blue Water Embedded, Inc.


Developers Guide

Macro Recorder:

The Macro Recorder functionality is implemented within the Pm_Event_Manager. As


events are posted to the event queue, Pm_Event_Manager saves information about
input events (mouse, touch, or keypad events) into an internal event record.

The macro recorder is started by calling Pm_Event_Manager::StartMacroRecorder. The


macro recorder is stopped by calling Pm_Event_Manager::StopMacroRecorder().

The array of recorded events is saved by calling either

Pm_Event_Manager::SaveMacroXMLFile() or

Pm_Event_Manager::SaveMacroCArray()

depending on the format of the desired output file format.

The two Save file APIs are required so that the events can be saved either as XML to
be read and played back on the target file system, or as a C array to be compiled and
linked with the target application for targets that do not have a filesystem.

Macro Playback:

Macro playback is handled by the Pm_Timer_Manager. If enabled, the timer manager


will provide API functions for reading a macro file, assigning an event array, and
starting/stopping playback. This functionality is built in to the Timer Manager so that
the application doesnt need to do anything special to use this component.

If the target has a filesystem and the macro file is in XML format, then the API
Pm_Timer_Manager::ReadMacroXmlFile() is used to read and parse the macro event
data. If the target has no filesystem and the macro data has been compiled into the
application, then the API Pm_Timer_Manager::AssignMacroEventList is used to
initialize the macro event list prior to beginning playback.

Blue Water Embedded, Inc. Page 57


Developers Guide

6 THE TIMER MANAGER

6.1 Pm_Timer_Manager

Pm_Timer_Manager is a timer service manager designed to simplify using timers in


your Prism application. Lots of user-interface events such as animations and screen
value updates tend to be time dependent, and a quick and easy to use timer facility is
helpful in creating animated and dynamic Prism applications.

Prism Timers are are not directly linked to hardware-level timer interrupts, and
should not be used for precise timing operations.

The Prism timer facility is generally driven by one operating system level timer. If there
is no operating system, some low-level timer facility must be implemented to provide a
time base into the Pm_Timer_Manager.

Time intervals are marked within Prism by calling the Pm_Timer_Manager::TimerTick


API function. For RTOS integrations provided by Blue Water Embedded, we have
already plummed in the necessary code to periodically call the TimerTick function. If
you are running standalone, you will need to incorporate a mechanism for calling the
TimerTick function.

Timers are invoked in your application software by calling the SetTimer API function.
Only Pm_Widget derived objects can create and use Prism timers, because Prism is
going to send an event to the timer owner when the timer expires. Prism notifies the
timer owner by calling the owners Notify function, therefore the timer owner must be a
Pm_Widget derived object.

Timers are started by calling the SetTimer() API function. The full prototype of this
function is:

void SetTimer(pm_int_t TimerId, pm_int_t FirstVal, pm_int_t RepeatVal)

The TimerId is any application defined timer Id value. This value is passed back to the
timer owner in the timeout event.Param data field. This allows one widget to start and
receive events from several timers simultaneously.

The FirstVal parameter specifies the intial timeout period. Note Prism timer intervals
are not absolute but are relative to the period at which the TimerTick function is called.
For most RTOS integrations and targets the TimerTick function is called at a 50ms
interval. The application software can use the #defined value PRISM_TICS_SEC as a
reference to setting timeout values in the application software.

Page 58 Blue Water Embedded, Inc.


Developers Guide

The RepeatVal parameter specifies how often the timeout should repeat after the first
timeout interval. If this value is 0, the timer will timout only once and will automatically
stop and delete itself after this first timeout interval.

Timers are stopped and deleted by calling the KillTimer(TimerId) API function. If
TimerId is non-zero, only the timer owned by the caller and having the requested Id
value will be stopped and deleted. If the TimerId value is 0, all timers owned by the
caller will be stopped and deleted.

The following is an example of using a timer in an application panel:

#define MY_TIMER_ID 1

// define the timeout event handler:

pm_event_table_entry MyPanel_Event_Table[] = {

{PM_EVENT_SHOW, PM_EVENT_HANDLER(&MyPanel::OnEventShow)},
.
.
};

// start the timer in the panel constructor. This can be done at any time,
// not just during panel construction:

MyPanel::MyPanel(.)
{

// create a timer with initial timeout of 1 second,


// and periodic timout of 500 ms thereafter:

StartTimer(MY_TIMER_ID, PRISM_TICS_SEC, PRISM_TICS_SEC / 2);


}

// and finally handle the timeout events:

pm_int_t MyPanel::OnEventTimeout(const pm_event_t &Event)


{
if (Event.Param == MY_TIMER_ID)
{
// do something here
}
else
{
return Pm_Panel::Notify(Event);
}
return 0;
}

Blue Water Embedded, Inc. Page 59


Developers Guide

7 THE RESOURCE MANAGER

7.1 Pm_Resource_Manager
The Prism Resource Manager is a fully static class that provides APIs for loading,
removing, and retrieving the various assets required by the application. These assets
might include bitmaps, fonts, color, strings, and any combination thereof.

Pm_Resource_Manager provides a default resource set during system startup. This


resource set includes a basic color scheme, strings for the pre-defined buttons such as
OK and Cancel, two pre-defined fonts, and system bitmaps for default items such as
scroll bar arrows.

Applications can define any number of additional resources, and can also replace the
default system resources. Usually resources are loaded from resource files, which can
be in source code, binary, or XML formats and any combination.
Pm_Resource_Manager provides APIs for loading resources from a file into RAM, or
optionally for loading resources in place and setting up RAM based tables pointing into
these resources located in FLASH or other non-volatile storage.

Resource files are automatically generated by Prism Insight. You have full control over
when resource files are generated and control over what is included in each resource
file. Resource files can be in Source format and/or binary formats.

Source format resource files are generated using normal C syntax and data structures.
You compile and link the source format resource files along with the remainder of your
application software. Source format resource files are the simplest to use but can
become large and cannot be installed at runtime in shipped binary units.

Binary format resource files are also produced by Prism Insight, but differ from source
format in that they are installed at runtime. Binary format resource files require either a
filesystem on the target hardware or some method for programming the binary data into
FLASH on the target system. Binary resource files are often used for runtime updates to
the system. Binary resource files can also be used when the target CPU has both
internal and external FLASH storarge. Usually code is placed in the internal storage,
while the binary resources are placed in the larger but slower external FLASH storage.

You can include any combination of source and binary format resource files in your
product. You might ship your product with one source format set of resources bound to
the application binary, but allow users to install optional binary resource files to add
languages or change color themes.

Page 60 Blue Water Embedded, Inc.


Developers Guide

7.1.1 Resource IDs


All resources are referenced by resource Id value. Resource Ids are nothing more than
indexes into the Pm_Resource_Manager tables of each resource type. Using resource
IDs in your application software insulates your software from changes in UI appearance
such as changes in colors or fonts.

Resource ID types use a simple naming convention to distinguish them and make the
Prism code easy to read. The resource Id name always prefixed with one of 4 prefixes:

CID : Color Id, such as CID_RED or CID_SHADOW

FID: Font Id, such as FID_MEDIUM_FONT

BID: Bitmap Id, such as BID_BUTTON_ICON

SID: String Id, such as SID_CONTINUE

7.1.2 Registering Resources

Resources must be installed or registered with Pm_Resource_Manager before they can


be used. This means simply the resource tables maintained by
Pm_Resource_Manager must be initialized with pointers to your graphics assets to
allow your widgets to utilize these assets.

Resources can be registered individually in a group. Usually resoures are loaded in


groups from tables that are generated by the Insight application. The API for loading a
group of resources from a table is

Pm_Resource_Manager::LoadConstResources(pm_res_table_t *pTable)

The pm_res_table_t is a structure containing pointers to arrays of each of the possible


resource types. The Prism Insight application usually produces these tables for you, but
you can also create your own.

Resources can also be loaded individually using the


Pm_Resource_Manager::AddResource() API functions. There is one AddResource API
function defined for each resource type.

7.2 Themes and Skin-ability


The final frontier for any application is the ability to let the user use themes and skins
for overall visual appearance. Prism allows the organization of your application to
Blue Water Embedded, Inc. Page 61
Developers Guide

contain multiple themes or skins. This is useful for devices that will have a large
number of screens and user profiles. Examples are Universal Remote Control device or
portable music player. Themes or skins are collections of any grouping of images,
fonts, strings and color resources. Themes can be changed at runtime, allowing you to
re-skin your application on the fly. You can compile more than one theme into your
application, or themes can be installed at runtime by loading binary or XML resource
files using a filesystem or other FLASH storage means.

Prism Insight allows you to generate resource files containing individual themes, or you
can generate a single resource file that contains multiple themes.

7.3 Retrieving Resource Pointers

You will often need to use and manipulate resources directly in your application
software. For example, you might want to obtain a pointer to a text string or a pointer to
a bitmap. APIs are provided for this purpose as the following:

Pm_Resource_Manager::GetColor(pm_uint_t ResId)

Pm_Resource_Manager::GetBitmap(pm_uint_t ResId)

Pm_Resource_Manager::GetFont(pm_uint_t ResId)

Pm_Resource_Manager::LookupString(pm_uint_t StringId)

Shorthand macros for these functions are also provide in the form of:

PBR(a) translates to Pm_Resource_Manager::GetBitmap(a)


PFR(a) translates to Pm_Resource_Manager::GetFont(a)
PCR(a) translates to Pm_Resource_Manager::GetColor(a)
PSR(a) translates to Pm_Resource_Manager::LookupString(a)

Page 62 Blue Water Embedded, Inc.


Developers Guide

8 THE PAINT ENGINE

8.1 Pm_Paint_Engine

Pm_Paint_Engine class is an abstract class which defines the functions and function
parameters available to applications and to the Prism widget and panel classes for
painting on the display device, or more accurately for painting into the frame buffer(s).

From the Pm_Paint_Engine class the base classes for each color depth and color
format are derived. These base classes provide the low-level drawing capability of a
particular paint engine for a particular color depth and format. Even if creating a new
paint engine for custom hardware, you will never need to implement the basic drawing
primitives in your software, as these primitives are already implemented in the color
depth specific base classes.

From the base class is derived the hardware-specific driver class. The driver class may
contain only hardware initialization code, or it might contain a large number of function
overrides in the case of a hardware accelerated graphics controller. Prism always
attempts to utilize all available hardware acceleration capabilities.

8.2 Pm_HiColor_Sim_Engine
The Pm_Paint_Engine derived classes always attempt to draw at the hardware specific
native color format. This ensures the least overhead and best runtime performance.
The one exception to this rule that that when running with the Pm_HiColor_Sim_Engine.
This paint engine always runs at 32-bpp internally, but converts the final output buffer to
the color format required by your hardware display device. The
Pm_HiColor_Sim_Engine allows advanced alpha-blending and fading effects even
when the final output device is a grayscale or color depth limited device.

The Pm_HiColor_Sim_Engine can be configured for any output device from 4-bpp
grayscale to 16-bit 5:6:5 color depth. Internally this driver always implements all
painting using 32-bit 8:8:8:8 color format. The final output buffer is then downsampled
to the final output color format. This downsampling step requires additional overhead,
and should only be used when the target CPU bandwidth is sufficient to allow this type
of operation.

If you are using the Pm_HiColor_Sim_Engine as your color-specific paint engine


template, you should configure Prism Insight for 32-bit color depth to insure your bitmap
and color resources are properly generated in your resource files by Prism Insight.

Blue Water Embedded, Inc. Page 63


Developers Guide

The following diagram illustrated the Pm_Paint_Engine class hierarchy and API usage:

Prism Application, Widgets, and Panels

Makes API calls to

Pm_Paint_Engine
(provides API definition and Painting entry points)

Base class for

prism_pe_base_x_bits_per_pix
(painting primitives at each color format)

Base class for

prism_pe_hardware_specific
(hardware specific init and optimization)

Directly writes to

Hardware Frame Buffer

There are many different Pm_Paint_Engine derived classes for different hardware
graphics controllers, different color depths, and different screen orientations. You will
normally include only one Pm_Paint_Engine derived driver class in your framework
build, except for special cases where multiple screen drivers are required because of
run time changes to screen orientation or graphics hardware. You will always include
the base Pm_Paint_Engine class and the color format specific template class in your
framework build.

Page 64 Blue Water Embedded, Inc.


Developers Guide

8.3 Screen Coordinates


Prism screen coordinates are always absolute pixel coordinates. Screen coordinates
are not relative to the callers position on the screen. The application making calls to
the Prism painting API functions such as Line and Rectangle will usually include the
callers screen position when calculating the coordinates to pass to these functions.

Position 0,0 is always the to-left most corner of the screen. This is true even if your
screen is rotated from its native mounting orientation. Increasing X coordinates move
from left to right across the screen. Increasing Y coordinates move from top to bottom
down the screen.

Positive Y values moving down the screen is opposite of the standard Cartesian x,y
plane; however, this convention has been used for graphical systems for many years
and it somewhat standard among graphics API systems.

8.4 Graphics Controllers

Prism provides a set of drivers for a large set of specific graphics controllers. Graphics
controllers can be internal to the die of the core CPU, or they can be external devices
communicated with over serial or parallel interface between CPU and graphics
controller/driver.

The graphics controller is responsible for generating the timing signals required by your
physical display and for refreshing the display by constantly shifting the pixel data to the
display, usually at a rate between 50 and 75 Hz. Configuring the graphics controller, no
matter how it is interfaced to the core CPU, is the job of the hardware-specific Prism
paint engine.

Graphics controllers require some physical memory for storing the pixel color data. This
memory is normally referred to as a frame buffer, i.e. a memory buffer that holds one
frame of pixel data. This memory might be part of the internal RAM of your core CPU, it
might be a portion of a large external SRAM, or it might be incorporated with an external
graphics controller that is integrated with your display (usually referred to as GRAM).

Regardless where the memory for your pixel data is located, the hardware specific
Prism paint engine is responsible for getting your pixel color values stored into this
frame buffer or buffers. Exactly how this data gets written into your frame buffer is
dependent on your hardware architecture and your Prism paint engine configuration.
We refer to this data channel as the Graphics Data Pipeline.

Blue Water Embedded, Inc. Page 65


Developers Guide

8.5 The Graphics Data Pipeline

When you paint lines, text, and bitmaps within Prism, this painting is usually NOT done
directly to the visible frame buffer, for a variety of reasons including the following:

1) For systems utilizing an external graphics controller which provides the frame
buffer memory, access to this memory is usually not random access or fast, but
instead requires registers on the external controller be written to specify the
memory address, following by reads or writes to another register to actually
reads or write data.

2) Modifying the visible frame buffer data while that buffer is being shifted to the
display can cause artifacts and tearing. Buffer updates are normally
synchronized with the LCD V-Sync vertical retrace signal.

3) Advanced canvas blending techniques such as screen fades require an


intermediate or composite buffer be created which is the sum of the background
and overlay canvases.

For these reasons the Prism paint engine classes support different models for defining
how the graphical information your application paints ends up in the visible frame buffer.
These different models are defined by a set of configuration options in the Insight
settings screens which generate a corresponding set of configuration flags in the
prism_settings.h header file. The following sections and diagrams are helpful in
understanding the Prism Graphics Data Pipeline models.

8.5.1 Double Buffering

Nearly all Prism paint engines support the concept of double-buffering. Double-
buffering means that at least two hardware frame buffers are maintained, and Prism
ping-pongs between the two buffers during each paint operation.

Double buffering requires that Prism maintain one visible buffer and one working
buffer. The visible buffer is being shifted to the display by the LCD controller
hardware. The working buffer is the buffer into which you are painting. When you
conclude a painting operation, Prism swaps the two buffers.

After the buffer swap, Prism must synchronize the two buffers to insure that graphics
integrity is maintained. Prism keeps track of the region with the working buffer that has
been modified, and copies this region to the new working buffer immediately after the
ping-pong swap operation.

Page 66 Blue Water Embedded, Inc.


Developers Guide

Hardware support for double-buffering is becoming more common; however, the real
key to fast double-buffering is having a DMA or 2D bit-blit engine accelerator to optimize
the buffer synchronization operation.

8.5.2 Multiple Canvases


When running in 16-bit color depth or higher, Prism supports the concept of multiple
drawing canvases and creating a final composite canvas in the output display buffer. In
this case, all paint operations always occur to an off-screen memory canvas. There can
be any number of memory canvases in play at one time. When a paint operation is
concluded, the composite canvas is recreated by first updating the background canvas,
then overlaying each of the managed software canvases.

Multiple software canvas support is required for screen fade transitions, but otherwise is
not required. Be aware this option can consume copious amounts of dynamic memory
if the additional canvases are large.

Multiple hardware canvases can also be supported. Multiple hardware canvases


means the target hardware supports more than one simultaneous frame buffer, and
these frame buffers may be displayed on different display screen or they may be
overlayed in hardware, with or without alpha blending, to create the final graphics
display.

8.5.3 Graphics Pipeline Diagrams


Model 1: No local buffer, all painting is done directly to remote GRAM:

In the diagram above, the Prism paint engine does NOT utilize any local frame buffer.
In this case, all painting functions are implemented to directly write to an external
display controller. This type of implementation is usually not preferred; however, it can
be the only solution for systems that do not have enough local memory available to hold
a frame buffer. Examples which utilize this type of architecture include certain ARM-

Blue Water Embedded, Inc. Page 67


Developers Guide

CortexM3 devices without external RAM, along with certain PIC type devices that
likewise have no memory bank large enough to hold a graphics frame buffer.

In this case, the Prism paint engine is organized such that all paint operations are
immediately rendered directly in the external GRAM (Graphics RAM) present on an
external controller/driver. Examples of these types of external controller include several
made by ILITEK, Himax, Solomon Systech, and Renesas.

Note, if the bus between the core CPU and external controller is a serial bus such as an
SPI interface, this archicture can experience performance bottlenecks.

Model 2: Single local frame buffer, no double buffering, single canvas:

The diagram above represents one of the simplest pipelines supported. In this case
there is one local frame buffer, and this frame buffer is directly driven to the display.
This model is avoided when possible to prevent tearing, unless the display image is
very static or all painting can be done with the vertical retrace period. This requires the
paint engine force synchronization with the Vertical Sync signal.

Model 3: Single local frame buffer, external controller with embedded GRAM:

The diagram above represents a common hardware / software architecture. A single


frame buffer is constructed into which Prism paints. When a sequence of painting
operations has completed, Prism transfers the modified portion of the local frame buffer
to the external GRAM.

This model requires more memory than model 1, to hold a local frame buffer. However,
the advantage is that for 16-bpp and higher color depths, Prism can support full alpha-

Page 68 Blue Water Embedded, Inc.


Developers Guide

blending, panel fades, and true anti-aliased text because the local frame buffer is fast
random access memory. This model also allows Prism to update the external GRAM
quickly in one window-mode transfer to the external controller. Prism always keeps
track of the invalid region of the local frame buffer, and therefore only this invalid region
is transferred after each screen update.

Model 4: Double buffering using local frame buffers

The diagram above illustrates another very common graphics pipeline model. In this
model, multiple graphics frame buffers are created in random-access memory that are
directly accessible to the core CPU. With each screen update, the working and
display buffers are toggled in a ping-pong fashion. This eliminates visual tearing of the
display, and on many hardware devices this double-buffering mechanism is hardware
accelerated.

This is a very common graphics pipeline model, and utilized on a broad range of
devices running at a large number of color depths and formats.

Model 5: Multiple software canvases with double-buffering:

Blue Water Embedded, Inc. Page 69


Developers Guide

The model above illustrates a Prism paint engine supporting multiple managed software
paint canvases. In this model, Prism create a composite of the background and overlay
canvases, and ping-pongs the composite display buffer in a mannor identical to the
direct double-buffering model.

Model 5 adds the ability to do screen fades and rapid screen transition animations to
your Prism application. This model uses much more memory than the simpler models,
but this is the price of more sophisticated graphical animations.

Model 6: Multiple software canvases, single buffering, external GRAM:

The model shown above is also a common implementation for systems utilizing an LCD
with integration GRAM, but requiring the sophisticated features such as screen
transitions and alpha blending. Note, this model is not much different than model 5,

Page 70 Blue Water Embedded, Inc.


Developers Guide

other than the GRAM is usually not local random-access memory but is instead external
memory that requires a specific protocol to modify.

8.6 Writing your own Hardware Specific Driver Class

The individual template drivers are described below.

prism_pe_base_1bpp (.cpp, .hpp)

This is the paint engine for monochrome operation. You should derive your hardware-
specific engine from this class if you are going to write a custom monochrome painting
driver.

prism_pe_base_4bpp (.cpp, .hpp)

These modules implement a 4 bit-per-pixel, 16 color or grayscale paint engine base. If


your target system uses 4-bit grayscale or color format, you should create your custom
driver by deriving it from this base class.

prism_pe_base_8bpp (.cpp, .hpp)

These modules implement a 256 color paint engine base. Both 3:3:2 RGB packed pixel
format and and 8-bit palette mode operation are supported by this base class.

prism_pe_base_16bpp (.cpp, .hpp)

This is the base class for 16 bit (65K Color) operation. Both 5:6:5 and 5:5:5 color
formats, in both RGB and BGR color order are supported by this base class.

prism_pe_base_24bpp (.cpp, .hpp)

This is the base class for 24-bit 8:8:8 operation. This class supports both RGB and BGR
color order.

prism_pe_base_32bpp (.cpp, .hpp)

This is the base class for 32-bit operation which is alpha-red-green-blue or blue-green-
red-alpha.

Blue Water Embedded, Inc. Page 71


Developers Guide

9 RUNNING ON YOUR DESKTOP

9.1 DESKTOP SIMULATION

Prism provides a set of paint engines and operating system integration files which
enable you to build and run your Prism application as a Microsoft Windows desktop
application or as a Linux/X11 desktop application.

We call this the Desktop Simulation Environment since you are not running Prism on
your intended target (although in some case Windows or X11 may be your final target!).

The Desktop Simulation Environment is as pixel accurate as possible, since Prism does
not utilize the underlying operating system drawing APIs to render graphics. Prism
utilizes its own painting APIs to render all graphics and text, even when running on the
desktop. This ensures your user-interface will look and function exactly the same on
your desktop and on your final target.

9.2 Paint Engines for Desktop Operation

For the Microsoft Windows environment, Prism provides the following paint engines to
allow you to run at the required color depth and format within a Windows window. Note
in some cases Microsoft does not support the required color format, in which case
Prism converts the Prism frame buffer data format into the next higher color format
which is supported by Microsoft. This does not affect the colors of your user interface in
any significant way, but does add a small amount of overhead when running on the
desktop. The performance of most desktop CPUs more than compensates for this.

prism_pe_windows_1bpp
prism_pe_windows_2bpp
prism_pe_windows_4bpp
prism_pe_windows_8bpp
prism_pe_windows_16bpp
prism_pe_windows_24bpp
prism_pe_windows_32bpp

For the Linux/X11 environment, the following desktop paint engines are provided:

prism_pe_x11_16bpp.cpp
prism_pe_x11_24bpp.cpp

Page 72 Blue Water Embedded, Inc.


Developers Guide

9.3 Operating System Integration files for Desktop Operation


To build and run with the MS Windows operating system, you should include the file
prism_for_win32.cpp in your Prism framework build. This file is found in the
\prism\source\rtos sub-directory.

To build and run with the Linux operating system, you should include the file
prism_for_x11.cpp in your Prism library build. This file is found in the \prism\source\rtos
sub-directory.

9.4 Screen Size

Its nearly impossible for Prism to correct for differences in pixel size between your
desktop environment and your target system. If pixels are packed more tightly on your
desktop because you are using a very high screen resolution, your Prism screens will
appear smaller on your desktop than they will be on your target. One way to
compensate for this is to run your desktop at a lower x,y resolution.

For the Windows desktop, Microsoft compilers version 8 (Visual Studio 2005), version 9
(Visual Studio 2008) and version 10 (Visual Studio 2010) are supported. For Linux
desktop the GNU toolchain is supported.

Blue Water Embedded, Inc. Page 73


Developers Guide

10 The Pm_Framework Class


The Prism Runtime Framework maintained by the Pm_Framework class. Static
member functions of this class grant access to the public APIs of the individual
framework components. The Pm_Framework class provides the following accessors
and helper functions:

static Pm_Screen_Manager *ScreenManager(void)

This static function returns a pointer to the active Pm_Screen_Manager instance. Any
thread can access the Pm_Screen_Manager at any time, even non-UI threads. The
following function returns the ID value of the top-most panel currently displayed:

pm_int_t GetTopPanelId(void)
{
Pm_Screen_Manager *ps = Pm_Framework::ScreenManager();

Pm_Widget *pTop = ps->First();

if (pTop)
{
return pTop->GetId();
}
return 0;
}

static Pm_Event_Manager *EventManager(void)

This static function returns a pointer to the applications instance of


Pm_Event_Manager. You will need to use this function in order to post events to other
panels or objects that are part of the application, and to make use of PrismTimer
facilities. The following example function demonstrates obtaining a pointer to the
Pm_Event_Manager instance and pushing a user-defined event into the Prism event
queue:

void SendPrismEvent(uint16_t EventType)


{
pm_event_t NewEvent(EventType);

Pm_Event_Manager *pEvntMgr = Pm_Widget::EventManager();


pEvntMgr->PostTail(NewEvent);
}

Page 74 Blue Water Embedded, Inc.


Developers Guide

10.1 APIs for Painting

Pm_Framework provides a set of helper APIs are to simplify paint operations. Painting
is done by the Pm_Paint_Engine instance, however these wrapper functions allow the
application software to simple call Line and PaintText without concern for the active
canvas or Paint Engine instance. This is not an exhaustive list, but a list of the most
commonly used painting API functions.

pm_bool_t OpenCanvas(const Pm_Region &Invalid)

Calls the Pm_Paint_Engine::OpenCanvas function passing the current object and


current objects default paint canvas. This function must be called before any painting
API functions to prepare the canvas for painting. The caller will not be allowed to paint
outside the region described by the parameter Invalid. Attemps to paint when a Canvas
has not been opened are ignored.

void CloseCanvas(void)

Terminates a painting operation. Note, calls to the OpenCanvas and CloseCanvas


functions can become nested (when a Parent widget invokes the Paint functions of its
children), and the Pm_Paint_Engine keeps track of this nesting to recognize when the
final CloseCanvas call is executed. When the canvas is closed, the canvas is flushed to
the frame buffer for managed canvases.

void Line(pm_int_t XStart, pm_int_t YStart, pm_int_t XEnd,


pm_int_t YEnd, PrismBrush &Brush)

This is a wrapper function for Pm_Paint_Engine::Line. This function locates the active
paint engine for the callers default canvas.

void Rectangle(const Pm_Region &Size, PrismBrush &Brush)

This is a wrapper function for Pm_Paint_Engine::Rectangle. This function locates the


active paint engine for the callers default canvas.

void Bitmap(PrismPoint Where, pm_bitmap_t *Getmap)


void Bitmap(PrismPoint Where, pm_uint_t BID)

These are a wrapper functions for Pm_Paint_Engine::Bitmap API functions. These


functions locate the active paint engine for the callers default canvas. The first version
accepts a pointer to a bitmap, the second version accepts a Bitmap ID.

Blue Water Embedded, Inc. Page 75


Developers Guide

void BitmapFill(Pm_Region Rect, pm_bitmap_t *Getmap)

This is a wrapper function for Pm_Paint_Engine::BitmapFill. This function locates the


active paint engine for the callers default canvas.

void PaintText(PrismPoint Where, const Pm_char_t *Text,


PrismBrush &Brush, pm_int_t Count = -1)

This is a wrapper function for the Pm_Paint_Engine::PaintText API function. This


function locates the active paint engine for the callers default canvas.

pm_int_t TextHeight(pm_font_t *Font)


pm_int_t TextHeight(pm_uint_t FontId)

These are wrapper functions for the Pm_Paint_Engine::TextHeight API functions.


These functions locate the active paint engine for the callers default canvas. The first
version accepts a pointer to a font; the second version accepts a font Id.

pm_int_t TextWidth(const char *Text, pm_font_t *Font)


pm_int_t TextWidth(const char *Text, pm_uint_t FontId)

These are wrapper functions for the Pm_Paint_Engine::TextWidth API functions. These
functions locate the active paint engine for the callers default canvas. The first version
accepts a pointer to a font; the second version accepts a font Id.

Page 76 Blue Water Embedded, Inc.


Developers Guide

11 ALL ABOUT WIDGETS

11.1 Using Pm_Widget

Pm_Widget is the base class from which all viewable Prism widgets are derived. The
Prism widget classes such as Pm_Button or Pm_Prompt provide custom Paint function
to tailor their appearance, and may provide custom event handler to tailor their
operation, but the core functionality of all widgets is defined by the Pm_Widget base
class and its member functions.

To really get the most out of Prism, you will need to learn the Pm_Widget public API
functions and feel comfortable overriding those functions to create your own custom
widgets. The Prism widget classes are in many ways designed to be rather simple, with
the goal being to keep the framework code size to a minimum and make it very easy for
you to derive your own custom classes from the Prism base implementations. This
allows you to extend the Prism framework easily and efficiently to produce a user-
interface that sets your product apart from all others.

The following sections will describe in detail the public functions and data members of
Pm_Widget. With this information, you will gain a clear understanding of how Prism
works.

11.2 Pm_Widget Overview


Pm_Widget contains a few critical member variables and API functions that are central
to the overall function of the Prism graphical presentation. Pm_Widget declares two
virtual member functions (among many others) that are utilized by the Framework
classes to cause Pm_Widget derived classes to paint themselves and process events.

The Pm_Widget::Paint(const Pm_Region &Invalid) function is called by


Pm_Screen_Manager whenever any visible object needs to repaint itself. This could be
done when the object is initially displayed, or because the object has just been brought
to the front, or because the some property of the object such as color or font has been
modified.

Pm_Screen_Manager keeps track of invalidated objects, and calls the objects Paint
member functions to refresh those invalid objects on the visible canvas. If you want to
customize the appearance of a widget beyond what can be accomplished with style
flags and colors and fonts, you will need to derive a custom class and override the Paint
member function. This gives you complete control of the objects appearance.

Blue Water Embedded, Inc. Page 77


Developers Guide

The Pm_Widget::Notify(const pm_event_t &Event) function is called by


Pm_Screen_Manager to pass an event received from the Pm_Event_Manager off to a
widget or panel for processing.

The Notify function for most classes simply processes the class event table, and if no
match is found passes the event to the base class. If you want to catch events, you
simply need to define your own event table for use by your class.

Pm_Widget also provides members and functions for linking widgets together, making
one widget the parent of another. This is how the tree-structured list of widgets that is
central to the organization of the Prism display is constructed. Pm_Widget always
keeps child objects linked in their Z-order, meaning the first object in the child linked-list
is always on top of any other sibling child objects, and the last child object in the linked
list of child object is always on the bottom. Even if child objects do not visually overlap,
this logical Z-ordering still occurs.

Pm_Widget provides a common set of style flags, status flags, and member variables
needed by all visible widget and panel types. These include, for example, a member
variable named mSize which determines an objects position and size on the canvas, as
well as the actual canvas Id to which this widget is painted.

Pm_Widget also maintains a small color table which is inherited by all widget classes.
Some classes extend this color table to support additional color values, but this base set
is common to all widgets.

11.3 Pm_Widget Members

This section focuses on the key API functions of the Pm_Widget class, explains their
purpose and function, and includes many code examples to demonstrate their use. For
a complete listing of the Pm_Widget API functions refer to the Prism API reference
manual.

Pm_Widget(const Pm_Region &Size, uint16_t Id = 0, uint32_t Style


= PM_BORDER_NONE)

Pm_Widget(uint16_t wId = 0, uint32_t Style = PM_BORDER_NONE)

These are the constructors for Pm_Widget. The Size parameter specifies the initial
region or position and size of the widget. The Id parameter is used by controls such as
buttons and sliders to report events back to their parent. The style parameter defines a
set of basic appearance attributes such as border style (thin, thick, raised),
transparency, and whether the widget is enabled or accepts user input.
Page 78 Blue Water Embedded, Inc.
Developers Guide

The second constructor differs from the first only in that the Size paramenter is not
required. In this case, the widget creates itself with a default size, and the application
should then call the Resize function to assign the widgets position and size before the
widget is displayed. This version is used if the widget size or position is not known at
the time of construction.

virtual pm_int_t Notify(const pm_event_t &Event)

This function is called by Pm_Screen_Manager to pass an event to a particular widget.


The default implementation of the Notify function is to traverse the objects Event Table
as described in the Pm_Event_Manager chapter. Custom widgets sometimes override
the Notify function to add additional logic before or after the Event Table lookup, or
might even eliminate the event table lookup entirely.

virtual void Paint(const Pm_Region &Invalid)

The Paint function is the function invoked by Pm_Screen_Manager to tell an object to


repaint itself. The Paint function is called when an object is invalid. Invalidations
happen automatically when an object is initially displayed or its properties are changed.

The Paint function is the most commonly overridden function when creating custom
widget classes. Overriding the Paint function is how you accomplish creating custom
widgets with your own required appearance.

The Invalid parameter passed to the paint function informs the widget of the screen area
that needs to be refreshed. This screen area will most often be as large or larger than
the widget or panel being painted, but in some cases the invalid region may not
encompass the entire widget. In those cases, the widget can optionally paint just that
area which overlaps the Invalid parameter.

Most often widgets ignore the Invalid parameter and simply pass this to the Paint
Engine OpenCanvas() API. This allows the Paint engine to limit your painting to the
invalid area, and your Paint function can simply refresh the entire widget every time the
Paint function is called. The paint engine will trim your paint operations to the invalid
area.

An example of a custom widget which overrides the Paint function is provided at the end
of this manual.

Blue Water Embedded, Inc. Page 79


Developers Guide

void Link(Pm_Widget *pWho, pm_bool_t DoShow = TRUE)


void LinkTail(Pm_Widget *pWho, pm_bool_t DoShow = TRUE)

These functions are used to add one object to another, by linking the object pWho to the
caller this. You can also link objects to each other by explicitly passing the caller, and
in:

Pm_Framework::ScreenManager()->Link(pWho);

The Link function makes pWho a child of the object being linked to, which becomes the
parent of pWho. Once an object has been linked to its parent, the parent object owns
the child. Deleting the parent object automatically deletes the child, and moving the
parent object automatically moves the child, and so on. When you Link a child object to
a visible window, that object becomes visible unless the DoShow parameter is set to
False.

The Link function always places the linked object at the front or of the Z-order of the
parents list of child objects. Re-Linking an object that is already a child of the parent
simply moves the object to the front of the child list, which places the object in front of
its siblings on the screen.

The LinkTail function shares all of the properties of the Link function, except the linked
object is linked at the back, or at the tail end of the parents child object list. The LinkTail
function is often used when adding elements to a Pm_List derived parent, to insure that
the elements maintain the same order in the parent list in which they were added to the
list.

Any type of object can be linked to any other, and this nesting can continue ad-infinitum
within the limits of your target system memory. For example a top-level panel might be
constructed, and to this panel you might link several child panels. Within those child
panels, you might link several different types of child buttons. Finally you might link the
top level panel to the screen manager. This is the common sequence in which complex
panels and screens are constructed.

Pm_Widget *Unlink(Pm_Widget *pWho)

The Unlink function serves the opposite purpose of Link. An object can be unlinked
from its parent at any time, in which case ownership of the object returns to the
application. The application may later Destroy the object, it it may re-link the object to
the same parent or even to a differing parent.

A single object should never be simultaneously linked to multiple parents! This could
cause the object to be doubly-deleted, if both parent objects are destroyed.

Page 80 Blue Water Embedded, Inc.


Developers Guide

The Unlink function causes a PM_EVENT_HIDE event to be sent to pWho, and to all of
the children of pWho, assuming pWho was linked to a visible parent.

void Destroy(Pm_Widget *pWho)

The Destroy function is used to Unlink and delete and object. Destroy is designed to be
a failsafe object cleanup function, and it is recommended that applications structured to
create panels when needed and delete panels when those panels are not required
always use the Destroy function to destroy panels and child widgets.

In addition to Unlinking and deleting pWho, the Destroy function performs the following
tasks:

- Kills any timers owned by the object or any children of the object.

- Purges the event queue of any events bound for pWho or any of pWhos
children.

- Checks for self-deletion, and insures this does not occur by requesting that
Pm_Screen_Manager destroys the object. Therefore, Destroy(this) is perfectly
safe and even expected in normal Prism applications.

- Insures that pWho and none of the children of pWho have captured input
device(s), and if so frees those input device(s).

void AddStyle(uint32_t Style)

This function is used to add style flags to an object. The available style flags are
documented in the API reference manual. Many style flags are specific to certain object
types, while others are supported by all object types.

Objects do not automatically invalidate themselves based on a change to the Style


flags. To force a visible object to re-paint after a change to the style flags, you must
Invalidate the object. The following example changes the style of an object and
Invalidates the object to force the object to repaint:

void EnableButton(Pm_Text_Btn *pb)


{
pb->AddStyle(PM_ACTIVE);
pb->Invalidate();
}

Blue Water Embedded, Inc. Page 81


Developers Guide

The Style flags supported by each object type are documented in the API reference
manual.

void RemoveStyle(uint32_t Mask)

This function removes the style flags contained in the Mask parameter from the objects
internal Style variable. Objects do not automatically invalidate themselves based on a
change to the Style flags.

void DisableButton(Pm_Text_Btn *pb)


{
pb->RemoveStyle(PM_ACTIVE);
pb->Invalidate();
}

uint32_t GetStyle(void)

This function returns the current style flags for an object.

void SetEventMask(uint16_t SendMask)

This function is used to modify which Child Event Notifications a widget should send to
its parent.

All widgets have a default set of event notifications that they enable and this is
documented in the Prism API reference manual. Prism widgets do not by default
enable all possible event notifications in order to reduce the number of events being
generated and processed by the Prism Event Mmanager. The SetEventMask function
is provided to allow you to enable or disable particular events from your child widgets.

pWidget->SetEventMask(pWidget->GetEventMask() |
EVENTMASK(PM_EVENT_FOCUS_LOST));

The following table lists the available event masks with a brief description of each:

Comments Default

PM_EVENT_SIZED Sent when any widget is moved or resized Disabled


PM_EVENT_FOCUS Sent when any widget gains input focus Disabled
PM_EVENT_FOCUS_LOST Sent when any widget loses input focus Disabled
PM_EVENT_CLICK Sent when any widget receives mouse or touch screen Enabled
pen down event
PM_EVENT_RCLICK Sent when any widget recieves mouse or touch screen Disabled
alternate pen down event

Page 82 Blue Water Embedded, Inc.


Developers Guide

PM_EVENT_TXT_SELECT Sent by text input widgets when the user selects a Disabled
block of text
PM_EVENT_TXT_EDIT Sent by text input widgets when the user modifies the Disabled
text input widget text value in any way
PM_EVENT_TXT_EDITDONE Sent when the user completes text modifications Enabled
(object loses focus or CR input key is received)

PM_EVENT_PAN_DONE Pm_Animated_Prompt sends this event when a Enabled


panning cycle is comleted.

PM_EVENT_TOGGLE_ON Pm_Toggle_Btn derived widgets send this event Enabled


PM_EVENT_TOGGLE_OFF Pm_Toggle_Btn derived widgets send this event Enabled
PM_EVENT_CHECK Pm_Exclusive_Btn derived widgets send this event Enabled
PM_EVENT_UNCHECK Pm_Exclusive_Btn derived widgets send this event Enabled

PM_EVENT_SPIN_UP Pm_Spin_Btn sends this event Enabled


PM_EVENT_SPIN_DOWN Pm_Spin_Btn sends this event Enabled

PM_EVENT_PAGE_SELECT Pm_Tab_Panel sends this event Enabled

PM_EVENT_NODE_SELECT Pm_Tree_View sends this event Enabled


PM_EVENT_NODE_DELETE Pm_Tree_View sends this event Enabled
PM_EVENT_NODE_OPEN Pm_Tree_View sends this event Disabled
PM_EVENT_NODE_CLOSE Pm_Tree_View sends this event Disabled
PM_EVENT_NODE_ALT_SEL Pm_Tree_View sends this event Enabled

PM_EVENT_LIST_SELECT Pm_List derived objects send this event Enabled

void Invalidate(const Pm_Region &Size)


void Invalidate(void)

These functions instruct the Pm_Screen_Manager to record that the caller is visually
invalid and needs to repaint. The first version passes the region defining the exact
invalid area, while the second version invalidates the entire mSize region of the caller.

Note that painting is not directly invoked by this function call. This function simply
creates a record of an invalidation. Later, when the Pm_Event_Manager finds the event
queue for this task is empty, the Pm_Screen_Manager will optimize the list of invalid
entries and invoke the necessary Paint functions to refresh the screen.

Blue Water Embedded, Inc. Page 83


Developers Guide

12 PROGRAMMING EXAMPLES
This chapter demonstrates several common programming tasks in order to illustrate the
use of the Pm_Widget class member functions. Remember all displayable Prism panel
and widget classes are derived at some point from class Pm_Widget, and therefore
these operations can be performed from within any member function of a derived class.

12.1 Determining the position of an object

One of the most basic properties of all Prism objects is the objects position on the
screen. Pm_Widget maintains this information, along with clipping and Z-ordering
information to insure that objects are only allowed to paint to the areas of the screen
that are owned by the object. An objects position is held in the Pm_Widget member
variable mSize, which is a value of type Pm_Region. You can always determine where
an object is at any time by examining the objects mSize data member. Pm_Widget
also maintains a separate but related member called mClient, which is an additional
Pm_Region member that indicates the client rectangle of the object. The mSize and
mClient variables can be equal for a borderless widget.

For example, by using the mSize variables and the Pm_Region::Overlap function, we
can easily determine if two objects overlap using the following code segment:

pm_bool_t MyPanel::CheckForOverlap(Pm_Widget *p1, Pm_Widget *p2)


{
if (p1->mSize.Overlap(p2->mSize))
{
return TRUE;
}
return FALSE;
}

12.2 Creating and displaying Panels and Widgets

The Pm_Widget member function Link() is used to attach one object to another. When
one object is linked to another, it becomes a child of the object is has been linked to.

When an object is linked to a visible parent, the object and all of its child objects
become visible (unless you explicitly prevent this). The Pm_Widget::Link(Pm_Widget
*pWhat, pm_bool_t Show) function links one object to another. The default value of the
Show parameter is TRUE, meaning when an object is linked to a visible parent, that
object also becomes visible.

Page 84 Blue Water Embedded, Inc.


Developers Guide

The following function creates a Pm_Panel, adds a Pm_Button to the panel, then
displays the panel by linking the panel to Pm_Screen_Manager:

void DisplayPanel(void)
{
Pm_Region Size;
Size.Set(0, 0, 239, 319);

Pm_Panel *pPanel = new Pm_Panel(Size, PM_BORDER_NONE);


pPanel->SetColor(PM_CI_NORMAL, CID_BLUE);

Size.Set(0, 0, 100, 100);


Pm_Text_Btn *pBtn = new Pm_Text_Btn(Size);

pPanel->Center(pBtn);
pPanel->Link(pBtn);

Pm_Screen_Manager *pScreen = Pm_Framework::ScreenManager();


pScreen->Center(pPanel);
pScreen->Link(pPanel);
}

The above example assumes the function is not a member of a Pm_Widget derived
class. If the example above is a member function of a Pm_Widget derived class, the
Pm_Framework:: scope resolution operator can be eliminated.

12.3 Unlinking and Destroying Objects


The Pm_Widget member function Unlink() is used to detach an object from the objects
parent. The Pm_Widget member function Destroy() is similar to Unlink(), although
Destroy() both unlinks the object and deletes the object from memory.

The Pm_Widget member function Parent() returns a pointer to the parent of the current
object. The returned pointer is also a pointer to a Pm_Widget. If the object has no
parent (i.e. the object has not been Linked to another object), the Parent() function will
return a NULL pointer.

It is acceptable, given enough dynamic memory is available, to create all of your user
interface panels during system startup and never delete them. In that case, the
application would create an array of pointers to the Pm_Panels that compose the user
interface, and the Unlink function would always be used to remove panels from the
display rather than the Destroy function. This is a common method for implementing
applications on failsafe secure devices to eliminate the runtime memory allocations
needed if panels are created and deleted as they are needed.

Blue Water Embedded, Inc. Page 85


Developers Guide

When any widget is linked to another, the widget is in effect owned by the parent
widget. Destroying the parent widget deletes all children of that parent as well as the
parent. If you unlink a widget or panel from its parent, you are responsible for the
widget from that point forward. You might at a later time link the widget once again to
some parent object, or you might destroy the widget. The important thing to remember
is that once you Unlink a widget from its parent, the Prism framework no longer has any
information about the widget and it is the responsibility of the application software to
track the widget at that point to prevent memory leaks.

12.4 Finding an objects children


The first child of any object can be found using the function First(). This returns a
pointer to the head of a linked-list of child objects. The linked list can be traversed using
the Next() function.

For example, an object could count the number of siblings (i.e. objects with the same
parent) it has using the following code sequence:

pm_int_t CountChildren(Pm_Widget *Parent)


{
pm_int_t Count = 0;
Pm_Widget *pChild = pParent->First();

while(pChild != NULL)
{
Count++;
pChild = pChild->Next();
}
return Count;
}

12.5 Reserved Widget Ids


A few object ID values are reserved by Prism for proper operation of dialog boxes and
event panels. Therefore you should always begin your private control enumeration with
a value of 1, so as not to overlap the reserved ID values, which are at the very top of the
valid ID range. The reserved object Ids are:

Page 86 Blue Water Embedded, Inc.


Developers Guide

enum PrismButtonIds {
PM_BTN_ID_OK = 1000,
PM_BTN_ID_APPLY,
PM_BTN_ID_YES,
PM_BTN_ID_NO,
PM_BTN_ID_CANCEL,
PM_BTN_ID_RETRY,
PM_BTN_ID_ABORT,
PM_BTN_ID_CLOSE
};

Buttons with the Ids listed above are automatically recognized by Pm_Panel derived
classes.

12.6 Using Widget Ids to identify panels and widgets


Object ID values can be used to identify an object. When an object sends a notification
event to a parent panel, the object ID is contained in the Param member of the
notification event.

At any time you can locate a child object using the objects ID with the Find() function.
Find will search the child list of the current object for an object with an ID value
matching the passed in value.

Object IDs can also useful for locating top-level panels. It is often the case one panel
needs to locate another panel, or some portion of the business logic wants to send a
user-defined message to a particular panel.

The following demonstrates finding a top-level panel based on the Panel Id, and
sending a user-defined message to the panel:

pm_bool_t SendEventToPanel(uint16_t PanelId, uint16_t EvenType)


{
pm_event_t NewEvent(EventType);

Pm_Widget *pPanel = Pm_Framework::ScreenManager()->Find(PanelId,


FALSE);

if(pPanel != NULL)
{
NewEvent.pTarget = pPanel;
Pm_Framework::EventManager()->PostTail(NewEvent);
return TRUE;
}
return FALSE;
}

Blue Water Embedded, Inc. Page 87


Developers Guide

12.7 Using Event Tables


To produce easy to read and robust code, the Prism library classes and the Prism
Insight application use Event Tables to simplify the task of catching events and acting
on them.

Event Tables are arrays of type pm_event_table_entry structures. The


pm_event_table_entry structure looks like this:

typedef struct {
uint32_t EventType;
pm_int_t (Pm_Widget::*Handler) (const pm_event_t &Event);
} pm_event_table_entry;

The EventType member is the Event.Type field you want to catch, and the Handler is
the address of the function that should be called when the event arrives. If we repeat
the previous example, the Event Table for the MainMenu class now looks like this:

pm_event_table_entry MainMenu_Events[] = {
{PM_EVENT_SHOW, PM_EVENT_HANDLER(&MainMenu::OnEventShow)},
{PM_CEN(BTN_ID_MENU1, PM_EVENT_CLICKED),
PM_EVENT_HANDLER(&MainMenu::OnEventMenu1Clicked)},
{PM_CEN(BTN_ID_MENU2, PM_EVENT_CLICKED),
PM_EVENT_HANDLER(&MainMenu::OnEventMenu2Clicked)},
{PM_CEN(BTN_ID_MENU3, PM_EVENT_CLICKED),
PM_EVENT_HANDLER(&MainMenu::OnEventMenu3Clicked)},

{0, NULL} // terminator


}

And the event handling functions look like this:

Page 88 Blue Water Embedded, Inc.


Developers Guide

pm_int_t MainMenu::OnEventShow(const pm_event_t &Event)


{
Pm_Panel::OnEventShow(Event);
SetColor(PCI_NORMAL, CID_BLUE);
return 0;
}

pm_int_t MainMenu::OnEventMenu1Clicked(const pm_event_t &Event)


{
Destroy(this);
GotoSubMenu(1);
return 0;
}

pm_int_t MainMenu::OnEventMenu2Clicked(const pm_event_t &Event)


{
Destroy(this);
GotoSubMenu(2);
return 0;
}

pm_int_t MainMenu::OnEventMenu3Clicked(const pm_event_t &Event)


{
Destroy(this);
GotoSubMenu(3);
return 0;
}

Observe the functions above are very short and easy to read. This is a dramatic
improvement in code style as compared to the long switch-case statement that often
results from not using Event Tables.

Finally, the Notify function when using Event Tables will look similar to this:

Blue Water Embedded, Inc. Page 89


Developers Guide

pm_int_t MainMenu::Notify(const pm_event_t &Event)


{
pm_event_table_entry *pEventList = Pm_Btn_Events;

while(pEventList->EventType)
{
if (pEventList->EventType == Event.Type)
{
if (pEventList->Handler == NULL)
{
return 0;
}
return PM_CALL_EVENT_HANDLER(*this, pEventList->Handler)(Event);
}
pEventList++;
}
return Pm_Panel::Notify(Event);
}

Note, Prism Insight automatically produces the Notify function and the Event Table for
you. All you need to do is create your child widgets and assign IDs to them, and Insight
will do the rest. This above information is provided so that you can understand exactly
what is occurring under the hood of your Event Tables and Event Handler functions.

12.8 Overriding the Paint() function

Prism provides for a high degree of customization in the appearance of each type of
panel and widget that compose your user interface via style flags, bitmap assignment,
color assignment, and font assignment. You can extend these capabilities further by
deriving your own widget types from the classes provided within the Prism framework.

In order to customize the appearance of a custom widget, you will generally need to
override the Paint() function. When you override this function in your custom widget
types, you now have full control over how and what the widget paints on the canvas
when the widget is visible.

The formal prototype of the Paint function is:

void Pm_Widget::Paint(const Pm_Region &Invalid)

The incoming Invalid parameter informs you of exactly what part of the panel or widget
needs to be repainted. You can generally just pass this parameter to the OpenCanvas
call that will begin your Paint function, but you can also use this parameter to determine
what needs to be repainted if your Paint function is very long or complex.

In the following example, we will create a new button class derived from Pm_Btn. This
class will override the Paint function to change the button color each time the button is

Page 90 Blue Water Embedded, Inc.


Developers Guide

pressed, and also display a counter value (0 9) that will increment each time the
button is clicked.

The class declaration will look like this:

class MyButton : public Pm_Btn


{
public:
MyButton(const Pm_Region &Size)
virtual pm_int_t Notify(const pm_event_t &Event);
virtual void Paint(const Pm_Region &Invalid);

private:

pm_int_t mClickCount;
};

The Notify function simply checks for PenDown events, and passes all other events to
the base class:

pm_int_t MyButton::Notify(const pm_event_t &Event)


{
if (Event.Type == PM_EVENT_PENDOWN)
{
mClickCount++;
}
return Pm_Btn::Notify(Event);
}

The MyButton::Paint function will look like this:

void MyButton::Paint(const Pm_Region &Invalid)


{
pm_Brush PaintBrush;
pm_char_t cTemp[4];

// color IDs 0 15 are the standard VGA color palette. Use these
// colors as my background color and change it each time I am clicked.

if (mClickCount >= 15)


{
mClickCount = 0;
}

SetColor(PCI_NORMAL, ClickCount); // note 1

#if defined(PRISM_GRADIENT_BUTTONS)
SetColor(PM_BCI_GRADIENT1_NORMAL, mClickCount);
SetColor(PM_BCI_GRADIENT1_HASFOCUS, mClickCount);
#endif

Blue Water Embedded, Inc. Page 91


Developers Guide

OpenCanvas(Invalid); // note 2

Pm_Btn::Paint(Invalid) // note 3

// draw count on top of button:

Pm_ltoa(ClickCount, cTemp, 10);


pm_point_t TextPoint;
TextPoint.x = mSize.Left;
TextPoint.y = mSize.Top;

PaintBrush.pFont = PFR(FID_MEDIUM_FONT); // note 4

TextPoint.x += (mSize.Width() TextWidth(cTemp, PaintBrush.pFont)) / 2;


TextPoint.y += (mSize.Height() TextHeight(PaintBrush.pFont)) / 2;

PaintText(TextPoint, cTemp, PaintBrush);

CloseCanvas(); // note 5
}

Running this code by adding this button type to a panel and clicking on the button
produces a series of button colors and counter values. The following image is a
sequence of screen shots resulting from running the above MyButton class:

Note 1: This is how we are changing the button color, by assigning the member
variables of the Pm_Btn class that hold the color values that will be used to paint the
button. If the button is painting a gradient fill, we need to assign a different set of color
that if the button is using a solid fill.

Page 92 Blue Water Embedded, Inc.


Developers Guide

Note 2: Before we call any painting API functions, we need to call OpenCanvas to
prepare the canvas for painting and to initialize the clipping area.

Note 3: This statement calls the base class Paint function to paint the button
background. It is very common to invoke the base class Paint function if your
customization will be drawn on top of the background painting.

Note 4: This statement loads a pm_font_t pointer into the brush we are using for
painting text. The font point is located by invoking the PFR macro, which is a shorthand
method of asking the resource manager for the font pointer corresponding to a font Id.
The 4 resource request macros and their expansion are:

#define PSR(a) Pm_Resource_Manager::LookupString(a)


#define PBR(a) Pm_Resource_Manager::GetBitmap(a)
#define PFR(a) Pm_Resource_Manager::GetFont(a)
#define PCR(a) Pm_Resource_Manager::GetColor(a)

The FID_MEDIUM_FONT is one of two always defined font Ids, the other being
FID_SMALL_FONT. You can always use these two fonts in your application, in addition
to any other fonts you have added to your resource list.

Note 5: You always need to end your Paint function with a call to CloseCanvas. If you
forget to call CloseCanvas, the canvas will be locked and no panels or widgets will be
able to paint on this canvas. This error is usually readily apparent and easily corrected.

12.9 Screen transitions and navigation example


For this example we will use the example project located in the
\prism\insight\project\music_player directory. This is the same project described in the
quickstart guide.

Often when Child Event Notifications are received, the user-interface must transition to
a new state or panel. This is very easy to accomplish, and there are many supporting
structures implemented by Prism in Pm_Screen_Manager to make state transitions and
screen navigation easy to accomplish.

The MainScreen class of the music player, implemented in the file mainscreen.cpp,
defines the following event table:

Blue Water Embedded, Inc. Page 93


Developers Guide

pm_event_table_entry MainScreen_Events[] = {
{PM_CEN(MainScreen::IDB_PLAYLISTS, PM_EVENT_CLICK),
PM_EVENT_HANDLER(&MainScreen::OnEventPlaylistsClicked)},
{PM_CEN(MainScreen::IDB_SETTINGS, PM_EVENT_CLICK),
PM_EVENT_HANDLER(&MainScreen::OnEventSettingsClicked)},
{PM_CEN(MainScreen::IDB_GENRES, PM_EVENT_CLICK),
PM_EVENT_HANDLER(&MainScreen::OnEventGenresClicked)},
{PM_CEN(MainScreen::IDB_SONGS, PM_EVENT_CLICK),
PM_EVENT_HANDLER(&MainScreen::OnEventSongsClicked)},
{PM_CEN(MainScreen::IDB_SETTINGS, PM_EVENT_CLICK),
PM_EVENT_HANDLER(&MainScreen::OnEventSettingsClicked)},
{PM_CEN(MainScreen::IDB_ARTISTS, PM_EVENT_CLICK),
PM_EVENT_HANDLER(&MainScreen::OnEventSettingsClicked)},
{PM_CEN(MainScreen::IDB_ALBUMNS, PM_EVENT_CLICK),
PM_EVENT_HANDLER(&MainScreen::OnEventSettingsClicked)},
{0, NULL}
};

Each of these events is CENs from the main screen child buttons. When a button is
clicked, the MainScreen handles the event as shown below:

pm_int_t MainScreen::OnEventPlaylistClicked(const pm_event_t &Event)


{
Pm_Panel *pw = new PlaylistScreen(0, 0);
pw->SetTransitionMode(TRANS_MODE_SLIDE_RIGHT, 0, 5, 1);
ScreenManager()->Link(pw);
return 0;
}

The above sequence creates an in instance of the PlaylistScreen class, assigns an


entry transition mode to the Pm_Panel derived class, and links the new class instance
to the screen manager to display the new panel.

The available Panel transition modes are defined in the prism_panel.hpp header file. If
no transition mode is defined, the panel is simply displayed immediately as soon as it is
linked to the Pm_Screen_Manager.

Note in this case the MainScreen did not destroy itself or remove itself from the display.
The MainScreen is therefore still linked to the Pm_Screen_Manager, and the new panel
is simply stacked on top of the MainScreen. Returning to the main screen therefore
requires nothing more than destroying the PlaylistScreen, as shown:

pm_int_t PlaylistScreen::OnEventCloseClicked(pm_event_t &Event)


{
Destroy(this);
return IDB_CLOSE;
}

The PlaylistScreen simply removes itself from the ScreenManager to return to the
MainScreen.

Page 94 Blue Water Embedded, Inc.


Developers Guide

This mechanism works fine for simple applications, but begins to have drawbacks as
the complexity of the application grows. One drawback is that this will only work if each
panel covers the entire display screen. If it did not, the old panel might still be visible
behind the new panel. In some cases this is desired, but if not a different method for
changing the displayed panel needs to be used.

The following example demonstrates destroying the MainScreen when the


PlaylistScreen is displayed, and then re-creating the MainScreen when the
PlaylistScreen exits:

pm_int_t MainScreen::OnEventPlaylistClicked(const pm_event_t &Event)


{
Pm_Panel *pw = new PlaylistScreen(0, 0);
pw->SetTransitionMode(TRANS_MODE_SLIDE_RIGHT, 0, 5, 1);
ScreenManager()->Link(pw);
Destroy(this); // delete this object from memory
return 0;
}

And the matching change to the PlaylistScreen code:

pm_int_t PlaylistScreen::OnEventCloseClicked(pm_event_t &Event)


{
MainScreen *ps = new MainScreen();
ScreenManager()->Link(ps);
Destroy(this);
return IDB_CLOSE;
}

12.10 Persistent Panels


The above example demonstrates creating panels just in time when they are needed
for the display, and deleting those panels when they are no longer required. This
mechanism is often used for large applications. It scales well and only enough dynamic
memory to hold one or two active screen objects is required at any one time.

A different approach to the problem involves creating all of the panels that may be
required by the application at system startup, and keeping pointers to these panels in an
application defined panel array. In this case, the Panels are never Destroyed or re-
created, they are simply Linked and Unlinked from the Pm_Screen_Manager as the
user navigates from screen to screen within the user interface. These are called
Persistent Panels because they are not re-created and deleted when needed, they are
always present in memory and they are simply displayed when required. The drawback
to persistent panels is that they can require a much larger heap space if you have a

Blue Water Embedded, Inc. Page 95


Developers Guide

large number of panels defined in your application, since all the panels are allocated at
once during system startup.

A less obvious advantage to persistent panels is they always re-appear in the same
state as they were left, unless the application software forces a change. Therefore, as
an example, if a panel has child toggle buttons for setting various options of the device,
these buttons need to be initialized to the proper state when the panel is constructed.
This means the proper state in this case must be stored off in some external data
structure that remembers the status of each setting.

With persistent panels, the panel is never re-constructed after the intial device power-
on. Therefore, each time the panel is displayed, the child toggle buttons are always in
the correct state, reflecting the last user setting, and no external structure for storing the
button states is required.

Page 96 Blue Water Embedded, Inc.

Potrebbero piacerti anche