
/*
 * CINELERRA
 * Copyright (C) 1997-2017 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 "bcsignals.h"
#include "cursors.h"
#include "histogram.h"
#include "histogramconfig.h"
#include "histogramwindow.h"
#include "keys.h"
#include "language.h"
#include "theme.h"

#include <unistd.h>




HistogramWindow::HistogramWindow(HistogramMain *plugin)
 : PluginClientWindow(plugin, 
	plugin->w, 
	plugin->h, 
	DP(440), 
	DP(500), 
	1)
{
	this->plugin = plugin; 
	active_value = 0;
}

HistogramWindow::~HistogramWindow()
{
}


void HistogramWindow::create_objects()
{
	int margin = plugin->get_theme()->widget_border;
	int x = margin, y = margin, x1 = margin;

	add_subwindow(mode_v = new HistogramMode(plugin, 
		x, 
		y,
		HISTOGRAM_VALUE,
		_("Value")));
	x += mode_v->get_w() + margin;
	add_subwindow(mode_r = new HistogramMode(plugin, 
		x, 
		y,
		HISTOGRAM_RED,
		_("Red")));
	x += mode_r->get_w() + margin;
	add_subwindow(mode_g = new HistogramMode(plugin, 
		x, 
		y,
		HISTOGRAM_GREEN,
		_("Green")));
	x += mode_g->get_w() + margin;
	add_subwindow(mode_b = new HistogramMode(plugin, 
		x, 
		y,
		HISTOGRAM_BLUE,
		_("Blue")));


	x = get_w() - margin - plugin->get_theme()->get_image_set("histogram_rgb_toggle")[0]->get_w();
	add_subwindow(parade_on = new HistogramParade(plugin, 
		this,
		x, 
		y,
		1));
	x -= parade_on->get_w() + margin; 
	add_subwindow(parade_off = new HistogramParade(plugin, 
		this,
		x, 
		y,
		0));


	x = x1;
	y += parade_on->get_h() + margin;
	add_subwindow(canvas_title1 = new BC_Title(margin, 
		y, 
		"-10%"));
	add_subwindow(canvas_title2 = new BC_Title(get_w() - get_text_width(MEDIUMFONT, "110%") - margin,
		y,
		"110%"));

	y += canvas_title2->get_h() + margin;
	x = x1;
	canvas_h = get_h() - y - DP(210);


	add_subwindow(low_input_carrot = new HistogramCarrot(plugin,
		this,
		x,
		y + canvas_h));

	x = low_input_carrot->get_w() / 2 + x;
	canvas_w = get_w() - x - x;

	title1_x = x;
	title2_x = x + (int)(canvas_w * -MIN_INPUT / FLOAT_RANGE);
	title3_x = x + (int)(canvas_w * (1.0 - MIN_INPUT) / FLOAT_RANGE);
	title4_x = x + (int)(canvas_w);





	add_subwindow(canvas = new HistogramCanvas(plugin,
		this,
		x, 
		y, 
		canvas_w, 
		canvas_h));

// Canvas border
	draw_3d_border(x - 2, 
		y - 2, 
		canvas_w + 4, 
		canvas_h + 4, 
		get_bg_color(),
		BLACK,
		MDGREY, 
		get_bg_color());

// Calculate output curve with no value function
	plugin->tabulate_curve(plugin->mode, 0);

	y += canvas->get_h();
	x = margin;

	add_subwindow(gamma_carrot = new HistogramCarrot(plugin,
		this,
		canvas->get_x() + 
			canvas->get_w() / 2 - 
			low_input_carrot->get_w() / 2 ,
		y));

	add_subwindow(high_input_carrot = new HistogramCarrot(plugin,
		this,
		canvas->get_x() + 
			canvas->get_w() - 
			low_input_carrot->get_w() / 2,
		y));
	y += low_input_carrot->get_h() + margin;


//	add_subwindow(title = new BC_Title(x, y, _("Input:")));
//	x += title->get_w() + margin;
	low_input = new HistogramText(plugin,
		this,
		x,
		y);
	low_input->create_objects();

	x = get_w() / 2 - low_input->get_w() / 2;
	gamma = new HistogramText(plugin,
		this,
		x,
		y);
	gamma->create_objects();


	x = get_w() - low_input->get_w() - margin;
	high_input = new HistogramText(plugin,
		this,
		x,
		y);
	high_input->create_objects();


	y += high_input->get_h() + margin;
	x = x1;



	add_subwindow(output = new HistogramSlider(plugin, 
		this,
		canvas->get_x(), 
		y, 
		canvas->get_w(),
		DP(20),
		0));
	output->update();

// Output border
	draw_3d_border(output->get_x() - 2, 
		output->get_y() - 2, 
		output->get_w() + 4, 
		output->get_h() + 4, 
		get_bg_color(),
		BLACK,
		MDGREY, 
		get_bg_color());


	y += output->get_h();



	add_subwindow(low_output_carrot = new HistogramCarrot(plugin,
		this,
		margin,
		y));

	add_subwindow(high_output_carrot = new HistogramCarrot(plugin,
		this,
		canvas->get_x() + 
			canvas->get_w() - 
			low_output_carrot->get_w() / 2,
		y));
	y += high_output_carrot->get_h() + margin;


//	add_subwindow(title = new BC_Title(x, y, _("Output:")));
//	x += title->get_w() + margin;
	low_output = new HistogramText(plugin,
		this,
		x,
		y);
	low_output->create_objects();
	high_output = new HistogramText(plugin,
		this,
		get_w() - low_output->get_w() - margin,
		y);
	high_output->create_objects();

	x = x1;
	y += high_output->get_h() + margin;

	add_subwindow(bar = new BC_Bar(x, y, get_w() - margin * 2));
	y += bar->get_h() + margin;

	add_subwindow(automatic = new HistogramAuto(plugin, 
		x, 
		y));

	int y1 = y;
	x = DP(200);
	add_subwindow(threshold_title = new BC_Title(x, y, _("Threshold:")));
	x += threshold_title->get_w() + margin;
	threshold = new HistogramText(plugin,
		this,
		x,
		y);
	threshold->create_objects();

	x = get_w() / 2;
	add_subwindow(reset = new HistogramReset(plugin, 
		x, 
		y + threshold->get_h() + margin));

	x = x1;
	y += automatic->get_h() + margin;
	add_subwindow(plot = new HistogramPlot(plugin, 
		x, 
		y));

	y += plot->get_h() + DP(5);
	add_subwindow(split = new HistogramSplit(plugin, 
		x, 
		y));

	update(1, 1, 1, 1);
	
	flash(0);
	show_window();
}



int HistogramWindow::resize_event(int w, int h)
{
	int xdiff = w - get_w();
	int ydiff = h - get_h();

	parade_on->reposition_window(parade_on->get_x() + xdiff,
		parade_on->get_y());
	parade_off->reposition_window(parade_off->get_x() + xdiff,
		parade_on->get_y());
	canvas_title2->reposition_window(canvas_title2->get_x() + xdiff,
		canvas_title2->get_y());

// Canvas follows window size
	canvas_w = canvas_w + xdiff;
	canvas_h = canvas_h + ydiff;
	canvas->reposition_window(canvas->get_x(),
		canvas->get_y(),
		canvas_w,
		canvas_h);

// Canvas border
	draw_3d_border(canvas->get_x() - 2, 
		canvas->get_y() - 2, 
		canvas_w + 4, 
		canvas_h + 4, 
		get_bg_color(),
		BLACK,
		MDGREY, 
		get_bg_color());

	low_input_carrot->reposition_window(low_input_carrot->get_x(),
		low_input_carrot->get_y() + ydiff);
	gamma_carrot->reposition_window(gamma_carrot->get_x(),
		gamma_carrot->get_y() + ydiff);
	high_input_carrot->reposition_window(high_input_carrot->get_x(),
		high_input_carrot->get_y() + ydiff);

	low_input->reposition_window(low_input->get_x(),
		low_input->get_y() + ydiff);
	gamma->reposition_window(w / 2 - gamma->get_w() / 2,
		gamma->get_y() + ydiff);
	high_input->reposition_window(high_input->get_x() + xdiff,
		high_input->get_y() + ydiff);

	output->reposition_window(output->get_x(),
		output->get_y() + ydiff,
		output->get_w() + xdiff,
		output->get_h());
	output->update();
	
// Output border
	draw_3d_border(output->get_x() - 2, 
		output->get_y() - 2, 
		output->get_w() + 4, 
		output->get_h() + 4, 
		get_bg_color(),
		BLACK,
		MDGREY, 
		get_bg_color());

	low_output_carrot->reposition_window(low_output_carrot->get_x(),
		low_output_carrot->get_y() + ydiff);
	high_output_carrot->reposition_window(high_output_carrot->get_x(),
		high_output_carrot->get_y() + ydiff);

	low_output->reposition_window(low_output->get_x(),
		low_output->get_y() + ydiff);
	high_output->reposition_window(high_output->get_x() + xdiff,
		high_output->get_y() + ydiff);

	bar->reposition_window(bar->get_x(),
		bar->get_y() + ydiff,
		bar->get_w() + xdiff);
	
	automatic->reposition_window(automatic->get_x(),
		automatic->get_y() + ydiff);
	threshold_title->reposition_window(threshold_title->get_x(),
		threshold_title->get_y() + ydiff);
	threshold->reposition_window(threshold->get_x(),
		threshold->get_y() + ydiff);
	reset->reposition_window(reset->get_x(),
		reset->get_y() + ydiff);
	
	plot->reposition_window(plot->get_x(),
		plot->get_y() + ydiff);
	split->reposition_window(split->get_x(),
		split->get_y() + ydiff);
	
	update(1, 1, 1, 1);

	plugin->w = w;
	plugin->h = h;
	flash();
	return 1;
}



int HistogramWindow::keypress_event()
{
	int result = 0;

	if(active_value)
	{
		float sign = 1;
		for(int i = 0; i < HISTOGRAM_MODES; i++)
		{
			if(active_value == &plugin->config.gamma[i])
				sign = -1;
		}

		if(get_keypress() == RIGHT || get_keypress() == UP)
		{
			*active_value += sign * PRECISION;
			plugin->config.boundaries();
			update(1, 1, 1, 0);
			plugin->send_configure_change();
			return 1;
		}
		else
		if(get_keypress() == LEFT || get_keypress() == DOWN)
		{
			*active_value -= sign * PRECISION;
			plugin->config.boundaries();
			update(1, 1, 1, 0);
			plugin->send_configure_change();
			return 1;
		}
	}
	
	return result;
}

void HistogramWindow::update(int do_canvases,
	int do_carrots,
	int do_text,
	int do_toggles)
{
	if(do_toggles)
	{
		automatic->update(plugin->config.automatic);
		mode_v->update(plugin->mode == HISTOGRAM_VALUE ? 1 : 0);
		mode_r->update(plugin->mode == HISTOGRAM_RED ? 1 : 0);
		mode_g->update(plugin->mode == HISTOGRAM_GREEN ? 1 : 0);
		mode_b->update(plugin->mode == HISTOGRAM_BLUE ? 1 : 0);
		plot->update(plugin->config.plot);
		split->update(plugin->config.split);
		parade_on->update(plugin->parade ? 1 : 0);
		parade_off->update(plugin->parade ? 0 : 1);
		output->update();
	}

	if(do_canvases)
	{
		update_canvas();
	}
	
	if(do_carrots)
	{
		low_input_carrot->update();
		high_input_carrot->update();
		gamma_carrot->update();
		low_output_carrot->update();
		high_output_carrot->update();
	}
	
	if(do_text)
	{
		low_input->update();
		gamma->update();
		high_input->update();
		low_output->update();
		high_output->update();
		threshold->update();
	}

	
}


void HistogramWindow::draw_canvas_mode(int mode, int color, int y, int h)
{
	int *accum = plugin->accum[mode];
	int accum_per_canvas_i = HISTOGRAM_SLOTS / canvas_w + 1;
	float accum_per_canvas_f = (float)HISTOGRAM_SLOTS / canvas_w;
	int normalize = 0;
	int max = 0;


// Draw histogram
	for(int i = 0; i < HISTOGRAM_SLOTS; i++)
	{
		if(accum && accum[i] > normalize) normalize = accum[i];
	}


	if(normalize)
	{
		for(int i = 0; i < canvas_w; i++)
		{
			int accum_start = (int)(accum_per_canvas_f * i);
			int accum_end = accum_start + accum_per_canvas_i;
			max = 0;
			for(int j = accum_start; j < accum_end; j++)
			{
				max = MAX(accum[j], max);
			}

//			max = max * h / normalize;
			max = (int)(log(max) / log(normalize) * h);

			canvas->set_color(BLACK);
			canvas->draw_line(i, y, i, y + h - max);
			canvas->set_color(color);
			canvas->draw_line(i, y + h - max, i, y + h);
		}
	}
	else
	{
		canvas->set_color(BLACK);
		canvas->draw_box(0, y, canvas_w, h);
	}

// Draw overlays
	canvas->set_color(WHITE);
	canvas->set_line_width(2);
	int y1;


// Draw output line
	for(int i = 0; i < canvas_w; i++)
	{
		float input = (float)i / 
				canvas_w * 
				FLOAT_RANGE + 
				MIN_INPUT;
		float output = plugin->calculate_level(input, 
			mode, 
			0);

		int y2 = h - (int)(output * h);
		if(i > 0)
		{
			canvas->draw_line(i - 1, y + y1, i, y + y2);
		}
		y1 = y2;
	}

	canvas->set_line_width(1);

}


void HistogramWindow::update_canvas()
{
	if(plugin->parade)
	{
		draw_canvas_mode(HISTOGRAM_RED, RED, 0, canvas_h / 3);
		draw_canvas_mode(HISTOGRAM_GREEN, GREEN, canvas_h / 3, canvas_h / 3);
		draw_canvas_mode(HISTOGRAM_BLUE, BLUE, canvas_h * 2 / 3, canvas_h - canvas_h * 2 / 3);
	}
	else
	{
		draw_canvas_mode(plugin->mode, MEGREY, 0, canvas_h);
	}


// Draw 0 and 100% lines.
	canvas->set_color(RED);
	int x = (int)(canvas_w * -MIN_INPUT / FLOAT_RANGE);
	canvas->draw_line(x, 
		0, 
		x, 
		canvas_h);
	x = (int)(canvas_w * (1.0 - MIN_INPUT) / FLOAT_RANGE);
	canvas->draw_line(x, 
		0, 
		x, 
		canvas_h);
	canvas->flash();
}




HistogramParade::HistogramParade(HistogramMain *plugin, 
	HistogramWindow *gui,
	int x, 
	int y,
	int value)
 : BC_Toggle(x, 
 	y, 
	value ? plugin->get_theme()->get_image_set("histogram_rgb_toggle") :
		plugin->get_theme()->get_image_set("histogram_toggle"),
	0)
{
	this->plugin = plugin;
	this->gui = gui;
	this->value = value;
	if(value)
		set_tooltip("RGB Parade on");
	else
		set_tooltip("RGB Parade off");
}

int HistogramParade::handle_event()
{
	update(1);
	plugin->parade = value;
	gui->update(1,
		0,
		0,
		1);
	return 1;
}







HistogramCanvas::HistogramCanvas(HistogramMain *plugin,
	HistogramWindow *gui,
	int x,
	int y,
	int w,
	int h)
 : BC_SubWindow(x,
 	y,
	w,
	h,
	BLACK)
{
	this->plugin = plugin;
	this->gui = gui;
}

int HistogramCanvas::button_press_event()
{
	int result = 0;
	if(is_event_win() && cursor_inside())
	{
		if(!plugin->dragging_point && 
			(!plugin->config.automatic || plugin->mode == HISTOGRAM_VALUE))
		{
			gui->deactivate();
		}
	}
	return result;
}

int HistogramCanvas::cursor_motion_event()
{
	if(is_event_win() && cursor_inside())
	{
	}
	return 0;
}

int HistogramCanvas::button_release_event()
{
	return 0;
}














HistogramReset::HistogramReset(HistogramMain *plugin, 
	int x,
	int y)
 : BC_GenericButton(x, y, _("Reset"))
{
	this->plugin = plugin;
}
int HistogramReset::handle_event()
{
	plugin->config.reset(0);
	((HistogramWindow*)plugin->thread->window)->update(1, 1, 1, 1);
	plugin->send_configure_change();
	return 1;
}







HistogramCarrot::HistogramCarrot(HistogramMain *plugin, 
	HistogramWindow *gui,
	int x, 
	int y)
 : BC_Toggle(x, 
 	y, 
	plugin->get_theme()->get_image_set("histogram_carrot"),
	0)
{
	this->plugin = plugin;
	this->gui = gui;
	drag_operation = 0;
}

HistogramCarrot::~HistogramCarrot()
{
}

float* HistogramCarrot::get_value()
{
	if(this == gui->low_input_carrot)
	{
		return &plugin->config.low_input[plugin->mode];
	}
	else
	if(this == gui->high_input_carrot)
	{
		return &plugin->config.high_input[plugin->mode];
	}
	else
	if(this == gui->gamma_carrot)
	{
		return &plugin->config.gamma[plugin->mode];
	}
	else
	if(this == gui->low_output_carrot)
	{
		return &plugin->config.low_output[plugin->mode];
	}
	else
	if(this == gui->high_output_carrot)
	{
		return &plugin->config.high_output[plugin->mode];
	}
}

void HistogramCarrot::update()
{
	int new_x = 0;
	float *value = get_value();

	if(this != gui->gamma_carrot)
	{	
		new_x = (int)(gui->canvas->get_x() +
			(*value - MIN_INPUT) *
			gui->canvas->get_w() /
			(MAX_INPUT - MIN_INPUT) -
			get_w() / 2);
	}
	else
	{
		float min = plugin->config.low_input[plugin->mode];
		float max = plugin->config.high_input[plugin->mode];
		float delta = (max - min) / 2.0;
		float mid = min + delta;
		float tmp = log10(1.0 / *value);
		tmp = mid + delta * tmp;

//printf("HistogramCarrot::update %d %f %f\n", __LINE__, *value, tmp);

			new_x = gui->canvas->get_x() -
				get_w() / 2 +
				(int)(gui->canvas->get_w() *
				(tmp - MIN_INPUT) / 
				(MAX_INPUT - MIN_INPUT));
	}

	reposition_window(new_x, get_y());
}

int HistogramCarrot::button_press_event()
{
	if(is_event_win() && get_buttonpress() == 1)
	{
		gui->deactivate();
		set_status(BC_Toggle::TOGGLE_DOWN);

		BC_Toggle::update(0);
		gui->active_value = get_value();
// Disable the other toggles
		if(this != gui->low_input_carrot) gui->low_input_carrot->BC_Toggle::update(0);
		if(this != gui->high_input_carrot) gui->high_input_carrot->BC_Toggle::update(0);
		if(this != gui->gamma_carrot) gui->gamma_carrot->BC_Toggle::update(0);
		if(this != gui->low_output_carrot) gui->low_output_carrot->BC_Toggle::update(0);
		if(this != gui->high_output_carrot) gui->high_output_carrot->BC_Toggle::update(0);
		starting_x = get_x();
		offset_x = gui->get_relative_cursor_x();
		offset_y = gui->get_relative_cursor_y();
//printf("HistogramCarrot::button_press_event %d %d %d\n", __LINE__, starting_x, offset_x);
		drag_operation = 1;
		draw_face(1, 1);
		return 1;
	}
	return 0;
}

int HistogramCarrot::button_release_event()
{
	int result = BC_Toggle::button_release_event();
	handle_event();
	drag_operation = 0;
	return result;
}

int HistogramCarrot::cursor_motion_event()
{
	int cursor_x = gui->get_relative_cursor_x();
	int cursor_y = gui->get_relative_cursor_y();
	int update_gui = 0;

	if(drag_operation)
	{
//printf("HistogramCarrot::cursor_motion_event %d %d\n", __LINE__, cursor_x);
		int new_x = starting_x + cursor_x - offset_x;

// Clamp x
// Get level from x
		float *value = get_value();
		if(this == gui->gamma_carrot)
		{
			float min = gui->low_input_carrot->get_x();
 			float max = gui->high_input_carrot->get_x();
 			float delta = (max - min) / 2.0;
 			if(delta >= 0.5)
 			{
 				float mid = min + delta;
				float tmp = (float)(new_x - mid) / 
					delta;
 				tmp = 1.0 / pow(10, tmp);
				CLAMP(tmp, MIN_GAMMA, MAX_GAMMA);
				*value = tmp;
//printf("HistogramCarrot::update %d %f\n", __LINE__, tmp);
			}
		}
		else
		{
			int min_x = gui->canvas->get_x() - get_w() / 2;
			int max_x = gui->canvas->get_x() + gui->canvas->get_w() - get_w() / 2;
			CLAMP(new_x, min_x, max_x);
			*value = MIN_INPUT + 
				(MAX_INPUT - MIN_INPUT) * 
				(new_x - min_x) / 
				(max_x - min_x);
		}

		reposition_window(new_x, get_y());
		flush();
	
		gui->update(1,
			(this == gui->low_input_carrot || this == gui->high_input_carrot),
			1,
			0);
		plugin->send_configure_change();

		return 1;
	}
	return 0;
}








HistogramSlider::HistogramSlider(HistogramMain *plugin, 
	HistogramWindow *gui,
	int x, 
	int y, 
	int w,
	int h,
	int is_input)
 : BC_SubWindow(x, y, w, h)
{
	this->plugin = plugin;
	this->gui = gui;
	this->is_input = is_input;
	operation = NONE;
}

int HistogramSlider::input_to_pixel(float input)
{
	return (int)((input - MIN_INPUT) / FLOAT_RANGE * get_w());
}

void HistogramSlider::update()
{
	int w = get_w();
	int h = get_h();
	int half_h = get_h() / 2;
	int quarter_h = get_h() / 4;
	int mode = plugin->mode;
	int r = 0xff;
	int g = 0xff;
	int b = 0xff;

	clear_box(0, 0, w, h);

	switch(mode)
	{
		case HISTOGRAM_RED:
			g = b = 0x00;
			break;
		case HISTOGRAM_GREEN:
			r = b = 0x00;
			break;
		case HISTOGRAM_BLUE:
			r = g = 0x00;
			break;
	}

	for(int i = 0; i < w; i++)
	{
		int color = (int)(i * 0xff / w);
		set_color(((r * color / 0xff) << 16) | 
			((g * color / 0xff) << 8) | 
			(b * color / 0xff));

		draw_line(i, 0, i, h);
	}


	flash();
}









HistogramAuto::HistogramAuto(HistogramMain *plugin, 
	int x, 
	int y)
 : BC_CheckBox(x, y, plugin->config.automatic, _("Automatic"))
{
	this->plugin = plugin;
}

int HistogramAuto::handle_event()
{
	plugin->config.automatic = get_value();
	plugin->send_configure_change();
	return 1;
}




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

int HistogramPlot::handle_event()
{
	plugin->config.plot = get_value();
	plugin->send_configure_change();
	return 1;
}




HistogramSplit::HistogramSplit(HistogramMain *plugin, 
	int x, 
	int y)
 : BC_CheckBox(x, y, plugin->config.split, _("Split output"))
{
	this->plugin = plugin;
}

int HistogramSplit::handle_event()
{
	plugin->config.split = get_value();
	plugin->send_configure_change();
	return 1;
}



HistogramMode::HistogramMode(HistogramMain *plugin, 
	int x, 
	int y,
	int value,
	char *text)
 : BC_Radial(x, y, plugin->mode == value, text)
{
	this->plugin = plugin;
	this->value = value;
}
int HistogramMode::handle_event()
{
	HistogramWindow *gui = (HistogramWindow*)plugin->thread->window;
	plugin->mode = value;
	plugin->current_point= -1;
	gui->active_value = 0;
	gui->low_input_carrot->BC_Toggle::update(0);
	gui->gamma_carrot->BC_Toggle::update(0);
	gui->high_input_carrot->BC_Toggle::update(0);
	gui->low_output_carrot->BC_Toggle::update(0);
	gui->high_output_carrot->BC_Toggle::update(0);
	gui->update(1, 1, 1, 1);
//	plugin->send_configure_change();
	return 1;
}










HistogramText::HistogramText(HistogramMain *plugin,
	HistogramWindow *gui,
	int x,
	int y)
 : BC_TumbleTextBox(gui, 
		0.0,
		(float)MIN_INPUT,
		(float)MAX_INPUT,
		x, 
		y, 
		DP(70))
{
	this->plugin = plugin;
	this->gui = gui;
	set_precision(DIGITS);
	set_increment(PRECISION);
}

float* HistogramText::get_value()
{
	if(this == gui->low_input)
	{
		return &plugin->config.low_input[plugin->mode];
	}
	else
	if(this == gui->high_input)
	{
		return &plugin->config.high_input[plugin->mode];
	}
	else
	if(this == gui->gamma)
	{
		return &plugin->config.gamma[plugin->mode];
	}
	else
	if(this == gui->low_output)
	{
		return &plugin->config.low_output[plugin->mode];
	}
	else
	if(this == gui->high_output)
	{
		return &plugin->config.high_output[plugin->mode];
	}
	else
	if(this == gui->threshold)
	{
		return &plugin->config.threshold;
	}
	
	return 0;
}

int HistogramText::handle_event()
{
	float *output = get_value();
	if(output)
	{
		*output = atof(get_text());
	}

	gui->update(1, 1, 0, 0);
	plugin->send_configure_change();
	return 1;
}

void HistogramText::update()
{
	float *output = get_value();
	if(output)
	{
		BC_TumbleTextBox::update(*output);
	}
}















