
/*
 * CINELERRA
 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "bcdisplayinfo.h"
#include "histogramengine.h"
#include "language.h"
#include "threshold.h"
#include "thresholdwindow.h"

#define COLOR_W xS(100)
#define COLOR_H yS(30)




ThresholdMin::ThresholdMin(ThresholdMain *plugin,
	ThresholdWindow *gui,
	int x,
	int y,
	int w)
 : BC_TumbleTextBox(gui,
	plugin->config.min,
	HISTOGRAM_MIN,
	HISTOGRAM_MAX,
	x,
	y,
	w)
{
	this->plugin = plugin;
	this->gui = gui;
}


int ThresholdMin::handle_event()
{
	plugin->config.min = atof(get_text());
	gui->canvas->draw();
	plugin->send_configure_change();
	return 1;
}









ThresholdMax::ThresholdMax(ThresholdMain *plugin,
	ThresholdWindow *gui,
	int x,
	int y,
	int w)
 : BC_TumbleTextBox(gui,
	plugin->config.max,
	HISTOGRAM_MIN,
	HISTOGRAM_MAX,
	x,
	y,
	w)
{
	this->plugin = plugin;
	this->gui = gui;
}

int ThresholdMax::handle_event()
{
	plugin->config.max = atof(get_text());
	gui->canvas->draw();
	plugin->send_configure_change();
	return 1;
}







ThresholdPlot::ThresholdPlot(ThresholdMain *plugin,
	int x,
	int y)
 : BC_CheckBox(x, y, plugin->config.plot, _("Plot histogram"))
{
	this->plugin = plugin;
}

int ThresholdPlot::handle_event()
{
	plugin->config.plot = get_value();

	plugin->send_configure_change();
	return 1;
}






ThresholdCanvas::ThresholdCanvas(ThresholdMain *plugin,
	ThresholdWindow *gui,
	int x,
	int y,
	int w,
	int h)
 : BC_SubWindow(x, y, w, h)
{
	this->plugin = plugin;
	this->gui = gui;
	state = NO_OPERATION;
}

int ThresholdCanvas::button_press_event()
{
	if(is_event_win() && cursor_inside())
	{
		activate();
		state = DRAG_SELECTION;
		if(shift_down())
		{
			x1 = (int)((plugin->config.min - HISTOGRAM_MIN) /
				(HISTOGRAM_MAX - HISTOGRAM_MIN) *
				get_w());
			x2 = (int)((plugin->config.max - HISTOGRAM_MIN) /
				(HISTOGRAM_MAX - HISTOGRAM_MIN) *
				get_w());
			center_x = (x2 + x1) / 2;
			if(abs(get_cursor_x() - x1) < abs(get_cursor_x() - x2))
			{
				x1 = get_cursor_x();
				center_x = x2;
			}
			else
			{
				x2 = get_cursor_x();
				center_x = x1;
			}
		}
		else
		{
			x1 = x2 = center_x = get_cursor_x();
		}

		plugin->config.min = x1 *
			(HISTOGRAM_MAX - HISTOGRAM_MIN) /
			get_w() +
			HISTOGRAM_MIN;
		plugin->config.max = x2 *
			(HISTOGRAM_MAX - HISTOGRAM_MIN) /
			get_w() +
			HISTOGRAM_MIN;

		draw();
		return 1;
	}
	return 0;
}

int ThresholdCanvas::button_release_event()
{
	if(state == DRAG_SELECTION)
	{
		state = NO_OPERATION;
		return 1;
	}
	return 0;
}

int ThresholdCanvas::cursor_motion_event()
{
	if(state == DRAG_SELECTION)
	{
		if(get_cursor_x() > center_x)
		{
			x1 = center_x;
			x2 = get_cursor_x();
		}
		else
		{
			x1 = get_cursor_x();
			x2 = center_x;
		}

		plugin->config.min = x1 *
			(HISTOGRAM_MAX - HISTOGRAM_MIN) /
			get_w() +
			HISTOGRAM_MIN;

		plugin->config.max = x2 *
			(HISTOGRAM_MAX - HISTOGRAM_MIN) /
			get_w() +
			HISTOGRAM_MIN;

		gui->min->update(plugin->config.min);
		gui->max->update(plugin->config.max);
		draw();
		plugin->send_configure_change();
		return 1;
	}
	return 0;
}

void ThresholdCanvas::draw()
{
	int max = 0;
	set_color(WHITE);
	draw_box(0, 0, get_w(), get_h());
	int border_x1 = (int)((0 - HISTOGRAM_MIN) /
		(HISTOGRAM_MAX - HISTOGRAM_MIN) *
		get_w());
	int border_x2 = (int)((1.0 - HISTOGRAM_MIN) /
		(HISTOGRAM_MAX - HISTOGRAM_MIN) *
		get_w());

	int x1 = (int)((plugin->config.min - HISTOGRAM_MIN) /
		(HISTOGRAM_MAX - HISTOGRAM_MIN) *
		get_w());
	int x2 = (int)((plugin->config.max - HISTOGRAM_MIN) /
		(HISTOGRAM_MAX - HISTOGRAM_MIN) *
		get_w());

	if(plugin->engine)
	{
		int64_t *array = plugin->engine->accum[HISTOGRAM_VALUE];


// Get normalizing factor
		for(int i = 0; i < get_w(); i++)
		{
			int division1 = i * HISTOGRAM_RANGE / get_w();
			int division2 = (i + 1) * HISTOGRAM_RANGE / get_w();
			int total = 0;
			for(int j = division1; j < division2; j++)
			{
				total += array[j];
			}
			if(total > max) max = total;
		}

		for(int i = 0; i < get_w(); i++)
		{
			int division1 = i * HISTOGRAM_RANGE / get_w();
			int division2 = (i + 1) * HISTOGRAM_RANGE / get_w();
			int total = 0;
			for(int j = division1; j < division2; j++)
			{
				total += array[j];
			}

			int pixels;
			if(max)
				pixels = total * get_h() / max;
			else
				pixels = 0;
			if(i >= x1 && i < x2)
			{
				set_color(BLUE);
				draw_line(i, 0, i, get_h() - pixels);
				set_color(WHITE);
				draw_line(i, get_h(), i, get_h() - pixels);
			}
			else
			{
				set_color(BLACK);
				draw_line(i, get_h(), i, get_h() - pixels);
			}
		}
	}
	else
	{


		set_color(BLUE);
		draw_box(x1, 0, x2 - x1, get_h());
	}

	set_color(RED);
	draw_line(border_x1, 0, border_x1, get_h());
	draw_line(border_x2, 0, border_x2, get_h());

	flash(1);
}






ThresholdLowColorButton::ThresholdLowColorButton(ThresholdMain *plugin, ThresholdWindow *window, int x, int y)
 : BC_GenericButton(x, y, _("Low Color"))
{
	this->plugin = plugin;
	this->window = window;
}

int ThresholdLowColorButton::handle_event()
{
	RGBA & color = plugin->config.low_color;
	window->low_color_thread->start_window(
		color.getRGB(),
		color.a);
	return 1;
}





ThresholdMidColorButton::ThresholdMidColorButton(ThresholdMain *plugin, ThresholdWindow *window, int x, int y)
 : BC_GenericButton(x, y, _("Mid Color"))
{
	this->plugin = plugin;
	this->window = window;
}

int ThresholdMidColorButton::handle_event()
{
	RGBA & color = plugin->config.mid_color;
	window->mid_color_thread->start_window(
		color.getRGB(),
		color.a);
	return 1;
}





ThresholdHighColorButton::ThresholdHighColorButton(ThresholdMain *plugin, ThresholdWindow *window, int x, int y)
 : BC_GenericButton(x, y, _("High Color"))
{
	this->plugin = plugin;
	this->window = window;
}

int ThresholdHighColorButton::handle_event()
{
	RGBA & color = plugin->config.high_color;
	window->high_color_thread->start_window(
		color.getRGB(),
		color.a);
	return 1;
}





ThresholdLowColorThread::ThresholdLowColorThread(ThresholdMain *plugin, ThresholdWindow *window)
 : ColorPicker(1, _("Low color"))
{
	this->plugin = plugin;
	this->window = window;
}

int ThresholdLowColorThread::handle_new_color(int output, int alpha)
{
	plugin->config.low_color.set(output, alpha);
	window->update_low_color();
	window->flush();
	plugin->send_configure_change();
	return 1;
}





ThresholdMidColorThread::ThresholdMidColorThread(ThresholdMain *plugin, ThresholdWindow *window)
 : ColorPicker(1, _("Mid color"))
{
	this->plugin = plugin;
	this->window = window;
}

int ThresholdMidColorThread::handle_new_color(int output, int alpha)
{
	plugin->config.mid_color.set(output, alpha);
	window->update_mid_color();
	window->flush();
	plugin->send_configure_change();
	return 1;
}





ThresholdHighColorThread::ThresholdHighColorThread(ThresholdMain *plugin, ThresholdWindow *window)
 : ColorPicker(1, _("High color"))
{
	this->plugin = plugin;
	this->window = window;
}

int ThresholdHighColorThread::handle_new_color(int output, int alpha)
{
	plugin->config.high_color.set(output, alpha);
	window->update_high_color();
	window->flush();
	plugin->send_configure_change();
	return 1;
}






ThresholdWindow::ThresholdWindow(ThresholdMain *plugin)
: PluginClientWindow(plugin, xS(450), yS(450), xS(450), yS(450), 1)
{
	this->plugin = plugin;
	this->min = 0;
	this->max = 0;
	this->canvas = 0;
	this->plot = 0;
	this->low_color = 0;
	this->mid_color = 0;
	this->high_color = 0;
	this->low_color_thread = 0;
	this->mid_color_thread = 0;
	this->high_color_thread = 0;
}

ThresholdWindow::~ThresholdWindow()
{
}

void ThresholdWindow::create_objects()
{
	int xs10 = xS(10), xs30 = xS(30), xs100 = xS(100);
	int ys10 = yS(10), ys160 = yS(160);
	int x = xs10;
	int y = ys10;
	add_subwindow(canvas = new ThresholdCanvas(plugin,
		this,
		x,
		y,
		get_w() - x - xs10,
		get_h() - ys160));
	canvas->draw();
	y += canvas->get_h() + ys10;

	add_subwindow(plot = new ThresholdPlot(plugin, x, y));
	y += plot->get_h() + ys10;


	add_subwindow(low_color = new ThresholdLowColorButton(plugin, this, x, y));
	low_color_x = x + xs10;
	low_color_y = y + low_color->get_h() + ys10;
	x += low_color->get_w() + xs10;

	add_subwindow(mid_color = new ThresholdMidColorButton(plugin, this, x, y));
	mid_color_x = x + xs10;
	mid_color_y = y + mid_color->get_h() + ys10;
	x += mid_color->get_w() + xs10;

	add_subwindow(high_color = new ThresholdHighColorButton(plugin, this, x, y));
	high_color_x = x + xs10;
	high_color_y = y + high_color->get_h() + ys10;

	y += low_color->get_h() + COLOR_H + ys10 + ys10;

	x = xs30;
	BC_Title * min_title;
	add_subwindow(min_title = new BC_Title(x, y, _("Min:")));
	x += min_title->get_w() + xs10;
	min = new ThresholdMin(plugin,
		this,
		x,
		y,
		xs100);
	min->create_objects();
	min->set_increment(0.1);


	x = mid_color->get_x() + mid_color->get_w() / 2;
	BC_Title * max_title;
	add_subwindow(max_title = new BC_Title(x, y, _("Max:")));
	x += max_title->get_w() + xs10;
	max = new ThresholdMax(plugin,
		this,
		x,
		y,
		xs100);
	max->create_objects();
	max->set_increment(0.1);


	low_color_thread  = new ThresholdLowColorThread(plugin, this);
	mid_color_thread  = new ThresholdMidColorThread(plugin, this);
	high_color_thread = new ThresholdHighColorThread(plugin, this);
	update_low_color();
	update_mid_color();
	update_high_color();

	show_window(1);
}

void ThresholdWindow::update_low_color()
{
	set_color(plugin->config.low_color.getRGB());
	draw_box(low_color_x, low_color_y, COLOR_W, COLOR_H);
	flash(low_color_x, low_color_y, COLOR_W, COLOR_H);
}

void ThresholdWindow::update_mid_color()
{
	set_color(plugin->config.mid_color.getRGB());
	draw_box(mid_color_x, mid_color_y, COLOR_W, COLOR_H);
	flash(mid_color_x, mid_color_y, COLOR_W, COLOR_H);
}

void ThresholdWindow::update_high_color()
{
	set_color(plugin->config.high_color.getRGB());
	draw_box(high_color_x, high_color_y, COLOR_W, COLOR_H);
	flash(high_color_x, high_color_y, COLOR_W, COLOR_H);
}

void ThresholdWindow::done_event(int result)
{
	low_color_thread->close_window();
	mid_color_thread->close_window();
	high_color_thread->close_window();
}



