<commit_before>#include <gtksourceview/gtksourceview.h>
#include <gtksourceview/gtksource.h>
#include <cstdio>
#include <string>
#include <iostream>
#include "Gtk.hpp"
using namespace Jazz;

GtkWidget* window 	= nullptr;
GtkWidget* toolbar 	= nullptr;
GtkWidget* swin 	= nullptr;
GtkWidget* source_view 	= nullptr;
GtkWidget* hbox 	= nullptr;
GtkWidget* notebook = nullptr;
//GtkWidget* frame	= nullptr;
//GtkWidget* label	= nullptr;
int tab_num = 1;
char bufferf[32];
char bufferl[32];
GtkSourceLanguageManager* language_manager = nullptr;

struct _Data
{
   GtkTextBuffer *buffer;
   GtkWindow     *parent;
};
typedef struct _Data Data;

static void close_tab(GtkButton* button, GtkWidget* child_obj)
{
	gint pagenum = gtk_notebook_page_num(GTK_NOTEBOOK(notebook), child_obj);

	gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), pagenum);
}

GtkWidget* new_tab_label(const std::string& title, GtkWidget* child_held)
{
	std::string shortname = "";
	if(title.find("\\")!=std::string::npos)
		shortname = title.substr(title.find_last_of("\\")+1);
	else
		shortname = title;
	// Create widgets that go in the new tab
	auto image = gtk_image_new_from_icon_name("window-close",GTK_ICON_SIZE_SMALL_TOOLBAR);
	auto box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
	auto tab_close_button = gtk_button_new();
	auto tab_label = gtk_label_new(shortname.c_str());
	// making close button
	gtk_button_set_relief(GTK_BUTTON(tab_close_button),GTK_RELIEF_NONE);
	gtk_button_set_focus_on_click(GTK_BUTTON(tab_close_button), false);
	gtk_button_set_image(GTK_BUTTON(tab_close_button), image);
	// pack the label on the left, and the button
	gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(tab_label), TRUE, TRUE, 0);
	gtk_box_pack_end(GTK_BOX(box), tab_close_button, TRUE, TRUE, 0);
	//
	g_signal_connect (tab_close_button, "clicked", G_CALLBACK(close_tab), child_held);//tab_label);
	// the box shows its widgets
	gtk_widget_show_all(GTK_WIDGET(box));

	return box;
}

GtkWidget* new_sourceview(bool scrollable = true)
{
	Gtk::SourceView source_view;

	if(scrollable)
	{
		Gtk::ScrolledWindow scrolled_window;

		scrolled_window.Add(source_view);
		scrolled_window.ShowAll();

		return scrolled_window.Object();
	}
	return source_view.Object();
}

static void new_file(GtkToolItem *button, void*)
{
	std::string str = "Page ";
	str += std::to_string(tab_num); //char* str = "Page";

	auto new_source_view = new_sourceview();
	auto new_tab_thing = new_tab_label(str, new_source_view);

	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), new_source_view, new_tab_thing);

	gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), -1);

	gtk_widget_show_all(notebook);
	//std::cout << tab_num << std::endl;
	tab_num++;
}
static void load_file(GtkToolItem *button, void*)
{
	GtkWidget* dialog = gtk_file_chooser_dialog_new("Open File",	GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN,
			"_Open", GTK_RESPONSE_ACCEPT, "_Cancel", GTK_RESPONSE_CANCEL, NULL);

	if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
	{
		gchar* filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( dialog ) );
		printf("Open: %s\n", filename);

		// Construct the new text view, the pointer is to a scrolled
		// window containing a sourceview because we didnt pass false
		auto new_sview = new_sourceview();
		auto tab_label = new_tab_label(filename, new_sview);
		auto source = gtk_bin_get_child (GTK_BIN(new_sview));
		auto buff = gtk_text_view_get_buffer(GTK_TEXT_VIEW( source ));

		GFile* new_file = g_file_new_for_path(filename);
		GtkSourceFile* new_source_file = gtk_source_file_new();

		gtk_source_file_set_location(new_source_file, new_file);

		GtkSourceFileLoader* loader = gtk_source_file_loader_new(
			GTK_SOURCE_BUFFER(buff), new_source_file);

		auto s_lang = gtk_source_language_manager_guess_language(
			language_manager,
			filename,
			nullptr);

		gtk_source_file_loader_load_async(
			loader, G_PRIORITY_DEFAULT, NULL, NULL, NULL,	NULL,
			[](GObject* source_obj, GAsyncResult* res, gpointer loader) -> void {
				GError* error = nullptr;
				gboolean success = gtk_source_file_loader_load_finish(
					(GtkSourceFileLoader*)loader, res, &error);
				if(success)
					puts("Successfully opened file");
				else
					printf("Failed to open file: %i, %s\n",
						error->code,error->message);
			},
			// Pass the loader as the user data, so that we can just keep
			// the lambda function as is
			(gpointer)loader);

		//gtk_text_buffer_set_text( buff, text_data, -1 );

		gtk_source_buffer_set_language(GTK_SOURCE_BUFFER(buff), s_lang);

		gtk_notebook_append_page(GTK_NOTEBOOK(notebook), new_sview, tab_label);

		gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), -1);

		gtk_widget_show_all(notebook);

		g_free( filename );
		g_object_unref(new_file);
		//g_free( text_data );
		tab_num++;
	}
	//gtk_widget_hide(dialog);
	gtk_widget_destroy(dialog);
}
static void save_file(GtkToolItem *button, void*)
{
	GtkWidget *dialog = gtk_file_chooser_dialog_new("Save file", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_SAVE,
			"_Save", GTK_RESPONSE_ACCEPT, "_Cancel", GTK_RESPONSE_CANCEL, NULL);

	if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
	{
		// First thing is to aquire the text buffer of the current tab
		Gtk::Notebook the_notebook(notebook);

		GtkWidget* page = the_notebook.CurrentPage().Object();
		GtkWidget* label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page);

		//GtkWidget* the_child = the_notebook.CurrentPage().Object();
		GtkSourceView* the_sourceview = nullptr;

		if(GTK_IS_SCROLLED_WINDOW(page)) //the_child))
			the_sourceview = GTK_SOURCE_VIEW(gtk_bin_get_child(GTK_BIN(page)));//the_child)));
		else
			the_sourceview = GTK_SOURCE_VIEW(page);//the_child);

		Gtk::SourceView sourceview(GTK_WIDGET(the_sourceview));

		Gtk::Buffer the_buffer = sourceview.GetBuffer();

		//Gtk::Buffer the_buffer(the_notebook.CurrentPage());

		//g_object_get( G_OBJECT( the_buffer.Object() ), "text", &text_data, NULL);
		gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER( dialog ));

		std::string filenm = filename;

		std::string shortname = filenm.substr(filenm.find_last_of("\\")+1);

		GList* children = gtk_container_get_children(GTK_CONTAINER(label));

		GList* label_child = g_list_first(children);

		gtk_label_set_text(GTK_LABEL(label_child->data), shortname.c_str()); //children->data, shortname);

		//g_file_set_contents( filename, text_data, -1, NULL);
		g_free( filename );
		//g_free( text_data );
	}
	//gtk_widget_hide(dialog);
	gtk_widget_destroy(dialog);
}
static void activate(GtkApplication* app, gpointer user_data)
{
	// initialize
	notebook = gtk_notebook_new();
	//data = g_slice_new(Data);
	window = gtk_application_window_new(app);
	toolbar = gtk_toolbar_new();
	hbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1);
	//
	language_manager = gtk_source_language_manager_get_default ();
	//
	GtkToolItem* new_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(new_button), "document-new");
	//
	GtkToolItem* open_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(open_button), "document-open");
	//
	GtkToolItem* save_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(save_button), "document-save");
	//
	GtkToolItem* seperator = gtk_separator_tool_item_new();
	//
	GtkToolItem* compile_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(compile_button), "system-run");
	//
	// signal connect
	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK( gtk_main_quit ), NULL);
	g_signal_connect (save_button, "clicked", G_CALLBACK(save_file), nullptr);
	g_signal_connect (open_button, "clicked", G_CALLBACK(load_file), nullptr);
	g_signal_connect (new_button, "clicked", G_CALLBACK(new_file), nullptr);
	// position
	gtk_box_pack_start(GTK_BOX(hbox), toolbar, FALSE, FALSE, 0);
	gtk_notebook_set_tab_pos (GTK_NOTEBOOK(notebook), GTK_POS_TOP);
	gtk_box_pack_end( GTK_BOX( hbox ), notebook, TRUE, TRUE, 0 );
	// insert toolbar items
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), new_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), open_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), save_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), seperator, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), compile_button, -1);
	// window set
	gtk_window_set_title(GTK_WINDOW(window), "Window");
	gtk_window_set_default_size(GTK_WINDOW(window), 600, 500);
	// connections
	gtk_container_add(GTK_CONTAINER(window), hbox);

	gtk_widget_show_all(window);
}

int main(int argc, char** argv)
{
	GtkApplication* app;

	app = gtk_application_new("ca.chr.gtk.jazz", G_APPLICATION_FLAGS_NONE);
	g_signal_connect(app, "activate", G_CALLBACK(activate), 0);
	int status = g_application_run(G_APPLICATION(app), argc, argv);
	g_object_unref(app);

	return status;
}
<commit_msg>added async save<commit_after>#include <gtksourceview/gtksourceview.h>
#include <gtksourceview/gtksource.h>
#include <cstdio>
#include <string>
#include <iostream>
#include "Gtk.hpp"
using namespace Jazz;

GtkWidget* window 	= nullptr;
GtkWidget* toolbar 	= nullptr;
GtkWidget* swin 	= nullptr;
GtkWidget* source_view 	= nullptr;
GtkWidget* hbox 	= nullptr;
GtkWidget* notebook = nullptr;
//GtkWidget* frame	= nullptr;
//GtkWidget* label	= nullptr;
int tab_num = 1;
char bufferf[32];
char bufferl[32];
GtkSourceLanguageManager* language_manager = nullptr;

struct _Data
{
   GtkTextBuffer *buffer;
   GtkWindow     *parent;
};
typedef struct _Data Data;

static void close_tab(GtkButton* button, GtkWidget* child_obj)
{
	gint pagenum = gtk_notebook_page_num(GTK_NOTEBOOK(notebook), child_obj);

	gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), pagenum);
}

GtkWidget* new_tab_label(const std::string& title, GtkWidget* child_held)
{
	std::string shortname = "";
	if(title.find("\\")!=std::string::npos)
		shortname = title.substr(title.find_last_of("\\")+1);
	else
		shortname = title;
	// Create widgets that go in the new tab
	auto image = gtk_image_new_from_icon_name("window-close",GTK_ICON_SIZE_SMALL_TOOLBAR);
	auto box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
	auto tab_close_button = gtk_button_new();
	auto tab_label = gtk_label_new(shortname.c_str());
	// making close button
	gtk_button_set_relief(GTK_BUTTON(tab_close_button),GTK_RELIEF_NONE);
	gtk_button_set_focus_on_click(GTK_BUTTON(tab_close_button), false);
	gtk_button_set_image(GTK_BUTTON(tab_close_button), image);
	// pack the label on the left, and the button
	gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(tab_label), TRUE, TRUE, 0);
	gtk_box_pack_end(GTK_BOX(box), tab_close_button, TRUE, TRUE, 0);
	//
	g_signal_connect (tab_close_button, "clicked", G_CALLBACK(close_tab), child_held);//tab_label);
	// the box shows its widgets
	gtk_widget_show_all(GTK_WIDGET(box));

	return box;
}

GtkWidget* new_sourceview(bool scrollable = true)
{
	Gtk::SourceView source_view;

	if(scrollable)
	{
		Gtk::ScrolledWindow scrolled_window;

		scrolled_window.Add(source_view);
		scrolled_window.ShowAll();

		return scrolled_window.Object();
	}
	return source_view.Object();
}

