+/* 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;
+}