visual graphing program [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 10
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 16 Exercise 10

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"
#include "std_lib_facilities.h"
#include <functional>

// layout
constexpr int xmax = 600;
constexpr int ymax = 600;

constexpr int x_orig = xmax / 2;
constexpr int y_orig = ymax / 2;
Point orig(x_orig, y_orig);

constexpr int r_min = -10;
constexpr int r_max = 10;

constexpr int n_points = 40;

constexpr int x_scale = 20;
constexpr int y_scale = 20;

// layout
constexpr int xoffset = 100;
constexpr int yoffset = 100;

constexpr int xspace = 100;
constexpr int yspace = 100;

constexpr int xlength = xmax - xoffset - xspace;
constexpr int ylength = ymax - yoffset - yspace;

typedef double Fcti(double);

double mysin(double x) { return sin(x); }
double mycos(double x) { return cos(x); }

template <class T> class myFct : public Shape {
public:
	myFct(Fcti* f, double r1, double r2, Point orig, int count = 100, double xscale = 25, double yscale = 25, T precision = 1.0);
	~myFct() {}

	void set_f(Fcti* p) { f = p; }
	void set_r1(double r) { r1 = r; }
	void set_r2(double r) { r2 = r; }
	void set_orig(Point o) { orig = o; }
	void set_count(int c) { count = c; }
	void set_xscale(double x) { xscale = x; }
	void set_yscale(double y) { yscale = y; }
	void set_precision(T p) { precision = p; }

	double get_r1() { return r1; }
	double get_r2() { return r2; }
	Point get_orig() { return orig; }
	int get_count() { return count; }
	double get_xscale() { return xscale; }
	double get_yscale() { return yscale; }
	T get_precision() { return precision; }

	void calc();
	void reset(Fcti* f, double r1, double r2, Point orig, int count = 100, double xscale = 25, double yscale = 25, T precision = 1.0);

private:
	Fcti* f;
	double r1;
	double r2;
	Point orig;
	int count;
	double xscale;
	double yscale;
	T precision;
};

template <class T> myFct<T>::myFct(Fcti* f, double r1, double r2, Point orig, int count, double xscale, double yscale, T precision)
	:f(f), r1(r1), r2(r2), orig(orig), count(count), xscale(xscale), yscale(yscale), precision(precision)
{
	calc();
}

template <class T> void myFct<T>::calc()
{
	if (r2 - r1 <= 0) error("bad graphing range");
	if (count <= 0) error("non-positive graphing count");
	double dist = (r2 - r1) / count;
	double r = r1;

	// had to add void clear_points() { points.clear(); }
	// to the protected section of the Shape class - annoying
	clear_points();	

	for (int i = 0; i < count; ++i) {
		int x = orig.x + int(int(r * xscale) / precision) * precision;
		int y = orig.y - int(int(f(r) * yscale) / precision) * precision;
		add(Point(x, y));
		r += dist;
	}
}

template <class T> void myFct<T>::reset(Fcti* f, double r1, double r2, Point orig, int count, double xscale, double yscale, T precision)
{
	set_f(f);
	set_r1(r1);
	set_r2(r2);
	set_orig(orig);
	set_count(count);
	set_xscale(xscale);
	set_yscale(yscale);
	set_precision(precision);

	calc();
}

// ------------------------------ GRAPHING END-------------------------

struct application_window : Window {
	enum graph_enum
	{
		sin_g, cos_g
	};

	application_window(Point xy, int w, int h, const string& title);

	void draw_graph();

private:

	//------------- LAYOUT

	// quit button
	Button quit_button;

	// convert button
	Button graph_button;

	// graph type button;
	Button graph_type;
	Menu graph_type_menu;

	// in
	In_box x_parameter;
	Out_box base_equation;
	Out_box equation;

	//
	graph_enum g_type;

	// axis
	Axis x_axis;
	Axis y_axis;

	// function
	myFct<double> funct;

	//double x_manipulation(double x, int m) { return x * m; }
	double my_sin(double x) { return sin(x); }
	double my_cos(double x) { return cos(x); }

	// actions invoked by callbacks
	void quit() { hide(); }

	void graph_type_menu_pressed() { graph_type.hide(); graph_type_menu.show(); }

	void sin_graph();
	void cos_graph();	

	// callback functions
	static void cb_quit(Address, Address pw) { reference_to<application_window>(pw).quit(); }
	static void cb_calculate(Address, Address pw) { reference_to<application_window>(pw).draw_graph(); }

	static void cb_graph_type_menu_pressed(Address, Address pw) { reference_to<application_window>(pw).graph_type_menu_pressed(); }

	static void cb_sin_graph(Address, Address pw) { reference_to<application_window>(pw).sin_graph(); }
	static void cb_cos_graph(Address, Address pw) { reference_to<application_window>(pw).cos_graph(); }

	//------------- LAYOUT END
};

application_window::application_window(Point xy, int w, int h, const string& title)
	: Window(xy, w, h, title)
	, quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
	, graph_button(Point(x_max() - 70, 20), 70, 20, "Graph", cb_calculate)
	, graph_type(Point(20, 0), 100, 20, "Graph Type", cb_graph_type_menu_pressed)
	, graph_type_menu(Point(20, 0), 100, 20, Menu::vertical, "Graph Type")
	, base_equation(Point(x_max() / 2, 0), 90, 20, "equation")
	, x_parameter(Point(100, 40), 20, 20, "t-paramter")
	, equation(Point(x_max() / 2, 40), 90, 20, "equation")
	, x_axis(Axis::x, Point(orig.x - 200, orig.y), 400, 20, "1 == 20")
	, y_axis(Axis::y, Point(orig.x, orig.y + 200), 400, 20, "1 == 20")
	, funct(mysin, r_min, r_max, orig, n_points, x_scale, y_scale)
{
	attach(quit_button);
	attach(graph_button);
	attach(graph_type);
	attach(base_equation);
	attach(x_parameter);
	attach(equation);

	graph_type_menu.attach(new Button(Point(0, 0), 0, 0, "sin", cb_sin_graph));
	graph_type_menu.attach(new Button(Point(0, 0), 0, 0, "cos", cb_cos_graph));

	attach(graph_type_menu);

	x_axis.set_color(Color::black);
	y_axis.set_color(Color::black);
	attach(x_axis);
	attach(y_axis);

	funct.set_color(FL_BLACK);
	attach(funct);
	funct.set_color(Color::invisible);

	graph_type_menu.hide();
}

void application_window::sin_graph()
{
	graph_type_menu.hide();
	graph_type.show();

	base_equation.put("y = sin(x) * t");
	g_type = sin_g;
}

void application_window::cos_graph()
{
	graph_type_menu.hide();
	graph_type.show();

	base_equation.put("y = cos(x) * t");
	g_type = cos_g;
}

void application_window::draw_graph()
{	
	// GRAPHS
	if(g_type == sin_g)
	{		
		equation.put("y = sin(x) * " + x_parameter.get_string());

		// most painful lambda to function pointer work-around ever.
		// saved the day:
		// https://deviorel.wordpress.com/2015/01/27/obtaining-function-pointers-from-lambdas-in-c/

		int t = x_parameter.get_int();
		auto la = [=](double x) { return sin(x) * t; };

		static function< double(double) > static_variable;
		static_variable = la;
		double(*ptr)(double) = [](double x) { return static_variable(x); };

		funct.reset(
			[](double x) { return static_variable(x); }
			, r_min
			, r_max
			, orig
			, n_points
			, x_scale
			, y_scale
		);

	}
	if(g_type == cos_g)
	{
		equation.put("y = cos(x) * " + x_parameter.get_string());

		int t = x_parameter.get_int();
		auto la = [=](double x) { return cos(x) * t; };

		static function< double(double) > static_variable;
		static_variable = la;
		double(*ptr)(double) = [](double x) { return static_variable(x); };

		funct.reset(
			[](double x) { return static_variable(x); }
			, r_min
			, r_max
			, orig
			, n_points
			, x_scale
			, y_scale
		);
	}

	funct.set_color(Color::visible);
	redraw();
}

// ------------------------------ INTERFACE END-------------------------

int main()
try {
	application_window win(Point(100, 100), xmax, ymax + 20, "currency converter");

	return gui_main();
}
catch (exception& e) {
	cerr << "exception: " << e.what() << endl;
	char c;
	while (cin >> c&& c != ';');
	return 1;
}
catch (...) {
	cerr << "exception\n";
	char c;
	while (cin >> c && c != ';');
	return 2;
}

visual calculator [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 9
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 16 Exercise 9

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"
#include "std_lib_facilities.h"

// ------------------------------ CALCULATOR ---------------------------

const char let = '#';
const char quitProg = 'Q';
const char print = ';';
const char number = '8';
const char name = 'a';
const char sqroot = 'S';
const char power = 'P';
const char constant = 'C';
const char reset = 'R';
const char help = 'H';

struct Token {
	char kind;
	double value;
	string name;
	Token(char ch) :kind(ch), value(0) { }
	Token(char ch, double val) :kind(ch), value(val) { }
	Token(char ch, string val) :kind(ch), name(val) { }
};

class Token_stream {
	bool full;
	Token buffer;
	;
public:
	Token_stream() :full(0), buffer(0) { }
	Token get(stringstream& ist);
	void unget(Token t) { buffer = t; full = true; }
	void ignore(char);
};

Token Token_stream::get(stringstream& ist)
{
	/*
	if (full) {
	full = false;
	return buffer;
	}

	char ch;
	ist >> ch;
	*/

	if (full) {
		full = false; return buffer;
	}
	char ch;
	ist.get(ch);

	while (isspace(ch)) {
		if (ch == '\n') return Token(print); // if newline detected, return print Token
		ist.get(ch);
	}

	switch (ch) {
	case '(':
	case ')':
	case '+':
	case '-':
	case '*':
	case '/':
	case '%':
	case ';':
	case '=':
	case 'k':
	case ',':
	{
		return Token(ch);
	}
	case '#':
	{
		return Token(let);
	}
	case '.':
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	{
		ist.unget();
		double val;
		ist >> val;
		return Token(number, val);
	}
	default:
	{
		if (isalpha(ch) || ch == '_') { //is ch a letter?
			string s;
			s += ch;
			while (ist.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_')) { //reads chars, strings or digits
				s += ch;
			}
			ist.unget(); //puts the most recently read character back into the stream
			if (s == "quit") return Token(quitProg);
			if (s == "sqrt") return Token(sqroot);
			if (s == "pow") return Token(power);
			if (s == "const") return Token(constant);
			if (s == "reset") return Token(reset);
			if (s == "help" || s == "Help") return Token(help);
			return Token(name, s);
		}
		error("Bad token");
		return Token(' ');
	}
	}
}

void Token_stream::ignore(char c)
{
	if (full && c == buffer.kind) {
		full = false;
		return;
	}
	full = false;
	char ch;
	while (cin >> ch) {
		if (ch == c) return;
	}
}

struct Variable {
	string name;
	double value;
	bool immutable;
	Variable(string n, double v, bool i) :name(n), value(v), immutable(i) { }
};

class Symbol_table {
public:
	vector<Variable> var_table;
	double get(string);
	void set(string, double);
	bool is_declared(string);
	double declare(char, stringstream& ist);
	bool is_immutable(string);
};

Token_stream ts;
double expression(stringstream& ist);
double primary(stringstream& ist);

double Symbol_table::get(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) {
			return var_table[i].value;
		}
	}
	error("get: undefined name ", s);
	return 0.0;
}

