/*
 * CF30Window.cpp
 *
 *  Created on: 29.11.2012
 *      Author: georg
 */

#include "CF30Window.h"
#include "UpdateInformation.h"

CF30Window::CF30Window()
: Gtk::Window(),
  //VBox
  m_device_VBox(false, 5),
  m_single_step_VBox(false, 5),
  m_set_counter_VBox(false, 5),
  m_ramp_VBox(false, 5),
  //HBox
  m_single_step_x_HBox(false, 5),
  m_single_step_y_HBox(false, 5),
  m_single_step_z_HBox(false, 5),
  m_set_counter_x_HBox(false, 5),
  m_set_counter_y_HBox(false, 5),
  m_set_counter_z_HBox(false, 5),
  m_ramp_x_HBox(false, 5),
  m_ramp_y_HBox(false, 5),
  m_ramp_z_HBox(false, 5),
  //Frame
  m_scale_bar_frame("Velocity"),
  m_stop_button_frame(" "),
  m_device_frame("Device"),
  m_relative_move_frame("Relative move"),
  m_single_step_frame("Single step"),
  m_absolute_move_frame("Absolute move"),
  m_set_counter_frame("Set counter"),
  m_information_table_frame("Position information"),
  m_controler_information_frame("Information"),
  m_ramp_frame("Ramp"),
  //Button
  m_scan_button("Scan - ComPort"),
  m_open_button("Open - ComPort"),
  m_close_button("Close - ComPort"),
  m_movement_button_stop("Stop"),
  m_move_relative_x_left("-X"),
  m_move_relative_y_left("-Y"),
  m_move_relative_z_left("-Z"),
  m_move_relative_x_right("+X"),
  m_move_relative_y_right("+Y"),
  m_move_relative_z_right("+Z"),
  m_move_single_step_x_right("+X"),
  m_move_single_step_y_right("+Y"),
  m_move_single_step_z_right("+Z"),
  m_move_single_step_x_left("-X"),
  m_move_single_step_y_left("-Y"),
  m_move_single_step_z_left("-Z"),
  m_move_absolute_position_x("X"),
  m_move_absolute_position_y("Y"),
  m_move_absolute_position_z("Z"),
  m_set_counter_x("Set-X"),
  m_set_counter_y("Set-Y"),
  m_set_counter_z("Set-Z"),
  m_set_ramp_x("Set-X"),
  m_set_ramp_y("Set-Y"),
  m_set_ramp_z("Set-Z"),
  m_get_ramp_x("Get-X"),
  m_get_ramp_y("Get-Y"),
  m_get_ramp_z("Get-Z"),
  m_quit_button("Quit"),
  //Scale-bar
  m_scale_bar_x(-movementControl.getMaxMovementSpeed(),movementControl.getMaxMovementSpeed(),100),
  m_scale_bar_y(-movementControl.getMaxMovementSpeed(),movementControl.getMaxMovementSpeed(),100),
  m_scale_bar_z(-movementControl.getMaxMovementSpeed(),movementControl.getMaxMovementSpeed(),100),
  //dropdown menu
  m_openDevice_textComboBox(true),
  //Label
  m_infoBox("Scan for connected\ndevices and open\na ComPort."),
  m_voltage_label("Voltage: "),
  m_relative_move_velocity_label("Velocity"),
  m_relative_move_steps_label("Steps"),
  m_absolute_move_velocity_label("Velocity"),
  m_absolute_move_position_label("Position"),

  m_main_grid(),
  m_scaleBar_grid(),
  m_absolute_move_grid(),
  m_relative_move_grid()
{
    // set window size
	set_default_size(400, 170);

    // set title
    set_title("CF30");

    connect_widgets_with_frames();

    attach_widgets_to_table();

    // Initialize widgets
	init_widgets();

	// connect signals
    connect_signals();

    // add table to window
    add(m_main_grid);

    // show all widgets
    show_all_children();

    m_close_button.hide();
}

CF30Window::~CF30Window() {
	movementControl.moveWithSpeed(MC_X_AXIS, 0);
	movementControl.moveWithSpeed(MC_Y_AXIS, 0);
	movementControl.moveWithSpeed(MC_Z_AXIS, 0);

	movementControl.closeComPort();
}

void CF30Window::setVoltageLabel(std::string text){
	m_voltage_label.set_text(text.c_str());
}

int CF30Window::getVoltage(){
	return movementControl.getVoltage();
}

/**
 * Updates the information which is shown in the chart.
 * The function will be frequently called, as long as the return value is zero.
 */
int CF30Window::updateInformationTreeView(){
	// Set scale widgets to zero if not dragged.
	if(set_x_toZero){
		m_scale_bar_x.set_value(0);
		set_x_toZero = false;
	}
	if(set_y_toZero){
		m_scale_bar_y.set_value(0);
		set_y_toZero = false;
	}
	if(set_z_toZero){
		m_scale_bar_z.set_value(0);
		set_z_toZero = false;
	}

	// Update TreeView
	int xPosition = movementControl.getPosition(MC_X_AXIS);
	int yPosition = movementControl.getPosition(MC_Y_AXIS);
	int zPosition = movementControl.getPosition(MC_Z_AXIS);

	int xRamp = movementControl.getRampValue(MC_X_AXIS);
	int yRamp = movementControl.getRampValue(MC_Y_AXIS);
	int zRamp = movementControl.getRampValue(MC_Z_AXIS);

	if(xPosition == -2 || yPosition == -2 || zPosition == -2 || xRamp == -2 || yRamp == -2 || zRamp == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return -1;
	}

	if(movementControl.getComPortHandle() == -1){
		xPosition = 0;
		yPosition = 0;
		zPosition = 0;
		xRamp = 0;
		yRamp = 0;
		zRamp = 0;
	}

	Gtk::TreeModel::Children childs = m_refTreeModel->children();

	Gtk::TreeNodeChildren::iterator iterChilds = childs.begin();
	Gtk::TreeModel::Row row = (Gtk::TreeModel::Row) (*(iterChilds));
	if(xPosition == row[m_Columns.m_col_position]){
		this->velocityX = 0;
	}
	row[m_Columns.m_col_velocity] = this->velocityX;
	row[m_Columns.m_col_position] = xPosition;
	row[m_Columns.m_col_step] = singleStep_moveDirection_x;
	row[m_Columns.m_col_ramp] = xRamp;

	iterChilds++;
	row = (Gtk::TreeModel::Row) (*(iterChilds));
	if(yPosition == row[m_Columns.m_col_position]){
			this->velocityY = 0;
		}
	row[m_Columns.m_col_velocity] = this->velocityY;
	row[m_Columns.m_col_position] = yPosition;
	row[m_Columns.m_col_step] = singleStep_moveDirection_y;
	row[m_Columns.m_col_ramp] = yRamp;

	iterChilds++;
	row = (Gtk::TreeModel::Row) (*(iterChilds));
	if(zPosition == row[m_Columns.m_col_position]){
		this->velocityZ = 0;
	}
	row[m_Columns.m_col_velocity] = this->velocityZ;
	row[m_Columns.m_col_position] = zPosition;
	row[m_Columns.m_col_step] = singleStep_moveDirection_z;
	row[m_Columns.m_col_ramp] = zRamp;

	if(movementControl.getComPortHandle() == -1){
		// Stop frequently calling this function
		return -1;
	}
	return 0;
}

