# To subscribers of the xforms list from Ivan Powis <Ivan.Powis@nottingham.ac.uk> :
I'm starting to write some support code for an enhanced version of an
older xforms application where there is now an additional need to
interact with a pseudo-colour image (rubber-band selection of regions)
and then do subsequent processing. I've identified the use of xforms
Canvas and Image support to do this within the broad existing
application framework. I've always chosen xforms to avoid getting too
close to raw X, but canvases seem to require a step in that direction,
hence I'm not certain my approach is correct! I've noted several minor
"problems" and am curious as to how to resolve them. I've attached a
cut down version of my coding (eg it doesn't actually put an image
onto the canvas) in case I've made some fundamental mistakes in the event
handling...
(1) Fdesign output by default puts a DOWN_BOX decoration on the
canvas. Is this border drawn _within_ the declared canvas dimensions?
If so where does the FL_IMAGE get pasted, because (0,0) on the canvas
is presumably already obscured by the border decoration. So is the
image offset by the border width or is it masked by the border? Other
evidence suggests to me the border decoration may be drawn outside the
canvas on the main form, but I'd appreciate clarification of this.
(2) The cursor in the canvas/image is supposed to be a cross-hair
changed by Enter/Leave events (see attached sample code). However, if
the mouse pointer happens to already lie the area of the display
screen where the canvas appears as the form first gets displayed no
such events get notified - so the cursor remains as its default
shape. Is there some better way to make sure the cursor will always
change when it happens to fall in the canvas?
(3) My routine for drawing a selection region on the canvas essentially
works. After drawing the rubber-banded area the user is to be allowed to
single click on the canvas to remove the visual selection, by XORing over it.
Running under KDE 2.0 on Mandrake Linux 7.2 (XFree 4) this final
step seems incredibly sluggish (ie nearly a second after the click)
before the selection is cleared. Additionally I notice that the
mouse pointer briefly flashes from the cross-hair back to the default
shape before the selection area gets erased. This sluggishness and
cursor flahing do not seem to happen with other Xservers, or
under say Gnome on the same linux box. Is this a problem with my approach,
xforms or KDE ?
(4) I can register event handlers for the canvas once it is created,
but before it is displayed (because no window id is required). But to
modify those registered events (eg to apply PointerMotionHintMask)
seems to need fl_remove_selected_xevent for which a valid window ID
is required. Ie this can't be done until after the canvas is displayed.
I find this a little inconsistent ... have I missed some other routines
which would enable the event handling to be fully setup before
the form was displayed?
------------------------------------------------------------------
/******************************************************************
// xf_image.c
// Routines for using xforms images pasted on canvas
// with interactive capability
//
// $Log$
******************************************************************/
#include <forms.h>
#include <stdlib.h>
#include <math.h>
/**** FD Structs ****/
typedef struct {
FL_FORM *trial;
void *vdata;
char *cdata;
long ldata;
FL_OBJECT *cnvs;
} FD_trial;
/*--- Data structures used by rubber banding ---*/
typedef struct{
FL_COORD ox, oy; /* starting x,y */
FL_COORD dx, dy; /* last displacement */
int drawn; /* flag set while box displayed */
char * (*xy_lab) (int x, int y, unsigned int state, FL_OBJECT *cnvs);
} XF_IM_DESC; /* SUPPORT FOR RUBBER BANDING */
#define ERR_MSG(a) fprintf(stderr,a)
#define DBG
#define CLR FL_GREEN
/* Prototypes */
void init_cnvs(FL_OBJECT *ob);
static int
expose_hndl(FL_OBJECT *, Window , int, int, XEvent *, void *);
static int
cross_hndl(FL_OBJECT *, Window , int, int, XEvent *, void *);
static int
motion_hndl(FL_OBJECT *, Window, int, int, XEvent *, void *);
/* Create Form with Canvas ... fdesigner stuff */
FD_trial *create_form_trial(void)
{
FL_OBJECT *obj;
FD_trial *fdui = (FD_trial *) fl_calloc(1, sizeof(*fdui));
fdui->trial = fl_bgn_form(FL_NO_BOX, 730, 630);
obj = fl_add_box(FL_UP_BOX,0,0,730,630,"");
fdui->cnvs = obj = fl_add_canvas(FL_NORMAL_CANVAS,50,50,610,470,"");
fl_end_form();
fdui->trial->fdui = fdui;
return fdui;
}
/* Return text for a one-liner cursor readout */
char *label_it(int x, int y, unsigned int state, FL_OBJECT *cnvs)
{
static char txt[50];
sprintf(txt,"X:%3d Y:%3d St:$%4x", x,y,state);
return txt;
}
/***************************************************
// MAIN
****************************************************/
int main(int argc, char *argv[])
{
FD_trial *fd_trial;
XF_IM_DESC desc;
int stat,i,j;
fl_initialize(&argc, argv, 0, 0, 0);
fd_trial = create_form_trial();
fl_show_form(fd_trial->trial,FL_PLACE_FREE,FL_FULLBORDER,"trial");
/* Setup canvas handlers */
init_cnvs(fd_trial->cnvs);
/* Attach storage to canvas u_vdata */
desc.drawn=0;
desc.xy_lab = label_it;
fd_trial->cnvs->u_vdata = (void *) &desc;
/* Normally could display image to canvas here */
while (fl_do_forms());
return 0;
}
/*------------------------------------------------------------------*/
/* Canvas specific stuff follows */
/*------------------------------------------------------------------*/
/* Setup canvas handlers */
void init_cnvs(FL_OBJECT *canvas)
{
/* Add canvas handlers */
fl_add_canvas_handler(canvas, Expose, expose_hndl,(void *) 0);
fl_add_canvas_handler(canvas, EnterNotify, cross_hndl,(void *) 0);
fl_add_canvas_handler(canvas, LeaveNotify, cross_hndl,(void *) 0);
fl_add_canvas_handler(canvas, MotionNotify, motion_hndl,(void *) 0);
fl_add_canvas_handler(canvas, ButtonPress, motion_hndl,(void *) 0);
fl_add_canvas_handler(canvas, ButtonRelease, motion_hndl,(void *) 0);
if( FL_ObjWin(canvas) == 0 ){
ERR_MSG("Canvas Window Unkown As Yet\n");
}else{
/* So how do I modify these before canvas is created ? */
fl_remove_selected_xevent(FL_ObjWin(canvas),
PointerMotionHintMask);
fl_remove_selected_xevent(FL_ObjWin(canvas),
Button2MotionMask);
}
return;
}
static int
expose_hndl(FL_OBJECT * ob, Window win, int w, int h, XEvent * xev, void *data)
{
int dmode;
XF_IM_DESC *xfm = (XF_IM_DESC *) ob->u_vdata;
/* Refresh image display here */
if(xfm->drawn){ /* deal with existing rbanded region */
dmode=fl_get_drawmode();
fl_drawmode(GXxor); /* redraw box */
fl_winset(win);
fl_rectf(xfm->ox,xfm->oy,xfm->dx,xfm->dy,CLR);
fl_drawmode(dmode);
}
return 0;
}
static int
cross_hndl(FL_OBJECT *ob, Window win, int w, int h, XEvent *xev, void *data)
{
switch(xev->type ){
case(EnterNotify):
fl_set_cursor(win,XC_crosshair);
break;
case(LeaveNotify):
fl_reset_cursor(win);
fl_hide_oneliner();
break;
default:
fl_print_xevent_name("Cross handler", xev);
}
return 0;
}
static int
motion_hndl(FL_OBJECT *ob, Window win, int w, int h, XEvent *xev, void *data)
{
int dmode;
char buf[50], *txt;
XF_IM_DESC *xfm = (XF_IM_DESC *) ob->u_vdata;
dmode=fl_get_drawmode();
switch(xev->type ){
case(MotionNotify):
if( xfm != NULL && xfm->xy_lab != NULL){
txt = xfm->xy_lab(xev->xmotion.x, xev->xmotion.y,
xev->xmotion.state, ob);
fl_show_oneliner(txt, ob->x + ob->form->x, ob->y+ob->form->y-20);
}else{
sprintf(buf,"x: %.3d y:%.3d, msk=$%x",
xev->xmotion.x, xev->xmotion.y, xev->xmotion.state);
fl_show_oneliner(buf,ob->x + ob->form->x, ob->y+ob->form->y-20);
}
if(xev->xmotion.state & (Button1Mask|Button3Mask)){ /*dragging*/
fl_drawmode(GXxor);
fl_winset(win);
if(xfm->drawn){ /* deal with existing rbanded region */
fl_rectf(xfm->ox,xfm->oy,xfm->dx,xfm->dy,CLR);
}
xfm->dx= xev->xmotion.x - xfm->ox;
xfm->dy= xev->xmotion.y - xfm->oy;
fl_rectf(xfm->ox,xfm->oy,xfm->dx,xfm->dy,CLR);
xfm->drawn=1;
fl_drawmode(dmode);
}
break;
case(ButtonPress):
switch (xev->xbutton.button) {
case (Button1):
case (Button3):
if(xfm->drawn){ /* deal with existing rbanded region */
fl_drawmode(GXxor); /* visually erase box */
fl_winset(win);
fl_rectf(xfm->ox,xfm->oy,xfm->dx,xfm->dy,CLR);
fl_drawmode(dmode);
xfm->drawn=0;
}
xfm->ox = xev->xbutton.x;
xfm->oy = xev->xbutton.y;
xfm->dx=xfm->dy=0;
break;
default:
#ifdef DBG
fprintf(stderr,"Unexpected Button Press $%x, State $%x\n",
xev->xbutton.button, xev->xbutton.state);
#endif
break;
}
break;
case (ButtonRelease):
switch (xev->xbutton.button) {
case (Button1):
break;
case (Button3):
break;
default:
#ifdef DBG
fprintf(stderr,"Unexpected Button Release $%x, State $%x\n",
xev->xbutton.button, xev->xbutton.state);
#endif
break;
}
break;
default:
fl_print_xevent_name("Motion handler", xev);
}
return 0;
}
/*---------------------------------------*/
-- -------------------------------------------------------------------- ___ ___/ _ __ / Ivan Powis [Ivan.Powis@Nottingham.ac.uk] / / / School of Chemistry / / _/ University of Nottingham / ___/ Nottingham NG7 2RD, UK / / TEL: +44-115-951-3467 / / FAX: +44-115-951-3562 _______/ ____/ http://www.chem.nott.ac.uk/IP.html --------------------------------------------------------------------_________________________________________________ To unsubscribe, send the message "unsubscribe" to xforms-request@bob.usuhs.mil or see http://bob.usuhs.mil/mailserv/xforms.html XForms Home Page: http://world.std.com/~xforms List Archive: http://bob.usuhs.mil/mailserv/list-archives/
This archive was generated by hypermail 2b29 : Fri May 11 2001 - 12:05:23 EDT