void Symbol_table::set(string s, double d)
{
	for (int i = 0; i <= var_table.size(); ++i) {
		if (var_table[i].name == s) {
			var_table[i].value = d;
			return;
		}
	}
	error("set: undefined name ", s);
}

bool Symbol_table::is_declared(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) return true;
	}
	return false;
}

double Symbol_table::declare(char kind, stringstream& ist)
{
	Token t = ts.get(ist);
	if (t.kind != name) {
		error("name expected in declaration");
	}

	string name = t.name;
	if (kind == let || kind == constant) {
		if (is_declared(name)) error(name, " declared twice");
	}
	else if (kind == reset) {
		if (!is_declared(name))
			error(name, " has not been declared");
		if (is_immutable(name))
			error(name, " is a constant");
	}
	else {
		error("unknown statement");
	}

	Token t2 = ts.get(ist);
	if (t2.kind != '=') error("= missing in declaration of ", name);
	double d = expression(ist);
	if (is_declared(name))
		set(name, d);
	else
		var_table.push_back(Variable(name, d, (kind == constant)));
	return d;
}

bool Symbol_table::is_immutable(string s)
{
	for (int i = 0; i<int(var_table.size()); ++i)
		if (var_table[i].name == s && var_table[i].immutable) return true;
	return false;
}

