This section discusses various approaches for defining new graphical objects. XPCE offers three approaches for defining new graphical objects:
text_box(TB, Text, Width, Height) :-
        new(TB, device),
        send(TB, display,
             new(B, box(Width, Height))),
        send(TB, display,
             new(T, text(Text, center, normal))),
        send(T, center, B?center).
For some applications, this is a suitable and simple approach. However, it is not a very good approach to build a library of GUI objects or, more in general, to make generic and reusable new graphical objects. The above object does not handle resize properly, and the user has to know the internal structure to modify the object.
->initialise' 
is refined to display the part of the compound graphical. `device->event' 
and `device->geometry' 
are normally redefined to define event-handling and resize of the new 
graphical object. See section 7.3.2 
for details.
->_redraw_area' 
can be redefined to define the look of a graphical. We will discuss the 
advantages and disadvantages of this approach in this section and give 
some examples.
The most basic way to (re)define the look of a graphical object is by 
redefining the method that paints the graphical. This method is called
->_redraw_area. The method ->_redraw_area cannot 
be called directly by the user, but it is called by the graphical 
infra-structure whenever the graphical needs to be repainted. The 
definition of the method is below:
<-area of the graphical.
It is not allowed for this method to paint outside the <-area 
of the receiver. There is no clipping (see ->clip) 
to prevent this. If there is no cheap way to prevent this, bracket the 
graphical operations in ->clip and ->unclip, 
but be aware that setting and undoing the clip-region is an expensive 
operation. Note that is is not necessary to limit the applied 
paint only inside the given argument Area. The graphical 
infra-structure automatically clips all graphical operation to this 
area. In general, Area should only be considered to avoid large 
numbers of unnecessary drawing operations.
There are three sets of methods to implement the drawing job. The 
first is `graphical->draw', 
that allows drawing other graphical objects in this place. The second 
are methods to manipulate the clipping and state of the graphical 
device. The last is a set of methods to realise primitive drawing 
operations, such as drawing lines, rectangles, images, text, etc. These 
methods can be used in any combination. It is allowed, but not 
obligatory, to call the ->send_super method in 
order to invoke the default behaviour of the graphical. These methods 
are summarised in table 
9. Full documentation is available from the online manual.
| ->draw | Paint other graphical | 
| ->clip | Clip to area 
or <-area of graphical | 
| ->unclip | Undo last ->clip | 
| ->save_graphics_state | Save current pen and colours | 
| ->restore_graphics_state | Restore saved values | 
| ->graphics_state | Set graphics attributes | 
| ->draw_arc | Draw ellipse-part | 
| ->draw_box | Draw rectangle (rounded, filled, etc.) | 
| ->draw_fill | Fill/invert/clear rectangle | 
| ->draw_image | Paint (part of) image | 
| ->draw_line | Draw a line segment | 
| ->draw_poly | Draw a polygon | 
| ->draw_text | Draw string in font | 
| ->paint_selected | Paint 
visual feedback of ->selected | 
| Table 9 : Methods for (re)defining ->_redraw_area | 
XPCE built-in class window does not provide a grid. Implementing a grid using graphical objects is difficult. The best approach would be to display a device on the window that provides the background and displays the lines of the grid. The resize and scroll messages need to be trapped to ensure the proper number of lines are displayed with the correct length. Furthermore, the code handling the inside of the window needs to be aware of the grid. It should ensure the grid is not exposed or deleted, etc.
It is much simpler to redefine the `window->_redraw_area' 
method, paint the grid and then call the super-method. The code is 
below.
:- pce_begin_class(grid_picture, picture,
                   "Graphical window with optional 
variable(grid,     '1..|size*' := 20, get,
         "Size of the grid").
variable(grid_pen, pen,               get,
         "Pen used to draw the grid").
initialise(P, Lbl:[name], Size:[size], Disp:[display]) :->
        send(P, send_super, initialise, Lbl, Size, Disp),
        (   get(@display, visual_type, monochrome)
        ->  Texture = dotted, Colour = black
        ;   Texture = none,   Colour = grey90
        ),
        send(P, slot, grid_pen, pen(1, Texture, Colour)).
'_redraw_area'(P, A:area) :->
        "Draw a grid"::
        get(P, grid, Grid),
        (   Grid \== @nil
        ->  (   integer(Grid)
            ->  GX = Grid,
                GY = Grid
            ;   object(Grid, size(GX< GY))
            ),
            send(P, save_graphics_state),
            get(P, grid_pen, pen(Pen, Texture, Colour)),
            send(P, graphics_state, Pen, Texture, Colour),
            object(A, area(X, Y, W, H)),
            StartX is (X//GX) * GX,
            StartY is (Y//GY) * GY,
            Xlines is ((W + X - StartX)+GX-1)//GX,
            Ylines is ((H + Y - StartY)+GY-1)//GY,
            (   between(1, Xlines, Xline),
                    Xnow is StartX + (Xline-1)*GX,
                    send(P, draw_line, Xnow, Y, Xnow, Y+H),
                fail
            ;   true
            ),
            (   between(1, Ylines, Yline),
                    Ynow is StartY + (Yline-1)*GY,
                    send(P, draw_line, X, Ynow, X+W, Ynow),
                fail
            ;   true
            ),
            send(P, restore_graphics_state)
        ;   true
        ),
        send(P, send_super, '_redraw_area', A).
grid(P, Grid:'1..|size*') :->
        send(P, slot, grid, Grid),
        send(P, redraw).                % changed?
grid_pen(P, Penn:pen) :->
        send(P, slot, grid_pen, Pen),
        send(P, redraw).                % changed?
:- pce_end_class.
The following example is yet another implementation of a shape filled 
with text. Redefining ->_redraw_area has several 
advantages and disadvantages over the device 
based implementation:
Implementing edit facilities for the text will be hard. The best 
approach would be to display a normal text 
object on top of the text-box and replace the <->string 
when editing is finished.
:- pce_begin_class(text_shape, graphical,
                   "text with box or ellipse").
variable(string,        char_array,     get,
         "Displayed string").
variable(font,          font,           get,
         "Font used to display string").
variable(shape,         {box,ellipse},  get,
         "Outline shape").
initialise(S, Str:string=char_array, Shape:shape={box,ellipse},
           W:width=int, H:height=int, Font:[font]) :->
        default(Font, normal, TheFont),
        send(S, send_super, initialise, 0, 0, W, H),
        send(S, slot, string, Str),
        send(S, slot, shape, Shape),
        send(S, slot, font, TheFont).
'_redraw_area'(S, _A:area) :->
        get(S, area, area(X, Y, W, H)),
        get(S, string, String),
        get(S, font, Font),
        get(S, shape, Shape),
        send(S, clip),                  % text may be bigger
        (   Shape == box
        ->  send(S, draw_box, X, Y, W, H)
        ;   send(S, draw_arc, X, Y, W, H)
        ),
        send(S, draw_text,
             String, Font, X, Y, W, H,
             center, center),
        send(S, unclip),
        send(S, send_super, redraw).
:- pce_end_class.