[Previous] [Contents] [Index] [Next]

RtMeter

A realtime meter

Class hierarchy:

PtWidget --> PtBasic --> RtMeter

For more information, see the diagram of the widget hierarchy.

PhAB icon:

RtMeter button in PhAB

Public header:

<photon/realtime/RtMeter.h>

Description:

The RtMeter widget is drawn as a half circle with divisional ticks at 1/4, 1/2, and 3/4 of the arc.


RtMeter


An RtMeter widget.


The needle can be moved with the mouse, the keyboard or programmatically:

With the mouse
A single mouse click moves the meter to the current mouse position; mouse motion with a button held down causes the needle to follow the mouse, through meter values.
With the keyboard
Two keys can be set up to move the needle:
Programatically
The Rt_ARG_METER_NEEDLE_POSITION resource can be used to set the needle position programmatically.

Up to 3 severity arcs can be drawn in colors to indicate different levels of the meter:

The widget bases its size on the text size and the specified dimensions. If the given dimensions are too small, it sizes itself appropriately based on the resize policy. The height of the widget depends on the radius of the meter, which in turn depends on the X dimension and text sizes.

Creating a 3-arc meter

To create a 3-arc meter with the default arc colors and positions (as shown above):

...
PhArea_t area = { { 10, 10 }, { 200, 200 } };
...    
PtSetArg(&args[0], Pt_ARG_AREA, &area, 0);
PtCreateWidget(RtMeter, parent, 1, args)
...

Creating a 1-arc meter

To create a 1-arc meter that can be moved by clicking the mouse buttons, has a minimum value of 0, has a maximum of 1000, and notifies you when the user moves the needle:


1-arc RtMeter


A one-arc RtMeter widget.


...
PhArea_t area = { { 10, 10 }, { 200, 200 } };
PtCallback_t cb[1] = { {moved_cb, NULL} };
    
PtSetArg(&args[0], Pt_ARG_AREA, &area, 0);
PtSetArg(&args[1], Rt_ARG_METER_MAX_NEEDLE_POSITION, 
         1000, 0);
PtSetArg(&args[2], Rt_CB_METER_MOVED, &cb[1], 0);
PtCreateWidget(RtMeter, parent, 3, args)
...

int moved_cb(PtWidget_t *widget, void *data, 
             PtCallbackInfo_t *info)
{
    RtMeterCallback_t *mydata;
    mydata = info->cbdata;

    printf("Got the callback. Position was: %d severity: %d\n ", 
            mydata->position, mydata->severity);
}
...

Creating a 3-arc meter movable by keys and mouse

To create a 3-arc meter whose needle can be moved

with an increment of 10 for each keystroke (for example, the meter will move 0, 10, 20, ... when you press the up-arrow key):

...
PhArea_t area = { { 10, 10 }, { 200, 200 } };
PtCallback_t cb[1] = { {moved_cb, NULL} };
    
PtSetArg(&args[0], Pt_ARG_AREA, &area, 0);
PtSetArg(&args[1], Rt_ARG_METER_KEY_LEFT, Pk_Down, 0);
PtSetArg(&args[2], Rt_ARG_METER_KEY_RIGHT, Pk_Up, 0);
PtSetArg(&args[3], Rt_ARG_METER_INCREMENT, 10, 0);
PtSetArg(&args[4], Rt_CB_METER_MOVED, &cb[1], 0);
PtCreateWidget( RtMeter, parent, 5, args );
...

int moved_cb( PtWidget_t *widget, void *data, 
              PtCallbackInfo_t *info)
{
    RtMeterCallback_t *mydata;
    mydata = info->cbdata;

    printf("Got the callback. Position was: %d severity: %d\n", 
           mydata->position, mydata->severity);
}

You'll notice that as you move the needle on the widget, there's very little flickering. This is because when the needle moves it's merely erased and then drawn at the new position. However, if you create a meter with Pg_TRANSPARENT as a fill color, you'll notice more flickering because the needle can't merely be erased - the background must be drawn as well. In this case, flickering is reduced by calculating a bounding rectangle for the needle and redrawing only that rectangle. The most flickering (redraw) occurs when the needle is at 45° or 135°.


Note: For flicker-free performance when using Pg_TRANSPARENT as a fill color, put the RtMeter inside a PtDBContainer widget.

Full meter example

#include <stdio.h>
#include <Pt.h>
#include <photon/realtime/RtMeter.h>

PtWidget_t  *window, *meter, *quit, *sev_lbl, *pos_lbl;

