/* Motif_struct.c 1.1 */ /* Copyright 1992, 1993 O'Reilly and Associates, Inc. Permission to use, copy, and modify this program is hereby granted, as long as this copyright notice appears in each copy of the program source code. */ #include #include #include #include #include #include #include #include #include #include #include "book_utils.h" /* Internal global variables */ static Widget top; static Display *dpy; static Window window; static PEXRenderer renderer; static PEXStructure struct_id; static Atom delete_window_atom; static float linewidth = 3.0; static int linetype = PEXLineTypeSolid; static PEXCoord2D *curve; static int num_points; /* Labels */ #define LINEWIDTH 1 #define LINETYPE 2 /* Parameters for the curve we display. */ #define NUM_CURVE_SEGMENTS 40 #define X_START 0.1 #define X_SIZE 0.8 #define Y_START 0.5 #define Y_SIZE 0.2 static void create_curve() { double dx, angle; int i; num_points = NUM_CURVE_SEGMENTS + 1; curve = (PEXCoord2D *) malloc( num_points * sizeof(PEXCoord2D) ); dx = X_SIZE / NUM_CURVE_SEGMENTS; curve[0].x = X_START; curve[0].y = Y_START + Y_SIZE; for ( i = 1; i <= NUM_CURVE_SEGMENTS; i++ ) { curve[i].x = curve[i-1].x + dx; angle = ((curve[i].x - X_START) / X_SIZE) * 2 * M_PI; curve[i].y = Y_START + Y_SIZE * cos( angle ); } } static void redraw() { /* Redraw the window, after first erasing (clearing) it. */ XClearWindow( dpy, window ); PEXRenderNetwork( dpy, window, renderer, struct_id ); XFlush( dpy ); } /* Callback for Expose events. */ static void expose( w, client_data, event ) Widget w; XtPointer client_data; XEvent *event; { /* Redraw when last Expose event received. */ if ( event->xexpose.count == 0 ) redraw(); } /* Callback function to set the linetype. */ static void set_linetype( w, client_data, call_data ) Widget w; int client_data; XtPointer call_data; { /* Replace the Set Linetype structure element. */ linetype = client_data; PEXSetEditingMode( dpy, struct_id, PEXStructureReplace ); PEXSetElementPtr( dpy, struct_id, PEXBeginning, 0 ); PEXSetElementPtrAtLabel( dpy, struct_id, LINETYPE, 1 ); PEXSetLineType( dpy, struct_id, PEXOCStore, linetype ); redraw(); } /* Callback function to set the linewidth. */ static void set_linewidth( w, client_data, call_data ) Widget w; int client_data; XtPointer call_data; { /* Replace the Set Linewidth structure element. */ linewidth = (float)client_data; PEXSetEditingMode( dpy, struct_id, PEXStructureReplace ); PEXSetElementPtr( dpy, struct_id, PEXBeginning, 0 ); PEXSetElementPtrAtLabel( dpy, struct_id, LINEWIDTH, 1 ); PEXSetLineWidth( dpy, struct_id, PEXOCStore, linewidth ); redraw(); } /* Callback function to quit the program. */ static void quit( w, client_data, call_data ) Widget w; XtPointer client_data; XmAnyCallbackStruct *call_data; { XClientMessageEvent *cm = &call_data->event->xclient; if ( cm->data.l[0] == delete_window_atom ) { XtDestroyWidget( top ); exit( 0 ); } } static void create_structure( dpy ) Display *dpy; { PEXColor color; /* Create the structure. */ struct_id = PEXCreateStructure( dpy ); /* Add the elements. */ SET_COLOR( 1, 1, 1, color ); /* white */ PEXSetLineColor( dpy, struct_id, PEXOCStore, PEXColorTypeRGB, &color ); PEXLabel( dpy, struct_id, PEXOCStore, LINEWIDTH ); PEXSetLineWidth( dpy, struct_id, PEXOCStore, linewidth ); PEXLabel( dpy, struct_id, PEXOCStore, LINETYPE ); PEXSetLineType( dpy, struct_id, PEXOCStore, linetype ); create_curve(); PEXPolyline2D( dpy, struct_id, PEXOCStore, num_points, curve ); free( curve ); } /* Macro to simplify creating buttons. */ #define ADD_BUTTON( _label, _w, _f, _val ) \ (XtAddCallback( XtVaCreateManagedWidget( (_label), \ xmPushButtonWidgetClass, (_w), NULL), \ XmNactivateCallback, (_f), (_val) )) main( argc, argv ) int argc; char *argv[]; { Widget form, canvas, bar, menu; XVisualInfo vis_info; XStandardColormap cmap_info; PEXColorApproxEntry capx_info; PEXRendererAttributes rattrs; XSetWindowAttributes wattrs; XtAppContext app; PEXExtensionInfo *pexinfo; char err[80]; /* Initialize the toolkit. */ top = XtVaAppInitialize( &app, "Motif_struct", NULL, 0, &argc, argv, NULL, NULL ); /* See what display is being used. */ dpy = XtDisplay( top ); /* See if a PEX extension exists and initialize PEXlib. */ if ( PEXInitialize( dpy, &pexinfo, 80, err ) != 0 ) { fprintf( stderr, "No PEX extension.\n" ); fprintf( stderr, "%s\n", err ); exit(1); } /* Determine the best visual to use. */ ora_find_best_visual( dpy, &vis_info ); /* Get a standard colormap for the visual. */ if ( !ora_get_standard_colormap( dpy, &vis_info, &cmap_info ) ) { fprintf ( stderr, "Cannot find a standard colormap\n" ); exit(1); } ora_set_stdcmap_approx( &vis_info, &cmap_info, &capx_info ); /* Set the visual, depth, and colormap for the shell. */ XtVaSetValues( top, XtNvisual, vis_info.visual, XtNdepth, vis_info.depth, XtNcolormap, cmap_info.colormap, NULL ); /* Create the program's containing form. */ form = XtVaCreateManagedWidget( NULL, xmFormWidgetClass, top, NULL ); /* Create the menu bar. */ bar = XmCreateMenuBar( form, "menubar", NULL, 0 ); XtVaSetValues( bar, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL ); XtManageChild( bar ); /* Create the Linetype menu. */ menu = XmCreatePulldownMenu( bar, "linetype", NULL, 0 ); XtVaCreateManagedWidget( "Linetype", xmCascadeButtonWidgetClass, bar, XmNsubMenuId, menu, NULL ); ADD_BUTTON( "solid", menu, set_linetype, PEXLineTypeSolid ); ADD_BUTTON( "dashed", menu, set_linetype, PEXLineTypeDashed ); ADD_BUTTON( "dotted", menu, set_linetype, PEXLineTypeDotted ); ADD_BUTTON( "dash-dot", menu, set_linetype, PEXLineTypeDashDot ); /* Create the Linetwidth menu. */ menu = XmCreatePulldownMenu( bar, "linewidth", NULL, 0 ); XtVaCreateManagedWidget( "Linewidth", xmCascadeButtonWidgetClass, bar, XmNsubMenuId, menu, NULL ); ADD_BUTTON( "very thin (1)", menu, set_linewidth, 1 ); ADD_BUTTON( "thin (2)", menu, set_linewidth, 2 ); ADD_BUTTON( "medium (3)", menu, set_linewidth, 3 ); ADD_BUTTON( "wide (4)", menu, set_linewidth, 4 ); ADD_BUTTON( "very wide (9)", menu, set_linewidth, 9 ); /* Create the widget we'll use as a drawing window. */ canvas = XtVaCreateManagedWidget( "canvas", xmDrawingAreaWidgetClass, form, XtVaTypedArg, XmNbackground, XmRString, "black", 6, XtNwidth, 250, XtNheight, 250, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, bar, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL ); /* Register an event handler for Expose events. */ XtAddEventHandler( canvas, ExposureMask, False, expose, 0 ); /* Realize the widgets. */ XtRealizeWidget( top ); /* Set up to use window manager DELETE_WINDOW protocol. */ delete_window_atom = XInternAtom( dpy, "WM_DELETE_WINDOW", TRUE ); XmAddWMProtocols( top, &delete_window_atom, 1 ); XmSetWMProtocolHooks( top, delete_window_atom, NULL, NULL, quit, NULL ); /* Set the backing store attribute. */ window = XtWindow( canvas ); wattrs.backing_store = NotUseful; XChangeWindowAttributes( dpy, window, CWBackingStore, &wattrs ); /* Create the renderer and the structure. */ if ( STRUCTURE_SPT( pexinfo ) ) { renderer = ora_setup_renderer( dpy, window, &capx_info, &rattrs ); create_structure( dpy ); } else { fprintf( stderr, "Structures not supported.\n" ); exit(5); } XtAppMainLoop( app ); return 0; }