/**
 * Initialize all widgets.
 */
void CF30Window::init_widgets(){
	m_main_grid.set_column_spacing(8);
	m_main_grid.set_row_spacing(8);

	int defaultBorderWidth = 4;
	// first row
	m_scale_bar_frame.set_border_width(defaultBorderWidth);
	m_scale_bar_frame.set_shadow_type(Gtk::SHADOW_NONE);
	m_scale_bar_frame.set_hexpand(true);
	m_scale_bar_frame.set_vexpand(true);
	m_stop_button_frame.set_border_width(defaultBorderWidth);
	m_stop_button_frame.set_shadow_type(Gtk::SHADOW_NONE);
	m_stop_button_frame.set_hexpand(true);
	m_stop_button_frame.set_vexpand(true);
	m_device_frame.set_border_width(defaultBorderWidth);
	m_device_frame.set_shadow_type(Gtk::SHADOW_NONE);
	m_device_frame.set_hexpand(true);
	m_device_frame.set_vexpand(true);
	// second row
	m_relative_move_frame.set_border_width(defaultBorderWidth);
	m_relative_move_frame.set_shadow_type(Gtk::SHADOW_NONE);
	m_relative_move_frame.set_hexpand(true);
	m_relative_move_frame.set_vexpand(true);
	m_single_step_frame.set_border_width(defaultBorderWidth);
	m_single_step_frame.set_shadow_type(Gtk::SHADOW_NONE);
	m_single_step_frame.set_hexpand(true);
	m_single_step_frame.set_vexpand(true);
	m_absolute_move_frame.set_border_width(defaultBorderWidth);
	m_absolute_move_frame.set_shadow_type(Gtk::SHADOW_NONE);
	m_absolute_move_frame.set_hexpand(true);
	m_absolute_move_frame.set_vexpand(true);
	m_set_counter_frame.set_border_width(defaultBorderWidth);
	m_set_counter_frame.set_shadow_type(Gtk::SHADOW_NONE);
	m_set_counter_frame.set_hexpand(true);
	m_set_counter_frame.set_vexpand(true);
	// third row
	m_information_table_frame.set_border_width(defaultBorderWidth);
	m_information_table_frame.set_shadow_type(Gtk::SHADOW_NONE);
	m_information_table_frame.set_hexpand(true);
	m_information_table_frame.set_vexpand(true);
	m_controler_information_frame.set_border_width(defaultBorderWidth);
	m_controler_information_frame.set_shadow_type(Gtk::SHADOW_NONE);
	m_controler_information_frame.set_size_request(150, 50);
	m_controler_information_frame.set_hexpand(true);
	m_controler_information_frame.set_vexpand(true);
	m_ramp_frame.set_border_width(defaultBorderWidth);
	m_ramp_frame.set_shadow_type(Gtk::SHADOW_NONE);
	m_ramp_frame.set_hexpand(true);
	m_ramp_frame.set_vexpand(true);
	// bottom row
	m_quit_button.set_hexpand(true);
	m_quit_button.set_vexpand(true);
	m_voltage_label.set_hexpand(true);
	m_voltage_label.set_vexpand(true);

	// init velocity section
	m_scale_bar_x.set_value(0);
	m_scale_bar_x.set_has_origin(false);
	m_scale_bar_x.set_events(Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON_PRESS_MASK);
	m_scale_bar_x.set_hexpand(true);
	m_scale_bar_x.set_vexpand(true);
	m_scale_bar_y.set_value(0);
	m_scale_bar_y.set_has_origin(false);
	m_scale_bar_y.set_events(Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON_PRESS_MASK);
	m_scale_bar_y.set_hexpand(true);
	m_scale_bar_y.set_vexpand(true);
	m_scale_bar_z.set_value(0);
	m_scale_bar_z.set_has_origin(false);
	m_scale_bar_z.set_events(Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON_PRESS_MASK);
	m_scale_bar_z.set_hexpand(true);
	m_scale_bar_z.set_vexpand(true);

	// resize all entrys
	int defaultWidth = 8;
	m_relative_move_velocity_x.set_width_chars(defaultWidth);
	m_relative_move_velocity_y.set_width_chars(defaultWidth);
	m_relative_move_velocity_z.set_width_chars(defaultWidth);
	m_relative_move_steps_x.set_width_chars(defaultWidth);
	m_relative_move_steps_y.set_width_chars(defaultWidth);
	m_relative_move_steps_z.set_width_chars(defaultWidth);
	m_absolute_move_velocity_x.set_width_chars(defaultWidth);
	m_absolute_move_velocity_y.set_width_chars(defaultWidth);
	m_absolute_move_velocity_z.set_width_chars(defaultWidth);
	m_absolute_move_position_x.set_width_chars(defaultWidth);
	m_absolute_move_position_y.set_width_chars(defaultWidth);
	m_absolute_move_position_z.set_width_chars(defaultWidth);
	m_set_counter_x_entrybox.set_width_chars(defaultWidth);
	m_set_counter_y_entrybox.set_width_chars(defaultWidth);
	m_set_counter_z_entrybox.set_width_chars(defaultWidth);
	m_ramp_value_x.set_width_chars(defaultWidth);
	m_ramp_value_y.set_width_chars(defaultWidth);
	m_ramp_value_z.set_width_chars(defaultWidth);

	m_voltage_label.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
	m_voltage_label.set_margin_left(5);

	this->singleStep_moveDirection_x = " ";
	this->singleStep_moveDirection_y = " ";
	this->singleStep_moveDirection_z = " ";

	// init information treeView
	// Create the Tree model:
	m_refTreeModel = Gtk::ListStore::create(m_Columns);
	m_information_treeView.set_model(m_refTreeModel);

	Gtk::TreeModel::Row row = *(m_refTreeModel->append());
	row[m_Columns.m_col_axis] = "X";
	row[m_Columns.m_col_velocity] = 0;
	row[m_Columns.m_col_position] = 0;
	row[m_Columns.m_col_step] = singleStep_moveDirection_x;
	row[m_Columns.m_col_ramp] = 0;

	row = *(m_refTreeModel->append());
	row[m_Columns.m_col_axis] = "Y";
	row[m_Columns.m_col_velocity] = 0;
	row[m_Columns.m_col_position] = 0;
	row[m_Columns.m_col_step] = singleStep_moveDirection_y;
	row[m_Columns.m_col_ramp] = 0;

	row = *(m_refTreeModel->append());
	row[m_Columns.m_col_axis] = "Z";
	row[m_Columns.m_col_velocity] = 0;
	row[m_Columns.m_col_position] = 0;
	row[m_Columns.m_col_step] = singleStep_moveDirection_z;
	row[m_Columns.m_col_ramp] = 0;

	//Add the TreeView's view columns:
	m_information_treeView.append_column("Axis", m_Columns.m_col_axis);
	m_information_treeView.append_column("Velocity", m_Columns.m_col_velocity);
	m_information_treeView.append_column_numeric("Position", m_Columns.m_col_position, "%010d" /* 10 digits, using leading zeroes. */);
	m_information_treeView.append_column("Step", m_Columns.m_col_step);
	m_information_treeView.append_column("Ramp", m_Columns.m_col_ramp);

	for(guint i = 0; i < 5; i++)
	{
		Gtk::TreeView::Column* pColumn = m_information_treeView.get_column(i);
		pColumn->set_reorderable();
	}

	// Set tooltips for widgets
	m_movement_button_stop.set_tooltip_text("Stops all movement.");
	m_open_button.set_tooltip_text("Open the virtual com port.");
	m_close_button.set_tooltip_text("Close the virtual com port and stop all movement.");
	m_scan_button.set_tooltip_text("Scan all devices in /dev/ttyUSB* and close the virtual com port");
}