// callback for meter moved
int meter_cb( PtWidget_t *widget, void *data, 
              PtCallbackInfo_t *info)
{
    RtMeterCallback_t *mydata;
    char pos[10], sev[5];
    PtArg_t args[2];

    mydata = info->cbdata;
    itoa(mydata->position, pos, 10);
    itoa(mydata->severity, sev, 10);

    // set the position label to the current position
    PtSetArg(&args[0], Pt_ARG_TEXT_STRING, pos, 0);
    PtSetResources(pos_lbl, 1, args);

    // set the severity label to the current severity
    PtSetArg(&args[0], Pt_ARG_TEXT_STRING, sev, 0);
    PtSetResources(sev_lbl, 1, args);

    return (Pt_CONTINUE);
}

// callback for the quit button
void quit_cb( PtWidget_t *widget, void *data, 
              PtCallbackInfo_t *info)
{
    exit (EXIT_SUCCESS);
}

void main(int argc, char *argv[])
{
    PtArg_t     args[10];
    PhDim_t     win_dim = { 300, 300 };
    PhArea_t    meter_area = { { 10, 20 }, { 280, 280 } };
    PhArea_t    sev_area = { { 125, 200 }, { 50, 20 } };
    PhArea_t    pos_area = { { 125, 230 }, { 50, 20} };
    PhArea_t    quit_area = { { 230, 270 }, { 60, 20 } };
    PtCallback_t callbacks[2] = { {meter_cb, NULL}, 
                                  {quit_cb, NULL} };
    int n = 0;

    PtSetArg( &args[n++], Pt_ARG_WINDOW_TITLE, 
              "RtMeter Demo", 0 );
    PtSetArg( &args[n++], Pt_ARG_DIM, &win_dim, 0 );
    window = PtAppInit( NULL, &argc, argv, n, args );

    // draw the meter with 3 arcs and a callback for meter moved
    n = 0;
    PtSetArg( &args[n++], Pt_ARG_AREA, &meter_area, 0 );
    PtSetArg( &args[n++], Rt_ARG_METER_MAX_NEEDLE_POSITION, 
              1000, 0 );
    PtSetArg( &args[n++], Rt_ARG_METER_TEXT_FONT, "helv12", 0 );
    PtSetArg( &args[n++], Rt_CB_METER_MOVED, &callbacks[0], 0 );

    // If you don't want your meter to be selectable, add
    // the following:
    //
    //  PtSetArg( &args[n++], Rt_ARG_METER_FLAGS, 
    //            RtM_NON_SELECTABLE, RtM_NON_SELECTABLE );

    meter = PtCreateWidget( RtMeter, window, n, args );

    // Draw a label to show the severity changes. 
    // The first label is the label to be changed,
    // and the second is the name of the parameter.
    n = 0;
    PtSetArg( &args[n++], Pt_ARG_AREA, &sev_area, 0 );
    PtSetArg( &args[n++], Pt_ARG_FLAGS, 
              Pt_HIGHLIGHTED | Pt_ETCH_HIGHLIGHT, \
              Pt_HIGHLIGHTED | Pt_ETCH_HIGHLIGHT);
    PtSetArg( &args[n++], Pt_ARG_BORDER_WIDTH, 1, 0);
    PtSetArg( &args[n++], Pt_ARG_TEXT_STRING, "1", 0);
    sev_lbl = PtCreateWidget( PtLabel, window, n, args );

    n = 0;
    sev_area.pos.x -= 60;
    PtSetArg( &args[n++], Pt_ARG_AREA, &sev_area, 0 );
    PtSetArg( &args[n++], Pt_ARG_TEXT_STRING, "Severity:", 0);
    PtCreateWidget( PtLabel, window, n, args );

    // Draw a label to show the position changes. 
    // The first label is the label to be changed, 
    // and the second is the name of the parameter.
    n = 0;
    PtSetArg( &args[n++], Pt_ARG_AREA, &pos_area, 0 );
    PtSetArg( &args[n++], Pt_ARG_FLAGS, 
              Pt_HIGHLIGHTED | Pt_ETCH_HIGHLIGHT, \
              Pt_HIGHLIGHTED | Pt_ETCH_HIGHLIGHT);
    PtSetArg( &args[n++], Pt_ARG_BORDER_WIDTH, 1, 0);
    PtSetArg( &args[n++], Pt_ARG_TEXT_STRING, "0", 0);
    pos_lbl = PtCreateWidget( PtLabel, window, n, args );

    n = 0;
    pos_area.pos.x -= 60;
    PtSetArg( &args[n++], Pt_ARG_AREA, &pos_area, 0 );
    PtSetArg( &args[n++], Pt_ARG_TEXT_STRING, "Position:", 0);
    PtCreateWidget( PtLabel, window, n, args );

    // draw a quit button
    n = 0;
    PtSetArg( &args[n++], Pt_ARG_AREA, &quit_area, 0 );
    PtSetArg( &args[n++], Pt_ARG_TEXT_STRING, "Quit", 0);
    PtSetArg( &args[n++], Pt_CB_ACTIVATE, &callbacks[1], 0);
    quit = PtCreateWidget( PtButton, window, n, args );

    PtRealizeWidget( window );

    PtMainLoop();
}