static void new_file(GtkToolItem *button, void*)
{
	std::string str = "Page ";
	str += std::to_string(tab_num); //char* str = "Page";

	auto new_source_view = new_sourceview();
	auto new_tab_thing = new_tab_label(str, new_source_view);

	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), new_source_view, new_tab_thing);

	gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), -1);

	gtk_widget_show_all(notebook);
	//std::cout << tab_num << std::endl;
	tab_num++;
}
static void load_file(GtkToolItem *button, void*)
{
	GtkWidget* dialog = gtk_file_chooser_dialog_new("Open File",	GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN,
			"_Open", GTK_RESPONSE_ACCEPT, "_Cancel", GTK_RESPONSE_CANCEL, NULL);

	if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
	{
		gchar* filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( dialog ) );
		printf("Open: %s\n", filename);

		// Construct the new text view, the pointer is to a scrolled
		// window containing a sourceview because we didnt pass false
		auto new_sview = new_sourceview();
		auto tab_label = new_tab_label(filename, new_sview);
		auto source = gtk_bin_get_child (GTK_BIN(new_sview));
		auto buff = gtk_text_view_get_buffer(GTK_TEXT_VIEW( source ));

		GFile* new_file = g_file_new_for_path(filename);
		GtkSourceFile* new_source_file = gtk_source_file_new();

		gtk_source_file_set_location(new_source_file, new_file);

		GtkSourceFileLoader* loader = gtk_source_file_loader_new(
			GTK_SOURCE_BUFFER(buff), new_source_file);

		auto s_lang = gtk_source_language_manager_guess_language(
			language_manager,
			filename,
			nullptr);

		gtk_source_file_loader_load_async(
			loader, G_PRIORITY_DEFAULT, NULL, NULL, NULL,	NULL,
			[](GObject* source_obj, GAsyncResult* res, gpointer loader) -> void {
				GError* error = nullptr;
				gboolean success = gtk_source_file_loader_load_finish(
					(GtkSourceFileLoader*)loader, res, &error);
				if(success)
					puts("Successfully opened file");
				else
					printf("Failed to open file: %i, %s\n",
						error->code,error->message);
			},
			// Pass the loader as the user data, so that we can just keep
			// the lambda function as is
			(gpointer)loader);

		//gtk_text_buffer_set_text( buff, text_data, -1 );

		gtk_source_buffer_set_language(GTK_SOURCE_BUFFER(buff), s_lang);

		gtk_notebook_append_page(GTK_NOTEBOOK(notebook), new_sview, tab_label);

		gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), -1);

		gtk_widget_show_all(notebook);

		g_free( filename );
		g_object_unref(new_file);
		//g_free( text_data );
		tab_num++;
	}
	//gtk_widget_hide(dialog);
	gtk_widget_destroy(dialog);
}
static void save_file(GtkToolItem *button, void*)
{
	GtkWidget *dialog = gtk_file_chooser_dialog_new("Save file", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_SAVE,
			"_Save", GTK_RESPONSE_ACCEPT, "_Cancel", GTK_RESPONSE_CANCEL, NULL);

	if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
	{
		// First thing is to aquire the text buffer of the current tab
		Gtk::Notebook the_notebook(notebook);

		GtkWidget* page = the_notebook.CurrentPage().Object();
		GtkWidget* label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page);

		//GtkWidget* the_child = the_notebook.CurrentPage().Object();
		GtkSourceView* the_sourceview = nullptr;

		if(GTK_IS_SCROLLED_WINDOW(page)) //the_child))
			the_sourceview = GTK_SOURCE_VIEW(gtk_bin_get_child(GTK_BIN(page)));//the_child)));
		else
			the_sourceview = GTK_SOURCE_VIEW(page);//the_child);

		Gtk::SourceView sourceview(GTK_WIDGET(the_sourceview));

		Gtk::Buffer the_buffer = sourceview.GetBuffer();

		//Gtk::Buffer the_buffer(the_notebook.CurrentPage());

		//g_object_get( G_OBJECT( the_buffer.Object() ), "text", &text_data, NULL);
		gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER( dialog ));

		GFile* new_file = g_file_new_for_path(filename);
		GtkSourceFile* new_source_file = gtk_source_file_new();

		gtk_source_file_set_location(new_source_file, new_file);

		GtkSourceFileSaver* new_srcfile_saver = gtk_source_file_saver_new_with_target(GTK_SOURCE_BUFFER(the_buffer.Object()), new_srcfile_saver, new_file);

		gtk_source_file_saver_save_async(
			new_srcfile_saver, G_PRIORITY_DEFAULT, NULL, NULL, NULL,	NULL,
			[](GObject* source_obj, GAsyncResult* res, gpointer saver) -> void {
				GError* error = nullptr;
				gboolean success = gtk_source_file_saver_save_finish(
					(GtkSourceFileSaver*)saver, res, &error);
				if(success)
					puts("Successfully saved file");
				else
					printf("Failed to save file: %i, %s\n",
						error->code,error->message);
			},
			// Pass the loader as the user data, so that we can just keep
			// the lambda function as is
			(gpointer)loader);

		std::string filenm = filename;

		std::string shortname = filenm.substr(filenm.find_last_of("\\")+1);

		GList* children = gtk_container_get_children(GTK_CONTAINER(label));

		GList* label_child = g_list_first(children);

		gtk_label_set_text(GTK_LABEL(label_child->data), shortname.c_str()); //children->data, shortname);

		//g_file_set_contents( filename, text_data, -1, NULL);
		g_free( filename );
		//g_free( text_data );
	}
	//gtk_widget_hide(dialog);
	gtk_widget_destroy(dialog);
}
static void activate(GtkApplication* app, gpointer user_data)
{
	// initialize
	notebook = gtk_notebook_new();
	//data = g_slice_new(Data);
	window = gtk_application_window_new(app);
	toolbar = gtk_toolbar_new();
	hbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1);
	//
	language_manager = gtk_source_language_manager_get_default ();
	//
	GtkToolItem* new_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(new_button), "document-new");
	//
	GtkToolItem* open_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(open_button), "document-open");
	//
	GtkToolItem* save_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(save_button), "document-save");
	//
	GtkToolItem* seperator = gtk_separator_tool_item_new();
	//
	GtkToolItem* compile_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(compile_button), "system-run");
	//
	// signal connect
	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK( gtk_main_quit ), NULL);
	g_signal_connect (save_button, "clicked", G_CALLBACK(save_file), nullptr);
	g_signal_connect (open_button, "clicked", G_CALLBACK(load_file), nullptr);
	g_signal_connect (new_button, "clicked", G_CALLBACK(new_file), nullptr);
	// position
	gtk_box_pack_start(GTK_BOX(hbox), toolbar, FALSE, FALSE, 0);
	gtk_notebook_set_tab_pos (GTK_NOTEBOOK(notebook), GTK_POS_TOP);
	gtk_box_pack_end( GTK_BOX( hbox ), notebook, TRUE, TRUE, 0 );
	// insert toolbar items
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), new_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), open_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), save_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), seperator, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), compile_button, -1);
	// window set
	gtk_window_set_title(GTK_WINDOW(window), "Window");
	gtk_window_set_default_size(GTK_WINDOW(window), 600, 500);
	// connections
	gtk_container_add(GTK_CONTAINER(window), hbox);

	gtk_widget_show_all(window);
}

int main(int argc, char** argv)
{
	GtkApplication* app;

	app = gtk_application_new("ca.chr.gtk.jazz", G_APPLICATION_FLAGS_NONE);
	g_signal_connect(app, "activate", G_CALLBACK(activate), 0);
	int status = g_application_run(G_APPLICATION(app), argc, argv);
	g_object_unref(app);

	return status;
}
<|endoftext|>


<commit_before>#include "BBE/BrotBoxEngine.h"

constexpr int WINDOW_WIDTH = 1280;
constexpr int WINDOW_HEIGHT = 720;

// Inspired by CodeParade
// See: https://www.youtube.com/watch?v=Z_zmZ23grXE

class MyGame : public bbe::Game
{
	constexpr static int particleTypes = 10;
	constexpr static float particleSize = 3;
	constexpr static float maxSpeed = 10;

	struct Particle
	{
		bbe::Vector2 pos;
		bbe::Vector2 speed;
		int particleType;
	};

	struct AttractionFunction
	{
		float min;
		float max;
		float half;
		float halfStrength;

		AttractionFunction(float min, float max, float halfStrength)
			: min(min), max(max), halfStrength(halfStrength), half((min + max) / 2.f)
		{

		}

		AttractionFunction(const AttractionFunction& other) = default;
		AttractionFunction(AttractionFunction&& other) = default;
		AttractionFunction& operator=(const AttractionFunction & other) = default;
		AttractionFunction& operator=(AttractionFunction && other) = default;

		bbe::Vector2 operator() (bbe::Vector2 a, bbe::Vector2 b) const
		{
			const bbe::Vector2 to = b - a;
			const float dist = to.getLength();

			if (dist >= max) return bbe::Vector2(0, 0);

			const bbe::Vector2 norm = to.normalize();

			if (dist >= half)
			{
				const float t = (dist - half) / (max - half);
				return norm * (bbe::Math::interpolateLinear(halfStrength, 0, t));
			}
			else if (dist >= min)
			{
				const float t = (dist - min) / (half - min);
				return norm * bbe::Math::interpolateLinear(0, halfStrength, t);
			}
			else if (dist >= 0.1f)
			{
				const float t = 2.f * min * (1.f / (min + 2.f) - 1.f / (dist + 2.f));
				return norm * t;
			}
			else
			{
				return bbe::Vector2(0, 0);
			}
		}
	};

	bbe::List<Particle> particles;
	bbe::Random rand;

	bbe::List<bbe::List<AttractionFunction>> attractionMatrix;

	bbe::List<bbe::Vector2> offsets;

	void placeRandomParticle()
	{
		particles.add(Particle{
			rand.randomVector2(WINDOW_WIDTH, WINDOW_HEIGHT),
			{0, 0},
			rand.randomInt(particleTypes)
		});
	}

	void generateRandomParticles()
	{
		particles.clear();
		for (int i = 0; i < 500; i++)
		{
			placeRandomParticle();
		}
	}

	void generateRandomAttractionMatrix()
	{
		attractionMatrix.clear();
		for (size_t i = 0; i < particleTypes; i++)
		{
			attractionMatrix.add({});
			for (size_t k = 0; k < particleTypes; k++)
			{
				const float min = rand.randomFloat() * 20 + 20 + particleSize;
				float attraction = rand.randomFloat() * 10 - 5;
				if (i == k)
				{
					attraction = 10;
				}
				attractionMatrix[i].add(AttractionFunction(
					particleSize * 20,
					200,
					attraction
				));
			}
		}
	}

	void gameStart()
	{
		generateRandomAttractionMatrix();
		generateRandomParticles();
	}

	virtual void onStart() override
	{
		offsets.add({ -WINDOW_WIDTH, -WINDOW_HEIGHT });
		offsets.add({ 0, -WINDOW_HEIGHT });
		offsets.add({ +WINDOW_WIDTH, -WINDOW_HEIGHT });
		offsets.add({ -WINDOW_WIDTH, 0 });
		offsets.add({ 0, 0 });
		offsets.add({ +WINDOW_WIDTH, 0 });
		offsets.add({ -WINDOW_WIDTH, +WINDOW_HEIGHT });
		offsets.add({ 0, +WINDOW_HEIGHT });
		offsets.add({ +WINDOW_WIDTH, +WINDOW_HEIGHT });
		gameStart();
	}
	virtual void update(float timeSinceLastFrame) override
	{
		for (size_t i = 0; i < particles.getLength(); i++)
		{
			for (size_t k = 0; k < particles.getLength(); k++)
			{
				if (i == k) continue;

				for (size_t m = 0; m < offsets.getLength(); m++)
				{
					const bbe::Vector2 otherParticlePos = particles[k].pos + offsets[m];
					const bbe::Vector2& thisParticle = particles[i].pos;
					const bbe::Vector2 moveDir = otherParticlePos - thisParticle;
					const AttractionFunction& attractionFunction = attractionMatrix[particles[i].particleType][particles[k].particleType];

					particles[i].speed += attractionFunction(particles[i].pos, otherParticlePos) * 0.1f;
				}
			}
			particles[i].speed *= 0.9f;
		}
		for (size_t i = 0; i < particles.getLength(); i++)
		{
			particles[i].pos += particles[i].speed * 0.03;
		}

		for (size_t i = 0; i < particles.getLength(); i++)
		{
			if (particles[i].pos.x < 0)
			{
				particles[i].pos.x += WINDOW_WIDTH;
			}
			if (particles[i].pos.x > WINDOW_WIDTH)
			{
				particles[i].pos.x -= WINDOW_WIDTH;
			}
			if (particles[i].pos.y < 0)
			{
				particles[i].pos.y += WINDOW_HEIGHT;
			}
			if (particles[i].pos.y > WINDOW_HEIGHT)
			{
				particles[i].pos.y -= WINDOW_HEIGHT;
			}
		}

		if (isKeyPressed(bbe::Key::SPACE))
		{
			gameStart();
		}
	}
	virtual void draw3D(bbe::PrimitiveBrush3D & brush) override
	{
	}
	virtual void draw2D(bbe::PrimitiveBrush2D & brush) override
	{
		for (size_t i = 0; i < particles.getLength(); i++)
		{
			brush.setColorHSV(particles[i].particleType * 360 * bbe::Math::GOLDEN_RATIO, 1, 1);
			brush.fillCircle(particles[i].pos.x - particleSize, particles[i].pos.y - particleSize, particleSize * 2, particleSize * 2);
		}
	}
	virtual void onEnd() override
	{
	}
};

