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

line drawing program + color & linestyle menu [fltk]

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

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Drill 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;

struct Lines_window : Window {
	Lines_window(Point xy, int w, int h, const string& title);
private:
	// data
	Open_polyline lines;

	// widgets
	Button next_button;	// add (next_x, next_y) to lines
	Button quit_button;	// end program
	In_box next_x;
	In_box next_y;
	Out_box xy_out;

	// color menu
	Menu color_menu;
	Button color_menu_button;
	void change_color(Color c) { lines.set_color(c); }
	void hide_color_menu() { color_menu.hide(); color_menu_button.show(); }

	// line style menu
	Menu line_style_menu;
	Button line_style_menu_button;
	void change_line_style(Line_style ls) { lines.set_style(ls); }
	void hide_line_style_menu() { line_style_menu.hide(); line_style_menu_button.show(); }

	// actions invoked by callbacks
	// color menu
	void red_pressed() { change_color(Color::red); hide_color_menu(); }
	void blue_pressed() { change_color(Color::blue); hide_color_menu(); }
	void black_pressed() { change_color(Color::black); hide_color_menu(); }
	void color_menu_pressed() { color_menu_button.hide(); color_menu.show(); }

	// line style menu
	void solid_pressed() { change_line_style(Line_style::solid); hide_line_style_menu(); }
	void dashed_pressed() { change_line_style(Line_style::dash); hide_line_style_menu(); }
	void dotted_pressed() { change_line_style(Line_style::dot); hide_line_style_menu(); }
	void line_style_menu_pressed() { line_style_menu_button.hide(); line_style_menu.show(); }

	void next();
	void quit();

	// callback functions
	// color
	static void cb_red(Address, Address);
	static void cb_blue(Address, Address);
	static void cb_black(Address, Address);
	static void cb_color_menu(Address, Address);

	// line style
	static void cb_solid(Address, Address);
	static void cb_dash(Address, Address);
	static void cb_dot(Address, Address);
	static void cb_line_style_menu(Address, Address);

	static void cb_next(Address, Address);
	static void cb_quit(Address, Address);
};

Lines_window::Lines_window(Point xy, int w, int h, const string& title)
	:Window(xy, w, h, title),
	next_button(Point(x_max() - 150, 0), 70, 20, "Next point", cb_next),
	quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit),
	next_x(Point(x_max() - 310, 0), 50, 20, "next x:"),
	next_y(Point(x_max() - 210, 0), 50, 20, "next y:"),
	xy_out(Point(100, 0), 100, 20, "current (x,y):"),
	color_menu(Point(x_max() - 70, 30), 70, 20, Menu::vertical, "color"),
	color_menu_button(Point(x_max() - 80, 30), 80, 20, "color menu", cb_color_menu),
	line_style_menu(Point(x_max() - 70, 90), 70, 20, Menu::vertical, "line style"),
	line_style_menu_button(Point(x_max() - 80, 90), 80, 20, "style menu", cb_line_style_menu)
{
	attach(next_button);
	attach(quit_button);
	attach(next_x);
	attach(next_y);
	attach(xy_out);

	// initialize out box and line color
	xy_out.put("no point");
	lines.set_color(Color::black);

	color_menu.attach(new Button(Point(0, 0), 0, 0, "red", cb_red));
	color_menu.attach(new Button(Point(0, 0), 0, 0, "blue", cb_blue));
	color_menu.attach(new Button(Point(0, 0), 0, 0, "black", cb_black));

	line_style_menu.attach(new Button(Point(0, 0), 0, 0, "solid", cb_solid));
	line_style_menu.attach(new Button(Point(0, 0), 0, 0, "dashed", cb_dash));
	line_style_menu.attach(new Button(Point(0, 0), 0, 0, "dotted", cb_dot));

	attach(color_menu);
	attach(line_style_menu);

	color_menu.hide();
	line_style_menu.hide();

	attach(line_style_menu_button);
	attach(color_menu_button);
	attach(lines);
}

void Lines_window::next()
{
	int x = next_x.get_int();
	int y = next_y.get_int();

	lines.add(Point(x, y));

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

	redraw();
}

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

// color callback
void Lines_window::cb_red(Address, Address pw)
{
	reference_to<Lines_window>(pw).red_pressed();
}