void CF30Window::attach_widgets_to_table(){
	// first row
	m_main_grid.attach(m_scale_bar_frame, 0, 0, 12, 5);
	m_main_grid.attach(m_stop_button_frame, 12, 0, 2, 5);
	m_main_grid.attach(m_device_frame, 14, 0, 4, 5);
	// second row
	m_main_grid.attach(m_relative_move_frame, 0, 5, 6, 3);
	m_main_grid.attach(m_absolute_move_frame, 6, 5, 6, 3);
	m_main_grid.attach(m_single_step_frame, 12, 5, 2, 3);
	m_main_grid.attach(m_set_counter_frame, 14, 5, 4, 3);
	// third row
	m_main_grid.attach(m_information_table_frame, 0, 8, 11, 3);
	m_main_grid.attach(m_controler_information_frame, 11, 8, 3, 3);
	m_main_grid.attach(m_ramp_frame, 14, 8, 4, 3);
	// bottom row
	m_main_grid.attach(m_voltage_label, 0, 11, 1, 1);
	m_main_grid.attach(m_quit_button, 16, 11, 2, 1);
}

void CF30Window::connect_widgets_with_frames(){
	// velocity section
	m_scaleBar_grid.attach(m_scale_bar_x, 0, 0, 7, 1);
	m_scaleBar_grid.attach(m_scale_bar_y, 0, 1, 7, 1);
	m_scaleBar_grid.attach(m_scale_bar_z, 0, 2, 7, 1);

	m_stop_button_frame.add(m_movement_button_stop);

	m_scale_bar_frame.add(m_scaleBar_grid);


	// device section
	m_device_VBox.pack_start(m_openDevice_textComboBox);
	m_device_VBox.pack_start(m_scan_button);
	m_device_VBox.pack_start(m_open_button);
	m_device_VBox.pack_start(m_close_button);

	m_device_frame.add(m_device_VBox);


	// relative move section
	m_relative_move_grid.attach(m_relative_move_velocity_label, 1, 0, 1, 1);
	m_relative_move_grid.attach(m_relative_move_steps_label, 3, 0, 1, 1);
	m_relative_move_grid.attach(m_move_relative_x_left, 0, 1, 1, 1);
	m_relative_move_grid.attach(m_move_relative_y_left, 0, 2, 1, 1);
	m_relative_move_grid.attach(m_move_relative_z_left, 0, 3, 1, 1);
	m_relative_move_grid.attach(m_relative_move_velocity_x, 1, 1, 2, 1);
	m_relative_move_grid.attach(m_relative_move_velocity_y, 1, 2, 2, 1);
	m_relative_move_grid.attach(m_relative_move_velocity_z, 1, 3, 2, 1);
	m_relative_move_grid.attach(m_relative_move_steps_x, 3, 1, 2, 1);
	m_relative_move_grid.attach(m_relative_move_steps_y, 3, 2, 2, 1);
	m_relative_move_grid.attach(m_relative_move_steps_z, 3, 3, 2, 1);
	m_relative_move_grid.attach(m_move_relative_x_right, 5, 1, 1, 1);
	m_relative_move_grid.attach(m_move_relative_y_right, 5, 2, 1, 1);
	m_relative_move_grid.attach(m_move_relative_z_right, 5, 3, 1, 1);

	m_relative_move_frame.add(m_relative_move_grid);


	// single step section
	m_single_step_x_HBox.pack_start(m_move_single_step_x_left);
	m_single_step_x_HBox.pack_start(m_move_single_step_x_right);
	m_single_step_y_HBox.pack_start(m_move_single_step_y_left);
	m_single_step_y_HBox.pack_start(m_move_single_step_y_right);
	m_single_step_z_HBox.pack_start(m_move_single_step_z_left);
	m_single_step_z_HBox.pack_start(m_move_single_step_z_right);

	m_single_step_VBox.pack_start(m_single_step_x_HBox);
	m_single_step_VBox.pack_start(m_single_step_y_HBox);
	m_single_step_VBox.pack_start(m_single_step_z_HBox);

	m_single_step_frame.add(m_single_step_VBox);


	// absolute move section
	m_absolute_move_grid.attach(m_absolute_move_velocity_label, 0, 0, 1, 1);
	m_absolute_move_grid.attach(m_absolute_move_position_label, 1, 0, 1, 1);
	m_absolute_move_grid.attach(m_absolute_move_velocity_x, 0, 1, 1, 1);
	m_absolute_move_grid.attach(m_absolute_move_velocity_y, 0, 2, 1, 1);
	m_absolute_move_grid.attach(m_absolute_move_velocity_z, 0, 3, 1, 1);
	m_absolute_move_grid.attach(m_absolute_move_position_x, 1, 1, 1, 1);
	m_absolute_move_grid.attach(m_absolute_move_position_y, 1, 2, 1, 1);
	m_absolute_move_grid.attach(m_absolute_move_position_z, 1, 3, 1, 1);
	m_absolute_move_grid.attach(m_move_absolute_position_x, 2, 1, 1, 1);
	m_absolute_move_grid.attach(m_move_absolute_position_y, 2, 2, 1, 1);
	m_absolute_move_grid.attach(m_move_absolute_position_z, 2, 3, 1, 1);

	m_absolute_move_frame.add(m_absolute_move_grid);


	// set counter section
	m_set_counter_x_HBox.pack_start(m_set_counter_x_entrybox);
	m_set_counter_x_HBox.pack_start(m_set_counter_x);
	m_set_counter_y_HBox.pack_start(m_set_counter_y_entrybox);
	m_set_counter_y_HBox.pack_start(m_set_counter_y);
	m_set_counter_z_HBox.pack_start(m_set_counter_z_entrybox);
	m_set_counter_z_HBox.pack_start(m_set_counter_z);

	m_set_counter_VBox.pack_start(m_set_counter_x_HBox);
	m_set_counter_VBox.pack_start(m_set_counter_y_HBox);
	m_set_counter_VBox.pack_start(m_set_counter_z_HBox);

	m_set_counter_frame.add(m_set_counter_VBox);


	// info table
	m_information_table_frame.add(m_information_table_scrolledWindow);
	m_information_table_scrolledWindow.add(m_information_treeView);
	// Only show the scrollbars when they are necessary:
	m_information_table_scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);

	// info
	m_controler_information_frame.add(m_infoBox);

	// ramp section
	m_ramp_x_HBox.pack_start(m_ramp_value_x);
	m_ramp_x_HBox.pack_start(m_set_ramp_x);
	m_ramp_x_HBox.pack_start(m_get_ramp_x);
	m_ramp_y_HBox.pack_start(m_ramp_value_y);
	m_ramp_y_HBox.pack_start(m_set_ramp_y);
	m_ramp_y_HBox.pack_start(m_get_ramp_y);
	m_ramp_z_HBox.pack_start(m_ramp_value_z);
	m_ramp_z_HBox.pack_start(m_set_ramp_z);
	m_ramp_z_HBox.pack_start(m_get_ramp_z);

	m_ramp_VBox.pack_start(m_ramp_x_HBox);
	m_ramp_VBox.pack_start(m_ramp_y_HBox);
	m_ramp_VBox.pack_start(m_ramp_z_HBox);

	m_ramp_frame.add(m_ramp_VBox);
}