int main()
{
	MyGame game;
	game.start(WINDOW_WIDTH, WINDOW_HEIGHT, "Particle Life");
    return 0;
}

<commit_msg>Removed magic number.<commit_after>#include "BBE/BrotBoxEngine.h"

constexpr int WINDOW_WIDTH = 1280;
constexpr int WINDOW_HEIGHT = 720;

// Inspired by CodeParade
// See: https://www.youtube.com/watch?v=Z_zmZ23grXE

class MyGame : public bbe::Game
{
	constexpr static size_t amountOfParticles = 500;
	constexpr static int particleTypes = 10;
	constexpr static float particleSize = 3;

	struct Particle
	{
		bbe::Vector2 pos;
		bbe::Vector2 speed;
		int particleType;
	};

	struct AttractionFunction
	{
		float min;
		float max;
		float half;
		float halfStrength;

		AttractionFunction(float min, float max, float halfStrength)
			: min(min), max(max), halfStrength(halfStrength), half((min + max) / 2.f)
		{

		}

		AttractionFunction(const AttractionFunction& other) = default;
		AttractionFunction(AttractionFunction&& other) = default;
		AttractionFunction& operator=(const AttractionFunction & other) = default;
		AttractionFunction& operator=(AttractionFunction && other) = default;

		bbe::Vector2 operator() (bbe::Vector2 a, bbe::Vector2 b) const
		{
			const bbe::Vector2 to = b - a;
			const float dist = to.getLength();

			if (dist >= max) return bbe::Vector2(0, 0);

			const bbe::Vector2 norm = to.normalize();

			if (dist >= half)
			{
				const float t = (dist - half) / (max - half);
				return norm * (bbe::Math::interpolateLinear(halfStrength, 0, t));
			}
			else if (dist >= min)
			{
				const float t = (dist - min) / (half - min);
				return norm * bbe::Math::interpolateLinear(0, halfStrength, t);
			}
			else if (dist >= 0.1f)
			{
				const float t = 2.f * min * (1.f / (min + 2.f) - 1.f / (dist + 2.f));
				return norm * t;
			}
			else
			{
				return bbe::Vector2(0, 0);
			}
		}
	};

	bbe::List<Particle> particles;
	bbe::Random rand;

	bbe::List<bbe::List<AttractionFunction>> attractionMatrix;

	bbe::List<bbe::Vector2> offsets;

	void placeRandomParticle()
	{
		particles.add(Particle{
			rand.randomVector2(WINDOW_WIDTH, WINDOW_HEIGHT),
			{0, 0},
			rand.randomInt(particleTypes)
		});
	}

	void generateRandomParticles()
	{
		particles.clear();
		for (int i = 0; i < amountOfParticles; i++)
		{
			placeRandomParticle();
		}
	}

	void generateRandomAttractionMatrix()
	{
		attractionMatrix.clear();
		for (size_t i = 0; i < particleTypes; i++)
		{
			attractionMatrix.add({});
			for (size_t k = 0; k < particleTypes; k++)
			{
				const float min = rand.randomFloat() * 20 + 20 + particleSize;
				float attraction = rand.randomFloat() * 10 - 5;
				if (i == k)
				{
					attraction = 10;
				}
				attractionMatrix[i].add(AttractionFunction(
					particleSize * 20,
					200,
					attraction
				));
			}
		}
	}

	void gameStart()
	{
		generateRandomAttractionMatrix();
		generateRandomParticles();
	}

	virtual void onStart() override
	{
		offsets.add({ -WINDOW_WIDTH, -WINDOW_HEIGHT });
		offsets.add({ 0, -WINDOW_HEIGHT });
		offsets.add({ +WINDOW_WIDTH, -WINDOW_HEIGHT });
		offsets.add({ -WINDOW_WIDTH, 0 });
		offsets.add({ 0, 0 });
		offsets.add({ +WINDOW_WIDTH, 0 });
		offsets.add({ -WINDOW_WIDTH, +WINDOW_HEIGHT });
		offsets.add({ 0, +WINDOW_HEIGHT });
		offsets.add({ +WINDOW_WIDTH, +WINDOW_HEIGHT });
		gameStart();
	}
	virtual void update(float timeSinceLastFrame) override
	{
		for (size_t i = 0; i < particles.getLength(); i++)
		{
			for (size_t k = 0; k < particles.getLength(); k++)
			{
				if (i == k) continue;

				for (size_t m = 0; m < offsets.getLength(); m++)
				{
					const bbe::Vector2 otherParticlePos = particles[k].pos + offsets[m];
					const bbe::Vector2& thisParticle = particles[i].pos;
					const bbe::Vector2 moveDir = otherParticlePos - thisParticle;
					const AttractionFunction& attractionFunction = attractionMatrix[particles[i].particleType][particles[k].particleType];

					particles[i].speed += attractionFunction(particles[i].pos, otherParticlePos) * 0.1f;
				}
			}
			particles[i].speed *= 0.9f;
		}
		for (size_t i = 0; i < particles.getLength(); i++)
		{
			particles[i].pos += particles[i].speed * 0.03;
		}

		for (size_t i = 0; i < particles.getLength(); i++)
		{
			if (particles[i].pos.x < 0)
			{
				particles[i].pos.x += WINDOW_WIDTH;
			}
			if (particles[i].pos.x > WINDOW_WIDTH)
			{
				particles[i].pos.x -= WINDOW_WIDTH;
			}
			if (particles[i].pos.y < 0)
			{
				particles[i].pos.y += WINDOW_HEIGHT;
			}
			if (particles[i].pos.y > WINDOW_HEIGHT)
			{
				particles[i].pos.y -= WINDOW_HEIGHT;
			}
		}

		if (isKeyPressed(bbe::Key::SPACE))
		{
			gameStart();
		}
	}
	virtual void draw3D(bbe::PrimitiveBrush3D & brush) override
	{
	}
	virtual void draw2D(bbe::PrimitiveBrush2D & brush) override
	{
		for (size_t i = 0; i < particles.getLength(); i++)
		{
			brush.setColorHSV(particles[i].particleType * 360 * bbe::Math::GOLDEN_RATIO, 1, 1);
			brush.fillCircle(particles[i].pos.x - particleSize, particles[i].pos.y - particleSize, particleSize * 2, particleSize * 2);
		}
	}
	virtual void onEnd() override
	{
	}
};