double pow_function(Token _t, stringstream& ist) {
	_t = ts.get(ist);
	if (_t.kind != '(') {
		error("'(' expected");
	}

	double x = expression(ist);

	_t = ts.get(ist);
	if (_t.kind != ',') {
		error("',' expected");
	}

	double n = expression(ist);
	_t = ts.get(ist);
	if (_t.kind == ')') {
		return pow(x, n);
	}
	else {
		error("Expected ')'");
	}
}

double sqrt_function(Token _t, stringstream& ist) {
	_t = ts.get(ist);
	if (_t.kind != '(') {
		error("'(' expected");
	}
	ts.unget(_t);
	double d = primary(ist);
	if (d < 0.0) {
		error("negative square root");
	}
	return sqrt(d);
}


Symbol_table st;

double primary(stringstream& ist)
{
	Token t = ts.get(ist);
	switch (t.kind) {
	case '(':
	{
		double d = expression(ist);
		t = ts.get(ist);
		if (t.kind != ')') error("')' expected");
		return d;
	}
	case '-':
	{
		return -primary(ist);
	}
	case '+':
	{
		return primary(ist);
	}
	case number:
	{
		return t.value;
	}
	case sqroot:
	{
		return sqrt_function(t, ist);
	}
	case power:
	{
		return pow_function(t, ist);
	}
	case name:
	{
		return st.get(t.name);
	}
	default:
	{
		error("primary expected");
		return 0.0;
	}
	}
}

double term(stringstream& ist)
{
	double left = primary(ist);
	while (true) {
		Token t = ts.get(ist);
		switch (t.kind) {
		case 'k':
		{
			left *= 1000;
			break;
		}
		case '*':
		{
			left *= primary(ist);
			break;
		}
		case '/':
		{
			double d = primary(ist);
			if (d == 0) error("divide by zero");
			left /= d;
			break;
		}
		case '%':
		{
			int i1 = narrow_cast<int>(left);
			int i2 = narrow_cast<int>(primary(ist));
			if (i2 == 0) error("%: divide by zero");
			left = i1%i2;
			break;
		}

		default: {
			ts.unget(t);
			return left;
		}
		}
	}
}

double expression(stringstream& ist)
{
	double left = term(ist);
	while (true) {
		Token t = ts.get(ist);
		switch (t.kind) {
		case '+':
		{
			left += term(ist);
			break;
		}
		case '-':
		{
			left -= term(ist);
			break;
		}
		default:
		{
			ts.unget(t);
			return left;
		}
		}
	}
}

double statement(stringstream& ist)
{
	Token t = ts.get(ist);
	double d;
	if (t.kind == let || t.kind == reset || t.kind == constant) {
		d = st.declare(t.kind, ist);
	}
	else {
		ts.unget(t);
		d = expression(ist);
	}
	t = ts.get(ist);
	if (t.kind != print) {
		error("Missing terminator");
	}

	return d;
}

void clean_up_mess()
{
	ts.ignore(print);
}

static void calculate(stringstream& ist, ostringstream& ost)
{
	while (ist) try {
		Token t = ts.get(ist);
		ts.unget(t);
		ost << statement(ist);
		break;
	}
	catch (runtime_error& e) {
		ost << e.what() << endl;
		clean_up_mess();
	}
}

// ------------------------------ CALCULATOR END------------------------

// ------------------------------ INTERFACE ----------------------------

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

struct application_window : Window {
	application_window(Point xy, int w, int h, const string& title);

private:

	//------------- LAYOUT

	// quit button
	Button quit_button;

	// convert button
	Button calculate_button;

	// in
	In_box value_in;
	Out_box value_out;

	// actions invoked by callbacks
	void quit() { hide(); }
	void cal();

	// callback functions
	static void cb_quit(Address, Address pw) { reference_to<application_window>(pw).quit(); }
	static void cb_calculate(Address, Address pw) { reference_to<application_window>(pw).cal(); }

	//------------- LAYOUT END
};

application_window::application_window(Point xy, int w, int h, const string& title)
	: Window(xy, w, h, title)
	, quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
	, calculate_button(Point(x_max() - 70, 20), 70, 20, "Calculate", cb_calculate)
	, value_in(Point(70, 60), 70, 20, "equation")
	, value_out(Point(x_max() / 2, 60), 70, 20, "solution")
{
	attach(quit_button);
	attach(calculate_button);
	attach(value_in);
	attach(value_out);
}

void application_window::cal()
{
	ostringstream os;
	stringstream ss;
	ss.str(value_in.get_string() + ";");
	
	calculate(ss, os);

	string s(os.str());
	value_out.put(s);
}

// ------------------------------ INTERFACE END-------------------------

int main()
try {
	application_window win(Point(100, 100), xmax, ymax + 20, "currency converter");
	return gui_main();
}
catch (exception& e) {
	cerr << "exception: " << e.what() << endl;
	char c;
	while (cin >> c&& c != ';');
	return 1;
}
catch (...) {
	cerr << "exception\n";
	char c;
	while (cin >> c && c != ';');
	return 2;
}

