A widget for use with Photon drawing primitives
For more information, see the diagram of the widget hierarchy.
<photon/PtRaw.h>
The PtRaw widget lets you use the Photon graphics drawing functions in applications that use widgets.
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 Building Custom Widgets. |
With a PtRaw widget, 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, your 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 have you, as application programmer, maintain the original data structure and redraw the contents of the canvas. If it takes a long time to render the contents of the canvas, consider rendering them into an image and copying the image into the canvas when it's 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 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_POINTER or Pt_ARG_USER_DATA resource of the PtRaw widget, so that your draw function can get it easily. 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. The draw function must handle its own clipping and highlighting.
Before your function begins drawing, it should establish its coordinate space correctly. First, get the coordinates of the clip rectangle or the widget canvas, by calling PtCalcCanvas() 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, based on:
The coordinates for the Pg* calls made within the draw function are relative to the canvas of PtRaw's parent. You need to translate the coordinates 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 PtCalcCanvas() 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 are automatically translated by the amount you specified in the call to PgSetTranslation().
If your draw function changes the current clipping (PtClipAdd()) or translation (PgSetTranslation()), be sure to restore them before returning from the draw function. |
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; PtSuperClassDraw(PtBasic, widget, damage); PtCalcCanvas(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.
Here's a more detailed 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_BEVEL_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, Pt_DEFAULT_PARENT, n, &args[0] ); … void draw( PtWidget_t *widget, PhTile_t *damage ) { PhRect_t rect; damage = damage; PtSuperClassDraw( PtBasic, widget, damage ); /* Find our canvas. */ PtCalcCanvas( 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_CALC_OPAQUE_F | See below | Pointer | NULL |
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 calculates the raw widget's opacity tile list:
int (*calc_opaque_f) (PtWidget_t *widget)
If this resource isn't set, the raw widget uses the function defined by PtBasic.
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)
If this resource isn't set, the raw widget uses the function defined by PtBasic.
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)
The damage argument points to a linked list of PhTile_t structures (see the Photon Library Reference) that identify which areas of the widget have been damaged.
If this resource isn't set, the raw widget uses the function defined by PtBasic.
For more information, see the Raw Drawing and Animation chapter of the Photon Programmer's Guide.
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)
If this resource isn't set, the raw widget uses the function defined by PtBasic.
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 this resource isn't set, the raw widget uses the function defined by PtBasic.
If the widget modifies an inherited resource, the “Default override” column indicates the new value. This modification affects any subclasses of the widget.