int main()
{
	MyGame game;
	game.start(WINDOW_WIDTH, WINDOW_HEIGHT, "Particle Life");
    return 0;
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "fields.h"
#include "multivalue.h"
#include "serialise.h"
#include "utils.h"
#include <xapian/query.h>

NumericFieldProcessor::NumericFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query
NumericFieldProcessor::operator()(const std::string &str)
{
	// For negative number, we receive _# and we serialise -#.
	std::string serialise(str.c_str());
	if (serialise.at(0) == '_') serialise.at(0) = '-';
	serialise = Serialise::numeric(serialise);
	if (serialise.size() == 0) {
		throw Xapian::QueryParserError("Didn't understand numeric specification '" + str + "'");
	}
	return Xapian::Query(prefix + serialise);
}

BooleanFieldProcessor::BooleanFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query BooleanFieldProcessor::operator()(const std::string &str)
{
	std::string serialise = Serialise::boolean(str);
	if (serialise.size() == 0) {
		throw Xapian::QueryParserError("Didn't understand bool specification '" + str + "'");
	}
	return Xapian::Query(prefix + serialise);
}

DateFieldProcessor::DateFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query DateFieldProcessor::operator()(const std::string &str)
{
	std::string serialise(str.c_str());
	if (serialise.at(0) == '_') serialise.at(0) = '-';
	serialise = Serialise::date(serialise);
	if (serialise.size() == 0) {
		throw Xapian::QueryParserError("Didn't understand date specification '" + str + "'");
	}
	return Xapian::Query(prefix + serialise);
}

GeoFieldProcessor::GeoFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query GeoFieldProcessor::operator()(const std::string &str)
{
	std::string serialise(str.c_str());
	serialise = Serialise::trixel_id(strtouInt64(serialise));
	return Xapian::Query(prefix + serialise);
}<commit_msg>Format and GeoFieldProcessor can receive a lot af uInt64 separates by WKT_SEPARATOR<commit_after>/*
 * Copyright (C) 2015 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "fields.h"
#include "multivalue.h"
#include "wkt_parser.h"
#include "serialise.h"
#include <xapian/query.h>

NumericFieldProcessor::NumericFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query
NumericFieldProcessor::operator()(const std::string &str)
{
	// For negative number, we receive _# and we serialise -#.
	std::string serialise(str.c_str());
	if (serialise.at(0) == '_') serialise.at(0) = '-';
	serialise = Serialise::numeric(serialise);
	if (serialise.empty()) {
		throw Xapian::QueryParserError("Didn't understand numeric specification '" + str + "'");
	}
	return Xapian::Query(prefix + serialise);
}

BooleanFieldProcessor::BooleanFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query BooleanFieldProcessor::operator()(const std::string &str)
{
	std::string serialise = Serialise::boolean(str);
	if (serialise.empty()) {
		throw Xapian::QueryParserError("Didn't understand bool specification '" + str + "'");
	}
	return Xapian::Query(prefix + serialise);
}

DateFieldProcessor::DateFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query DateFieldProcessor::operator()(const std::string &str)
{
	std::string serialise(str.c_str());
	if (serialise.at(0) == '_') serialise.at(0) = '-';
	serialise = Serialise::date(serialise);
	if (serialise.empty()) {
		throw Xapian::QueryParserError("Didn't understand date specification '" + str + "'");
	}
	return Xapian::Query(prefix + serialise);
}

GeoFieldProcessor::GeoFieldProcessor(const std::string &prefix_): prefix(prefix_) {}

Xapian::Query GeoFieldProcessor::operator()(const std::string &str)
{
	std::vector<std::string> values;
	stringTokenizer(str, WKT_SEPARATOR, values);
	std::vector<std::string>::const_iterator it(values.begin());
	std::string serialise(Serialise::trixel_id(strtouInt64(*it)));
	for (it++ ; it != values.end(); it++) {
		serialise += Serialise::trixel_id(strtouInt64(*it));
	}
	return Xapian::Query(prefix + serialise);
}<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#include    <mutex>

#include    "../Containers/Mapping.h"
#include    "../Debug/Trace.h"
#include    "../Containers/Concrete/Queue_Array.h"

#include    "BlockingQueue.h"
#include    "Common.h"
#include    "Thread.h"

#include    "SignalHandlers.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Execution;
using   namespace   Stroika::Foundation::Memory;

using   Containers::Mapping;
using   Containers::Queue;
using   Containers::Set;

// maybe useful while debugging signal code, but VERY unsafe
// and could easily be the source of bugs/deadlocks!
#ifndef qDoDbgTraceOnSignalHandlers_
#define qDoDbgTraceOnSignalHandlers_    0
#endif

namespace   {
    bool    IsSigIgnore_ (const Set<SignalHandler>& sigSet)
    {
        return sigSet.size () == 1 and sigSet.Contains (SignalHandlerRegistry::kIGNORED);
    }
}

/*
 ********************************************************************************
 *********** Execution::SignalHandlerRegistry::SafeSignalsManager ***************
 ********************************************************************************
 */
namespace {
    Queue<SignalID> mkQ_ ()
    {
        Containers::Concrete::Queue_Array<SignalID> signalQ;
        signalQ.SetCapacity (25);  // quite arbitrary - @todo make configurable somehow...
        return signalQ;
    }
}

struct SignalHandlerRegistry::SafeSignalsManager::Rep_ {
    Rep_ ()
        : fHandlers_ ()
        , fIncomingSafeSignals_ (mkQ_ ())
        , fBlockingQueuePusherThread_ ()
    {
        Thread watcherThread ([this] () {
            // This is a safe context
            Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::Signals::{}::fBlockingQueueDelegatorThread_");
            while (true) {
                Debug::TraceContextBumper trcCtx1 ("Waiting for next safe signal");
                SignalID    i   =   fIncomingSafeSignals_.RemoveHead ();
                Debug::TraceContextBumper trcCtx2 ("Invoking SAFE signal handlers");
                DbgTrace (L"(signal: %s)", SignalToName (i).c_str ());
                for (SignalHandler sh : fHandlers_.LookupValue (i)) {
                    Assert (sh.GetType () == SignalHandler::Type::eSafe);
                    IgnoreExceptionsExceptThreadAbortForCall (sh (i));
                }
            }
        });
        watcherThread.SetThreadName (L"Signal Handler Safe Execution Thread");
        watcherThread.Start ();
        fBlockingQueuePusherThread_ = std::move (watcherThread);
    }
    ~Rep_ ()
    {
        Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::SignalHandlerRegistry::SafeSignalsManager::Rep_::~Rep_");
        fBlockingQueuePusherThread_.AbortAndWaitForDone ();
    }
    Containers::Mapping<SignalID, Containers::Set<SignalHandler>>   fHandlers_;
    BlockingQueue<SignalID>                                         fIncomingSafeSignals_;
    Thread                                                          fBlockingQueuePusherThread_;

    void    NotifyOfArrivalOfPossiblySafeSignal (SignalID signal)
    {
        // harmless - but pointless - to add signals that will be ignored
        if (fHandlers_.Lookup (signal).IsPresent ()) {
            fIncomingSafeSignals_.AddTail (signal);
        }
    }
};

/*
 ********************************************************************************
 *********** Execution::SignalHandlerRegistry::SafeSignalsManager ***************
 ********************************************************************************
 */
shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_>  SignalHandlerRegistry::SafeSignalsManager::sTheRep_;

SignalHandlerRegistry::SafeSignalsManager::SafeSignalsManager ()
{
    Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::SignalHandlerRegistry::CTOR");
    Assert (sTheRep_ == nullptr);
    sTheRep_ = make_shared<SignalHandlerRegistry::SafeSignalsManager::Rep_> ();
}

SignalHandlerRegistry::SafeSignalsManager::~SafeSignalsManager ()
{
    Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::SignalHandlerRegistry::DTOR");
    shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_> tmp = SignalHandlerRegistry::SafeSignalsManager::sTheRep_;
    sTheRep_.reset ();
    // avoid slight race - after reset above - could still be processing a signal (holding refcount above zero).
    // this check and abort/wait guaratess at least no more thread running (though other stuff - like signal handling - could
    // still be running)
    if (tmp != nullptr) {
        tmp->fBlockingQueuePusherThread_.AbortAndWaitForDone ();
    }
}

/*
 ********************************************************************************
 ******************** Execution::SignalHandlerRegistry **************************
 ********************************************************************************
 */
const   SignalHandler   SignalHandlerRegistry::kIGNORED =   SignalHandler (SIG_IGN, SignalHandler::Type::eDirect);

SignalHandlerRegistry&  SignalHandlerRegistry::Get ()
{
    /*
     * Safe - even thread safe - ASSUMING never called after end of main. Then results undefined.
     */
    shared_ptr<SignalHandlerRegistry>   sp = _Stroika_Foundation_ExecutionSignalHandlers_ModuleData_.Actual ().fTheRegistry;
    if (sp == nullptr) {
        auto    critSec { make_unique_lock (_Stroika_Foundation_ExecutionSignalHandlers_ModuleData_.Actual ().fMutex) };
        sp = _Stroika_Foundation_ExecutionSignalHandlers_ModuleData_.Actual ().fTheRegistry;    // avoid race, and avoid locking unless needed
        if (sp == nullptr) {
            sp.reset (new SignalHandlerRegistry ());
            Assert (_Stroika_Foundation_ExecutionSignalHandlers_ModuleData_.Actual ().fTheRegistry == nullptr);
            _Stroika_Foundation_ExecutionSignalHandlers_ModuleData_.Actual ().fTheRegistry = sp;
        }
    }
    Assert (sp != nullptr);
    return *sp;
}

SignalHandlerRegistry::SignalHandlerRegistry ()
    : fDirectHandlers_ ()
{
#if     qDebug
    static  int nConstructed = 0;
    nConstructed++;
    Assert (nConstructed == 1);
#endif
    Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::SignalHandlerRegistry::CTOR");
}

SignalHandlerRegistry::~SignalHandlerRegistry ()
{
    Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::SignalHandlerRegistry::DTOR");
    Assert (SafeSignalsManager::sTheRep_ == nullptr);  // must be cleared first
}

Set<SignalID>   SignalHandlerRegistry::GetHandledSignals () const
{
    // @todo redo using Mapping<>::Keys () when implemented...
    Set<SignalID>   result;
    for (auto i : fDirectHandlers_) {
        result.Add (i.fKey);
    }
    shared_ptr<SafeSignalsManager::Rep_> tmp = SafeSignalsManager::sTheRep_;
    if (tmp != nullptr) {
        for (auto i : tmp->fHandlers_) {
            result.Add (i.fKey);
        }
    }
    return result;
}

Set<SignalHandler>  SignalHandlerRegistry::GetSignalHandlers (SignalID signal) const
{
    Set<SignalHandler>  result  =   fDirectHandlers_.LookupValue (signal);
    shared_ptr<SafeSignalsManager::Rep_> tmp = SafeSignalsManager::sTheRep_;
    if (tmp != nullptr) {
        result += tmp->fHandlers_.LookupValue (signal);
    }
    return result;
}

void    SignalHandlerRegistry::SetSignalHandlers (SignalID signal)
{
    SetSignalHandlers (signal, Set<SignalHandler> ());
}

void    SignalHandlerRegistry::SetSignalHandlers (SignalID signal, SignalHandler handler)
{
    SetSignalHandlers (signal, Set<SignalHandler> ({handler}));
}

void    SignalHandlerRegistry::SetSignalHandlers (SignalID signal, const Set<SignalHandler>& handlers)
{
    Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::SignalHandlerRegistry::{}::SetSignalHandlers");
    DbgTrace (L"(signal = %s, handlers.size () = %d, ....)", SignalToName (signal).c_str (), handlers.size ());

    shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_> tmp = SignalHandlerRegistry::SafeSignalsManager::sTheRep_;
    if (handlers.empty ()) {
        /*
         *  No handlers means use default.
         */
        fDirectHandlers_.Remove (signal);
        if (tmp != nullptr) {
            tmp->fHandlers_.Remove (signal);
        }
        Verify (::signal (signal, SIG_DFL) != SIG_ERR);
        DbgTrace (L"DID ::signal (%s, SIG_DFL)", SignalToName (signal).c_str ());
    }
    else if (IsSigIgnore_ (handlers)) {
        Assert (handlers.size () == 1);
        fDirectHandlers_.Add (signal, handlers);
        if (tmp != nullptr) {
            tmp->fHandlers_.Remove (signal);
        }
        Verify (::signal (signal, SIG_IGN) != SIG_ERR);
        DbgTrace (L"DID ::signal (%s, SIG_IGN)", SignalToName (signal).c_str ());
    }
    else {
        Set<SignalHandler>  directHandlers;
        Set<SignalHandler>  safeHandlers;
        handlers.Apply ([&directHandlers, &safeHandlers] (SignalHandler si) {
            switch (si.GetType ()) {
                case SignalHandler::Type::eDirect: {
                        directHandlers.Add (si);
                    }
                    break;
                case SignalHandler::Type::eSafe: {
                        safeHandlers.Add (si);
                    }
                    break;
            }
        });
        Assert (directHandlers.size () + safeHandlers.size () == handlers.size ());
        fDirectHandlers_.Add (signal, directHandlers);
        if (not safeHandlers.empty ()) {
            // To use safe signal handlers, you must have a SignalHandlerRegistry::SafeSignalsManager
            // defined first. It is recommended that you define an instance of
            // SignalHandlerRegistry::SafeSignalsManager handler; should be defined in main ()
            Require (SafeSignalsManager::sTheRep_ != nullptr);
        }
        if (tmp != nullptr) {
            if (safeHandlers.empty ()) {
                tmp->fHandlers_.Remove (signal);
            }
            else {
                tmp->fHandlers_.Add (signal, safeHandlers);
            }
        }
        Verify (::signal (signal, FirstPassSignalHandler_) != SIG_ERR);
        DbgTrace (L"DID ::signal (%s, FirstPassSignalHandler_)", SignalToName (signal).c_str ());
    }
}

void    SignalHandlerRegistry::AddSignalHandler (SignalID signal, SignalHandler handler)
{
    Set<SignalHandler>  s   =   GetSignalHandlers (signal);
    s.Add (handler);
    SetSignalHandlers (signal, s);
}

void    SignalHandlerRegistry::RemoveSignalHandler (SignalID signal, SignalHandler handler)
{
    Set<SignalHandler>  s   =   GetSignalHandlers (signal);
    Require (s.Contains (handler));
    s.Remove (handler);
    SetSignalHandlers (signal, s);
}

void    SignalHandlerRegistry::DefaultCrashSignalHandler (SignalID signal)
{
    DbgTrace (L"Serious Signal Error trapped: %s ... Aborting", SignalToName (signal).c_str ());
    abort ();
}

Containers::Set<SignalID>   SignalHandlerRegistry::GetStandardCrashSignals ()
{
    Containers::Set<SignalID>   results;
    results.Add (SIGABRT);
    results.Add (SIGILL);
    results.Add (SIGFPE);
    results.Add (SIGSEGV);
#if     qPlatform_POSIX
    results.Add (SIGSYS);
    results.Add (SIGBUS);
#endif
    return results;
}

Containers::Set<SignalID>    SignalHandlerRegistry::GetStandardTerminationSignals ()
{
    Containers::Set<SignalID>   results;
    results.Add (SIGABRT);
    results.Add (SIGINT);
    results.Add (SIGTERM);
    results.Add (SIGILL);
    results.Add (SIGFPE);
    results.Add (SIGSEGV);
#if     qPlatform_POSIX
    results.Add (SIGHUP);
    results.Add (SIGQUIT);
    results.Add (SIGSYS);
    results.Add (SIGBUS);
    results.Add (SIGPIPE);
    results.Add (SIGXCPU);
    results.Add (SIGXFSZ);
#endif
    return results;
}

void    SignalHandlerRegistry::SetStandardCrashHandlerSignals (SignalHandler handler, const Containers::Set<SignalID>& forSignals)
{
    for (SignalID s : forSignals) {
        if (s != SIGABRT) {
            SetSignalHandlers (s, handler);
        }
    }
}

void    SignalHandlerRegistry::FirstPassSignalHandler_ (SignalID signal)
{
#if     qDoDbgTraceOnSignalHandlers_
    Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::SignalHandlerRegistry::FirstPassSignalHandler_");
    DbgTrace (L"(signal = %s)", SignalToName (signal).c_str ());
#endif
    SignalHandlerRegistry&  SHR =   Get ();

    {
        // Copy out of Stroika-based containers, because these may throw thread-abort exceptions.
        // The Set<> and Mapping<> code I'm thinking of here. Just use stl code (stuff that wont throw abort exceptions)
        vector<SignalHandler>   shs;
        {
            Thread::SuppressInterruptionInContext  suppressContext;
            for (SignalHandler sh : SHR.fDirectHandlers_.LookupValue (signal)) {
                shs.push_back (sh);
            }
        }
        for (SignalHandler sh : shs) {
            sh (signal);
        }
    }

    shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_> tmp = SignalHandlerRegistry::SafeSignalsManager::sTheRep_;
    if (tmp != nullptr) {
        tmp->NotifyOfArrivalOfPossiblySafeSignal (signal);
    }
}
<commit_msg>use (experimentally for now) sigaction instead of signal API - since seems to fix bug where signals stop working on 2nd created thread for AIX<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#include    <mutex>

#include    "../Containers/Mapping.h"
#include    "../Debug/Trace.h"
#include    "../Containers/Concrete/Queue_Array.h"

#include    "BlockingQueue.h"
#include    "Common.h"
#include    "Thread.h"

#include    "SignalHandlers.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Execution;
using   namespace   Stroika::Foundation::Memory;

using   Containers::Mapping;
using   Containers::Queue;
using   Containers::Set;

// maybe useful while debugging signal code, but VERY unsafe
// and could easily be the source of bugs/deadlocks!
#ifndef qDoDbgTraceOnSignalHandlers_
#define qDoDbgTraceOnSignalHandlers_    0
#endif

namespace   {
    bool    IsSigIgnore_ (const Set<SignalHandler>& sigSet)
    {
        return sigSet.size () == 1 and sigSet.Contains (SignalHandlerRegistry::kIGNORED);
    }
}

/*
 ********************************************************************************
 *********** Execution::SignalHandlerRegistry::SafeSignalsManager ***************
 ********************************************************************************
 */
namespace {
    Queue<SignalID> mkQ_ ()
    {
        Containers::Concrete::Queue_Array<SignalID> signalQ;
        signalQ.SetCapacity (25);  // quite arbitrary - @todo make configurable somehow...
        return signalQ;
    }
}

struct SignalHandlerRegistry::SafeSignalsManager::Rep_ {
    Rep_ ()
        : fHandlers_ ()
        , fIncomingSafeSignals_ (mkQ_ ())
        , fBlockingQueuePusherThread_ ()
    {
        Thread watcherThread ([this] () {
            // This is a safe context
            Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::Signals::{}::fBlockingQueueDelegatorThread_");
            while (true) {
                Debug::TraceContextBumper trcCtx1 ("Waiting for next safe signal");
                SignalID    i   =   fIncomingSafeSignals_.RemoveHead ();
                Debug::TraceContextBumper trcCtx2 ("Invoking SAFE signal handlers");
                DbgTrace (L"(signal: %s)", SignalToName (i).c_str ());
                for (SignalHandler sh : fHandlers_.LookupValue (i)) {
                    Assert (sh.GetType () == SignalHandler::Type::eSafe);
                    IgnoreExceptionsExceptThreadAbortForCall (sh (i));
                }
            }
        });
        watcherThread.SetThreadName (L"Signal Handler Safe Execution Thread");
        watcherThread.Start ();
        fBlockingQueuePusherThread_ = std::move (watcherThread);
    }
    ~Rep_ ()
    {
        Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::SignalHandlerRegistry::SafeSignalsManager::Rep_::~Rep_");
        fBlockingQueuePusherThread_.AbortAndWaitForDone ();
    }
    Containers::Mapping<SignalID, Containers::Set<SignalHandler>>   fHandlers_;
    BlockingQueue<SignalID>                                         fIncomingSafeSignals_;
    Thread                                                          fBlockingQueuePusherThread_;

    void    NotifyOfArrivalOfPossiblySafeSignal (SignalID signal)
    {
        // harmless - but pointless - to add signals that will be ignored
        if (fHandlers_.Lookup (signal).IsPresent ()) {
            fIncomingSafeSignals_.AddTail (signal);
        }
    }
};

/*
 ********************************************************************************
 *********** Execution::SignalHandlerRegistry::SafeSignalsManager ***************
 ********************************************************************************
 */
shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_>  SignalHandlerRegistry::SafeSignalsManager::sTheRep_;

SignalHandlerRegistry::SafeSignalsManager::SafeSignalsManager ()
{
    Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::SignalHandlerRegistry::CTOR");
    Assert (sTheRep_ == nullptr);
    sTheRep_ = make_shared<SignalHandlerRegistry::SafeSignalsManager::Rep_> ();
}

SignalHandlerRegistry::SafeSignalsManager::~SafeSignalsManager ()
{
    Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::SignalHandlerRegistry::DTOR");
    shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_> tmp = SignalHandlerRegistry::SafeSignalsManager::sTheRep_;
    sTheRep_.reset ();
    // avoid slight race - after reset above - could still be processing a signal (holding refcount above zero).
    // this check and abort/wait guaratess at least no more thread running (though other stuff - like signal handling - could
    // still be running)
    if (tmp != nullptr) {
        tmp->fBlockingQueuePusherThread_.AbortAndWaitForDone ();
    }
}

/*
 ********************************************************************************
 ******************** Execution::SignalHandlerRegistry **************************
 ********************************************************************************
 */
const   SignalHandler   SignalHandlerRegistry::kIGNORED =   SignalHandler (SIG_IGN, SignalHandler::Type::eDirect);

SignalHandlerRegistry&  SignalHandlerRegistry::Get ()
{
    /*
     * Safe - even thread safe - ASSUMING never called after end of main. Then results undefined.
     */
    shared_ptr<SignalHandlerRegistry>   sp = _Stroika_Foundation_ExecutionSignalHandlers_ModuleData_.Actual ().fTheRegistry;
    if (sp == nullptr) {
        auto    critSec { make_unique_lock (_Stroika_Foundation_ExecutionSignalHandlers_ModuleData_.Actual ().fMutex) };
        sp = _Stroika_Foundation_ExecutionSignalHandlers_ModuleData_.Actual ().fTheRegistry;    // avoid race, and avoid locking unless needed
        if (sp == nullptr) {
            sp.reset (new SignalHandlerRegistry ());
            Assert (_Stroika_Foundation_ExecutionSignalHandlers_ModuleData_.Actual ().fTheRegistry == nullptr);
            _Stroika_Foundation_ExecutionSignalHandlers_ModuleData_.Actual ().fTheRegistry = sp;
        }
    }
    Assert (sp != nullptr);
    return *sp;
}

SignalHandlerRegistry::SignalHandlerRegistry ()
    : fDirectHandlers_ ()
{
#if     qDebug
    static  int nConstructed = 0;
    nConstructed++;
    Assert (nConstructed == 1);
#endif
    Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::SignalHandlerRegistry::CTOR");
}

SignalHandlerRegistry::~SignalHandlerRegistry ()
{
    Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::SignalHandlerRegistry::DTOR");
    Assert (SafeSignalsManager::sTheRep_ == nullptr);  // must be cleared first
}

Set<SignalID>   SignalHandlerRegistry::GetHandledSignals () const
{
    // @todo redo using Mapping<>::Keys () when implemented...
    Set<SignalID>   result;
    for (auto i : fDirectHandlers_) {
        result.Add (i.fKey);
    }
    shared_ptr<SafeSignalsManager::Rep_> tmp = SafeSignalsManager::sTheRep_;
    if (tmp != nullptr) {
        for (auto i : tmp->fHandlers_) {
            result.Add (i.fKey);
        }
    }
    return result;
}

Set<SignalHandler>  SignalHandlerRegistry::GetSignalHandlers (SignalID signal) const
{
    Set<SignalHandler>  result  =   fDirectHandlers_.LookupValue (signal);
    shared_ptr<SafeSignalsManager::Rep_> tmp = SafeSignalsManager::sTheRep_;
    if (tmp != nullptr) {
        result += tmp->fHandlers_.LookupValue (signal);
    }
    return result;
}

void    SignalHandlerRegistry::SetSignalHandlers (SignalID signal)
{
    SetSignalHandlers (signal, Set<SignalHandler> ());
}

void    SignalHandlerRegistry::SetSignalHandlers (SignalID signal, SignalHandler handler)
{
    SetSignalHandlers (signal, Set<SignalHandler> ({handler}));
}

void    SignalHandlerRegistry::SetSignalHandlers (SignalID signal, const Set<SignalHandler>& handlers)
{
    Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::SignalHandlerRegistry::{}::SetSignalHandlers");
    DbgTrace (L"(signal = %s, handlers.size () = %d, ....)", SignalToName (signal).c_str (), handlers.size ());

    shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_> tmp = SignalHandlerRegistry::SafeSignalsManager::sTheRep_;

    auto sigSetHandler = [] (SignalID signal) {
#if     qPlatform_POSIX
        struct sigaction sa;
        sa.sa_handler = FirstPassSignalHandler_;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = SA_RESTART; /* Restart functions if interrupted by handler */
        Verify (::sigaction (signal, &sa, NULL) == 0);
#else
        Verify (::signal (signal, FirstPassSignalHandler_) != SIG_ERR);
#endif
        DbgTrace (L"DID ::signal (%s, FirstPassSignalHandler_)", SignalToName (signal).c_str ());
    };
    auto sigSetDefault = [] (SignalID signal) {
#if     qPlatform_POSIX
        struct sigaction sa;
        sa.sa_handler = SIG_DFL;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = SA_RESTART; /* Restart functions if interrupted by handler */
        Verify (::sigaction (signal, &sa, NULL) == 0);
#else
        Verify (::signal (signal, SIG_DFL) != SIG_ERR);
#endif
        DbgTrace (L"DID ::signal (%s, SIG_DFL)", SignalToName (signal).c_str ());
    };
    auto sigSetIgnore = [] (SignalID signal) {
#if     qPlatform_POSIX
        struct sigaction sa;
        sa.sa_handler = SIG_IGN;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = SA_RESTART; /* Restart functions if interrupted by handler */
        Verify (::sigaction (signal, &sa, NULL) == 0);
#else
        Verify (::signal (signal, SIG_IGN) != SIG_ERR);
#endif
        DbgTrace (L"DID ::signal (%s, SIG_IGN)", SignalToName (signal).c_str ());
    };
    if (handlers.empty ()) {
        /*
         *  No handlers means use default.
         */
        fDirectHandlers_.Remove (signal);
        if (tmp != nullptr) {
            tmp->fHandlers_.Remove (signal);
        }
        sigSetDefault (signal);
    }
    else if (IsSigIgnore_ (handlers)) {
        Assert (handlers.size () == 1);
        fDirectHandlers_.Add (signal, handlers);
        if (tmp != nullptr) {
            tmp->fHandlers_.Remove (signal);
        }
        sigSetIgnore (signal);
    }
    else {
        Set<SignalHandler>  directHandlers;
        Set<SignalHandler>  safeHandlers;
        handlers.Apply ([&directHandlers, &safeHandlers] (SignalHandler si) {
            switch (si.GetType ()) {
                case SignalHandler::Type::eDirect: {
                        directHandlers.Add (si);
                    }
                    break;
                case SignalHandler::Type::eSafe: {
                        safeHandlers.Add (si);
                    }
                    break;
            }
        });
        Assert (directHandlers.size () + safeHandlers.size () == handlers.size ());
        fDirectHandlers_.Add (signal, directHandlers);
        if (not safeHandlers.empty ()) {
            // To use safe signal handlers, you must have a SignalHandlerRegistry::SafeSignalsManager
            // defined first. It is recommended that you define an instance of
            // SignalHandlerRegistry::SafeSignalsManager handler; should be defined in main ()
            Require (SafeSignalsManager::sTheRep_ != nullptr);
        }
        if (tmp != nullptr) {
            if (safeHandlers.empty ()) {
                tmp->fHandlers_.Remove (signal);
            }
            else {
                tmp->fHandlers_.Add (signal, safeHandlers);
            }
        }
        sigSetHandler (signal);
    }
}

void    SignalHandlerRegistry::AddSignalHandler (SignalID signal, SignalHandler handler)
{
    Set<SignalHandler>  s   =   GetSignalHandlers (signal);
    s.Add (handler);
    SetSignalHandlers (signal, s);
}

void    SignalHandlerRegistry::RemoveSignalHandler (SignalID signal, SignalHandler handler)
{
    Set<SignalHandler>  s   =   GetSignalHandlers (signal);
    Require (s.Contains (handler));
    s.Remove (handler);
    SetSignalHandlers (signal, s);
}

void    SignalHandlerRegistry::DefaultCrashSignalHandler (SignalID signal)
{
    DbgTrace (L"Serious Signal Error trapped: %s ... Aborting", SignalToName (signal).c_str ());
    abort ();
}

Containers::Set<SignalID>   SignalHandlerRegistry::GetStandardCrashSignals ()
{
    Containers::Set<SignalID>   results;
    results.Add (SIGABRT);
    results.Add (SIGILL);
    results.Add (SIGFPE);
    results.Add (SIGSEGV);
#if     qPlatform_POSIX
    results.Add (SIGSYS);
    results.Add (SIGBUS);
#endif
    return results;
}

Containers::Set<SignalID>    SignalHandlerRegistry::GetStandardTerminationSignals ()
{
    Containers::Set<SignalID>   results;
    results.Add (SIGABRT);
    results.Add (SIGINT);
    results.Add (SIGTERM);
    results.Add (SIGILL);
    results.Add (SIGFPE);
    results.Add (SIGSEGV);
#if     qPlatform_POSIX
    results.Add (SIGHUP);
    results.Add (SIGQUIT);
    results.Add (SIGSYS);
    results.Add (SIGBUS);
    results.Add (SIGPIPE);
    results.Add (SIGXCPU);
    results.Add (SIGXFSZ);
#endif
    return results;
}

void    SignalHandlerRegistry::SetStandardCrashHandlerSignals (SignalHandler handler, const Containers::Set<SignalID>& forSignals)
{
    for (SignalID s : forSignals) {
        if (s != SIGABRT) {
            SetSignalHandlers (s, handler);
        }
    }
}

void    SignalHandlerRegistry::FirstPassSignalHandler_ (SignalID signal)
{
#if     qDoDbgTraceOnSignalHandlers_
    Debug::TraceContextBumper trcCtx ("Stroika::Foundation::Execution::SignalHandlerRegistry::FirstPassSignalHandler_");
    DbgTrace (L"(signal = %s)", SignalToName (signal).c_str ());
#endif
    SignalHandlerRegistry&  SHR =   Get ();

    {
        // Copy out of Stroika-based containers, because these may throw thread-abort exceptions.
        // The Set<> and Mapping<> code I'm thinking of here. Just use stl code (stuff that wont throw abort exceptions)
        vector<SignalHandler>   shs;
        {
            Thread::SuppressInterruptionInContext  suppressContext;
            for (SignalHandler sh : SHR.fDirectHandlers_.LookupValue (signal)) {
                shs.push_back (sh);
            }
        }
        for (SignalHandler sh : shs) {
            sh (signal);
        }
    }

    shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_> tmp = SignalHandlerRegistry::SafeSignalsManager::sTheRep_;
    if (tmp != nullptr) {
        tmp->NotifyOfArrivalOfPossiblySafeSignal (signal);
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#include "../../StroikaPreComp.h"

#include "../../Characters/Format.h"
#include "../../Characters/ToString.h"
#include "../../Containers/Collection.h"
#include "../../Execution/ErrNoException.h"
#include "../../Execution/StringException.h"
#include "../../Memory/BLOB.h"

#include "SocketAddress.h"

using std::byte;

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Memory;
using namespace Stroika::Foundation::IO;
using namespace Stroika::Foundation::IO::Network;

/*
 ********************************************************************************
 ********************* IO::Network::SocketAddress *******************************
 ********************************************************************************
 */
#if qPlatform_Windows
SocketAddress::SocketAddress (const SOCKET_ADDRESS& sockaddr)
    : fSocketAddress_ ()
{
    if (sockaddr.iSockaddrLength > sizeof (fSocketAddressStorage_))
        [[UNLIKELY_ATTR]]
        {
            Execution::Throw (Execution::StringException (L"bad socket address size"));
        }
    (void)::memcpy (&fSocketAddressStorage_, sockaddr.lpSockaddr, sockaddr.iSockaddrLength);
}
#endif

String SocketAddress::ToString () const
{
    if (IsInternetAddress ()) {
        return Characters::ToString (GetInternetAddress ()) + L":" + Characters::Format (L"%d", static_cast<int> (GetPort ()));
    }
    else {
        return Characters::ToString (Memory::BLOB (reinterpret_cast<const byte*> (&fSocketAddress_), reinterpret_cast<const byte*> (&fSocketAddress_) + sizeof (fSocketAddress_)));
    }
}

/*
 ********************************************************************************
 ********************* IO::Network::SocketAddresses *****************************
 ********************************************************************************
 */
Traversal::Iterable<SocketAddress> Network::SocketAddresses (const Traversal::Iterable<InternetAddress>& internetAddresses, uint16_t portNumber)
{
    Containers::Collection<SocketAddress> tmp;
    for (auto&& i : internetAddresses) {
        tmp += SocketAddress{i, portNumber};
    }
    return tmp;
}
<commit_msg>fixed tostring() on SOcketAddress to grab right bytes<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#include "../../StroikaPreComp.h"

#include "../../Characters/Format.h"
#include "../../Characters/ToString.h"
#include "../../Containers/Collection.h"
#include "../../Execution/ErrNoException.h"
#include "../../Execution/StringException.h"
#include "../../Memory/BLOB.h"

#include "SocketAddress.h"

using std::byte;

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Memory;
using namespace Stroika::Foundation::IO;
using namespace Stroika::Foundation::IO::Network;

/*
 ********************************************************************************
 ********************* IO::Network::SocketAddress *******************************
 ********************************************************************************
 */
#if qPlatform_Windows
SocketAddress::SocketAddress (const SOCKET_ADDRESS& sockaddr)
    : fSocketAddress_ ()
{
    if (sockaddr.iSockaddrLength > sizeof (fSocketAddressStorage_))
        [[UNLIKELY_ATTR]]
        {
            Execution::Throw (Execution::StringException (L"bad socket address size"));
        }
    (void)::memcpy (&fSocketAddressStorage_, sockaddr.lpSockaddr, sockaddr.iSockaddrLength);
}
#endif

String SocketAddress::ToString () const
{
    if (IsInternetAddress ()) {
        return Characters::ToString (GetInternetAddress ()) + L":" + Characters::Format (L"%d", static_cast<int> (GetPort ()));
    }
    else {
        return Characters::ToString (Memory::BLOB (reinterpret_cast<const byte*> (&fSocketAddress_), reinterpret_cast<const byte*> (&fSocketAddress_) + GetRequiredSize ()));
    }
}

/*
 ********************************************************************************
 ********************* IO::Network::SocketAddresses *****************************
 ********************************************************************************
 */
Traversal::Iterable<SocketAddress> Network::SocketAddresses (const Traversal::Iterable<InternetAddress>& internetAddresses, uint16_t portNumber)
{
    Containers::Collection<SocketAddress> tmp;
    for (auto&& i : internetAddresses) {
        tmp += SocketAddress{i, portNumber};
    }
    return tmp;
}
<|endoftext|>


<commit_before>/*
 *  mitkFiberBundleMapper2D.cpp
 *  mitk-all
 *
 *  Created by HAL9000 on 1/17/11.
 *  Copyright 2011 __MyCompanyName__. All rights reserved.
 *
 */

#include "mitkFiberBundleXMapper2D.h"
#include <mitkBaseRenderer.h>

#include <vtkActor.h>
#include <vtkPolyDataMapper.h>
#include <vtkPlane.h>
#include <vtkPolyData.h>
//#include <vtkPropAssembly.h>

//#include <vtkPainterPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkLookupTable.h>
#include <vtkPoints.h>
#include <vtkCamera.h>
#include <vtkPolyLine.h>
#include <vtkRenderer.h>
#include <vtkCellArray.h>
#include <vtkMatrix4x4.h>

//#include <mitkGeometry3D.h>
#include <mitkPlaneGeometry.h>
#include <mitkSliceNavigationController.h>

#include <mitkShaderRepository.h>
#include <mitkShaderProperty.h>
#include <mitkStandardFileLocations.h>

#include <QCoreApplication>
#include <QFile>

mitk::FiberBundleXMapper2D::FiberBundleXMapper2D()
{

}

mitk::FiberBundleXMapper2D::~FiberBundleXMapper2D()
{
}

mitk::FiberBundleX* mitk::FiberBundleXMapper2D::GetInput()
{
    return dynamic_cast< mitk::FiberBundleX * > ( GetData() );
}

void mitk::FiberBundleXMapper2D::Update(mitk::BaseRenderer * renderer)
{

    if ( !this->IsVisible( renderer ) )
    {
        return;
    }

    // Calculate time step of the input data for the specified renderer (integer value)
    // this method is implemented in mitkMapper
    this->CalculateTimeStep( renderer );

    //check if updates occured in the node or on the display
    FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
    const DataNode *node = this->GetDataNode();
    if ( (localStorage->m_LastUpdateTime < node->GetMTime())
         || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified?
         || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) )
    {
        //    MITK_INFO << "UPDATE NEEDED FOR _ " << renderer->GetName();
        this->GenerateDataForRenderer( renderer );
    }

    if ((localStorage->m_LastUpdateTime < renderer->GetDisplayGeometry()->GetMTime()) ) //was the display geometry modified? e.g. zooming, panning)
    {

        this->UpdateShaderParameter(renderer);

    }

}

void mitk::FiberBundleXMapper2D::UpdateShaderParameter(mitk::BaseRenderer * renderer)
{
    FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);

    //get information about current position of views
    mitk::SliceNavigationController::Pointer sliceContr = renderer->GetSliceNavigationController();
    mitk::PlaneGeometry::ConstPointer planeGeo = sliceContr->GetCurrentPlaneGeometry();

    //generate according cutting planes based on the view position
    float sliceN[3], planeOrigin[3];

    // since shader uses camera coordinates, transform origin and normal from worldcoordinates to cameracoordinates

    planeOrigin[0] = (float) planeGeo->GetOrigin()[0];
    planeOrigin[1] = (float) planeGeo->GetOrigin()[1];
    planeOrigin[2] = (float) planeGeo->GetOrigin()[2];

    sliceN[0] = planeGeo->GetNormal()[0];
    sliceN[1] = planeGeo->GetNormal()[1];
    sliceN[2] = planeGeo->GetNormal()[2];

    float tmp1 = planeOrigin[0] * sliceN[0];
    float tmp2 = planeOrigin[1] * sliceN[1];
    float tmp3 = planeOrigin[2] * sliceN[2];
    float d1 = tmp1 + tmp2 + tmp3; //attention, correct normalvector

    float plane1[4];
    plane1[0] = sliceN[0];
    plane1[1] = sliceN[1];
    plane1[2] = sliceN[2];
    plane1[3] = d1;

    float thickness = 2.0;
    if(!this->GetDataNode()->GetPropertyValue("Fiber2DSliceThickness",thickness))
        MITK_INFO << "FIBER2D SLICE THICKNESS PROPERTY ERROR";

    bool fiberfading = false;
    if(!this->GetDataNode()->GetPropertyValue("Fiber2DfadeEFX",fiberfading))
        MITK_INFO << "FIBER2D SLICE FADE EFX PROPERTY ERROR";

    int fiberfading_i = 1;
    if (!fiberfading)
        fiberfading_i = 0;

    localStorage->m_PointActor->GetProperty()->AddShaderVariable("slicingPlane",4, plane1);
    localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberThickness",1, &thickness);
    localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberFadingON",1,  &fiberfading_i);

}

// ALL RAW DATA FOR VISUALIZATION IS GENERATED HERE.
// vtkActors and Mappers are feeded here
void mitk::FiberBundleXMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer)
{

    //the handler of local storage gets feeded in this method with requested data for related renderwindow
    FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);

    //this procedure is depricated,
    //not needed after initializaton anymore
    mitk::DataNode* node = this->GetDataNode();
    if ( node == NULL )
    {
        MITK_INFO << "check DATANODE: ....[Fail] ";
        return;
    }
    ///////////////////////////////////

    ///THIS GET INPUT
    mitk::FiberBundleX* fbx = this->GetInput();

    vtkSmartPointer<vtkLookupTable> lut = vtkLookupTable::New();
    lut->Build();
    localStorage->m_PointMapper->SetScalarModeToUsePointFieldData();

    // set Opacity
    float tmpopa;
    this->GetDataNode()->GetOpacity(tmpopa, NULL);
    localStorage->m_PointActor->GetProperty()->SetOpacity((double) tmpopa);

    // set color
    if (fbx->GetCurrentColorCoding() != NULL){
        localStorage->m_PointMapper->SelectColorArray(fbx->GetCurrentColorCoding());
        MITK_INFO << "MapperFBX 2D: " << fbx->GetCurrentColorCoding();
        if(fbx->GetCurrentColorCoding() == "custom"){
            float temprgb[3];
            this->GetDataNode()->GetColor( temprgb, NULL );
            double trgb[3] = { (double) temprgb[0], (double) temprgb[1], (double) temprgb[2] };
            localStorage->m_PointActor->GetProperty()->SetColor(trgb);
        }
    }

    localStorage->m_PointMapper->SetLookupTable(lut);  //apply the properties after the slice was set

    //  feed the vtk fiber mapper with point data ...TODO do in constructor
    localStorage->m_PointMapper->SetInput(fbx->GetFiberPolyData());
    localStorage->m_PointActor->SetMapper(localStorage->m_PointMapper);
    localStorage->m_PointActor->GetProperty()->ShadingOn();

    // Applying shading properties
    {
        //Superclass::ApplyProperties( ls->m_Actor, renderer ) ;
        // VTK Properties
        //ApplyMitkPropertiesToVtkProperty( this->GetDataNode(), ls->m_Actor->GetProperty(), renderer );
        // Shaders
        mitk::ShaderRepository::GetGlobalShaderRepository()->ApplyProperties(this->GetDataNode(),localStorage->m_PointActor,renderer, localStorage->m_LastUpdateTime);
    }

    this->UpdateShaderParameter(renderer);

    // We have been modified => save this for next Update()
    localStorage->m_LastUpdateTime.Modified();

}