New resources:

Resource C type Pt type Default
Rt_ARG_METER_COLOR PgColor_t Scalar Pg_BLACK
Rt_ARG_METER_FLAGS unsigned short Flag RtM_SELECTABLE
Rt_ARG_METER_FONT_COLOR PgColor_t Scalar Pg_BLACK
Rt_ARG_METER_INCREMENT int Scalar 5
Rt_ARG_METER_KEY_LEFT int Scalar Pk_Left
Rt_ARG_METER_KEY_RIGHT int Scalar Pk_Right
Rt_ARG_METER_LEVEL1_COLOR PgColor_t Scalar Pg_GREEN
Rt_ARG_METER_LEVEL1_POS short Scalar 50
Rt_ARG_METER_LEVEL2_COLOR PgColor_t Scalar Pg_YELLOW
Rt_ARG_METER_LEVEL2_POS short Scalar 75
Rt_ARG_METER_LEVEL3_COLOR PgColor_t Scalar Pg_RED
Rt_ARG_METER_MAX_NEEDLE_POSITION short Scalar 100
Rt_ARG_METER_MIN_NEEDLE_POSITION short Scalar 0
Rt_ARG_METER_NEEDLE_COLOR PgColor_t Scalar Pg_WHITE
Rt_ARG_METER_NEEDLE_POSITION short Scalar 0
Rt_ARG_METER_NUM_SEVERITY_LEVELS short Scalar 3
Rt_ARG_METER_TEXT_FONT char * String "helv10"
Rt_CB_METER_MOVED PtCallback_t * Link NULL

Rt_ARG_METER_COLOR

C type Pt type Default
PgColor_t Scalar Pg_BLACK

The color for the center circle, outline of the meter, and divisional ticks.

Rt_ARG_METER_FLAGS

C type Pt type Default
unsigned short Flag RtM_SELECTABLE

The valid bits are:

RtM_NON_SELECTABLE
Make the meter noninteractive.
RtM_SELECTABLE
Make the meter interactive.
RtM_NO_TEXT
Don't display the minimum and maximum text strings.

Rt_ARG_METER_FONT_COLOR

C type Pt type Default
PgColor_t Scalar Pg_BLACK

The font color for the minimum and maximum strings.

Rt_ARG_METER_INCREMENT

C type Pt type Default
int Scalar 5

The increment used when the keyboard is used to move the meter's needle. Every press of the assigned keys will move the meter this distance.

Rt_ARG_METER_KEY_LEFT

C type Pt type Default
int Scalar Pk_Left

The key, as defined in <photon/PkKeyDef.h>, that's to be used to move the meter's needle to the left. The default value is the left arrow, Pk_Left.


Note: Pt_ARG_FLAGS must have Pt_GETS_FOCUS set.

Rt_ARG_METER_KEY_RIGHT

C type Pt type Default
int Scalar Pk_Right

The key, as defined in <photon/PkKeyDef.h>, that's to be used to move the meter's needle to the right. The default value is the right arrow, Pk_Right.


Note: Pt_ARG_FLAGS must have Pt_GETS_FOCUS set.

Rt_ARG_METER_LEVEL1_COLOR

C type Pt type Default
PgColor_t Scalar Pg_GREEN

The color of the first severity arc.

Rt_ARG_METER_LEVEL1_POS

C type Pt type Default
short Scalar 50

The position of the end of the first severity arc, expressed as a percentage of the whole. If the minimum and/or maximum value(s) change, the location of the arc is updated to remain at this percentage.

Rt_ARG_METER_LEVEL2_COLOR

C type Pt type Default
PgColor_t Scalar Pg_YELLOW

The color of the second severity arc.

Rt_ARG_METER_LEVEL2_POS

C type Pt type Default
short Scalar 75