visual currency converter [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 8
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 8

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"
#include <time.h>

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

enum currencies
{
	euro = 0, pound
};

struct application_window : Window {
	application_window(Point xy, int w, int h, const string& title, const string& conversion_rate_file_location);

private:

	//------------- DATA

	currencies from;
	currencies to;

	// data
	float conversion_rate;

	// methods
	float get_conversion(const string& crfl);

	//------------- DATA END


	//------------- LAYOUT

	// quit button
	Button quit_button;

	// convert button
	Button convert_button;

	// menu button
	Button from_menu_button;
	Button to_menu_button;

	// menu
	Menu from_menu;
	Menu to_menu;

	// in
	In_box value_in;
	Out_box value_out;
	Out_box value_in_currency;	
	Out_box value_out_currency;

	// actions invoked by callbacks
	void quit() { hide(); }

	void convert();

	void hide_from_menu() { from_menu.hide(); from_menu_button.show(); }
	void hide_to_menu() { to_menu.hide(); to_menu_button.show(); }

	void from_menu_pressed() { from_menu_button.hide(); from_menu.show(); }
	void to_menu_pressed() { to_menu_button.hide(); to_menu.show(); }

	void from_euro_pressed() { hide_from_menu(); value_in_currency.put("euro"); from = euro; }
	void from_pound_pressed() { hide_from_menu(); value_in_currency.put("pound"); from = pound; }

	void to_euro_pressed() { hide_to_menu(); value_out_currency.put("euro"); to = euro; }
	void to_pound_pressed() { hide_to_menu(); value_out_currency.put("pound"); to = pound; }
	
	// callback functions
	static void cb_quit(Address, Address pw) { reference_to<application_window>(pw).quit(); }

	static void cb_convert(Address, Address pw) { reference_to<application_window>(pw).convert(); }

	static void cb_from_menu(Address, Address pw) {	reference_to<application_window>(pw).from_menu_pressed(); }
	static void cb_from_euro(Address, Address pw) { reference_to<application_window>(pw).from_euro_pressed(); }
	static void cb_from_pound(Address, Address pw) { reference_to<application_window>(pw).from_pound_pressed(); }

	static void cb_to_menu(Address, Address pw) { reference_to<application_window>(pw).to_menu_pressed(); }
	static void cb_to_euro(Address, Address pw) { reference_to<application_window>(pw).to_euro_pressed(); }
	static void cb_to_pound(Address, Address pw) { reference_to<application_window>(pw).to_pound_pressed(); }

	//------------- LAYOUT END
};

application_window::application_window(Point xy, int w, int h, const string& title, const string& conversion_rate_file_location)
	: Window(xy, w, h, title)
	, quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
	, convert_button(Point(x_max() - 70, 20), 70, 20, "Convert", cb_convert)
	, from_menu_button(Point(0, 20), 70, 20, "From", cb_from_menu)
	, to_menu_button(Point(x_max() / 2, 20), 70, 20, "To", cb_to_menu)
	, from_menu(Point(0, 20), 70, 20, Menu::vertical, "From")
	, to_menu(Point(x_max() / 2, 20), 70, 20, Menu::vertical, "To")
	, value_in(Point(0, 60), 70, 20, "enter value")
	, value_out(Point(x_max() / 2, 60), 70, 20, "")
	, value_in_currency(Point(70, 60), 70, 20, "")
	, value_out_currency(Point(x_max() / 2 + 70, 60), 70, 20, "")
{
	conversion_rate = get_conversion(conversion_rate_file_location);

	from = euro;
	to = euro;

	attach(quit_button);
	attach(convert_button);
	attach(from_menu_button);
	attach(to_menu_button);

	attach(value_in);
	attach(value_out);

	attach(value_in_currency);
	attach(value_out_currency);

	value_in_currency.put("euro");
	value_out_currency.put("euro");

	from_menu.attach(new Button(Point(0, 0), 0, 0, "euro", cb_from_euro));
	from_menu.attach(new Button(Point(0, 0), 0, 0, "pound", cb_from_pound));

	to_menu.attach(new Button(Point(0, 0), 0, 0, "euro", cb_to_euro));
	to_menu.attach(new Button(Point(0, 0), 0, 0, "pound", cb_to_pound));

	attach(to_menu);
	attach(from_menu);

	to_menu.hide();
	from_menu.hide();
}

float application_window::get_conversion(const string& crfl)
{
	string iname = crfl;
	ifstream ist(iname);

	float rate;
	if (!ist) { error("File could not be read: ", iname); }
	else { ist >> rate; }

	return rate;
}

void application_window::convert()
{
	float input = strtof((value_in.get_string()).c_str(), 0);

	if (from == euro && to == pound)
	{
		input *= conversion_rate;

		ostringstream ss;
		ss << input;
		string s(ss.str());

		value_out.put(s);
	}
	else if (from == pound && to == euro)
	{
		input *= 1.0 + (1.0 - conversion_rate);

		ostringstream ss;
		ss << input;
		string s(ss.str());

		value_out.put(s);
	}
	else
	{
		ostringstream ss;
		ss << input;
		string s(ss.str());

		value_out.put(s);
	}
}

int main()
try
{
	application_window win(Point(100, 100), xmax, ymax + 20, "currency converter", "Data/conversion_rate.txt");
	return gui_main();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}
catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}
Input:
Text file: Data/conversion_rate.txt
0.87

