#include <X11/Xaw/Toggle.h>
#include <X11/Xaw/Scrollbar.h>
+#include <cairo/cairo.h>
+#include <cairo/cairo-xlib.h>
+
#include "common.h"
#include "backend.h"
#include "xboard.h"
};
void
+MarkMenuItem (char *menuRef, int state)
+{
+ MenuItem *item = MenuNameToItem(menuRef);
+
+ if(item) {
+ Arg args[2];
+ XtSetArg(args[0], XtNleftBitmap, state ? xMarkPixmap : None);
+ XtSetValues(item->handle, args, 1);
+ }
+}
+
+void
GetWidgetText (Option *opt, char **buf)
{
Arg arg;
{ // handle expose and mouse events on Graph widget
Dimension w, h;
Arg args[16];
- int j, button=10, f=1;
- Option *opt;
+ int j, button=10, f=1, sizing=0;
+ Option *opt, *graph = (Option *) client_data;
+ PointerCallback *userHandler = graph->target;
+
if (!XtIsRealized(widget)) return;
switch(event->type) {
- case Expose:
- if (((XExposeEvent*)event)->count > 0) return; // don't bother if further exposure is pending
- /* Get client area */
+ case Expose: // make handling of expose events generic, just copying from memory buffer (->choice) to display (->textValue)
+ /* Get window size */
j = 0;
XtSetArg(args[j], XtNwidth, &w); j++;
XtSetArg(args[j], XtNheight, &h); j++;
XtGetValues(widget, args, j);
- break;
+
+ if(w < graph->max || w > graph->max + 1 || h != graph->value) { // use width fudge of 1 pixel
+ if(((XExposeEvent*)event)->count >= 0) { // suppress sizing on expose for ordered redraw in response to sizing.
+ sizing = 1;
+ graph->max = w; graph->value = h; // note: old values are kept if we we don't exceed width fudge
+ }
+ } else w = graph->max;
+
+ if(sizing && ((XExposeEvent*)event)->count > 0) { graph->max = 0; return; } // don't bother if further exposure is pending during resize
+ if(!graph->textValue || sizing) { // create surfaces of new size for display widget
+ if(graph->textValue) cairo_surface_destroy((cairo_surface_t *)graph->textValue);
+ graph->textValue = (char*) cairo_xlib_surface_create(xDisplay, XtWindow(widget), DefaultVisual(xDisplay, 0), w, h);
+ }
+ if(sizing) { // the memory buffer was already created in GenericPopup(),
+ // to give drawing routines opportunity to use it before first expose event
+ // (which are only processed when main gets to the event loop, so after all init!)
+ // so only change when size is no longer good
+ if(graph->choice) cairo_surface_destroy((cairo_surface_t *) graph->choice);
+ graph->choice = (char**) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h);
+ break;
+ }
+ w = ((XExposeEvent*)event)->width;
+ if(((XExposeEvent*)event)->x + w > graph->max) w--; // cut off fudge pixel
+ if(w) ExposeRedraw(graph, ((XExposeEvent*)event)->x, ((XExposeEvent*)event)->y, w, ((XExposeEvent*)event)->height);
+ return;
case MotionNotify:
f = 0;
w = ((XButtonEvent*)event)->x; h = ((XButtonEvent*)event)->y;
}
}
button *= f;
- opt = ((PointerCallback*) client_data)(button, w, h);
+ opt = userHandler(button, w, h);
if(opt) { // user callback specifies a context menu; pop it up
XUngrabPointer(xDisplay, CurrentTime);
XtCallActionProc(widget, "XawPositionSimpleMenu", event, &(opt->name), 1);
XSync(xDisplay, False);
}
+void
+GraphExpose (Option *opt, int x, int y, int w, int h)
+{
+ XExposeEvent e;
+ if(!opt->handle) return;
+ e.x = x; e.y = y; e.width = w; e.height = h; e.count = -1; e.type = Expose; // count = -1: kludge to suppress sizing
+ GraphEventProc(opt->handle, (caddr_t) opt, (XEvent *) &e); // fake expose event
+}
+
static void
GenericCallback (Widget w, XtPointer client_data, XtPointer call_data)
{ // all Buttons in a dialog (including OK, cancel) invoke this
if(engineDlg) { // Settings popup for engine: format through heuristic
int n = currentCps->nrOptions;
- if(!n) { DisplayNote(_("Engine has no options")); currentCps = NULL; return 0; }
if(n > 50) width = 4; else if(n>24) width = 2; else width = 1;
height = n / width + 1;
if(n && (currentOption[n-1].type == Button || currentOption[n-1].type == SaveButton)) currentOption[n].min = SAME_ROW; // OK on same line
option[i].handle = (void*)
(last = XtCreateManagedWidget("graph", widgetClass, form, args, j));
XtAddEventHandler(last, ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask, False,
- (XtEventHandler) GraphEventProc, option[i].target); // mandatory user-supplied expose handler
+ (XtEventHandler) GraphEventProc, &option[i]); // mandatory user-supplied expose handler
if(option[i].min & SAME_ROW) last = forelast, forelast = lastrow;
+ option[i].choice = (char**) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, option[i].max, option[i].value); // image buffer
break;
case PopUp: // note: used only after Graph, so 'last' refers to the Graph widget
option[i].handle = (void*) CreateComboPopup(last, option + i, i + 256*dlgNr, TRUE, option[i].value);