/**
 * Connect all used signals to the particular function.
 */
void CF30Window::connect_signals(){
	// ----------------- Buttons ---------------------

	m_scan_button.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_scan_button_clicked));
	m_open_button.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_open_button_clicked));

	m_movement_button_stop.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_movement_button_stop_clicked));

	m_move_relative_x_left.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_move_relative_x_left_clicked));
	m_move_relative_y_left.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_move_relative_y_left_clicked));
	m_move_relative_z_left.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_move_relative_z_left_clicked));
	m_move_relative_x_right.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_move_relative_x_right_clicked));
	m_move_relative_y_right.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_move_relative_y_right_clicked));
	m_move_relative_z_right.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_move_relative_z_right_clicked));

	m_move_single_step_x_left.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_move_single_step_x_left_clicked));
	m_move_single_step_y_left.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_move_single_step_y_left_clicked));
	m_move_single_step_z_left.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_move_single_step_z_left_clicked));
	m_move_single_step_x_right.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_move_single_step_x_right_clicked));
	m_move_single_step_y_right.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_move_single_step_y_right_clicked));
	m_move_single_step_z_right.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_move_single_step_z_right_clicked));

	m_move_absolute_position_x.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_move_absolute_position_x_clicked));
	m_move_absolute_position_y.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_move_absolute_position_y_clicked));
	m_move_absolute_position_z.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_move_absolute_position_z_clicked));

	m_set_counter_x.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_set_counter_x_clicked));
	m_set_counter_y.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_set_counter_y_clicked));
	m_set_counter_z.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_set_counter_z_clicked));

	m_set_ramp_x.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_set_ramp_x_clicked));
	m_set_ramp_y.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_set_ramp_y_clicked));
	m_set_ramp_z.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_set_ramp_z_clicked));
	m_get_ramp_x.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_get_ramp_x_clicked));
	m_get_ramp_y.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_get_ramp_y_clicked));
	m_get_ramp_z.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_get_ramp_z_clicked));

	m_close_button.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_close_button_clicked));
	m_quit_button.signal_clicked().connect(sigc::mem_fun(*this, &CF30Window::on_quit_button_clicked));

	// ----------------- Scalebars ---------------------

	m_scale_bar_x.signal_value_changed().connect(sigc::mem_fun(*this, &CF30Window::scale_bar_x_moved));
	m_scale_bar_y.signal_value_changed().connect(sigc::mem_fun(*this, &CF30Window::scale_bar_y_moved));
	m_scale_bar_z.signal_value_changed().connect(sigc::mem_fun(*this, &CF30Window::scale_bar_z_moved));
	m_scale_bar_x.signal_button_release_event().connect(sigc::mem_fun(*this, &CF30Window::scaleBar_x_released), false);
	m_scale_bar_x.signal_button_press_event().connect(sigc::mem_fun(*this, &CF30Window::scaleBar_x_pressed), false);
	m_scale_bar_y.signal_button_release_event().connect(sigc::mem_fun(*this, &CF30Window::scaleBar_y_released), false);
	m_scale_bar_y.signal_button_press_event().connect(sigc::mem_fun(*this, &CF30Window::scaleBar_y_pressed), false);
	m_scale_bar_z.signal_button_release_event().connect(sigc::mem_fun(*this, &CF30Window::scaleBar_z_released), false);
	m_scale_bar_z.signal_button_press_event().connect(sigc::mem_fun(*this, &CF30Window::scaleBar_z_pressed), false);

	// ----------------- Entry -----------------

	m_relative_move_velocity_x.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::relativeMoveVelocity_checkInput_x));
	m_relative_move_velocity_y.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::relativeMoveVelocity_checkInput_y));
	m_relative_move_velocity_z.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::relativeMoveVelocity_checkInput_z));
	m_relative_move_steps_x.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::relativeMoveSteps_checkInput_x));
	m_relative_move_steps_y.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::relativeMoveSteps_checkInput_y));
	m_relative_move_steps_z.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::relativeMoveSteps_checkInput_z));

	m_absolute_move_velocity_x.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::absoluteMoveVelocity_checkInput_x));
	m_absolute_move_velocity_y.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::absoluteMoveVelocity_checkInput_y));
	m_absolute_move_velocity_z.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::absoluteMoveVelocity_checkInput_z));
	m_absolute_move_position_x.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::absoluteMovePosition_checkInput_x));
	m_absolute_move_position_y.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::absoluteMovePosition_checkInput_y));
	m_absolute_move_position_z.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::absoluteMovePosition_checkInput_z));

	m_set_counter_x_entrybox.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::setCounter_checkInput_x));
	m_set_counter_y_entrybox.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::setCounter_checkInput_y));
	m_set_counter_z_entrybox.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::setCounter_checkInput_z));

	m_ramp_value_x.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::rampValue_checkInput_x));
	m_ramp_value_y.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::rampValue_checkInput_y));
	m_ramp_value_z.signal_changed().connect(sigc::mem_fun(*this, &CF30Window::rampValue_checkInput_z));
}

