/* Written by Dan Heller and Paula Ferguson. * Copyright 1994, O'Reilly & Associates, Inc. * Permission to use, copy, and modify this program without * restriction is hereby granted, as long as this copyright * notice appears in each copy of the program source code. * This program is freely distributable without licensing fees and * is provided without guarantee or warrantee expressed or implied. * This program is -not- in the public domain. */ /* dynapix.c -- Display a bitmap in a MainWindow, but allow the user * to change the bitmap and its color dynamically. The design of the * program is structured on the pulldown menus of the menubar and the * callback routines associated with them. To allow the user to choose * a new bitmap, the "Open" button pops up a FileSelectionDialog where * a new bitmap file can be chosen. */ #include <Xm/MainW.h> #include <Xm/Label.h> #include <Xm/MessageB.h> #include <Xm/FileSB.h> /* Globals: the toplevel window/widget and the label for the bitmap. * "colors" defines the colors we use, "cur_color" is the current * color being used, and "cur_bitmap" references the current bitmap file. */ Widget toplevel, label; String colors[] = { "Black", "Red", "Green", "Blue" }; Pixel cur_color; char cur_bitmap[1024] = "xlogo64"; /* make large enough for full pathnames */ main(argc, argv) int argc; char *argv[]; { Widget main_w, menubar, menu, widget; XtAppContext app; Pixmap pixmap; XmString file, edit, help, open_, quit, red, green, blue, black; void file_cb(), change_color(), help_cb(); XtSetLanguageProc (NULL, NULL, NULL); /* Initialize toolkit and parse command line options. */ toplevel = XtVaAppInitialize (&app, "Demos", NULL, 0, &argc, argv, NULL, NULL); /* main window contains a MenuBar and a Label displaying a pixmap */ main_w = XtVaCreateManagedWidget ("main_window", xmMainWindowWidgetClass, toplevel, XmNscrollBarDisplayPolicy, XmAS_NEEDED, XmNscrollingPolicy, XmAUTOMATIC, NULL); /* Create a simple MenuBar that contains three menus */ file = XmStringCreateLocalized ("File"); edit = XmStringCreateLocalized ("Edit"); help = XmStringCreateLocalized ("Help"); menubar = XmVaCreateSimpleMenuBar (main_w, "menubar", XmVaCASCADEBUTTON, file, 'F', XmVaCASCADEBUTTON, edit, 'E', XmVaCASCADEBUTTON, help, 'H', NULL); XmStringFree (file); XmStringFree (edit); /* don't free "help" compound string yet -- reuse it later */ /* Tell the menubar which button is the help menu */ if (widget = XtNameToWidget (menubar, "button_2")) XtVaSetValues (menubar, XmNmenuHelpWidget, widget, NULL); /* First menu is the File menu -- callback is file_cb() */ open_ = XmStringCreateLocalized ("Open..."); quit = XmStringCreateLocalized ("Quit"); XmVaCreateSimplePulldownMenu (menubar, "file_menu", 0, file_cb, XmVaPUSHBUTTON, open_, 'N', NULL, NULL, XmVaSEPARATOR, XmVaPUSHBUTTON, quit, 'Q', NULL, NULL, NULL); XmStringFree (open_); XmStringFree (quit); /* Second menu is the Edit menu -- callback is change_color() */ black = XmStringCreateLocalized (colors[0]); red = XmStringCreateLocalized (colors[1]); green = XmStringCreateLocalized (colors[2]); blue = XmStringCreateLocalized (colors[3]); menu = XmVaCreateSimplePulldownMenu (menubar, "edit_menu", 1, change_color, XmVaRADIOBUTTON, black, 'k', NULL, NULL, XmVaRADIOBUTTON, red, 'R', NULL, NULL, XmVaRADIOBUTTON, green, 'G', NULL, NULL, XmVaRADIOBUTTON, blue, 'B', NULL, NULL, XmNradioBehavior, True, /* RowColumn resources to enforce */ XmNradioAlwaysOne, True, /* radio behavior in Menu */ NULL); XmStringFree (black); XmStringFree (red); XmStringFree (green); XmStringFree (blue); /* Initialize menu so that "black" is selected. */ if (widget = XtNameToWidget (menu, "button_0")) XtVaSetValues (widget, XmNset, True, NULL); /* Third menu is the help menu -- callback is help_cb() */ XmVaCreateSimplePulldownMenu (menubar, "help_menu", 2, help_cb, XmVaPUSHBUTTON, help, 'H', NULL, NULL, NULL); XmStringFree (help); /* we're done with it; now we can free it */ XtManageChild (menubar); /* user can still specify the initial bitmap */ if (argv[1]) strcpy (cur_bitmap, argv[1]); /* initialize color */ cur_color = BlackPixelOfScreen (XtScreen (toplevel)), /* create initial bitmap */ pixmap = XmGetPixmap (XtScreen (toplevel), cur_bitmap, cur_color, WhitePixelOfScreen (XtScreen (toplevel))); if (pixmap == XmUNSPECIFIED_PIXMAP) { puts ("can't create initial pixmap"); exit (1); } /* Now create label using pixmap */ label = XtVaCreateManagedWidget ("label", xmLabelWidgetClass, main_w, XmNlabelType, XmPIXMAP, XmNlabelPixmap, pixmap, NULL); /* set the label as the "work area" of the main window */ XtVaSetValues (main_w, XmNmenuBar, menubar, XmNworkWindow, label, NULL); XtRealizeWidget (toplevel); XtAppMainLoop (app); } void unmanagechild (widget, client_data, call_data) Widget widget; XtPointer client_data; XtPointer call_data; { XtUnmanageChild(widget); } /* Any item the user selects from the File menu calls this function. * It will either be "Open" (item_no == 0) or "Quit" (item_no == 1). */ void file_cb(widget, client_data, call_data) Widget widget; /* menu item that was selected */ XtPointer client_data; /* the index into the menu */ XtPointer call_data; /* unused */ { static Widget dialog; /* make it static for reuse */ extern void load_pixmap(); int item_no = (int) client_data; if (item_no == 1) /* the "quit" item */ exit (0); /* "Open" was selected. Create a Motif FileSelectionDialog w/callback */ if (!dialog) { dialog = XmCreateFileSelectionDialog (toplevel, "file_sel", NULL, 0); XtAddCallback (dialog, XmNokCallback, load_pixmap, NULL); XtAddCallback (dialog, XmNcancelCallback, unmanagechild, NULL); } XtManageChild (dialog); XtPopup (XtParent (dialog), XtGrabNone); } /* The OK button was selected from the FileSelectionDialog (or, the user * double-clicked on a file selection). Try to read the file as a bitmap. * If the user changed colors, we call this function directly from change_color() * to reload the pixmap. In this case, we pass NULL as the callback struct * so we can identify this special case. */ void load_pixmap(dialog, client_data, call_data) Widget dialog; XtPointer client_data; XtPointer call_data; { Pixmap pixmap; char *file = NULL; XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *) call_data; if (cbs) { if (!XmStringGetLtoR (cbs->value, XmFONTLIST_DEFAULT_TAG, &file)) return; /* internal error */ (void) strcpy (cur_bitmap, file); XtFree (file); /* free allocated data from XmStringGetLtoR() */ } pixmap = XmGetPixmap (XtScreen (toplevel), cur_bitmap, cur_color, WhitePixelOfScreen (XtScreen (toplevel))); if (pixmap == XmUNSPECIFIED_PIXMAP) printf ("Can't create pixmap from %s\n", cur_bitmap); else { Pixmap old; XtVaGetValues (label, XmNlabelPixmap, &old, NULL); XmDestroyPixmap (XtScreen (toplevel), old); XtVaSetValues (label, XmNlabelType, XmPIXMAP, XmNlabelPixmap, pixmap, NULL); } } /* called from any of the "Edit" menu items. Change the color of the * current bitmap being displayed. Do this by calling load_pixmap(). */ void change_color(widget, client_data, call_data) Widget widget; /* menu item that was selected */ XtPointer client_data; /* the index into the menu */ XtPointer call_data; /* unused */ { XColor xcolor, unused; Display *dpy = XtDisplay (label); Colormap cmap = DefaultColormapOfScreen (XtScreen (label)); int item_no = (int) client_data; if (XAllocNamedColor (dpy, cmap, colors[item_no], &xcolor, &unused) == 0 || cur_color == xcolor.pixel) return; cur_color = xcolor.pixel; load_pixmap (widget, NULL, NULL); } #define MSG \ "Use the FileSelection dialog to find bitmap files to\n\ display in the scrolling area in the main window. Use\n\ the edit menu to display the bitmap in different colors." /* The help button in the help menu from the menubar was selected. * Display help information defined above for how to use the program. * This is done by creating a Motif information dialog box. Again, * make the dialog static so we can reuse it. */ void help_cb(widget, client_data, call_data) Widget widget; XtPointer client_data; XtPointer call_data; { static Widget dialog; if (!dialog) { Arg args[5]; int n = 0; XmString msg = XmStringCreateLtoR (MSG, XmFONTLIST_DEFAULT_TAG); XtSetArg (args[n], XmNmessageString, msg); n++; dialog = XmCreateInformationDialog (toplevel, "help_dialog", args, n); } XtManageChild (dialog); XtPopup (XtParent (dialog), XtGrabNone); }