#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);
}