/**
 * Searches /dev/ttyUSB* for CF30 controller which can be opened.
 */
void CF30Window::check_connected_controller(){
	if(movementControl.getComPortHandle() != -1){
		on_close_button_clicked();
	}
	int counter = 0;
	DIR *d;
	struct dirent *dir;
	d = opendir("/dev/");
	if(d){
		m_openDevice_textComboBox.remove_all();
		while((dir = readdir(d)) != NULL){
			std::string dirName = dir->d_name;
			if(dirName.find("ttyUSB") == 0){
				int success = movementControl.openComPort(("/dev/"+dirName).c_str());
				if(success == 0 && movementControl.getVoltage() > 2000){
					movementControl.closeComPort();
					m_openDevice_textComboBox.append(("/dev/"+dirName).c_str());
					counter++;
				} else if(success == 0){
					movementControl.closeComPort();
				} else if(success == -2){
					Gtk::MessageDialog dia(*this,"You need root-access to open the device.\n" + ("/dev/" + dirName), false, Gtk::MESSAGE_ERROR);
					dia.run();
					return;
				}
			}
		}
		closedir(d);

		std::string number = "";
		std::stringstream ss;
		ss << counter;
		number = ss.str();
		if(counter >= 1 && m_openDevice_textComboBox.get_active_text() == ""){
			m_openDevice_textComboBox.set_active(0);
		}
		if(counter == 1){
			m_infoBox.set_text("Scanning completed.\n" + number + " device found.");
		} else {
			m_infoBox.set_text("Scanning completed.\n" + number + " devices found.");
			if(counter == 0 && SystemControl::searchFor_FTDI_kernelModul() == -1){
				errorMessageOutput(CF30_ERROR_NO_FTDI_KERNELMODULE);
				return;
			}
		}
	} else {
		Gtk::MessageDialog dia(*this,"Can't open /dev/.", false, Gtk::MESSAGE_ERROR);
		dia.run();
		return;
	}
}

// ----------------- Buttons ---------------------

void CF30Window::on_scan_button_clicked(){
	check_connected_controller();
}

void CF30Window::on_open_button_clicked(){
	// check if comPort is already open
	if(movementControl.getComPortHandle() == -1){
		// read input string
		std::string device = (m_openDevice_textComboBox.get_entry())->get_text();
		if(device == ""){
			Gtk::MessageDialog dia(*this,"Please enter a directory or chose a scanned device.", false, Gtk::MESSAGE_ERROR);
			dia.run();
			return;
		}
		// open ComPort
		int done = movementControl.openComPort(device.c_str());
		if(done == -1){
			device = "Can't open " + device;
			Gtk::MessageDialog dia(*this, device.c_str());
			dia.run();
			return;
		}
		m_close_button.show();
		m_open_button.hide();
		g_timeout_add(1000, UpdateInformation::updateStatusinformationWhileConnected, this);
		g_timeout_add(150, UpdateInformation::updateInformationTreeview, this);
		m_infoBox.set_text("Ready to use.");
	} else {
		Gtk::MessageDialog dia(*this,"ComPort is already open!");
		dia.run();
		return;
	}
}

void CF30Window::on_movement_button_stop_clicked(){
	int answer = movementControl.getComPortHandle();
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	movementControl.moveWithSpeed(MC_X_AXIS, 0);
	movementControl.moveWithSpeed(MC_Y_AXIS, 0);
	movementControl.moveWithSpeed(MC_Z_AXIS, 0);
}