flying airplane image animation [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 7
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:
//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 7

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"
#include <time.h>

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

// HANDS
struct Airplane : Shape
{
	Airplane(string content_location, Point& position, int canvas_width, int canvas_height)
		: content_location(content_location)
		, position(position)
		, canvas_width(canvas_width)
		, canvas_height(canvas_height)
	{
		image_width = 250;
		image_height = 150;
		velocity = Point(1, 1);
	}

	void move();
	void draw_lines() const;

	string content_location;
	Point position;

	Point velocity;

	int image_width;
	int image_height;

	int canvas_width;
	int canvas_height;
};

void Airplane::move()
{
	

	if (position.x <= canvas_width - image_width)
	{
		position.x += velocity.x;
	}
	if (position.y <= canvas_height - image_height)
	{
		position.y += velocity.y;
	}

	if (position.x == canvas_width - image_width || position.x == 0)
	{
		velocity.x *= -1;
	}
	if (position.y == canvas_height - image_height || position.y == 0)
	{
		velocity.y *= -1;
	}

}

void Airplane::draw_lines() const
{
	Image image0(position, content_location);
	image0.set_mask(Point(100, 70), image_width, image_height);

	if (color().visibility()) {		
		// draw content image
		image0.draw();
	}
}

struct animation_window : Window {
	animation_window(Point xy, int w, int h, const string& title)
		: Window(xy, w, h, title),
		quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit),
		start_stop_button(Point(x_max() - 70, 20), 70, 20, "Start/Stop", cb_start_stop)
	{
		attach(quit_button);
		attach(start_stop_button);
		//position = Point(0, 0);
		Airplane plane("Data/airplanes-work-1.jpg", Point(0, 0), w, h);
		run = false;

		while (true) {
			Fl::wait();
			Sleep(10);
			draw_shape(plane);
			if (run)
			{
				plane.move();
				Fl::redraw();
			}
			
		}
	}

	Vector_ref<Shape> s;
	void draw_shape(Airplane& plane);

	Button quit_button;
	Button start_stop_button;

	bool run;

private:

	static void cb_quit(Address, Address addr) { reference_to<animation_window>(addr).quit(); }
	static void cb_start_stop(Address, Address addr) { reference_to<animation_window>(addr).start_stop(); }

	void quit() { hide(); }
	void start_stop()
	{
		if (run) { run = false; }
		else { run = true; }
	}

};

void animation_window::draw_shape(Airplane& plane)
{
	if (s.size() != 0)
	{
		for (int i = 0; i < s.size(); i++)
		{
			detach(s[i]);
		}
	}

	s.push_back(plane);
	attach(s[s.size() - 1]);
}

int main()
try
{
	animation_window win(Point(100, 100), xmax, ymax + 20, "flying airplane");

	return gui_main();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}
catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}

analog clock [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 6
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 6

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"
#include <time.h>

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

// HANDS
struct Hands : Open_polyline
{
	Hands(Point center, Point end, Fl_Color color)
	{
		add(Point(center));
		add(Point(end));
		c = color;
	}

	void draw_lines() const;
	Fl_Color c;
};

void Hands::draw_lines() const
{
	fl_color(c);
	Open_polyline::draw_lines();
}

struct Analog_clock_window : Window {
	Analog_clock_window(Point xy, int w, int h, const string& title)
		: Window(xy, w, h, title),
		quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
	{
		attach(quit_button);		

		while (true) {
			Fl::wait();
			Sleep(1000);			
			cout << "sleep" << endl;
			draw_shape();
			Fl::redraw();
		}
	}
	
	Vector_ref<Shape> s;
	void draw_shape();

	Button quit_button;

private:
	time_t rawtime;
	bool button_pushed;

	void print_current_time(time_t &rt);

	static void cb_quit(Address, Address addr) { reference_to<Analog_clock_window>(addr).quit(); }
	void quit() { hide(); }
};

void Analog_clock_window::print_current_time(time_t &rt)
{
	#pragma warning(disable : 4996) //_CRT_SECURE_NO_WARNINGS

	struct tm * timeinfo;
	timeinfo = localtime(&rt);
	printf("Current local time and date: %s", asctime(timeinfo));

	cout << timeinfo->tm_sec << endl;
}

void Analog_clock_window::draw_shape()
{
	if (s.size() != 0)
	{
		for (int i = 0; i < s.size(); i++)
		{
			detach(s[i]);
		}
	}

	Point center(xmax / 2, ymax / 2);

	for (int i = 0; i < 12; i++)
	{
		Point pt1(0, -100);
		Point pt2(0, -95);
		double rad = ((2 * M_PI) / 12) * i;

		Point rotated_pt1 = Point(cos(rad) * pt1.x - sin(rad) * pt1.y, sin(rad) * pt1.x + cos(rad) * pt1.y);
		Point rotated_pt2 = Point(cos(rad) * pt2.x - sin(rad) * pt2.y, sin(rad) * pt2.x + cos(rad) * pt2.y);

		s.push_back(new Hands(Point(rotated_pt1.x + center.x, rotated_pt1.y + center.y), Point(rotated_pt2.x + center.x, rotated_pt2.y + center.y), Color::black));
		attach(s[s.size() - 1]);
	}

	#pragma warning(disable : 4996) //_CRT_SECURE_NO_WARNINGS
	time_t rawT;
	time(&rawT);

	struct tm * timeinfo;
	timeinfo = localtime(&rawT);
	asctime(timeinfo);

	printf("Current local time and date: %s", asctime(timeinfo));

	// SECOND HAND
	Point origin_Pt1(0, -100);

	double rad = timeinfo->tm_sec * ((2 * M_PI) / 60);
	Point rotated_Pt1 = Point(cos(rad) * origin_Pt1.x - sin(rad) * origin_Pt1.y, sin(rad) * origin_Pt1.x + cos(rad) * origin_Pt1.y);
	
	s.push_back(new Hands(center, Point(rotated_Pt1.x + center.x , rotated_Pt1.y + center.y), Color::red));
	attach(s[s.size() - 1]);
	
	// MINUTE HAND
	Point origin_Pt2(0, -80);

	rad = timeinfo->tm_min * ((2 * M_PI) / 60);
	Point rotated_Pt2 = Point(cos(rad) * origin_Pt2.x - sin(rad) * origin_Pt2.y, sin(rad) * origin_Pt2.x + cos(rad) * origin_Pt2.y);

	s.push_back(new Hands(center, Point(rotated_Pt2.x + center.x, rotated_Pt2.y + center.y), Color::blue));
	attach(s[s.size() - 1]);

	// HOUR HAND
	Point origin_Pt3(0, -60);

	rad = timeinfo->tm_hour * ((2 * M_PI) / 12) + (timeinfo->tm_min * ((2 * M_PI) / 60)) / 12;
	Point rotated_Pt3 = Point(cos(rad) * origin_Pt3.x - sin(rad) * origin_Pt3.y, sin(rad) * origin_Pt3.x + cos(rad) * origin_Pt3.y);

	s.push_back(new Hands(center, Point(rotated_Pt3.x + center.x, rotated_Pt3.y + center.y), Color::black));
	attach(s[s.size() - 1]);
}

int main()
try
{
	Analog_clock_window win(Point(100, 100), xmax, ymax + 20, "analog clock");

	return gui_main();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}
catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}