void Lines_window::cb_blue(Address, Address pw)
{
	reference_to<Lines_window>(pw).blue_pressed();
}

void Lines_window::cb_black(Address, Address pw)
{
	reference_to<Lines_window>(pw).black_pressed();
}

void Lines_window::cb_color_menu(Address, Address pw)
{
	reference_to<Lines_window>(pw).color_menu_pressed();
}

// line style callback
void Lines_window::cb_solid(Address, Address pw)
{
	reference_to<Lines_window>(pw).solid_pressed();
}

void Lines_window::cb_dash(Address, Address pw)
{
	reference_to<Lines_window>(pw).dashed_pressed();
}

void Lines_window::cb_dot(Address, Address pw)
{
	reference_to<Lines_window>(pw).dotted_pressed();
}

void Lines_window::cb_line_style_menu(Address, Address pw)
{
	reference_to<Lines_window>(pw).line_style_menu_pressed();
}

// next + quit callback
void Lines_window::cb_next(Address, Address pw)
{
	reference_to<Lines_window>(pw).next();
}

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

int main()
try
{
	Lines_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;
}

line drawing program + color menu [fltk]

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

Output:

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

#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 Lines_window : Window {
	Lines_window(Point xy, int w, int h, const string& title);
private:
	// data
	Open_polyline lines;

	// widgets
	Button next_button;	// add (next_x, next_y) to lines
	Button quit_button;	// end program
	In_box next_x;
	In_box next_y;
	Out_box xy_out;
	Menu color_menu;
	Button menu_button;

	void change(Color c) { lines.set_color(c); }

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

	// actions invoked by callbacks
	void red_pressed() { change(Color::red); hide_menu(); }
	void blue_pressed() { change(Color::blue); hide_menu(); }
	void black_pressed() { change(Color::black); hide_menu(); }
	void menu_pressed() { menu_button.hide(); color_menu.show(); }
	void next();
	void quit();

	// callback functions
	static void cb_red(Address, Address);
	static void cb_blue(Address, Address);
	static void cb_black(Address, Address);
	static void cb_menu(Address, Address);
	static void cb_next(Address, Address);
	static void cb_quit(Address, Address);
};

Lines_window::Lines_window(Point xy, int w, int h, const string& title)
	:Window(xy, w, h, title),
	next_button(Point(x_max() - 150, 0), 70, 20, "Next point", cb_next),
	quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit),
	next_x(Point(x_max() - 310, 0), 50, 20, "next x:"),
	next_y(Point(x_max() - 210, 0), 50, 20, "next y:"),
	xy_out(Point(100, 0), 100, 20, "current (x,y):"),
	color_menu(Point(x_max() - 70, 30), 70, 20, Menu::vertical, "color"),
	menu_button(Point(x_max() - 80, 30), 80, 20, "color menu", cb_menu)
{
	attach(next_button);
	attach(quit_button);
	attach(next_x);
	attach(next_y);
	attach(xy_out);
	xy_out.put("no point");
	color_menu.attach(new Button(Point(0, 0), 0, 0, "red", cb_red));
	color_menu.attach(new Button(Point(0, 0), 0, 0, "blue", cb_blue));
	color_menu.attach(new Button(Point(0, 0), 0, 0, "black", cb_black));
	attach(color_menu);
	color_menu.hide();
	attach(menu_button);
	attach(lines);
}

void Lines_window::next()
{
	int x = next_x.get_int();
	int y = next_y.get_int();

	lines.add(Point(x, y));

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

	redraw();
}

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

void Lines_window::cb_red(Address, Address pw)
{
	reference_to<Lines_window>(pw).red_pressed();
}

void Lines_window::cb_blue(Address, Address pw)
{
	reference_to<Lines_window>(pw).blue_pressed();
}

void Lines_window::cb_black(Address, Address pw)
{
	reference_to<Lines_window>(pw).black_pressed();
}

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

void Lines_window::cb_next(Address, Address pw)
{
	reference_to<Lines_window>(pw).next();
}

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

int main()
try
{
	Lines_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;
}

line drawing program [fltk]

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

Output:

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

#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 Lines_window : Window {
	Lines_window(Point xy, int w, int h, const string& title);