void CF30Window::on_move_relative_x_left_clicked(){
	int velocity = 0;
	int steps = 0;
	std::istringstream iss(m_relative_move_velocity_x.get_text());
	iss >> velocity;
	std::istringstream iiss(m_relative_move_steps_x.get_text());
	iiss >> steps;
	if(steps > 0){
		steps = -steps;
	}
	int answer = movementControl.moveRelativeToPosition(MC_X_AXIS, velocity, steps);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	this->velocityX = -std::abs(velocity);
}

void CF30Window::on_move_relative_y_left_clicked(){
	int velocity = 0;
	int steps = 0;
	std::istringstream iss(m_relative_move_velocity_y.get_text());
	iss >> velocity;
	std::istringstream iiss(m_relative_move_steps_y.get_text());
	iiss >> steps;
	if(steps > 0){
		steps = -steps;
	}
	int answer = movementControl.moveRelativeToPosition(MC_Y_AXIS, velocity, steps);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	this->velocityY = -std::abs(velocity);
}

void CF30Window::on_move_relative_z_left_clicked(){
	int velocity = 0;
	int steps = 0;
	std::istringstream iss(m_relative_move_velocity_z.get_text());
	iss >> velocity;
	std::istringstream iiss(m_relative_move_steps_z.get_text());
	iiss >> steps;
	if(steps > 0){
		steps = -steps;
	}
	int answer = movementControl.moveRelativeToPosition(MC_Z_AXIS, velocity, steps);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	this->velocityZ = -std::abs(velocity);
}

void CF30Window::on_move_relative_x_right_clicked(){
	int velocity = 0;
	int steps = 0;
	std::istringstream iss(m_relative_move_velocity_x.get_text());
	iss >> velocity;
	std::istringstream iiss(m_relative_move_steps_x.get_text());
	iiss >> steps;
	if(steps < 0){
		steps = -steps;
	}
	int answer = movementControl.moveRelativeToPosition(MC_X_AXIS, velocity, steps);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	this->velocityX = std::abs(velocity);
}

void CF30Window::on_move_relative_y_right_clicked(){
	int velocity = 0;
	int steps = 0;
	std::istringstream iss(m_relative_move_velocity_y.get_text());
	iss >> velocity;
	std::istringstream iiss(m_relative_move_steps_y.get_text());
	iiss >> steps;
	if(steps < 0){
		steps = -steps;
	}
	int answer = movementControl.moveRelativeToPosition(MC_Y_AXIS, velocity, steps);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	this->velocityY = std::abs(velocity);
}

void CF30Window::on_move_relative_z_right_clicked(){
	int velocity = 0;
	int steps = 0;
	std::istringstream iss(m_relative_move_velocity_z.get_text());
	iss >> velocity;
	std::istringstream iiss(m_relative_move_steps_z.get_text());
	iiss >> steps;
	if(steps < 0){
		steps = -steps;
	}
	int answer = movementControl.moveRelativeToPosition(MC_Z_AXIS, velocity, steps);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	this->velocityZ = std::abs(velocity);
}

void CF30Window::on_move_single_step_x_right_clicked(){
	int answer = movementControl.moveRelativeToPosition(MC_X_AXIS, 100, 1);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	singleStep_moveDirection_x = "+";
	this->velocityX = 1;
}

void CF30Window::on_move_single_step_y_right_clicked(){
	int answer = movementControl.moveRelativeToPosition(MC_Y_AXIS, 100, 1);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	singleStep_moveDirection_y = "+";
	this->velocityY = 1;
}

void CF30Window::on_move_single_step_z_right_clicked(){
	int answer = movementControl.moveRelativeToPosition(MC_Z_AXIS, 100, 1);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	singleStep_moveDirection_z = "+";
	this->velocityZ = 1;
}

void CF30Window::on_move_single_step_x_left_clicked(){
	int answer = movementControl.moveRelativeToPosition(MC_X_AXIS, -100, -1);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	singleStep_moveDirection_x = "-";
	this->velocityX = -1;
}

void CF30Window::on_move_single_step_y_left_clicked(){
	int answer = movementControl.moveRelativeToPosition(MC_Y_AXIS, -100, -1);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	singleStep_moveDirection_y = "-";
	this->velocityY = -1;
}

void CF30Window::on_move_single_step_z_left_clicked(){
	int answer = movementControl.moveRelativeToPosition(MC_Z_AXIS, -100, -1);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	singleStep_moveDirection_z = "-";
	this->velocityZ = -1;
}

void CF30Window::on_move_absolute_position_x_clicked(){
	int velocity = 0;
	int position = 0;
	std::istringstream iss(m_absolute_move_velocity_x.get_text());
	iss >> velocity;
	std::istringstream iiss(m_absolute_move_position_x.get_text());
	iiss >> position;
	int answer = movementControl.moveAbsoluteToPosition(MC_X_AXIS, velocity, position);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}

	velocity = abs(velocity);
	Gtk::TreeModel::Children childs = m_refTreeModel->children();
	Gtk::TreeNodeChildren::iterator iterChilds = childs.begin();
	Gtk::TreeModel::Row row = (Gtk::TreeModel::Row) (*(iterChilds));
	if(position < row[m_Columns.m_col_position]){
		this->velocityX = -velocity;
	} else {
		this->velocityX = velocity;
	}
}

void CF30Window::on_move_absolute_position_y_clicked(){
	int velocity = 0;
	int position = 0;
	std::istringstream iss(m_absolute_move_velocity_y.get_text());
	iss >> velocity;
	std::istringstream iiss(m_absolute_move_position_y.get_text());
	iiss >> position;
	int answer = movementControl.moveAbsoluteToPosition(MC_Y_AXIS, velocity, position);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}

	velocity = abs(velocity);
	Gtk::TreeModel::Children childs = m_refTreeModel->children();
	Gtk::TreeNodeChildren::iterator iterChilds = childs.begin();
	iterChilds++;
	Gtk::TreeModel::Row row = (Gtk::TreeModel::Row) (*(iterChilds));
	if(position < row[m_Columns.m_col_position]){
		this->velocityY = -velocity;
	} else {
		this->velocityY = velocity;
	}
}

