[C++] ”プログラミング入門” : Gui.h, Gui.cpp 全ソースコード

#ifndef GUI_GUARD
#define GUI_GUARD

#include "Point.h"
#include <FL/Fl_Widget.H>
#include "Window.h"

namespace Graph_lib {
	
typedef void* Address;
typedef void (*Callback)(Address,Address);

template<class W> W& reference_to(Address pw)
{
	return *static_cast<W*>(pw);
}


class Widget {
public:
	Widget(Point xy, int w, int h, const string& s, Callback cb)
		:loc(xy), width(w), height(h), label(s), do_it(cb)
	{ }

	virtual void move(int dx,int dy) { hide(); pw->position(loc.x+=dx, loc.y+=dy); show(); }
	virtual void hide() { pw->hide(); }
	virtual void show() { pw->show(); }
	virtual void attach(Window&) = 0;

	Point loc;
	int width;
	int height;
	string label;
	Callback do_it;

	virtual ~Widget() { }

	/*
	Widget(const Widget& a) :loc(a.loc) { error("attempt to copy Widget by constructor"); }
	Widget& operator=(const Widget& a)
	{
			error("attempt to copy Widget by cassignment");
			return *this;
	}
	*/

protected:
	Window* own;
	Fl_Widget* pw;
private:
	Widget& operator=(const Widget&);
	Widget(const Widget&);
};

class Button : public Widget {
public:
	Button(Point xy, int ww, int hh, const string& s, Callback cb)
	:Widget(xy,ww,hh,s,cb)
	{ 
	}
	void attach(Window& win);
};

struct In_box : Widget {
	In_box(Point xy, int w, int h, const string& s)
		:Widget(xy,w,h,s,0)
		{
		}
	int get_int();
	string get_string();

	void attach(Window& win);
};

struct Out_box : Widget {
	Out_box(Point xy, int w, int h, const string& s/*, Window& win*/)
		:Widget(xy,w,h,s,0)
		{
		}
	void put(int);
	void put(const string&);

	void attach(Window& win);
};

struct Menu : Widget {
	enum Kind { horizontal, vertical };
	Menu(Point xy, int w, int h, Kind kk, const string& s);
	Vector_ref<Button> selection;
	Kind k;
	int offset;
	int attach(Button& b);
	int attach(Button* p);
	void show() { for (int i = 0; i<selection.size(); ++i) selection[i].show(); }
	void hide() { for (int i = 0; i<selection.size(); ++i) selection[i].hide(); }
	void move(int dx, int dy)
		{ for (int i = 0; i<selection.size(); ++i) selection[i].move(dx,dy); }
//	int insert(int i, const Button& b);	// not implemented

	void attach(Window& win)
	{
		for (int i=0; i<selection.size(); ++i) win.attach(selection[i]);
	}	

};
}
#endif
#include "Gui.h"
#include <FL/Fl_Input.H>
#include <FL/Fl_Output.H>
#include <FL/Fl_Button.H>
#include "std_lib_facilities.h"

using namespace Graph_lib;

void Button::attach(Window& win)
{
	pw = new Fl_Button(loc.x, loc.y, width, height, label.c_str());
	pw->callback(reinterpret_cast<Fl_Callback*>(do_it), &win);
	own = &win;
}

int In_box::get_int()
{
	Fl_Input& pi = reference_to<Fl_Input>(pw);
//	return atoi(pi.value());
	const char* p = pi.value();
	if (!isdigit(p[0])) return -999999;
	return atoi(p);
}

string In_box::get_string()
{
	Fl_Input& pi = reference_to<Fl_Input>(pw);
	return string(pi.value());
}

void In_box::attach(Window& win)
{
	pw = new Fl_Input(loc.x, loc.y, width, height, label.c_str());
	own = &win;
}

void Out_box::put(int i)
{
	Fl_Output& po = reference_to<Fl_Output>(pw);
	std::stringstream ss;
	ss << i;
	po.value(ss.str().c_str());
}

void Out_box::put(const string& s)
{
	reference_to<Fl_Output>(pw).value(s.c_str());
}

void Out_box::attach(Window& win)
{
	pw = new Fl_Output(loc.x, loc.y, width, height, label.c_str());
	own = &win;
}

Menu::Menu(Point xy, int w, int h, Kind kk, const string& s)
:Widget(xy,w,h,s,0), k(kk), offset(0)
{
}

int Menu::attach(Button& b)
{
	b.width = width;
	b.height = height;

	switch(k) {
	case horizontal:
		b.loc = Point(loc.x+offset,loc.y);
		offset+=b.width;
		break;
	case vertical:
		b.loc = Point(loc.x,loc.y+offset);
		offset+=b.height;
		break;
	}
	selection.push_back(&b);
	return int(selection.size()-1);
}

int Menu::attach(Button* p)
{
//	owned.push_back(p);
	return attach(*p);
}