private:
	// data
	Open_polyline lines;

	// widgets
	Button next_button;	// add (next_x, next_y) to lines
	Button quit_button;	// end program
	In_box next_x;
	In_box next_y;
	Out_box xy_out;

	// actions invoked by callbacks
	void next();
	void quit();

	// callback functions
	static void cb_next(Address, Address);
	static void cb_quit(Address, Address);
};

Lines_window::Lines_window(Point xy, int w, int h, const string& title)
	:Window(xy, w, h, title),
	next_button(Point(x_max() - 150, 0), 70, 20, "Next point", cb_next),
	quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit),
	next_x(Point(x_max() - 310, 0), 50, 20, "next x:"),
	next_y(Point(x_max() - 210, 0), 50, 20, "next y:"),
	xy_out(Point(100, 0), 100, 20, "current (x,y):")
{
	attach(next_button);
	attach(quit_button);
	attach(next_x);
	attach(next_y);
	attach(xy_out);
	xy_out.put("no point");
	lines.set_color(Color::black);
	attach(lines);
}

void Lines_window::next()
{
	int x = next_x.get_int();
	int y = next_y.get_int();

	lines.add(Point(x, y));

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

	redraw();
}

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

void Lines_window::cb_next(Address, Address pw)
{
	reference_to<Lines_window>(pw).next();
}

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

int main()
try
{
	Lines_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;
}

Graphical user interface – Fast Light Toolkit [FLTK]

What is FLTK? As described on fltk.org:

“FLTK (pronounced “fulltick”) is a cross-platform C++ GUI toolkit for UNIX®/Linux® (X11), Microsoft® Windows®, and MacOS® X. FLTK provides modern GUI functionality without the bloat and supports 3D graphics via OpenGL® and its built-in GLUT emulation.
FLTK is designed to be small and modular enough to be statically linked, but works fine as a shared library. FLTK also includes an excellent UI builder called FLUID that can be used to create applications in minutes.”

Download FLTK here.

How to install FLTK under Visual Stduio 2017 Community
How to compile FLTK – [following the instruction of fltk.org] This approach apparently prevents cross-contamination. Instead of copying files and folders from fltk-1.3.4 to the Visual Studio Community 2017 folder structure, the include and library paths are propperly (I hope so!) added to the project.
How to compile FLTK – [following the instruction of Principles and Practice using C++]

FLTK Examples:
Chapter 12 – A Display Model [using FLTK]
Chapter 13 – Graphics Classes [using FLTK]
Chapter 14 – Graphics Class Design [using FLTK]
Chapter 15 – Graphing Functions and Data [using FLTK]
Chapter 16 – Graphical User Interface [using FLTK]

Average temperature data of Cambridge, England and Cambridge, Massachusetts graphing [fltk]

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

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 15 Exercise 11

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

ostream& operator<<(ostream& out, Point& a) {
	out << "(" << a.x << "," << a.y << ")";
	return out;
}

// 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 = 400;

constexpr int x_scale = 2;
constexpr int y_scale = 2;

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;


int main()
try
{
	Point tl(100, 100);
	Simple_window win(tl, xmax, ymax, "Function graphs");

	// x axis
	Axis x(Axis::x, Point(xoffset, ymax - yoffset), xlength, 12,
		"month    Jan  Feb   Mar  Apr  May  Jun   Jul    Aug  Sep  Oct  Nov   Dec");
	x.set_color(Color::black);
	x.label.move(-100, 0);
	win.attach(x);

	// y axis
	Axis y(Axis::y, Point(yoffset, ymax - yoffset), ylength, 20, "temperature in 0 - 20 C");
	y.set_color(Color::black);
	win.attach(y);

	// data
	// Cambridge, England monthly normal weather 2016
	vector<double> camb_eng_temp = { 
		3.7,
		3.8,
		6.1,
		8.0,
		11.4,
		14.3,
		16.8,
		16.9,
		14.1,
		10.5,
		6.5,
		4.7
	};

	// Cambridge, Massachusetts monthly normal weather 2016
	vector<double> camb_mas_temp = {
		-1.9,
		-0.9,
		3.7,
		8.9,
		14.6,
		19.8,
		23.1,
		22.2,
		18.2,
		12.7,
		7.4,
		0.9
	};

	// graph
	Open_polyline cet; // Cambridge, England
	Open_polyline cmt; // Cambridge, Massachusetts

	for (int i = 0; i < 12; i++) {
		cet.add(Point(xoffset + i * (xlength / 12), (yspace + ylength) - camb_eng_temp[i] * 20));
		cmt.add(Point(xoffset + i * (xlength / 12), (yspace + ylength) - camb_mas_temp[i] * 20));
	}

	cet.set_color(Color::red);
	win.attach(cet);

	cmt.set_color(Color::blue);
	win.attach(cmt);

	win.wait_for_button();
	keep_window_open();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}

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