vtkProp* mitk::FiberBundleXMapper2D::GetVtkProp(mitk::BaseRenderer *renderer)
{

    //MITK_INFO << "FiberBundleMapper2D GetVtkProp(renderer)";
    this->Update(renderer);
    return m_LSH.GetLocalStorage(renderer)->m_PointActor;

}

void mitk::FiberBundleXMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{    //add shader to datano

    //####### load shader from file #########
    QString applicationDir = QCoreApplication::applicationDirPath();

    if (applicationDir.endsWith("bin"))
        applicationDir.append("/");
    else if (applicationDir.endsWith("MacOS"))
    {
        //on osx, check if path for installer or MITK development is needed
        applicationDir.append("/");
        QFile f( applicationDir+"FiberTrackingLUTBaryCoords.bin" );
        if( !f.exists() ) // if file does not exist, then look in MITK development build directory
            applicationDir.append("../../../");
    }else
        applicationDir.append("\\..\\");

    mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( applicationDir.toStdString().c_str(), false );
    mitk::ShaderRepository::Pointer shaderRepository = mitk::ShaderRepository::GetGlobalShaderRepository();
    shaderRepository->LoadShader(mitk::StandardFileLocations::GetInstance()->FindFile("mitkShaderFiberClipping.xml"));

    //####################################################################
    node->SetProperty("shader",mitk::ShaderProperty::New("mitkShaderFiberClipping"));
    mitk::ShaderRepository::GetGlobalShaderRepository()->AddDefaultProperties(node,renderer,overwrite);

    //add other parameters to propertylist
    node->AddProperty( "Fiber2DSliceThickness", mitk::FloatProperty::New(2.0f), renderer, overwrite );
    node->AddProperty( "Fiber2DfadeEFX", mitk::BoolProperty::New(true), renderer, overwrite );

    Superclass::SetDefaultProperties(node, renderer, overwrite);
}

