]> git.cworth.org Git - acre/commitdiff
Add a simple X-based demo program
authorCarl Worth <cworth@cworth.org>
Thu, 7 Nov 2013 04:09:48 +0000 (20:09 -0800)
committerCarl Worth <cworth@cworth.org>
Thu, 7 Nov 2013 04:09:48 +0000 (20:09 -0800)
This is the same chart as in acre-test, but in an interactive program
using Xlib and cairo.

So far, the only interactivity is that it redraws the chart to match
any changes to window size.

Makefile
acre-x.c [new file with mode: 0644]

index a14d677174f67aec9d5bc08cf96c1eab15c4ef50..b1fcaeb4252b4c16ac5a82cdb80f684046e3dd59 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-bin_PROGRAMS = acre-test
+bin_PROGRAMS = acre-test acre-x
 
 acre_test_SOURCES = \
        acre-test.c \
@@ -14,11 +14,18 @@ acre_test_CFLAGS=$$(pkg-config --cflags pangocairo lcms) \
        -Wmissing-prototypes -Wmissing-declarations \
        -Wnested-externs -Wno-unused-parameter
 
+acre_x_LDFLAGS=$(acre_test_LDFLAGS) -lX11
+
+acre_x_CFLAGS=$(acre_test_CFLAGS)
+
 all: $(bin_PROGRAMS)
 
 acre-test: acre-test.o acre.o xmalloc.o
        $(CC) $(LDFLAGS) $(acre_test_LDFLAGS) $(acre_test_CFLAGS) $(CFLAGS) -o $@ $^
 
+acre-x: acre-x.o acre.o xmalloc.o
+       $(CC) $(LDFLAGS) $(acre_x_LDFLAGS) $(acre_x_CFLAGS) $(CFLAGS) -o $@ $^
+
 %.o: %.c
        $(CC) $(LDFLAGS) $(acre_test_LDFLAGS) $(acre_test_CFLAGS) $(CFLAGS) -c -o $@ $<
 
diff --git a/acre-x.c b/acre-x.c
new file mode 100644 (file)
index 0000000..4e2cd0f
--- /dev/null
+++ b/acre-x.c
@@ -0,0 +1,182 @@
+/* acre - A cairo-based library for creating plots and charts.
+ *
+ * Copyright © 2009 Carl Worth <cworth@cworth.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <stdbool.h>
+
+#include <X11/Xlib.h>
+#include <cairo-xlib.h>
+
+#include "acre.h"
+#include "math.h"
+
+static acre_t *
+load_chart (void)
+{
+       acre_t *acre;
+       acre_data_t *data0, *data1, *data2;
+       int i;
+
+       acre = acre_create ();
+       acre_set_x_axis_label (acre, "X axis");
+       acre_set_y_axis_label (acre, "Y axis");
+
+       data0 = acre_data_create ();
+       data1 = acre_data_create ();
+       data2 = acre_data_create ();
+
+       acre_data_set_name (data0, "Data 0");
+       acre_data_set_name (data1, "Data 1");
+       acre_data_set_name (data2, "Data 2");
+
+       for (i = 0; i <= 100; i++) {
+               acre_data_add_point_2d (data0, i,   0 - (i/3.0)*(i/3.0));
+       }
+
+       for (i = 0; i < 100; i++) {
+               double t = 1.0 - (i / 100.0);
+               acre_data_add_point_2d (data1, i, -1000 * (1.0 - t*t*t));
+       }
+       
+       for (i = 0; i <= 1000; i++) {
+               double t, x, y;
+               t = i/10.0 - 50;
+               x = t + 50;
+               if (t == 0.0)
+                       y = -200;
+               else
+                       y = -1200 + 1000 * sin(t) / t;
+               acre_data_add_point_2d (data2, x, y);
+       }
+
+       acre_add_data (acre, data0);
+       acre_add_data (acre, data1);
+       acre_add_data (acre, data2);
+
+       acre_set_title (acre, "All the data");
+
+       return acre;
+}
+
+static void
+draw (Display *dpy, Window window, Visual *visual, acre_t *acre,
+      int width, int height)
+{
+       cairo_t *cr;
+       cairo_surface_t *surface;
+
+       surface = cairo_xlib_surface_create (dpy, window, visual,
+                                            width, height);
+       cr = cairo_create (surface);
+
+       /* Erase to white */
+       cairo_set_source_rgb (cr, 1, 1, 1);
+       cairo_paint (cr);
+
+       acre_draw (acre, cr, width, height);
+
+       cairo_destroy (cr);
+
+       cairo_surface_destroy (surface);
+}
+
+
+static void
+handle_events(Display *dpy, Window window, Visual *visual,
+             acre_t *acre, int width, int height)
+{
+        XEvent xev;
+        KeyCode quit_code = XKeysymToKeycode (dpy, XStringToKeysym("Q"));
+       bool need_redraw = false;
+
+        while (1) {
+                if (! XPending (dpy) && need_redraw)
+                       draw (dpy, window, visual, acre, width, height);
+
+               XNextEvent (dpy, &xev);
+                switch (xev.type) {
+                case KeyPress:
+                        if (xev.xkey.keycode == quit_code) {
+                                return;
+                        }
+                        break;
+                case ConfigureNotify:
+                        width = xev.xconfigure.width;
+                        height = xev.xconfigure.height;
+                        break;
+                case Expose:
+                        if (xev.xexpose.count == 0)
+                               need_redraw = 1;
+                        break;
+                }
+        }
+}
+
+int
+main (void)
+{
+        Display *dpy;
+        Window window, root;
+       Visual *visual;
+       acre_t *acre;
+       XSetWindowAttributes window_attr;
+       Colormap colormap;
+       unsigned long window_mask, event_mask;
+       unsigned long white;
+
+       int width = 800;
+       int height = 600;
+
+       acre = load_chart ();
+
+        dpy = XOpenDisplay (NULL);
+
+        if (dpy == NULL) {
+                fprintf(stderr, "Failed to open display %s\n",
+                        XDisplayName(NULL));
+                return 1;
+        }
+
+       root = DefaultRootWindow (dpy);
+       white = WhitePixel (dpy, DefaultScreen (dpy));
+       visual = DefaultVisual (dpy, DefaultScreen (dpy));
+       colormap = XCreateColormap (dpy, root, visual, AllocNone);
+       event_mask = KeyPressMask | StructureNotifyMask | ExposureMask;
+
+       window_mask = 0;
+       window_mask |= CWBackPixel;     window_attr.background_pixel = white;
+       window_mask |= CWBorderPixel;   window_attr.border_pixel = white;
+       window_mask |= CWColormap;      window_attr.colormap = colormap;
+       window_mask |= CWEventMask;     window_attr.event_mask = event_mask;
+
+        window = XCreateWindow(dpy, root, 0, 0, width, height, 0,
+                              DefaultDepth (dpy, DefaultScreen (dpy)),
+                              InputOutput, visual,
+                              window_mask, &window_attr);
+
+        XMapWindow (dpy, window);
+
+        handle_events (dpy, window, visual, acre, width, height);
+
+       acre_destroy (acre);
+
+        XDestroyWindow (dpy, window);
+        XCloseDisplay (dpy);
+
+        return 0;
+}