labeled points data graphing [fltk]

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

Output:

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

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

ostream& operator<<(ostream& out, Point& a) {
	out << "(" << a.x << "," << a.y << ")";
	return out;
}

// 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 = 400;

constexpr int x_scale = 2;
constexpr int y_scale = 2;

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;

class bar_graph : public Shape
{
public:
	bar_graph(Point origin, vector<Point>& data, int x_scale, int r1_min, int r1_max, int y_scale, int r2_min, int r2_max, Color col, string label);

	void draw_lines() const;

	vector<Point>& get_data() { return data; }

private:
	Point origin;
	vector<Point>& data;

	int x_scale;
	int r1_min;
	int r1_max;

	int y_scale;
	int r2_min;
	int r2_max;

	int bar_width;

	Color col;
	string label;
};

bar_graph::bar_graph(Point origin, vector<Point>& data, int x_scale, int r1_min, int r1_max, int y_scale, int r2_min, int r2_max, Color col, string label)
	: origin(origin),
	data(data),
	x_scale(x_scale),
	r1_min(r1_min),
	r1_max(r1_max),
	y_scale(y_scale),
	r2_min(r2_min),
	r2_max(r2_max),
	bar_width(bar_width),
	col(col),
	label(label)
{

}

void bar_graph::draw_lines() const
{
	int ds = data.size();
	cout << ds << endl;


	for (int i = 0; i < data.size(); i++) {

		int h = data[i].x;
		int c = data[i].y;

		// scale factor
		double sx = (xlength / 2.0) / (r1_max - r1_min);
		double sy = (ylength / 2.0) / (r2_max - r2_min);

		// draw point
		Point p(origin.x + (h - r1_min) * sx, origin.y - (c - r2_min) * sy);
		cout << p << endl;

		Graph_lib::Circle crcl(p, 3);
		crcl.set_color(col);
		crcl.set_fill_color(col);
		crcl.draw();

		// draw label
		string point_label = "(" + to_string(data[i].x) + "," + to_string(data[i].y) + ")";
		Text l(p, point_label);
		l.set_color(Color::red);

		l.draw();

	}

	// graph label
	Text gl(Point(origin.x - 90, origin.y + 15), label);
	gl.set_color(col);

	gl.draw();
}

int main()
try
{
	Point tl(100, 100);
	Simple_window win(tl, xmax, ymax, "Function graphs.");

	int r1_min = 170;
	int r1_max = 180;

	int r2_min = 7;
	int r2_max = 23;

	// notch label x
	string x_notch = "1 == " + to_string((r1_max - r1_min) / 10);

	// notch label y
	ostringstream strs;
	strs << setprecision(2) << (r2_max - r2_min) / 10.0;
	string y_notch = "1 == " + strs.str();

	// x axis
	Axis x(Axis::x, Point(orig.x - 200, orig.y), 400, 20, x_notch);
	x.set_color(Color::black);
	win.attach(x);

	// y axis
	Axis y(Axis::y, Point(orig.x, orig.y + 200), 400, 20, y_notch);
	y.set_color(Color::black);
	win.attach(y);

	// people height data
	vector<Point> d = {
		Point(170, 7),
		Point(175, 9),
		Point(180, 23),
		Point(173, 8),
		Point(178, 20),
		Point(177, 15),
		Point(171, 10),
		Point(174, 19)
	};

	// bar graph
	bar_graph bg(orig, d, x_scale, r1_min, r1_max, y_scale, r2_min, r2_max, Color::blue, "labeled points");
	win.attach(bg);

	win.wait_for_button();
	keep_window_open();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}

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

bar graph – group of people height data graphing [fltk]

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

Output:

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

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

ostream& operator<<(ostream& out, Point& a) {
	out << "(" << a.x << "," << a.y << ")";
	return out;
}