randomly moving shape [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 5
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 5

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

struct My_window : Window {
	My_window(Point xy, int w, int h, const string& title, string url)
		: Window(xy, w, h, title),
		next_button_pushed(false),
		next_button(Point(x_max() - 140, 0), 70, 20, "Next", cb_next),
		quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit),
		url(url),
		counter(0)
	{
		attach(next_button);
		attach(quit_button);

		// open input stream
		ifstream ist(url);
		int input_x;
		char comma;
		int input_y;

		// store data in vectors
		while (ist >> input_x >> comma >> input_y)
		{
			in_x.push_back(input_x);
			in_y.push_back(input_y);
		}
	}

	void wait_for_button()
	{
		while (!next_button_pushed) Fl::wait();
		next_button_pushed = false;
		Fl::redraw();
	}

	Button next_button;
	Button quit_button;
	
private:
	bool next_button_pushed;
	string url;
	int counter;
	Vector_ref<Shape> s;

	vector<int> in_x;
	vector<int> in_y;

	static void cb_next(Address, Address addr)
	{
		reference_to<My_window>(addr).next();
	}

	static void cb_quit(Address, Address addr)
	{
		reference_to<My_window>(addr).quit();
	}

	void next();
	void quit() { hide(); }
};

void My_window::next()
{
	if (s.size() < in_x.size())
	{
		if (s.size() != 0) { detach(s[s.size() - 1]); }
		s.push_back(new Circle(Point(in_x[counter], in_y[counter]), 20));
		attach(s[s.size() - 1]);
		redraw();
		counter++;
	}
}

int main()
try
{
	My_window win(Point(100, 100), xmax, ymax + 20, "next buttons window", "Data/point_sequence.txt");
	return gui_main();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}
catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}

shape drawing with menu [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 4
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 4

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"

// layout
constexpr int xmax = 600;
constexpr int ymax = 400;

// QUAD
struct Quad_center : Closed_polyline
{
	Quad_center(Point center, int w, int h)
	{
		add(Point(center.x - w / 2, center.y - h / 2));
		add(Point(center.x + w / 2, center.y - h / 2));
		add(Point(center.x + w / 2, center.y + h / 2));
		add(Point(center.x - w / 2, center.y + h / 2));
		
	}

	void draw_lines() const;
};

void Quad_center::draw_lines() const
{
	fl_color(FL_BLACK);
	Closed_polyline::draw_lines();
}

// TRIANGLE
struct Triangle : Closed_polyline
{
	Triangle(Point origin, int edge_length)
	{
		int h = sqrt(3) / 2 * edge_length;

		Point p(origin.x - edge_length / 2, origin.y + edge_length / 2);
		add(p);		
		add(Point(p.x + edge_length, p.y));
		add(Point(p.x + edge_length / 2, p.y - h));
	}

	void draw_lines() const;
};

void Triangle::draw_lines() const
{
	fl_color(FL_BLACK);
	Closed_polyline::draw_lines();
}

// HEXAGON
struct Hexagon : Closed_polyline
{
	Hexagon(Point origin, int radius)
	{
		int n = 6;
		for (int i = 0; i < n; i++) {
			add(Point(origin.x + radius * cos(2 * M_PI * i / n), origin.y + radius * sin(2 * M_PI * i / n)));
		}
	}

	void draw_lines() const;
};

void Hexagon::draw_lines() const
{
	fl_color(FL_BLACK);
	Closed_polyline::draw_lines();
}

// DRAW SHAPES WINDOW
struct Shapes_window : Window {
	Shapes_window(Point xy, int w, int h, const string& title);
private:
	// data
	enum Shapes
	{
		circle, square, triangle , hexagon
	};

	Vector_ref<Shape> s;

	// widgets
	Button quit_button;	// end program
	In_box draw_pos_x;
	In_box draw_pos_y;
	Out_box xy_out;
	Menu shape_menu;
	Button menu_button;

	void hide_menu() { shape_menu.hide(); menu_button.show(); }

	// actions invoked by callbacks
	void menu_pressed() { menu_button.hide(); shape_menu.show(); }
	void draw_shape(Shapes s);
	void quit();

	// callback functions
	static void cb_circle(Address, Address);
	static void cb_square(Address, Address);
	static void cb_triangle(Address, Address);
	static void cb_hexagon(Address, Address);
	static void cb_menu(Address, Address);
	static void cb_quit(Address, Address);
};

Shapes_window::Shapes_window(Point xy, int w, int h, const string& title)
	:Window(xy, w, h, title),
	quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit),
	draw_pos_x(Point(x_max() - 310, 0), 50, 20, "pos x:"),
	draw_pos_y(Point(x_max() - 210, 0), 50, 20, "pos y:"),
	xy_out(Point(100, 0), 100, 20, "drawn at (x,y):"),
	shape_menu(Point(x_max() - 70, 30), 70, 20, Menu::vertical, "shape"),
	menu_button(Point(x_max() - 80, 30), 80, 20, "shape menu", cb_menu)
{
	attach(quit_button);
	attach(draw_pos_x);
	attach(draw_pos_y);
	attach(xy_out);

	xy_out.put("no shape");

	shape_menu.attach(new Button(Point(0, 0), 0, 0, "circle", cb_circle));
	shape_menu.attach(new Button(Point(0, 0), 0, 0, "square", cb_square));
	shape_menu.attach(new Button(Point(0, 0), 0, 0, "triangle", cb_triangle));
	shape_menu.attach(new Button(Point(0, 0), 0, 0, "hexagon", cb_hexagon));
	
	attach(shape_menu);
	shape_menu.hide();
	attach(menu_button);
}

