A widget for use with Photon drawing primitives
PtWidget --> PtBasic --> PtRaw
For more information, see the diagram of the widget hierarchy.
<photon/PtRaw.h>
The PtRaw class provides you with widget that lets you use the Photon graphics drawing functions.
The PtRaw class provides a good starting point for creating custom widgets. However, custom widgets require their own Initialization, Extent, and Connect methods in addition to a Draw method. Since the PtRaw widget is typically used for drawing, the Draw function PtRaw supports is described in detail in this chapter. If you'd like more information about when to use an Initialization, Extent, or Connect function, see the Building Custom Widgets manual. |
With a PtRaw canvas, you can draw using raw Photon graphics primitives without completely losing what you've drawn when the widget is damaged. If the widget is damaged, the application is notified so that it may redraw whatever it had previously drawn.
You must refresh the contents of the canvas whenever they become damaged. This is necessary because Photon doesn't keep track of the widget's raw contents for you. It's more efficient to allow the application programmer to maintain the original data structure and re-render the contents of the canvas. If a significant amount of time must be expended rendering the contents of the canvas, it's better to render them into an image and copy the image into the canvas when it is damaged.
The canvas is considered damaged whenever one of the following situations occurs:
The PtRaw widget defines a drawing function, Pt_ARG_RAW_DRAW_F, which is invoked any time the contents of the canvas have to be refreshed due to damage.
Don't call the drawing function directly from your program. Instead, damage the widget by calling PtDamageWidget(), and let the library call the drawing function. |
The drawing function you provide for the canvas gets two arguments when it's invoked:
For simple situations where the widget's contents don't change, you could put the drawing primitives in the draw function directly. But it's more likely that the contents will change dynamically. In this case, you should create a data structure, or model, that defines the contents of the canvas.
Place a pointer to this data structure in the Pt_ARG_USER_DATA resource of the PtRaw widget, so that it can be obtained easily by your draw function. This function should be able to walk the data structure you've provided and to render the contents of the canvas based on that information.
Before your function begins drawing, it should establish its coordinate space correctly. First, obtain the coordinates of the clip rectangle or the widget canvas. This is done by calling PtBasicWidgetCanvas() with the raw widget and the address of a rectangle to be filled with the boundaries of the raw widget's clip region.
Once you've determined the clip region, you should determine a scale factor and translation for drawing. You determine the scale factor based on:
You should also set a translation to compensate for the raw widget's margins. The edge of the margins is given as the rectangle's upper-left corner given by the PtBasicWidgetCanvas() function. Add the rectangle's upper-left corner to any translation you wish to perform on the model and pass this value to PgSetTranslation().
This function takes two parameters. The second parameter should be set to the constant Pg_RELATIVE. When rendering your model, scale the values by your scale factor. The coordinates will automatically be translated by the amount you specified in the call to PgSetTranslation().
The simple example below shows a drawing function that fills the entire canvas with blue:
void raw_draw(PtWidget_t *widget, PhTile_t *damage) { PhRect_t rect; PtBasicWidgetCanvas(widget, &rect); PgSetFillColor(Pg_BLUE); PgDrawRect(&rect, Pg_DRAW_FILL); }
If your model doesn't explicitly represent color information, make sure you set the stroke color to the value contained in the Pt_ARG_COLOR resource and the fill color to the value specified in the Pt_ARG_FILL_COLOR resource.
PtRaw lets you combine widgets and Pg* functions. You should use this widget to cover any area in which "raw drawing" is to take place. The draw function you specify for this widget will be called whenever the area needs repair.
The coordinates for the Pg* calls made within the draw function are relative to the canvas of PtRaw's parent. The draw function must handle its own clipping and highlighting.
If the draw function changes clipping (PtClipAdd()) or the current translation (PgSetTranslation()) they must be restored before the draw function returns.
Here's an example of setting up and using a PtRaw widget:
pos.x = 220; dim.w = 200, dim.h = 200; n=0; PtSetArg( &args[n], Pt_ARG_DIM, &dim, 0 );n++; PtSetArg( &args[n], Pt_ARG_POS, &pos, 0 );n++; PtSetArg( &args[n], Pt_ARG_RAW_DRAW_F, &draw, 1 );n++; PtSetArg( &args[n], Pt_ARG_BORDER_WIDTH, 2, 0 );n++; PtSetArg( &args[n], Pt_ARG_FLAGS, Pt_TRUE, Pt_SELECTABLE | Pt_HIGHLIGHTED );n++; PtSetArg( &args[n], Pt_CB_ARM, &aback, 1 );n++; PtCreateWidget(PtRaw, NULL, n, &args[0] ); ... void draw( PtWidget_t *widget, PhTile_t *damage ) { PhRect_t rect; damage = damage; PtSuperClassDraw( PtBasic, widget, damage ); //find our canvas PtBasicWidgetCanvas( widget, &rect ); //clip to our basic canvas (it's only polite). PtClipAdd( widget, &rect ); //Do our drawing... PgSetStrokeColor( Pg_RED ); PgDrawRect( &rect , Pg_DRAW_STROKE ); rect.ul.x++; rect.ul.y++; rect.lr.y--; rect.lr.x--; PgSetStrokeColor( Pg_WHITE ); PgDrawRect( &rect , Pg_DRAW_STROKE ); //remove our clipping PtClipRemove(); }
For more information, see the Raw Drawing and Animation chapter of the Photon Programmer's Guide.
Resource | C type | Pt type | Default |
---|---|---|---|
Pt_ARG_RAW_CONNECT_F | See below | Pointer | NULL |
Pt_ARG_RAW_DRAW_F | See below | Pointer | NULL |
Pt_ARG_RAW_EXTENT_F | See below | Pointer | NULL |
Pt_ARG_RAW_INIT_F | See below | Pointer | NULL |
C type | Pt type | Default |
---|---|---|
See below | Pointer | NULL |
A function that creates any regions needed by the widget (normally PtWidget does this for you):
int (*connect_f) (PtWidget_t *widget)
C type | Pt type | Default |
---|---|---|
See below | Pointer | NULL |
A function that renders the widget on the screen:
void (*draw_f) (PtWidget_t *widget, PhTile_t *damage)
C type | Pt type | Default |
---|---|---|
See below | Pointer | NULL |
A function that determines the exact size of the widget based on default values and/or the widget's position, size, margins, borders, and highlighting information:
void (*extent_f) (PtWidget_t *widget)
C type | Pt type | Default |
---|---|---|
See below | Pointer | NULL |
This function is typically used by widgets that create children. It checks to ensure that all members used in a subsequent call to the extent function are correctly assigned.
int (*init_f) (PtWidget_t *widget)
If the widget modifies an inherited resource, the "Default override" column indicates the new value. This modification affects any subclasses of the widget.