void CF30Window::on_move_absolute_position_z_clicked(){
	int velocity = 0;
	int position = 0;
	std::istringstream iss(m_absolute_move_velocity_z.get_text());
	iss >> velocity;
	std::istringstream iiss(m_absolute_move_position_z.get_text());
	iiss >> position;
	int answer = movementControl.moveAbsoluteToPosition(MC_Z_AXIS, velocity, position);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}

	velocity = abs(velocity);
	Gtk::TreeModel::Children childs = m_refTreeModel->children();
	Gtk::TreeNodeChildren::iterator iterChilds = childs.begin();
	iterChilds++;
	iterChilds++;
	Gtk::TreeModel::Row row = (Gtk::TreeModel::Row) (*(iterChilds));
	if(position < row[m_Columns.m_col_position]){
		this->velocityZ = -velocity;
	} else {
		this->velocityZ = velocity;
	}
}

void CF30Window::on_set_counter_x_clicked(){
	int counter = 0;
	std::istringstream iss(m_set_counter_x_entrybox.get_text());
	iss >> counter;
	int answer = movementControl.setPosition(MC_X_AXIS, counter);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
}

void CF30Window::on_set_counter_y_clicked(){
	int counter = 0;
	std::istringstream iss(m_set_counter_y_entrybox.get_text());
	iss >> counter;
	int answer = movementControl.setPosition(MC_Y_AXIS, counter);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
}

void CF30Window::on_set_counter_z_clicked(){
	int counter = 0;
	std::istringstream iss(m_set_counter_z_entrybox.get_text());
	iss >> counter;
	int answer = movementControl.setPosition(MC_Z_AXIS, counter);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
}

void CF30Window::on_set_ramp_x_clicked(){
	int value = 0;
	std::istringstream iss(m_ramp_value_x.get_text());
	iss >> value;
	int answer = movementControl.changeRampValue(MC_X_AXIS, value);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
}

void CF30Window::on_set_ramp_y_clicked(){
	int value = 0;
	std::istringstream iss(m_ramp_value_y.get_text());
	iss >> value;
	int answer = movementControl.changeRampValue(MC_Y_AXIS, value);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
}

void CF30Window::on_set_ramp_z_clicked(){
	int value = 0;
	std::istringstream iss(m_ramp_value_z.get_text());
	iss >> value;
	int answer = movementControl.changeRampValue(MC_Z_AXIS, value);
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
}

void CF30Window::on_get_ramp_x_clicked(){
	int value = movementControl.getRampValue(MC_X_AXIS);
	if( value == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	} else if(value == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	} else {
		int rampValue = value;
		std::string s;
		std::ostringstream outStream;
		outStream << rampValue;
		s = outStream.str();

		m_ramp_value_x.set_text(s.c_str());

		return;
	}
}

void CF30Window::on_get_ramp_y_clicked(){
	int value = movementControl.getRampValue(MC_Y_AXIS);
	if( value == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	}  else if(value == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	} else {
		int rampValue = value;
		std::string s;
		std::ostringstream outStream;
		outStream << rampValue;
		s = outStream.str();

		m_ramp_value_y.set_text(s.c_str());

		return;
	}
}

void CF30Window::on_get_ramp_z_clicked(){
	int value = movementControl.getRampValue(MC_Z_AXIS);
	if( value == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		return;
	}  else if(value == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	} else {
		int rampValue = value;
		std::string s;
		std::ostringstream outStream;
		outStream << rampValue;
		s = outStream.str();

		m_ramp_value_z.set_text(s.c_str());

		return;
	}
}

void CF30Window::on_close_button_clicked(){
	movementControl.moveWithSpeed(MC_X_AXIS, 0);
	movementControl.moveWithSpeed(MC_Y_AXIS, 0);
	movementControl.moveWithSpeed(MC_Z_AXIS, 0);

	movementControl.closeComPort();

	m_infoBox.set_text("Please open a\nComPort.");

	m_open_button.show();
	m_close_button.hide();
}

void CF30Window::on_quit_button_clicked(){
	if(movementControl.getComPortHandle() != -1){
		on_close_button_clicked();
	}

	Gtk::Main::quit();
}

// ----------------- Scalebars ---------------------

void CF30Window::scale_bar_x_moved(){
	if(movementControl.getComPortHandle() == -1 && (int)m_scale_bar_x.get_value() == 0){
		return;
	}
	int answer = movementControl.moveWithSpeed(MC_X_AXIS, (int)m_scale_bar_x.get_value());
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		m_scale_bar_x.set_value(0);
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	this->velocityX = (int)m_scale_bar_x.get_value();
}

void CF30Window::scale_bar_y_moved(){
	if(movementControl.getComPortHandle() == -1 && (int)m_scale_bar_y.get_value() == 0){
		return;
	}
	int answer = movementControl.moveWithSpeed(MC_Y_AXIS, (int)m_scale_bar_y.get_value());
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		m_scale_bar_y.set_value(0);
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	this->velocityY = (int)m_scale_bar_y.get_value();
}

void CF30Window::scale_bar_z_moved(){
	if(movementControl.getComPortHandle() == -1 && (int)m_scale_bar_z.get_value() == 0){
		return;
	}
	int answer = movementControl.moveWithSpeed(MC_Z_AXIS, (int)m_scale_bar_z.get_value());
	if(answer == -1){
		errorMessageOutput(CF30_ERROR_COMPORT_IS_CLOSED);
		m_scale_bar_z.set_value(0);
	} else if(answer == -2){
		on_close_button_clicked();
		errorMessageOutput(CF30_ERROR_CONNECTION_LOST);
		return;
	}
	this->velocityZ = (int)m_scale_bar_z.get_value();
}

bool CF30Window::scaleBar_x_released(GdkEventButton* event){
	set_x_toZero = true;
	return false;
}

bool CF30Window::scaleBar_x_pressed(GdkEventButton* event){
	set_x_toZero = false;
	return false;
}

bool CF30Window::scaleBar_y_released(GdkEventButton* event){
	set_y_toZero = true;
	return false;
}

bool CF30Window::scaleBar_y_pressed(GdkEventButton* event){
	set_y_toZero = false;
	return false;
}

bool CF30Window::scaleBar_z_released(GdkEventButton* event){
	set_z_toZero = true;
	return false;
}

bool CF30Window::scaleBar_z_pressed(GdkEventButton* event){
	set_z_toZero = false;
	return false;
}

// ----------------- Entry ---------------------