// 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 = 400;

constexpr int x_scale = 2;
constexpr int y_scale = 2;

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;

struct ppl_height
{
	ppl_height(double height, int count)
		:height(height), count(count) {	}
	double height;
	int count;
};

void read_data(string location, vector<ppl_height>& v)
{
	ifstream ist(location);
	if (!ist) { error("no such file exists", location); }

	char comma;
	double height;
	int count;

	while (ist >> height >> comma >> count)
	{
		if (ist.eof()) {
			break;
		}
		v.push_back(ppl_height(height, count));
	}

}

class bar_graph : public Shape
{
public:
	bar_graph(Point origin, vector<ppl_height>& data, int x_scale, int r1_min, int r1_max, int y_scale, int r2_min, int r2_max, int bar_width, Color col, string label);

	void draw_lines() const;

	vector<ppl_height>& get_data() { return data; }

private:
	Point origin;
	vector<ppl_height>& data;

	int x_scale;
	int r1_min;
	int r1_max;

	int y_scale;
	int r2_min;
	int r2_max;

	int bar_width;

	Color col;
	string label;
};

bar_graph::bar_graph(Point origin, vector<ppl_height>& data, int x_scale, int r1_min, int r1_max, int y_scale, int r2_min, int r2_max, int bar_width, Color col, string label)
	:	origin(origin),
		data(data),
		x_scale(x_scale),
		r1_min(r1_min),
		r1_max(r1_max),
		y_scale(y_scale),
		r2_min(r2_min),
		r2_max(r2_max),
		bar_width(bar_width),
		col(col),
		label(label)
{

}

void bar_graph::draw_lines() const
{
	int ds = data.size();


	for (int i = 0; i < data.size(); i++) {

		double w = double(bar_width / 2);
		int h = data[i].height;
		int c = data[i].count;

		// scale factor
		double sx = (xlength / 2.0) / (r1_max - r1_min);
		double sy = (ylength / 2.0) / (r2_max - r2_min);
		
		Point p0(origin.x + (h - r1_min) * sx - w, origin.y - c * sy);
		Point p1(origin.x + (h - r1_min) * sx + w, origin.y);

		Graph_lib::Rectangle r(p0, p1);

		r.set_color(col);
		r.set_fill_color(col);

		r.draw();

		// bar labels
		string hl = to_string((int)data[i].height);
		Text height_label(Point(p1.x - bar_width, p1.y + 15), hl);
		height_label.set_color(col);
		height_label.draw();
		
		string cl = to_string((int)data[i].count);
		Text count_label(Point(p0.x, p0.y - 10), cl);
		count_label.set_color(col);
		count_label.draw();

	}

	// graph label
	Text gl(Point(origin.x - 70, origin.y + 15), label);
	gl.set_color(col);

	gl.draw();
}

int main()
try
{
	Point tl(100, 100);
	Simple_window win(tl, xmax, ymax, "Function graphs.");

	int r1_min = 160;
	int r1_max = 200;

	int r2_min = 5;
	int r2_max = 30;

	int bar_width = 15;
	
	// notch label x
	string x_notch = "1 == " + to_string((r1_max - r1_min) / 10);

	// notch label y
	ostringstream strs;
	strs << setprecision(2) << (r2_max - r2_min) / 10.0;
	string y_notch = "1 == " + strs.str();

	// x axis
	Axis x(Axis::x, Point(orig.x - 200, orig.y), 400, 20, x_notch);
	x.set_color(Color::black);
	win.attach(x);

	// y axis
	Axis y(Axis::y, Point(orig.x, orig.y + 200), 400, 20, y_notch);
	y.set_color(Color::black);
	win.attach(y);

	// people height data
	vector<ppl_height> d = {	ppl_height(170, 7),
								ppl_height(175, 9),
								ppl_height(180, 23),
								ppl_height(185, 17),
								ppl_height(190, 6),
								ppl_height(195, 1)
	};

	// stream data from file
	vector<ppl_height> dff;
	string location = "input/height_data.txt";
	read_data(location, dff);

	// bar graph
	bar_graph bg(orig, dff, x_scale, r1_min, r1_max, y_scale, r2_min, r2_max, bar_width, Color::blue, "bar graph");
	win.attach(bg);

	win.wait_for_button();
	keep_window_open();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}

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