void Shapes_window::draw_shape(Shapes shape)
{

	if (draw_pos_x.get_int() == -999999)
	{
		xy_out.put("enter position");
	}
	else {

		int x = draw_pos_x.get_int();
		int y = draw_pos_y.get_int();

		switch (shape)
		{
		case circle: { s.push_back(new Circle(Point(x, y), 20)); break; }
		case square: { s.push_back(new Quad_center(Point(x, y), 40, 40)); break; }
		case triangle: { s.push_back(new Triangle(Point(x, y), 40)); break; }
		case hexagon: { s.push_back(new Hexagon(Point(x, y), 20)); break; }
		}

		// update current position readout
		ostringstream ss;
		ss << '(' << x << ',' << y << ')';
		xy_out.put(ss.str());

		attach(s[s.size() - 1]);
		redraw();
		hide_menu();
	}
}

void Shapes_window::quit()
{
	hide();
}

void Shapes_window::cb_circle(Address, Address pw)
{
	reference_to<Shapes_window>(pw).draw_shape(circle);
}

void Shapes_window::cb_square(Address, Address pw)
{
	reference_to<Shapes_window>(pw).draw_shape(square);
}

void Shapes_window::cb_triangle(Address, Address pw)
{
	reference_to<Shapes_window>(pw).draw_shape(triangle);
}

void Shapes_window::cb_hexagon(Address, Address pw)
{
	reference_to<Shapes_window>(pw).draw_shape(hexagon);
}

void Shapes_window::cb_menu(Address, Address pw)
{
	reference_to<Shapes_window>(pw).menu_pressed();
}

void Shapes_window::cb_quit(Address, Address pw)
{
	reference_to<Shapes_window>(pw).quit();
}

int main()
try
{
	Shapes_window win(Point(100, 100), xmax, ymax, "lines");
	return gui_main();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}

catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}

button changing random location on click [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 3
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 3

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"
#include <random>

inline int rand_int(int min, int max)
{
	static default_random_engine ran;
	return uniform_int_distribution<>(min, max)(ran);
}

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

struct My_window : Window {
	My_window(Point xy, int w, int h, const string& title)
		: Window(xy, w, h, title),
		next_button_pushed(false),
		next_button(Point(x_max() - 140, 0), 70, 20, "Next", cb_next),
		quit_button_pushed(false),
		quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
	{
		attach(next_button);
		attach(quit_button);
	}

	void wait_for_button()
	{
		while (!next_button_pushed) Fl::wait();
		next_button_pushed = false;
		Fl::redraw();
	}

	Button next_button;
	Button quit_button;

private:
	bool next_button_pushed;
	bool quit_button_pushed;

	static void cb_next(Address, Address addr)
	{
		reference_to<My_window>(addr).next();
	}

	static void cb_quit(Address, Address addr)
	{
		reference_to<My_window>(addr).quit();
	}

	void next() { next_button_pushed = true; }
	void quit() { hide(); }
};

struct Random_button_win : My_window
{
	Random_button_win(Point xy, int w, int h, const string& title, const string& url)
		:My_window(xy, w, h, title),
		url(url),
		rand_button(Point(xmax/2, ymax/2), 40, 40, "", cb_rand),
		button_image(Point(xmax / 2, ymax / 2), url)
	{
		attach(rand_button);
		button_image.set_mask(Point(xmax / 2, ymax / 2), 40, 40);
		attach(button_image);
	}
		
	Button rand_button;
	Image button_image;
	
private:
	string url;

	static void cb_rand(Address, Address addr)
	{
		static_cast<Random_button_win*>(addr)->change_button_pos();
	}

	void change_button_pos()
	{
		rand_button.hide();

		int current_x = rand_button.loc.x;
		int current_y = rand_button.loc.y;

		int new_x = rand_int(0, xmax - 40) - current_x;
		int new_y = rand_int(20, ymax - 40) - current_y;
		
		rand_button.move(new_x, new_y);
		button_image.move(new_x, new_y);
		redraw();
	}
};

int main()
try
{
	Random_button_win win(Point(100, 100), xmax, ymax + 20, "random buttons window", "Data/supercell.jpg");
	return gui_main();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}
catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}