void CF30Window::relativeMoveVelocity_checkInput_x(){
	std::string value = checkForNumericInput(m_relative_move_velocity_x.get_text(), movementControl.getMaxMovementSpeed());
	m_relative_move_velocity_x.set_text(value.c_str());
}

void CF30Window::relativeMoveVelocity_checkInput_y(){
	std::string value = checkForNumericInput(m_relative_move_velocity_y.get_text(), movementControl.getMaxMovementSpeed());
	m_relative_move_velocity_y.set_text(value.c_str());
}

void CF30Window::relativeMoveVelocity_checkInput_z(){
	std::string value = checkForNumericInput(m_relative_move_velocity_z.get_text(), movementControl.getMaxMovementSpeed());
	m_relative_move_velocity_z.set_text(value.c_str());
}

void CF30Window::relativeMoveSteps_checkInput_x(){
	std::string value = checkForNumericInput(m_relative_move_steps_x.get_text(), movementControl.getMaxPosition());
	m_relative_move_steps_x.set_text(value.c_str());
}

void CF30Window::relativeMoveSteps_checkInput_y(){
	std::string value = checkForNumericInput(m_relative_move_steps_y.get_text(), movementControl.getMaxPosition());
	m_relative_move_steps_y.set_text(value.c_str());
}

void CF30Window::relativeMoveSteps_checkInput_z(){
	std::string value = checkForNumericInput(m_relative_move_steps_z.get_text(), movementControl.getMaxPosition());
	m_relative_move_steps_z.set_text(value.c_str());
}

void CF30Window::absoluteMoveVelocity_checkInput_x(){
	std::string value = checkForNumericInput(m_absolute_move_velocity_x.get_text(), movementControl.getMaxMovementSpeed());
	m_absolute_move_velocity_x.set_text(value.c_str());
}

void CF30Window::absoluteMoveVelocity_checkInput_y(){
	std::string value = checkForNumericInput(m_absolute_move_velocity_y.get_text(), movementControl.getMaxMovementSpeed());
	m_absolute_move_velocity_y.set_text(value.c_str());
}

void CF30Window::absoluteMoveVelocity_checkInput_z(){
	std::string value = checkForNumericInput(m_absolute_move_velocity_z.get_text(), movementControl.getMaxMovementSpeed());
	m_absolute_move_velocity_z.set_text(value.c_str());
}

void CF30Window::absoluteMovePosition_checkInput_x(){
	std::string value = checkForNumericInput(m_absolute_move_position_x.get_text(), movementControl.getMaxPosition());
	m_absolute_move_position_x.set_text(value.c_str());
}

void CF30Window::absoluteMovePosition_checkInput_y(){
	std::string value = checkForNumericInput(m_absolute_move_position_y.get_text(), movementControl.getMaxPosition());
	m_absolute_move_position_y.set_text(value.c_str());
}

void CF30Window::absoluteMovePosition_checkInput_z(){
	std::string value = checkForNumericInput(m_absolute_move_position_z.get_text(), movementControl.getMaxPosition());
	m_absolute_move_position_z.set_text(value.c_str());
}

void CF30Window::setCounter_checkInput_x(){
	std::string value = checkForNumericInput(m_set_counter_x_entrybox.get_text(), movementControl.getMaxPosition());
	m_set_counter_x_entrybox.set_text(value.c_str());
}

void CF30Window::setCounter_checkInput_y(){
	std::string value = checkForNumericInput(m_set_counter_y_entrybox.get_text(), movementControl.getMaxPosition());
	m_set_counter_y_entrybox.set_text(value.c_str());
}

void CF30Window::setCounter_checkInput_z(){
	std::string value = checkForNumericInput(m_set_counter_z_entrybox.get_text(), movementControl.getMaxPosition());
	m_set_counter_z_entrybox.set_text(value.c_str());
}

void CF30Window::rampValue_checkInput_x(){
	std::string value = checkForNumericInput(m_ramp_value_x.get_text(), movementControl.getMaxRampValue());
	m_ramp_value_x.set_text(value.c_str());
}

void CF30Window::rampValue_checkInput_y(){
	std::string value = checkForNumericInput(m_ramp_value_y.get_text(), movementControl.getMaxRampValue());
	m_ramp_value_y.set_text(value.c_str());
}
void CF30Window::rampValue_checkInput_z(){
	std::string value = checkForNumericInput(m_ramp_value_z.get_text(), movementControl.getMaxRampValue());
	m_ramp_value_z.set_text(value.c_str());
}

/**
 * If input contains alphabetic characters the function will erase them and return the remaining string.
 */
std::string CF30Window::checkForNumericInput(std::string input, int maxValue){
	for(unsigned int i = 0; i < input.size(); i++){
		switch(input[i]){
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			break;
		case '-':
			if(i != 0 || maxValue == movementControl.getMaxRampValue()){
				input.erase(i, 1);
				return input;
			}
			break;
		default:
			input.erase(i, 1);
			return input;
			break;
		}
	}
	int value = 0;
	std::istringstream iss(input);
	iss >> value;
	if(value > maxValue){
		std::ostringstream oss;
		oss << maxValue;
		return oss.str();
	} else if (value < -maxValue){
		std::ostringstream oss;
		oss << -maxValue;
		return oss.str();
	}

	return input;
}

/**
 * Shows a error message in a dialog window.
 * @param messageFlag: indicates which message will be printed
 */
void CF30Window::errorMessageOutput(CF30_ERROR_Message_flag messageFlag){
	std::string messageFlagString;
	std::ostringstream os;
	os << messageFlag;
	messageFlagString = os.str();
	Gtk::MessageDialog dia(*this, "Some error occurred. " + messageFlagString, false , Gtk::MESSAGE_ERROR);

	switch((int)messageFlag){
	case CF30_ERROR_NO_FTDI_KERNELMODULE:
		dia.set_message("Can't find FTDI kernelmodule!\nPlease check if the CF30 controller is connected.");
		break;
	case CF30_ERROR_CONNECTION_LOST:
		dia.set_message("Connection lost.\nComPort has been closed!");
		break;
	case CF30_ERROR_COMPORT_IS_CLOSED:
		dia.set_message("ComPort has not been opened!");
		break;
	default:
		break;
	}
	dia.run();
}