// following methods are essential, they actually call the GetVtkProp() method
// which returns the desired actors
void mitk::FiberBundleXMapper2D::MitkRenderOverlay(BaseRenderer* renderer)
{
    //   MITK_INFO << "FiberBundleMapper2D MitkRenderOVerlay(renderer)";
    if ( this->IsVisible(renderer)==false )
        return;

    if ( this->GetVtkProp(renderer)->GetVisibility() )
    {
        this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer());
    }
}

void mitk::FiberBundleXMapper2D::MitkRenderOpaqueGeometry(BaseRenderer* renderer)
{
    //  MITK_INFO << "FiberBundleMapper2D MitkRenderOpaqueGeometry(renderer)";
    if ( this->IsVisible( renderer )==false )
        return;

    if ( this->GetVtkProp(renderer)->GetVisibility() )
        this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() );
}
void mitk::FiberBundleXMapper2D::MitkRenderTranslucentGeometry(BaseRenderer* renderer)
{
    //  MITK_INFO << "FiberBundleMapper2D MitkRenderTranslucentGeometry(renderer)";
    if ( this->IsVisible(renderer)==false )
        return;

    //TODO is it possible to have a visible BaseRenderer AND an invisible VtkRenderer???
    if ( this->GetVtkProp(renderer)->GetVisibility() )
        this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer());

}
void mitk::FiberBundleXMapper2D::MitkRenderVolumetricGeometry(BaseRenderer* renderer)
{
    //  MITK_INFO << "FiberBundleMapper2D MitkRenderVolumentricGeometry(renderer)";
    if(IsVisible(renderer)==false)
        return;

    //TODO is it possible to have a visible BaseRenderer AND an invisible VtkRenderer???
    if ( GetVtkProp(renderer)->GetVisibility() )
        this->GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer());

}

