All pastes #506371 Raw Edit

Someone

public text v1 · immutable
·published 2007-05-23 22:44 UTC
rendered paste body
module gui.gui;

import bcd.xcb.xcb;
import lodepng.png;
import std.stdio;
import std.file;
import std.string;

GUI gui;

class GUI{
	xcb_connection_t* conn;
	xcb_screen_t* screen;
	
	Window[xcb_window_t] windows;
	Button[xcb_window_t] buttons;

	
	xcb_generic_event_t* event;
		
	this(){
		int screen_num;
		conn = xcb_connect(null, &screen_num);
		
		/* Get the preferred screen. */
		xcb_screen_iterator_t screen_iter = xcb_setup_roots_iterator(xcb_get_setup(conn));
		while(screen_num--)
			xcb_screen_next(&screen_iter);
		screen = screen_iter.data;
	}
	
	Window addWindow(geometry geom){
		Window w = new Window(screen.root, 0, 0, geom); //Position handled by the window manager
		xcb_change_window_attributes(gui.conn, w.id, XCB_CW_EVENT_MASK, cast(uint*)[XCB_EVENT_MASK_RESIZE_REDIRECT]);
		windows[w.id] = w;
		return w;
	}
	
	void loop(){
		loop:
		
		xcb_flush(gui.conn);
		
		event = xcb_wait_for_event(conn);
		switch(event.response_type){
			case XCB_BUTTON_PRESS:
				xcb_button_press_event_t* e = cast(xcb_button_press_event_t* )event;
				if(e.event in buttons)
					buttons[e.event].onPress();

				break;
			case XCB_BUTTON_RELEASE:
				xcb_button_release_event_t* e = cast(xcb_button_release_event_t* )event;

				if(e.event in buttons)
					buttons[e.event].onRelease();

				break;
			case XCB_RESIZE_REQUEST://FIX
				writefln("2"); //windows[id].recalculate();
				break;
			default:
				break;
		}
		goto loop;
	}
}

struct geometry{
	uint width;
	uint height;
}

geometry Geometry(uint width, uint height){
	geometry geom;
	geom.width = width;
	geom.height = height;
	return geom;
}

class Window{
	xcb_window_t id;

	Window[] subwindows;
	
	this(xcb_window_t parent, int x, int y, geometry geom){
		id = xcb_generate_id(gui.conn);
			
		xcb_create_window(gui.conn,                          /* connection    */
			0,                             /* depth         */
			id,                        /* window id     */
			parent,                   /* parent window */
			x, y,                          /* x, y          */
			geom.width, geom.height,                /* width, height */
			0,                             /* border_width  */
			XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class         */
			gui.screen.root_visual,            /* visual        */
			0, /* masks */
			null);
	}
	
	void map(){
		xcb_map_window(gui.conn, id);
	}
	
	void unmap(){
		xcb_unmap_window(gui.conn, id);
	}
	
	void resize(geometry geom){
		xcb_configure_window(gui.conn, id, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
			cast(uint*)[geom.width, geom.height]);
	}
	
	void moveResize(int x, int y, geometry geom){
		xcb_configure_window(gui.conn, id, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, cast(uint*)[x, y, geom.width, geom.height]);
	}
	
	geometry getGeometry(){
		xcb_get_geometry_reply_t* attr = xcb_get_geometry_reply(gui.conn, xcb_get_geometry(gui.conn, id), null);
		return Geometry(attr.width,attr.height);
	}
	
	void setBackground(char[] filename){
		ubyte[] data;
		Info info = lodepng.png.decode32(data, cast(ubyte[])read(filename));
		//if (info.error != 0)
			//throw new Exception("Error loading png " ~ filename ~ ", errorcode: " ~ toString(info.error));
		if(data.length % 4 != 0)
			throw new Exception("Failcopter");
		for(uint i; i<data.length; i+=4){
			ubyte temp = data[i+2];
			data[i+2] = data[i];
			data[i] = temp;
		}
		xcb_gcontext_t gc = xcb_generate_id(gui.conn);
		xcb_create_gc(gui.conn, gc, gui.screen.root, 0, null);
		xcb_pixmap_t pixmap = xcb_generate_id(gui.conn);
		/* Fill in the pixmap */
		
		xcb_create_pixmap (gui.conn,         /* Pointer to the xcb_connection_t structure */
			24,     /* Depth of the screen */
			pixmap,       /* Id of the pixmap */
			gui.screen.root,
			info.w, info.h);   /* Height of the window (in pixels) */
		xcb_put_image(gui.conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
			pixmap, gc,
			info.w, info.h, /* width, height */
			0, 0,           /* dst_x, dst_y */
			0, 24,          /* left_pad, depth */
			data.length, data.ptr);
		xcb_configure_window(gui.conn, id, XCB_CW_BACK_PIXMAP, cast(uint*)[pixmap]);
	}

	void recalculate(){
		foreach(w; subwindows)
			w.recalculate();
	}
	
	Container addContainer(int x, int y, geometry geom){
		Container c = new Container(this, x, y, geom);
		subwindows ~= c;
		return c;
	}
	Container addContainer(float x1, float y1, float x2, float y2){
		Container c = new Container(this, x1, y1, x2, y2);
		subwindows ~= c;
		return c;
	}
	Button addButton(int x, int y, geometry geom){
		Button b = new Button(this, x, y, geom);
		subwindows ~= b;
		return b;
	}
	Button addButton(float x1, float y1, float x2, float y2){
		Button b = new Button(this, x1, y1, x2, y2);
		subwindows ~= b;
		return b;
	}
}

class Container : Window{
	bool relative = false;
	Window parent;
	float w1,w2,h1,h2;
	
	this(Window p, int x, int y, geometry geom){
		parent = p;
		super(parent.id, x, y, geom);
		map();
	}
	this(Window p, float x1, float y1, float x2, float y2){
		relative = true;
		
		w1 = x1;
		w2 = x2;
		h1 = y1;
		h2 = y2;

		this(p, 0, 0, Geometry(0,0));

		recalculate();
	}

	void recalculate(){
		if(relative){
			geometry geom = parent.getGeometry();
			int x, y;
			x = cast(int)(cast(float)geom.width * w1);
			y = cast(int)(cast(float)geom.height * h1);
			geom.width = cast(uint)(cast(float)w2*geom.width) - x;
			geom.height = cast(uint)(cast(float)h2*geom.height) - y;
			
			//std.math.rndtol
			
			writefln(x);
			writefln(y);
			writefln(geom.width);
			writefln(geom.height);
		
			moveResize(x, y, geom);
		}
		super.recalculate();
	}
}

class Button : Container{
	void delegate() onPress;
	void delegate() onRelease;
	this(Window p, int x, int y, geometry geom){
		super(p, x, y, geom);
		xcb_change_window_attributes(gui.conn, id, XCB_CW_EVENT_MASK, cast(uint*)[XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS]);
		gui.buttons[id] = this;
	}
	this(Window p, float x1, float y1, float x2, float y2){
		super(p, x1, y1, x2, y2);
		xcb_change_window_attributes(gui.conn, id, XCB_CW_EVENT_MASK, cast(uint*)[XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS]);
		gui.buttons[id] = this;
	}
}

void main(){
	gui = new GUI();

	Window w = gui.addWindow(Geometry(150,150));
	//Button b = w.addButton(0, 0, Geometry(150,150));
	Button b = w.addButton(.1f,.1f,.9f,.9f);
	//b.setBackground("/home/joe/plasma.png"); //FIX
	b.onRelease = &w.unmap;
	b.onPress = {writefln("pressed");};
	
	w.map();
	
	gui.loop();
}