checker board square buttons [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 2
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 2

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

struct My_window : Window {
	My_window(Point xy, int w, int h, const string& title)
		: Window(xy, w, h, title),
		next_button_pushed(false),
		next_button(Point(x_max() - 140, 0), 70, 20, "Next", cb_next),
		quit_button_pushed(false),
		quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
	{
		attach(next_button);
		attach(quit_button);
	}

	void wait_for_button()
		// modified event loop
		// handle all events (as per default), but quit when button_pushed becomes true
		// this allows graphics without control inversion
	{
		while (!next_button_pushed) Fl::wait();
		next_button_pushed = false;
		Fl::redraw();
	}

	Button next_button;
	Button quit_button;

private:
	bool next_button_pushed;
	bool quit_button_pushed;

	static void cb_next(Address, Address addr) // callback for next_button
											   //	{ reference_to<Simple_window>(addr).next(); }
	{
		reference_to<My_window>(addr).next();
	}

	static void cb_quit(Address, Address addr) // callback for quit_button
											   //	{ reference_to<Simple_window>(addr).quit(); }
	{
		reference_to<My_window>(addr).quit();
	}

	void next() { next_button_pushed = true; }
	void quit() { hide(); }
};

struct cheker_board_buttons : My_window
{
	cheker_board_buttons(Point xy, int w, int h, const string& title)
		:My_window(xy, w, h, title)
	{
		int x_size = xmax / 4;
		int y_size = ymax / 4;

		// initialize buttons
		buttons.push_back(new Button(Point(0, 20), x_size, y_size, "b0", cb_change_0));
		buttons.push_back(new Button(Point(x_size, 20), x_size, y_size, "b1", cb_change_1));
		buttons.push_back(new Button(Point(x_size * 2, 20), x_size, y_size, "b2", cb_change_2));
		buttons.push_back(new Button(Point(x_size * 3, 20), x_size, y_size, "b3", cb_change_3));
		buttons.push_back(new Button(Point(0, y_size + 20), x_size, y_size, "b4", cb_change_4));
		buttons.push_back(new Button(Point(x_size, y_size + 20), x_size, y_size, "b5", cb_change_5));
		buttons.push_back(new Button(Point(x_size * 2, y_size + 20), x_size, y_size, "b6", cb_change_6));
		buttons.push_back(new Button(Point(x_size * 3, y_size + 20), x_size, y_size, "b7", cb_change_7));
		buttons.push_back(new Button(Point(0, y_size * 2 + 20), x_size, y_size, "b8", cb_change_8));
		buttons.push_back(new Button(Point(x_size, y_size * 2 + 20), x_size, y_size, "b9", cb_change_9));
		buttons.push_back(new Button(Point(x_size * 2, y_size * 2 + 20), x_size, y_size, "b10", cb_change_10));
		buttons.push_back(new Button(Point(x_size * 3, y_size * 2 + 20), x_size, y_size, "b11", cb_change_11));
		buttons.push_back(new Button(Point(0, y_size * 3 + 20), x_size, y_size, "b12", cb_change_12));
		buttons.push_back(new Button(Point(x_size, y_size * 3 + 20), x_size, y_size, "b13", cb_change_13));
		buttons.push_back(new Button(Point(x_size * 2, y_size * 3 + 20), x_size, y_size, "b14", cb_change_14));
		buttons.push_back(new Button(Point(x_size * 3, y_size * 3 + 20), x_size, y_size, "b15", cb_change_15));

		// attach buttons
		for (int i = 0; i < buttons.size(); i++) { attach(buttons[i]); }
	}

	// button setup
	Vector_ref<Button> buttons;
	int last = 16;
	void reset_button() { if(last != 16) { buttons[last].show(); } }	

	// button behaviour
	void change_b0() { reset_button(); last = 0; buttons[0].hide(); };
	void change_b1() { reset_button(); last = 1; buttons[1].hide(); };
	void change_b2() { reset_button(); last = 2; buttons[2].hide(); };
	void change_b3() { reset_button(); last = 3; buttons[3].hide(); };
	void change_b4() { reset_button(); last = 4; buttons[4].hide(); };
	void change_b5() { reset_button(); last = 5; buttons[5].hide(); };
	void change_b6() { reset_button(); last = 6; buttons[6].hide(); };
	void change_b7() { reset_button(); last = 7; buttons[7].hide(); };
	void change_b8() { reset_button(); last = 8; buttons[8].hide(); };
	void change_b9() { reset_button(); last = 9; buttons[9].hide(); };
	void change_b10() { reset_button(); last = 10; buttons[10].hide(); };
	void change_b11() { reset_button(); last = 11; buttons[11].hide(); };
	void change_b12() { reset_button(); last = 12; buttons[12].hide(); };
	void change_b13() { reset_button(); last = 13; buttons[13].hide(); };
	void change_b14() { reset_button(); last = 14; buttons[14].hide(); };
	void change_b15() { reset_button(); last = 15; buttons[15].hide(); };

private:
	vector<bool> pressed;

	// call back functions
	static void cb_change_0(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b0(); }
	static void cb_change_1(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b1(); }
	static void cb_change_2(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b2(); }
	static void cb_change_3(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b3(); }
	static void cb_change_4(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b4(); }
	static void cb_change_5(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b5(); }
	static void cb_change_6(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b6(); }
	static void cb_change_7(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b7(); }
	static void cb_change_8(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b8(); }
	static void cb_change_9(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b9(); }
	static void cb_change_10(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b10(); }
	static void cb_change_11(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b11(); }
	static void cb_change_12(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b12(); }
	static void cb_change_13(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b13(); }
	static void cb_change_14(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b14(); }
	static void cb_change_15(Address, Address addr) { reference_to<cheker_board_buttons>(addr).change_b15(); }
};

int main()
try
{
	cheker_board_buttons win(Point(100, 100), xmax, ymax + 20, "checker board buttons");
	return gui_main();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}

catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}

exploring the window class [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 1
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 1

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"

// layout
constexpr int xmax = 600;
constexpr int ymax = 400;

struct My_window : Window {
	My_window(Point xy, int w, int h, const string& title)
		: Window(xy, w, h, title),
		next_button_pushed(false),
		next_button(Point(x_max() - 140, 0), 70, 20, "Next", cb_next),
		quit_button_pushed(false),
		quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
	{
		attach(next_button);
		attach(quit_button);
	}

	void wait_for_button()
		// modified event loop
		// handle all events (as per default), but quit when button_pushed becomes true
		// this allows graphics without control inversion
	{
		while (!next_button_pushed) Fl::wait();
		next_button_pushed = false;
		Fl::redraw();
	}

	Button next_button;
	Button quit_button;

private:
	bool next_button_pushed;
	bool quit_button_pushed;

	static void cb_next(Address, Address addr) // callback for next_button
											   //	{ reference_to<Simple_window>(addr).next(); }
	{
		reference_to<My_window>(addr).next();
	}

	static void cb_quit(Address, Address addr) // callback for quit_button
											   //	{ reference_to<Simple_window>(addr).quit(); }
	{
		reference_to<My_window>(addr).quit();
	}

	void next() { next_button_pushed = true; }
	void quit() { hide(); }
};

int main()
try
{
	My_window win(Point(100, 100), xmax, ymax, "quit+next");
	return gui_main();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}

catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}