mitk::FiberBundleXMapper2D::FBXLocalStorage::FBXLocalStorage()
{
    m_PointActor = vtkSmartPointer<vtkActor>::New();
    m_PointMapper = vtkSmartPointer<vtkPolyDataMapper>::New();

}
<commit_msg>add transparency to fiber2D shader and mapper<commit_after>/*
 *  mitkFiberBundleMapper2D.cpp
 *  mitk-all
 *
 *  Created by HAL9000 on 1/17/11.
 *  Copyright 2011 __MyCompanyName__. All rights reserved.
 *
 */

#include "mitkFiberBundleXMapper2D.h"
#include <mitkBaseRenderer.h>

#include <vtkActor.h>
#include <vtkPolyDataMapper.h>
#include <vtkPlane.h>
#include <vtkPolyData.h>
//#include <vtkPropAssembly.h>

//#include <vtkPainterPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkLookupTable.h>
#include <vtkPoints.h>
#include <vtkCamera.h>
#include <vtkPolyLine.h>
#include <vtkRenderer.h>
#include <vtkCellArray.h>
#include <vtkMatrix4x4.h>

//#include <mitkGeometry3D.h>
#include <mitkPlaneGeometry.h>
#include <mitkSliceNavigationController.h>

#include <mitkShaderRepository.h>
#include <mitkShaderProperty.h>
#include <mitkStandardFileLocations.h>

#include <QCoreApplication>
#include <QFile>

mitk::FiberBundleXMapper2D::FiberBundleXMapper2D()
{

}

mitk::FiberBundleXMapper2D::~FiberBundleXMapper2D()
{
}

mitk::FiberBundleX* mitk::FiberBundleXMapper2D::GetInput()
{
    return dynamic_cast< mitk::FiberBundleX * > ( GetData() );
}

void mitk::FiberBundleXMapper2D::Update(mitk::BaseRenderer * renderer)
{

    if ( !this->IsVisible( renderer ) )
    {
        return;
    }

    // Calculate time step of the input data for the specified renderer (integer value)
    // this method is implemented in mitkMapper
    this->CalculateTimeStep( renderer );

    //check if updates occured in the node or on the display
    FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
    const DataNode *node = this->GetDataNode();
    if ( (localStorage->m_LastUpdateTime < node->GetMTime())
         || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified?
         || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) )
    {
        //    MITK_INFO << "UPDATE NEEDED FOR _ " << renderer->GetName();
        this->GenerateDataForRenderer( renderer );
    }

    if ((localStorage->m_LastUpdateTime < renderer->GetDisplayGeometry()->GetMTime()) ) //was the display geometry modified? e.g. zooming, panning)
    {

        this->UpdateShaderParameter(renderer);

    }

}

void mitk::FiberBundleXMapper2D::UpdateShaderParameter(mitk::BaseRenderer * renderer)
{
    FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);

    //get information about current position of views
    mitk::SliceNavigationController::Pointer sliceContr = renderer->GetSliceNavigationController();
    mitk::PlaneGeometry::ConstPointer planeGeo = sliceContr->GetCurrentPlaneGeometry();

    //generate according cutting planes based on the view position
    float sliceN[3], planeOrigin[3];

    // since shader uses camera coordinates, transform origin and normal from worldcoordinates to cameracoordinates

    planeOrigin[0] = (float) planeGeo->GetOrigin()[0];
    planeOrigin[1] = (float) planeGeo->GetOrigin()[1];
    planeOrigin[2] = (float) planeGeo->GetOrigin()[2];

    sliceN[0] = planeGeo->GetNormal()[0];
    sliceN[1] = planeGeo->GetNormal()[1];
    sliceN[2] = planeGeo->GetNormal()[2];

    float tmp1 = planeOrigin[0] * sliceN[0];
    float tmp2 = planeOrigin[1] * sliceN[1];
    float tmp3 = planeOrigin[2] * sliceN[2];
    float d1 = tmp1 + tmp2 + tmp3; //attention, correct normalvector

    float plane1[4];
    plane1[0] = sliceN[0];
    plane1[1] = sliceN[1];
    plane1[2] = sliceN[2];
    plane1[3] = d1;

    float thickness = 2.0;
    if(!this->GetDataNode()->GetPropertyValue("Fiber2DSliceThickness",thickness))
        MITK_INFO << "FIBER2D SLICE THICKNESS PROPERTY ERROR";

    bool fiberfading = false;
    if(!this->GetDataNode()->GetPropertyValue("Fiber2DfadeEFX",fiberfading))
        MITK_INFO << "FIBER2D SLICE FADE EFX PROPERTY ERROR";

    int fiberfading_i = 1;
    if (!fiberfading)
        fiberfading_i = 0;

    // set Opacity
    float fiberOpacity;
    this->GetDataNode()->GetOpacity(fiberOpacity, NULL);

    localStorage->m_PointActor->GetProperty()->AddShaderVariable("slicingPlane",4, plane1);
    localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberThickness",1, &thickness);
    localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberFadingON",1,  &fiberfading_i);
    localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberOpacity", 1, &fiberOpacity);

}

// ALL RAW DATA FOR VISUALIZATION IS GENERATED HERE.
// vtkActors and Mappers are feeded here
void mitk::FiberBundleXMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer)
{

    //the handler of local storage gets feeded in this method with requested data for related renderwindow
    FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);

    //this procedure is depricated,
    //not needed after initializaton anymore
    mitk::DataNode* node = this->GetDataNode();
    if ( node == NULL )
    {
        MITK_INFO << "check DATANODE: ....[Fail] ";
        return;
    }
    ///////////////////////////////////

    ///THIS GET INPUT
    mitk::FiberBundleX* fbx = this->GetInput();

    vtkSmartPointer<vtkLookupTable> lut = vtkLookupTable::New();
    lut->Build();
    localStorage->m_PointMapper->SetScalarModeToUsePointFieldData();

    // set color
    if (fbx->GetCurrentColorCoding() != NULL){
        localStorage->m_PointMapper->SelectColorArray(fbx->GetCurrentColorCoding());
        MITK_INFO << "MapperFBX 2D: " << fbx->GetCurrentColorCoding();
        if(fbx->GetCurrentColorCoding() == "custom"){
            float temprgb[3];
            this->GetDataNode()->GetColor( temprgb, NULL );
            double trgb[3] = { (double) temprgb[0], (double) temprgb[1], (double) temprgb[2] };
            localStorage->m_PointActor->GetProperty()->SetColor(trgb);
        }
    }

    localStorage->m_PointMapper->SetLookupTable(lut);  //apply the properties after the slice was set

    //  feed the vtk fiber mapper with point data ...TODO do in constructor
    localStorage->m_PointMapper->SetInput(fbx->GetFiberPolyData());
    localStorage->m_PointActor->SetMapper(localStorage->m_PointMapper);
    localStorage->m_PointActor->GetProperty()->ShadingOn();

    // Applying shading properties
    {
        //Superclass::ApplyProperties( ls->m_Actor, renderer ) ;
        // VTK Properties
        //ApplyMitkPropertiesToVtkProperty( this->GetDataNode(), ls->m_Actor->GetProperty(), renderer );
        // Shaders
        mitk::ShaderRepository::GetGlobalShaderRepository()->ApplyProperties(this->GetDataNode(),localStorage->m_PointActor,renderer, localStorage->m_LastUpdateTime);
    }

    this->UpdateShaderParameter(renderer);

    // We have been modified => save this for next Update()
    localStorage->m_LastUpdateTime.Modified();

}