The position of the end of the second severity arc, expressed as a percentage of the whole. If the minimum and/or maximum value(s) change, the location of the arc is updated to remain at this percentage.

Rt_ARG_METER_LEVEL3_COLOR

C type Pt type Default
PgColor_t Scalar Pg_RED

The color of the third severity arc.

Rt_ARG_METER_MAX_NEEDLE_POSITION

C type Pt type Default
short Scalar 100

The maximum needle position; also the value drawn as the maximum.

Rt_ARG_METER_MIN_NEEDLE_POSITION

C type Pt type Default
short Scalar 0

The minimum needle position; also the value drawn as the minimum.

Rt_ARG_METER_NEEDLE_COLOR

C type Pt type Default
PgColor_t Scalar Pg_WHITE

The color of the meter's needle.

Rt_ARG_METER_NEEDLE_POSITION

C type Pt type Default
short Scalar 0

The current needle position, somewhere between the minimum and maximum needle position. If the position is above the maximum, the maximum is used; if the position is below the minimum, the minimum is used.

Rt_ARG_METER_NUM_SEVERITY_LEVELS

C type Pt type Default
short Scalar 3

The number of severity arcs (levels) that the meter displays. This must be 1, 2, or 3. If this resource is set higher than 3, only 3 arcs are displayed.

Rt_ARG_METER_TEXT_FONT

C type Pt type Default
char * String "helv10"

The font for the minimum and maximum strings.

Rt_CB_METER_MOVED

C type Pt type Default
PtCallback_t * Link NULL

A list of callbacks invoked when the needle is moved. Each callback is passed a PtCallbackInfo_t structure that contains at least the following members:

reason
The name of the callback resource (Rt_CB_METER_MOVED) that caused this callback to be invoked.
reason_subtype
Why the callback was invoked:

For more information, see PhEvent_t in the Photon Library Reference.

event
The event that caused the callback. If event is NULL, then the callback was invoked because the Rt_ARG_METER_NEEDLE_POSITION resource was set.
cbdata
A pointer to an RtMeterCallback_t structure that contains at least:
int position
The current position of the needle between the minimum and maximum positions.
int severity
The severity arc number that the needle current lies in, between 1 and the number of arcs.

These callbacks should return Pt_CONTINUE.

Inherited resources:

If the widget modifies an inherited resource, the "Default override" column indicates the new value. This modification affects any subclasses of the widget.

Resource Inherited from Default override
Pt_ARG_AREA PtWidget
Pt_ARG_BANDWIDTH_THRESHOLD PtBasic Not used by this class.
Pt_ARG_BITMAP_CURSOR PtWidget
Pt_ARG_BORDER_WIDTH PtWidget
Pt_ARG_BOT_BORDER_COLOR PtBasic
Pt_ARG_COLOR PtBasic Not used by this class.
Pt_ARG_CURSOR_COLOR PtWidget
Pt_ARG_CURSOR_TYPE PtWidget
Pt_ARG_DATA PtWidget
Pt_ARG_DIM PtWidget
Pt_ARG_EFLAGS PtWidget
Pt_ARG_FILL_COLOR PtBasic Pg_TRANSPARENT
Pt_ARG_FILL_PATTERN PtBasic Not used by this class.
Pt_ARG_FLAGS PtWidget Pt_GETS_FOCUS
Pt_ARG_HELP_TOPIC PtWidget
Pt_ARG_HIGHLIGHT_ROUNDNESS PtBasic
Pt_ARG_MARGIN_HEIGHT PtBasic 2
Pt_ARG_MARGIN_WIDTH PtBasic 2
Pt_ARG_POS PtWidget
Pt_ARG_RESIZE_FLAGS PtWidget Pt_RESIZE_XY_AS_REQUIRED
Pt_ARG_TOP_BORDER_COLOR PtBasic
Pt_ARG_TRANS_PATTERN PtBasic
Pt_ARG_USER_DATA PtWidget
Pt_CB_ACTIVATE PtBasic
Pt_CB_ARM PtBasic
Pt_CB_BLOCKED PtWidget
Pt_CB_DESTROYED PtWidget
Pt_CB_DISARM PtBasic
Pt_CB_GOT_FOCUS PtBasic
Pt_CB_HOTKEY PtWidget
Pt_CB_LOST_FOCUS PtBasic
Pt_CB_MENU PtBasic
Pt_CB_RAW PtWidget
Pt_CB_REALIZED PtWidget
Pt_CB_REPEAT PtBasic
Pt_CB_UNREALIZED PtWidget

[Previous] [Contents] [Index] [Next]