added frontend
This commit is contained in:
parent
6446c9b24d
commit
6a2edcde49
9 changed files with 337 additions and 0 deletions
24
frontend/Makefile
Executable file
24
frontend/Makefile
Executable file
|
@ -0,0 +1,24 @@
|
|||
# adding cairo.pc
|
||||
export PKG_CONFIG_PATH:=/usr/lib/x86_64-linux-gnu/pkgconfig/
|
||||
|
||||
# programs
|
||||
CC = gcc
|
||||
PC=pkg-config
|
||||
RM=rm
|
||||
|
||||
TARGET=frontend
|
||||
OBJS=Plot.o XWindow.o cairotest.o
|
||||
|
||||
CFLAGS = -Wall `$(PC) --cflags cairomm-xlib-1.0`
|
||||
LIBS = -lm `$(PC) --libs cairomm-xlib-1.0`
|
||||
INC = -I/usr/include/cairomm-1.0/
|
||||
|
||||
all: $(OBJS)
|
||||
$(CC) $(OBJS) $(LIBS) -o $(TARGET)
|
||||
|
||||
%.o: %.cpp
|
||||
$(CC) $(CFLAGS) $(INC) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) frontend
|
||||
$(RM) $(OBJS)
|
108
frontend/Plot.cpp
Normal file
108
frontend/Plot.cpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "Plot.h"
|
||||
|
||||
PlotSeries::PlotSeries(PlotSeries::Style style, Color color)
|
||||
: color(color), style(style)
|
||||
{ }
|
||||
|
||||
void PlotSeries::draw(RefPtr<Context> ctx) {
|
||||
ctx->set_source_rgb(color.red, color.green, color.blue); /* set series color */
|
||||
|
||||
/* determine maxima and minima for autoscale */
|
||||
double min = DBL_MAX, max = DBL_MIN;
|
||||
for (std::list<double>::iterator it = begin(); it != end(); it++) {
|
||||
if (*it > max) max = *it;
|
||||
if (*it < min) min = *it;
|
||||
}
|
||||
|
||||
/* stroke */
|
||||
|
||||
int width = 800;//dynamic_cast<RefPtr<XlibSurface>>(ctx->get_target())->get_width();
|
||||
int height = 400;//dynamic_cast<RefPtr<XlibSurface>>(ctx->get_target())->get_height();
|
||||
|
||||
ctx->move_to(Plot::PADDING, (height/2) + (height-2*Plot::PADDING) * (front()/max));
|
||||
|
||||
int i = 0;
|
||||
for (std::list<double>::iterator it = begin(); it != end(); it++) {
|
||||
i++;
|
||||
ctx->line_to(i * 2 + Plot::PADDING, (height/2) + (height-2*Plot::PADDING) * (*it/max*0.5));
|
||||
}
|
||||
ctx->stroke();
|
||||
}
|
||||
|
||||
Plot::Plot(int width, int height)
|
||||
: width(width), height(height)
|
||||
{
|
||||
window = XWindow::create("Frontend", 1, 1, width, height);
|
||||
surface = XlibSurface::create(window->getDisplay(), window->getWindow(), window->getVisual(), width, height);
|
||||
}
|
||||
|
||||
void Plot::draw() {
|
||||
RefPtr<Context> ctx = Context::create(surface);
|
||||
ctx->set_antialias(ANTIALIAS_SUBPIXEL);
|
||||
|
||||
/* background */
|
||||
ctx->set_source_rgb(0, 0, 0); /* black */
|
||||
ctx->paint();
|
||||
|
||||
ctx->set_source_rgb(0, 0.7, 0.1); /* axis & tick color */
|
||||
drawAxes(ctx);
|
||||
drawTicks(ctx);
|
||||
|
||||
for (std::list<PlotSeries *>::iterator it = series.begin(); it != series.end(); it++) {
|
||||
(*it)->draw(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void Plot::drawAxes(RefPtr<Context> ctx) {
|
||||
ctx->set_line_width(1.8);
|
||||
|
||||
/* x-axis */
|
||||
ctx->move_to(PADDING, height-PADDING);
|
||||
ctx->line_to(width-PADDING, height-PADDING);
|
||||
ctx->stroke();
|
||||
|
||||
/* y-axis */
|
||||
ctx->move_to(PADDING, height-PADDING);
|
||||
ctx->line_to(PADDING, PADDING);
|
||||
ctx->stroke();
|
||||
|
||||
/* arrows (arcs) */
|
||||
ctx->move_to(width-PADDING-2, height-PADDING-4);
|
||||
ctx->line_to(width-PADDING+5, height-PADDING);
|
||||
ctx->line_to(width-PADDING-2, height-PADDING+4);
|
||||
ctx->stroke();
|
||||
|
||||
ctx->move_to(PADDING-4, PADDING+2);
|
||||
ctx->line_to(PADDING, PADDING-5);
|
||||
ctx->line_to(PADDING+4, PADDING+2);
|
||||
ctx->stroke();
|
||||
}
|
||||
|
||||
void Plot::drawTicks(RefPtr<Context> ctx) {
|
||||
int ticks = 20;
|
||||
int intv_x = (width-2*PADDING)/ticks;
|
||||
int intv_y = (height-2*PADDING)/ticks;
|
||||
|
||||
ctx->set_line_width(1);
|
||||
|
||||
for (int i = 0; i < ticks; i++) {
|
||||
/* x-axis */
|
||||
ctx->move_to(PADDING + i*intv_x, height-PADDING-3);
|
||||
ctx->line_to(PADDING + i*intv_x, height-PADDING+3);
|
||||
ctx->stroke();
|
||||
|
||||
/* y-axis */
|
||||
ctx->move_to(PADDING-3, PADDING + (i+1)*intv_y);
|
||||
ctx->line_to(PADDING+3, PADDING + (i+1)*intv_y);
|
||||
ctx->stroke();
|
||||
}
|
||||
}
|
||||
|
||||
Plot::~Plot() {
|
||||
|
||||
}
|
50
frontend/Plot.h
Normal file
50
frontend/Plot.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#ifndef _PLOT_H_
|
||||
#define _PLOT_H_
|
||||
|
||||
#include <list>
|
||||
#include <cairomm/cairomm.h>
|
||||
#include <cairomm/xlib_surface.h>
|
||||
|
||||
#include "XWindow.h"
|
||||
|
||||
using namespace Cairo;
|
||||
|
||||
struct Color {
|
||||
double red, green, blue, alpha;
|
||||
};
|
||||
|
||||
class PlotSeries : public std::list<double> {
|
||||
|
||||
public:
|
||||
Color color;
|
||||
enum Style { STYLE_LINE, STYLE_SPLINE, STYLE_SCATTER } style;
|
||||
|
||||
PlotSeries(enum Style style, Color color);
|
||||
void draw(RefPtr<Context> ctx);
|
||||
};
|
||||
|
||||
class Plot {
|
||||
|
||||
friend class PlotSeries;
|
||||
|
||||
public:
|
||||
Plot(int width = 400, int height = 300);
|
||||
virtual ~Plot();
|
||||
|
||||
void draw();
|
||||
|
||||
std::list<PlotSeries *> series;
|
||||
|
||||
protected:
|
||||
RefPtr<XWindow> window;
|
||||
RefPtr<Surface> surface;
|
||||
|
||||
int width, height;
|
||||
|
||||
void drawAxes(RefPtr<Context> ctx);
|
||||
void drawTicks(RefPtr<Context> ctx);
|
||||
|
||||
static const int PADDING = 20;
|
||||
};
|
||||
|
||||
#endif /* _PLOT_H_ */
|
BIN
frontend/Plot.o
Normal file
BIN
frontend/Plot.o
Normal file
Binary file not shown.
60
frontend/XWindow.cpp
Normal file
60
frontend/XWindow.cpp
Normal file
|
@ -0,0 +1,60 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "XWindow.h"
|
||||
|
||||
Display * XWindow::display = NULL;
|
||||
int XWindow::windows = 0;
|
||||
int XWindow::screen = 0;
|
||||
|
||||
XException::XException(const char *reason) {
|
||||
fprintf(stderr, "%s\n", reason);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
XWindow::XWindow(const char *title, int x, int y, int width, int height, unsigned long background) {
|
||||
Window rootWindow;
|
||||
|
||||
screen = XDefaultScreen(display);
|
||||
rootWindow = XRootWindow(display, screen);
|
||||
|
||||
window = XCreateSimpleWindow(display, rootWindow, x, y, width, height, 0, 0, background);
|
||||
|
||||
XStoreName(display, window, title);
|
||||
XSelectInput(display, window, ExposureMask | ButtonPressMask);
|
||||
XMapWindow(display, window);
|
||||
}
|
||||
|
||||
XWindow::~XWindow() {
|
||||
windows--;
|
||||
|
||||
if (windows == 0) {
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
Display * XWindow::getDisplay() {
|
||||
if (display == NULL) {
|
||||
throw new XException("There exists no connection to an XServer!");
|
||||
}
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
void XWindow::connect(std::string display_name) {
|
||||
display = XOpenDisplay(display_name.c_str());
|
||||
|
||||
if (display == NULL) {
|
||||
throw XException("Cannot open display!");
|
||||
}
|
||||
}
|
||||
|
||||
void XWindow::disconnect() {
|
||||
XCloseDisplay(display);
|
||||
}
|
||||
|
||||
Cairo::RefPtr<XWindow> XWindow::create(const char *title, int x, int y, int width, int height, unsigned long background) {
|
||||
XWindow *win = new XWindow(title, x, y, width, height, background);
|
||||
return Cairo::RefPtr<XWindow>(win);
|
||||
}
|
49
frontend/XWindow.h
Normal file
49
frontend/XWindow.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#ifndef _XWINDOW_H_
|
||||
#define _XWINDOW_H_
|
||||
|
||||
#include <cairomm/refptr.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
class XException {
|
||||
public:
|
||||
XException(const char * reason);
|
||||
};
|
||||
|
||||
class XWindow {
|
||||
|
||||
public:
|
||||
XWindow(
|
||||
const char *title,
|
||||
int x = 1, int y = 1,
|
||||
int width = 800, int height = 600,
|
||||
unsigned long background = 0
|
||||
);
|
||||
|
||||
virtual ~XWindow();
|
||||
|
||||
Window getWindow() { return window; };
|
||||
Visual * getVisual() { return XDefaultVisual(display, screen); };
|
||||
|
||||
static Display * getDisplay();
|
||||
|
||||
static void connect(std::string display);
|
||||
static void disconnect();
|
||||
|
||||
static Cairo::RefPtr<XWindow> create(
|
||||
const char *title,
|
||||
int x = 1, int y = 1,
|
||||
int width = 800, int height = 600,
|
||||
unsigned long background = 0
|
||||
);
|
||||
|
||||
protected:
|
||||
Window window;
|
||||
|
||||
static Display *display;
|
||||
static int screen;
|
||||
static int windows; /* reference counter to open windows */
|
||||
};
|
||||
|
||||
#endif /* _XWINDOW_H_ */
|
BIN
frontend/XWindow.o
Normal file
BIN
frontend/XWindow.o
Normal file
Binary file not shown.
46
frontend/cairotest.cpp
Normal file
46
frontend/cairotest.cpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#include "XWindow.h"
|
||||
#include "Plot.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace Cairo;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
XWindow::connect(":0"); // TODO parse from argv
|
||||
|
||||
XEvent e;
|
||||
Color blue = { 0, 0, 1 };
|
||||
Color red = { 1, 0, 0 };
|
||||
Plot testPlot(800, 400);
|
||||
Plot testPlot2(800, 400);
|
||||
|
||||
PlotSeries *demo1 = new PlotSeries(PlotSeries::STYLE_LINE, blue);
|
||||
PlotSeries *demo2 = new PlotSeries(PlotSeries::STYLE_LINE, red);
|
||||
testPlot.series.push_back(demo1);
|
||||
testPlot2.series.push_back(demo2);
|
||||
|
||||
double phi = 0;
|
||||
double last = 0;
|
||||
|
||||
while (1) {
|
||||
phi += 1e-1;
|
||||
|
||||
last += -10 + rand()%21;
|
||||
|
||||
demo2->push_back(last);
|
||||
|
||||
if (demo2->size() > 400) demo2->pop_front();
|
||||
|
||||
demo1->clear();
|
||||
for (int i = 0; i < 300; i++) {
|
||||
demo1->push_back(0.7*sin(i*phi/1e3)*sin(i * (M_PI/30.0) + phi));
|
||||
}
|
||||
|
||||
usleep(0.2*1e5);
|
||||
testPlot.draw();
|
||||
testPlot2.draw();
|
||||
}
|
||||
}
|
BIN
frontend/cairotest.o
Normal file
BIN
frontend/cairotest.o
Normal file
Binary file not shown.
Loading…
Add table
Reference in a new issue