vtkProp* mitk::FiberBundleXMapper2D::GetVtkProp(mitk::BaseRenderer *renderer)
{

    //MITK_INFO << "FiberBundleMapper2D GetVtkProp(renderer)";
    this->Update(renderer);
    return m_LSH.GetLocalStorage(renderer)->m_PointActor;

}

void mitk::FiberBundleXMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{    //add shader to datano

    //####### load shader from file #########
    QString applicationDir = QCoreApplication::applicationDirPath();

    if (applicationDir.endsWith("bin"))
        applicationDir.append("/");
    else if (applicationDir.endsWith("MacOS"))
    {
        //on osx, check if path for installer or MITK development is needed
        applicationDir.append("/");
        QFile f( applicationDir+"FiberTrackingLUTBaryCoords.bin" );
        if( !f.exists() ) // if file does not exist, then look in MITK development build directory
            applicationDir.append("../../../");
    }else
        applicationDir.append("\\..\\");

    mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( applicationDir.toStdString().c_str(), false );
    mitk::ShaderRepository::Pointer shaderRepository = mitk::ShaderRepository::GetGlobalShaderRepository();
    shaderRepository->LoadShader(mitk::StandardFileLocations::GetInstance()->FindFile("mitkShaderFiberClipping.xml"));

    //####################################################################
    node->SetProperty("shader",mitk::ShaderProperty::New("mitkShaderFiberClipping"));
    mitk::ShaderRepository::GetGlobalShaderRepository()->AddDefaultProperties(node,renderer,overwrite);

    //add other parameters to propertylist
    node->AddProperty( "Fiber2DSliceThickness", mitk::FloatProperty::New(2.0f), renderer, overwrite );
    node->AddProperty( "Fiber2DfadeEFX", mitk::BoolProperty::New(true), renderer, overwrite );

    Superclass::SetDefaultProperties(node, renderer, overwrite);
}

// following methods are essential, they actually call the GetVtkProp() method
// which returns the desired actors
void mitk::FiberBundleXMapper2D::MitkRenderOverlay(BaseRenderer* renderer)
{
    //   MITK_INFO << "FiberBundleMapper2D MitkRenderOVerlay(renderer)";
    if ( this->IsVisible(renderer)==false )
        return;

    if ( this->GetVtkProp(renderer)->GetVisibility() )
    {
        this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer());
    }
}

void mitk::FiberBundleXMapper2D::MitkRenderOpaqueGeometry(BaseRenderer* renderer)
{
    //  MITK_INFO << "FiberBundleMapper2D MitkRenderOpaqueGeometry(renderer)";
    if ( this->IsVisible( renderer )==false )
        return;

    if ( this->GetVtkProp(renderer)->GetVisibility() )
        this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() );
}
void mitk::FiberBundleXMapper2D::MitkRenderTranslucentGeometry(BaseRenderer* renderer)
{
    //  MITK_INFO << "FiberBundleMapper2D MitkRenderTranslucentGeometry(renderer)";
    if ( this->IsVisible(renderer)==false )
        return;

    //TODO is it possible to have a visible BaseRenderer AND an invisible VtkRenderer???
    if ( this->GetVtkProp(renderer)->GetVisibility() )
        this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer());

}
void mitk::FiberBundleXMapper2D::MitkRenderVolumetricGeometry(BaseRenderer* renderer)
{
    //  MITK_INFO << "FiberBundleMapper2D MitkRenderVolumentricGeometry(renderer)";
    if(IsVisible(renderer)==false)
        return;

    //TODO is it possible to have a visible BaseRenderer AND an invisible VtkRenderer???
    if ( GetVtkProp(renderer)->GetVisibility() )
        this->GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer());

}

mitk::FiberBundleXMapper2D::FBXLocalStorage::FBXLocalStorage()
{
    m_PointActor = vtkSmartPointer<vtkActor>::New();
    m_PointMapper = vtkSmartPointer<vtkPolyDataMapper>::New();

}
<|endoftext|>


<commit_before>#include "filehandlertest.h"
/**
 * @brief runTestSuite
 * @return all pass errorcode,
 * outputs information about which tests passed if
 * PRINTS set in header to terminal
 *
 */
//void filehandler_testsuite::runTestSuite(){
//    FileHandler* fileHandler = new FileHandler();
//    std::string dirpath = WORKSPACE;
//    Project* proj  = fileHandler->createProject("POI_PROJ");
//    directoryTest(fileHandler, proj);
//    fileTest(fileHandler, proj);
//    projectHandlingTest(fileHandler, proj);
//}

//
// Tests that creation, manipulation and deletion of
// projects functions as intended
//
FileHandlerTest::FileHandlerTest(){

}
/**
 * @brief FileHandlerTest::projectHandlingTest
 * not much to test currently, will be extended
 * with furter implementation of project manipulation
 */
void FileHandlerTest::projectHandlingTest(){
    FileHandler* fh = new FileHandler();
    Project* proj =  fh->createProject("/TEST_PROJ");
    std::string v1 = "video1.txt"; // names for testfiles
    std::string v2 = "video2.txt";
    std::string v3 = "video3.txt";
    ID vid1 = fh->createFile(v1, proj->m_dir);  // create testfiles
    ID vid2 = fh->createFile(v2, proj->m_dir);
    ID vid3 = fh->createFile(v3, proj->m_dir);

    fh->addVideo(proj, fh->getFile(vid1)); //add tesfiles as videos to project.
    fh->addVideo(proj, fh->getFile(vid2));
    fh->addVideo(proj, fh->getFile(vid3));
    fh->saveProject(proj);
    //check file contents
    fh->loadProject(fh->getDir(proj->m_dir));
    //check project contentss
}
//
// Test that creation and deletion of directories are working correctly.
//
void FileHandlerTest::directoryTest(){
    FileHandler* fh = new FileHandler();
    std::string dirpath = std::string(WORKSPACE) + std::string("/TEST_PROJ");
    int err = fh->createDirectory(dirpath);
    QCOMPARE(err, 0);
    QCOMPARE(fh->deleteDirectory(dirpath), 0);
}
// fileTest tests following functions, see filehandler.h
//
// ID createDirectory(std::string path);
// int deleteDirectory(std::string dirpath);
// ID createFile(std::string filename, ID dirID);
// int deleteFile(ID id);
// void writeFile(ID id, std::string text);

void FileHandlerTest::fileTest(){
    FileHandler* fh = new FileHandler();
    std::string dirpath = std::string(WORKSPACE) + "/TEST_MAP";
    std::string filename = "filetest.txt";
    ID dir = fh->createDirectory(dirpath);
    ID fileID  = fh->createFile(filename,dir); //Create file ID = i    (1)
    ID fileID2  = fh->createFile(filename,dir); // Create file ID = i+1 (2)
    QCOMPARE(fileID2 - fileID, 1);                         // check if 1 && 2 is true
    QVERIFY(fh->getFile(fileID) == fh->getFile(fileID2)); //check that (1), (2) point to same file.

    // TEST FILE WRITE AND FILE READ
    fh->writeFile(fileID, filename);   //write to file "filetest.txt"
    //read and check if file contains filename"
    std::string readText;
    fh->readFile(fileID,1, readText); // read from file
    QCOMPARE(readText, filename); // d = 0 if test passes
    //delete file and check if it is not there
    QCOMPARE(fh->deleteFile(fileID), 0); // check that delete was done correctly
    QCOMPARE(fh->deleteDirectory(dirpath), 0); //delete directory

}

<commit_msg>small fix<commit_after>#include "filehandlertest.h"
/**
 * @brief runTestSuite
 * @return all pass errorcode,
 * outputs information about which tests passed if
 * PRINTS set in header to terminal
 *
 */
//void filehandler_testsuite::runTestSuite(){
//    FileHandler* fileHandler = new FileHandler();
//    std::string dirpath = WORKSPACE;
//    Project* proj  = fileHandler->createProject("POI_PROJ");
//    directoryTest(fileHandler, proj);
//    fileTest(fileHandler, proj);
//    projectHandlingTest(fileHandler, proj);
//}

//
// Tests that creation, manipulation and deletion of
// projects functions as intended
//
FileHandlerTest::FileHandlerTest(){

}
/**
 * @brief FileHandlerTest::projectHandlingTest
 * not much to test currently, will be extended
 * with furter implementation of project manipulation
 */
void FileHandlerTest::projectHandlingTest(){
    FileHandler* fh = new FileHandler();
    Project* proj =  fh->createProject("/TEST_PROJ");
    std::string v1 = "video1.txt"; // names for testfiles
    std::string v2 = "video2.txt";
    std::string v3 = "video3.txt";
    ID vid1 = fh->createFile(v1, proj->m_dir);  // create testfiles
    ID vid2 = fh->createFile(v2, proj->m_dir);
    ID vid3 = fh->createFile(v3, proj->m_dir);

    fh->addVideo(proj, fh->getFile(vid1)); //add tesfiles as videos to project.
    fh->addVideo(proj, fh->getFile(vid2));
    fh->addVideo(proj, fh->getFile(vid3));
    fh->saveProject(proj);
    //check file contents
    fh->loadProject(fh->getDir(proj->m_dir));
    //check project contentss
    fh->deleteFile(vid1);
    fh->deleteFile(vid2);
    fh->deleteFile(vid3);
    fh->deleteProject(proj);
}
//
// Test that creation and deletion of directories are working correctly.
//
void FileHandlerTest::directoryTest(){
    FileHandler* fh = new FileHandler();
    std::string dirpath = std::string(WORKSPACE) + std::string("/TEST_PROJ");
    int err = fh->createDirectory(dirpath);
    QCOMPARE(err, 0);
    QCOMPARE(fh->deleteDirectory(dirpath), 0);
}
// fileTest tests following functions, see filehandler.h
//
// ID createDirectory(std::string path);
// int deleteDirectory(std::string dirpath);
// ID createFile(std::string filename, ID dirID);
// int deleteFile(ID id);
// void writeFile(ID id, std::string text);

void FileHandlerTest::fileTest(){
    FileHandler* fh = new FileHandler();
    std::string dirpath = std::string(WORKSPACE) + "/TEST_MAP";
    std::string filename = "filetest.txt";
    ID dir = fh->createDirectory(dirpath);
    ID fileID  = fh->createFile(filename,dir); //Create file ID = i    (1)
    ID fileID2  = fh->createFile(filename,dir); // Create file ID = i+1 (2)
    QCOMPARE(fileID2 - fileID, 1);                         // check if 1 && 2 is true
    QVERIFY(fh->getFile(fileID) == fh->getFile(fileID2)); //check that (1), (2) point to same file.

    // TEST FILE WRITE AND FILE READ
    fh->writeFile(fileID, filename);   //write to file "filetest.txt"
    //read and check if file contains filename"
    std::string readText;
    fh->readFile(fileID,1, readText); // read from file
    QCOMPARE(readText, filename); // d = 0 if test passes
    //delete file and check if it is not there
    QCOMPARE(fh->deleteFile(fileID), 0); // check that delete was done correctly
    QCOMPARE(fh->deleteDirectory(dirpath), 0); //delete directory

}

<|endoftext|>