
/*
 * CINELERRA
 * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
 * Copyright (C) 2003-2016 Cinelerra CV contributors
 *
 * 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 "clip.h"
#include "cwindow.h"
#include "cwindowgui.h"
#include "datatype.h"
#include "bchash.h"
#include "edl.h"
#include "edlsession.h"
#include "formatpresets.h"
#include "language.h"
#include "levelwindow.h"
#include "levelwindowgui.h"
#include "mainerror.h"
#include "mainundo.h"
#include "mutex.h"
#include "mwindow.h"
#include "mwindowgui.h"
#include "new.h"
#include "preferences.h"
#include "rotateframe.h"
#include "setformat.h"
#include "theme.h"
#include "vframe.h"
#include "vwindow.h"
#include "vwindowgui.h"



SetFormat::SetFormat(MWindow *mwindow)
 : BC_MenuItem(_("Format..."), _("Shift-F"), 'F')
{
	set_shift(1);
	this->mwindow = mwindow;
	thread = new SetFormatThread(mwindow);
}

SetFormat::~SetFormat()
{
	delete thread;
}

int SetFormat::handle_event()
{
	if(!thread->running())
	{
		thread->start();
	}
	else
	{
// window_lock has to be locked but window can't be locked until after
// it is known to exist, so we neglect window_lock for now
		if(thread->window)
		{
			thread->window_lock->lock("SetFormat::handle_event");
			thread->window->lock_window("SetFormat::handle_event");
			thread->window->raise_window();
			thread->window->unlock_window();
			thread->window_lock->unlock();
		}
	}
	return 1;
}

SetFormatThread::SetFormatThread(MWindow *mwindow)
 : Thread(1, 0, 0)
{
	this->mwindow = mwindow;
	window_lock = new Mutex("SetFormatThread::window_lock");
	window = 0;
}

SetFormatThread::~SetFormatThread()
{
	if( running() ) {
		window->set_done(1);
		cancel();
	}
	join();
	delete window_lock;
}

void SetFormatThread::run()
{
	orig_dimension[0] = dimension[0] = mwindow->edl->session->output_w;
	orig_dimension[1] = dimension[1] = mwindow->edl->session->output_h;
	auto_aspect = mwindow->defaults->get("AUTOASPECT", 0);
	constrain_ratio = 0;
	ratio[0] = ratio[1] = 1;

	new_settings = new EDL;
	new_settings->create_objects();
	new_settings->copy_session(mwindow->edl);

// This locks mwindow, so it must be done outside window_lock
 	int x = mwindow->gui->get_abs_cursor_x(1) - mwindow->theme->setformat_w / 2;
	int y = mwindow->gui->get_abs_cursor_y(1) - mwindow->theme->setformat_h / 2;

	window_lock->lock("SetFormatThread::run 1");
	window = new SetFormatWindow(mwindow, this, x, y);
	window->create_objects();
	window_lock->unlock();

	int result = window->run_window();


	window_lock->lock("SetFormatThread::run 2");
	delete window;
	window = 0;
	window_lock->unlock();


	if(!result)
	{
		apply_changes();
	}

	mwindow->defaults->update("AUTOASPECT", auto_aspect);
	new_settings->Garbage::remove_user();
}

void SetFormatThread::apply_changes()
{
	double new_samplerate = new_settings->session->sample_rate;
	double old_samplerate = mwindow->edl->session->sample_rate;
	double new_framerate = new_settings->session->frame_rate;
	double old_framerate = mwindow->edl->session->frame_rate;
	int new_channels = new_settings->session->audio_channels;
	CLAMP(new_channels, 1, MAXCHANNELS);



	mwindow->undo->update_undo_before();

	memcpy(&mwindow->preferences->channel_positions[new_channels - 1],
		new_settings->session->achannel_positions,
		sizeof(mwindow->preferences->channel_positions[new_channels - 1]));


	mwindow->edl->copy_session(new_settings, 1);
	mwindow->edl->session->output_w = dimension[0];
	mwindow->edl->session->output_h = dimension[1];
	mwindow->edl->retrack();
	mwindow->edl->rechannel();
	mwindow->edl->resample(old_samplerate, new_samplerate, TRACK_AUDIO);
	mwindow->edl->resample(old_framerate, new_framerate, TRACK_VIDEO);
	mwindow->save_backup();
	mwindow->undo->update_undo_after(_("set format"), LOAD_ALL);

	mwindow->resync_guis();
}

void SetFormatThread::update()
{
	window->sample_rate->update(new_settings->session->sample_rate);
	window->channels->update((int64_t)new_settings->session->audio_channels);
	window->frame_rate->update((float)new_settings->session->frame_rate);

	auto_aspect = 0;
	window->auto_aspect->update(0);

	constrain_ratio = 0;
	dimension[0] = new_settings->session->output_w;
	window->dimension[0]->update((int64_t)dimension[0]);
	dimension[1] = new_settings->session->output_h;
	window->dimension[1]->update((int64_t)dimension[1]);

	ratio[0] = (float)dimension[0] / orig_dimension[0];
	window->ratio[0]->update(ratio[0]);
	ratio[1] = (float)dimension[1] / orig_dimension[1];
	window->ratio[1]->update(ratio[1]);

	window->aspect_w->update(new_settings->session->aspect_w);
	window->aspect_h->update(new_settings->session->aspect_h);
	window->interlace_pulldown->update(new_settings->session->interlace_mode);
	window->color_model->update_value(new_settings->session->color_model);

	window->canvas->draw();
}

void SetFormatThread::update_window()
{
	int i, result, modified_item = 0, dimension_modified = 0, ratio_modified = 0;

	for(i = 0, result = 0; i < 2 && !result; i++)
	{
		if(dimension[i] < 0)
		{
			dimension[i] *= -1;
			result = 1;
			modified_item = i;
			dimension_modified = 1;
		}
		if(ratio[i] < 0)
		{
			ratio[i] *= -1;
			result = 1;
			modified_item = i;
			ratio_modified = 1;
		}
	}

	if(result)
	{
		if(dimension_modified)
			ratio[modified_item] = (float)dimension[modified_item] / orig_dimension[modified_item];

		if(ratio_modified && !constrain_ratio)
		{
			dimension[modified_item] = (int)(orig_dimension[modified_item] * ratio[modified_item]);
			window->dimension[modified_item]->update((int64_t)dimension[modified_item]);
		}

		for(i = 0; i < 2; i++)
		{
			if(dimension_modified ||
				(i != modified_item && ratio_modified))
			{
				if(constrain_ratio) ratio[i] = ratio[modified_item];
				window->ratio[i]->update(ratio[i]);
			}

			if(ratio_modified ||
				(i != modified_item && dimension_modified))
			{
				if(constrain_ratio)
				{
					dimension[i] = (int)(orig_dimension[i] * ratio[modified_item]);
					window->dimension[i]->update((int64_t)dimension[i]);
				}
			}
		}
	}

	update_aspect();
}

void SetFormatThread::update_aspect()
{
	if(auto_aspect)
	{
		char string[BCTEXTLEN];
		MWindow::create_aspect_ratio(new_settings->session->aspect_w,
			new_settings->session->aspect_h,
			dimension[0],
			dimension[1]);
		sprintf(string, "%.02f", new_settings->session->aspect_w);
		window->aspect_w->update(string);
		sprintf(string, "%.02f", new_settings->session->aspect_h);
		window->aspect_h->update(string);
	}
}


SetFormatWindow::SetFormatWindow(MWindow *mwindow,
	SetFormatThread *thread, int x, int y)
 : BC_Window(_(PROGRAM_NAME ": Set Format"), x, y,
	mwindow->theme->setformat_w, mwindow->theme->setformat_h,
	-1, -1, 0, 0, 1)
{
	this->mwindow = mwindow;
	this->thread = thread;
	presets = 0;
// *** CONTEXT_HELP ***
	context_help_set_keyword("Project and Media Attributes");
}
SetFormatWindow::~SetFormatWindow()
{
	delete presets;
}

/* W Ratio, H Ratio
Sets the ratio of the new canvas size (W, H) to the old (previous) canvas size (W, H). 
The new canvas size is recalculated based upon a certain factor in the W Ratio, 
H Ratio fields. A practical use-case: The current resolution is 640x480, and for some reason 
you want it to be 1.33 times wider. You don't have to calculate what 640x1.33 is; 
you type 1.33 into the "W" input instead, and Cinelerra calculates it for you. */

void SetFormatWindow::create_objects()
{
	lock_window("SetFormatWindow::create_objects");
	int x = xS(10), y = mwindow->theme->setformat_y1;
	BC_TextBox *textbox;
	BC_Title *title;
	mwindow->theme->draw_setformat_bg(this);

	presets = new SetFormatPresets(mwindow, this, x, y);
	presets->create_objects();
	x = presets->x; //  y = presets->y;
	y = mwindow->theme->setformat_y2;

	add_subwindow(new BC_Title(mwindow->theme->setformat_x1, y,
		_("Audio"), LARGEFONT));
	y = mwindow->theme->setformat_y3;

	add_subwindow(new BC_Title(mwindow->theme->setformat_x1, y,
		_("Samplerate:")));
	add_subwindow(sample_rate = new SetSampleRateTextBox(thread,
		mwindow->theme->setformat_x2,
		y));
	add_subwindow(new SampleRatePulldown(mwindow, sample_rate,
		mwindow->theme->setformat_x2 + sample_rate->get_w(), y));

	y += mwindow->theme->setformat_margin;
	add_subwindow(new BC_Title(mwindow->theme->setformat_x1, y,
		_("Channels:")));
	add_subwindow(channels = new SetChannelsTextBox(thread,
		mwindow->theme->setformat_x2, y));
	add_subwindow(new BC_ITumbler(channels, 0, MAXCHANNELS,
		mwindow->theme->setformat_x2 + channels->get_w(), y));

	y += mwindow->theme->setformat_margin;
	add_subwindow(new BC_Title(mwindow->theme->setformat_x1, y,
		_("Channel positions:")));
	y += mwindow->theme->setformat_margin;
	add_subwindow(channels_reset = new SetChannelsReset(thread,
		mwindow->theme->setformat_x1, y,
		_("Reset")));
	add_subwindow(canvas = new SetChannelsCanvas(mwindow,
		thread,
		mwindow->theme->setformat_channels_x,
		mwindow->theme->setformat_channels_y,
		mwindow->theme->setformat_channels_w,
		mwindow->theme->setformat_channels_h));
	canvas->draw();



	y = mwindow->theme->setformat_y2;
	add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
		y,
		_("Video"),
		LARGEFONT));

	y = mwindow->theme->setformat_y3;
	add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
		y,
		_("Frame rate:")));
	add_subwindow(frame_rate = new SetFrameRateTextBox(thread,
		mwindow->theme->setformat_x4,
		y));
	add_subwindow(new FrameRatePulldown(mwindow,
		frame_rate,
		mwindow->theme->setformat_x4 + frame_rate->get_w(),
		y));

	y += mwindow->theme->setformat_margin;
	add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
		y,
		_("Canvas size:")));

	y += mwindow->theme->setformat_margin;
	add_subwindow(title = new BC_Title(mwindow->theme->setformat_x3, y, _("Width:")));
	add_subwindow(dimension[0] = new ScaleSizeText(mwindow->theme->setformat_x4,
		y,
		thread,
		&(thread->dimension[0])));

	y += mwindow->theme->setformat_margin;
	add_subwindow(new BC_Title(mwindow->theme->setformat_x3, y, _("Height:")));
	add_subwindow(dimension[1] = new ScaleSizeText(mwindow->theme->setformat_x4,
		y,
		thread,
		&(thread->dimension[1])));

	x = mwindow->theme->setformat_x4 + dimension[0]->get_w();
	FrameSizePulldown *pulldown;
	add_subwindow(pulldown = new FrameSizePulldown(mwindow->theme,
		dimension[0],
		dimension[1],
		x,
		y - mwindow->theme->setformat_margin));

	add_subwindow(new FormatSwapExtents(mwindow,
		thread,
		this,
		x + pulldown->get_w() + 5,
		y - mwindow->theme->setformat_margin));

	y += mwindow->theme->setformat_margin;
	add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
		y,
		_("W Ratio:")));
	add_subwindow(ratio[0] = new ScaleRatioText(mwindow->theme->setformat_x4,
		y,
		thread,
		&(thread->ratio[0])));

	y += mwindow->theme->setformat_margin;
	add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
		y,
		_("H Ratio:")));
	add_subwindow(ratio[1] = new ScaleRatioText(mwindow->theme->setformat_x4,
		y,
		thread,
		&(thread->ratio[1])));

	y += mwindow->theme->setformat_margin;
	add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
		y,
		_("Color model:")));
	x = mwindow->theme->setformat_x4;
	add_subwindow(textbox = new BC_TextBox(x, y, xS(100), 1, ""));
	x += textbox->get_w();
	add_subwindow(color_model = new ColormodelPulldown(mwindow, textbox,
		&thread->new_settings->session->color_model, x, y));

	y += mwindow->theme->setformat_margin;
	add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
		y,
		_("Display Aspect ratio:")));
	y += mwindow->theme->setformat_margin;
	x = mwindow->theme->setformat_x3;
	add_subwindow(aspect_w = new ScaleAspectText(x, y, thread,
		&(thread->new_settings->session->aspect_w)));
	x += aspect_w->get_w() + xS(5);
	add_subwindow(new BC_Title(x, y, ":"));
	x += xS(10);
	add_subwindow(aspect_h = new ScaleAspectText(x,
		y,
		thread,
		&(thread->new_settings->session->aspect_h)));
	x += aspect_h->get_w();
	add_subwindow(new AspectPulldown(mwindow,
		aspect_w,
		aspect_h,
		x,
		y));
	x += xS(30);
	add_subwindow(auto_aspect = new ScaleAspectAuto(x, y, thread));
	y += mwindow->theme->setformat_margin;

	// --------------------
	add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
		y,
		_("Interlace mode:")));
	add_subwindow(textbox = new BC_TextBox(mwindow->theme->setformat_x4, y,
		xS(140), 1, ""));
	add_subwindow(interlace_pulldown = new InterlacemodePulldown(mwindow,
		textbox, &(thread->new_settings->session->interlace_mode),
		(ArrayList<BC_ListBoxItem*>*)&mwindow->interlace_project_modes,
		mwindow->theme->setformat_x4 + textbox->get_w(), y));
	y += mwindow->theme->setformat_margin;
	
	add_subwindow(new BC_Title(mwindow->theme->setformat_x3,
               y+10,
               _("Note: W/H ratio fields means multipliers \nrelative to previous canvas size \n")));

	BC_OKTextButton *ok;
	BC_CancelTextButton *cancel;
	add_subwindow(ok = new BC_OKTextButton(this));
	add_subwindow(cancel = new BC_CancelTextButton(this));
	add_subwindow(new SetFormatApply((ok->get_x() + cancel->get_x()) / 2,
		ok->get_y(), thread));
	flash();
	show_window();
	unlock_window();
}

const char* SetFormatWindow::get_preset_text()
{
	return "";
}


SetFormatPresets::SetFormatPresets(MWindow *mwindow,
	SetFormatWindow *gui,
	int x,
	int y)
 : FormatPresets(mwindow, 0, gui, x, y)
{

}

SetFormatPresets::~SetFormatPresets()
{
}

int SetFormatPresets::handle_event()
{
	format_gui->thread->update();
	return format_gui->channels_reset->handle_event();
}

EDL* SetFormatPresets::get_edl()
{
	return format_gui->thread->new_settings;
}



SetSampleRateTextBox::SetSampleRateTextBox(SetFormatThread *thread, int x, int y)
 : BC_TextBox(x, y, xS(100), 1, (int64_t)thread->new_settings->session->sample_rate)
{
	this->thread = thread;
}
int SetSampleRateTextBox::handle_event()
{
	thread->new_settings->session->sample_rate = CLIP(atol(get_text()), 1, 1000000);
	return 1;
}

SetChannelsTextBox::SetChannelsTextBox(SetFormatThread *thread, int x, int y)
 : BC_TextBox(x, y, xS(100), 1, thread->new_settings->session->audio_channels)
{
	this->thread = thread;
}
int SetChannelsTextBox::handle_event()
{
	int new_channels = CLIP(atoi(get_text()), 0, MAXCHANNELS);
	thread->new_settings->session->audio_channels = new_channels;
	if(new_channels > 0) {
		memcpy(thread->new_settings->session->achannel_positions,
			&thread->mwindow->preferences->channel_positions[new_channels - 1],
			sizeof(thread->new_settings->session->achannel_positions));
	}

	thread->window->canvas->draw();
	return 1;
}

SetChannelsReset::SetChannelsReset(SetFormatThread *thread, int x, int y, const char *text)
 : BC_GenericButton(x, y, text)
{
	this->thread = thread;
}

int SetChannelsReset::handle_event()
{
	int channels = thread->new_settings->session->audio_channels;
	int *achannels = thread->new_settings->session->achannel_positions;
	for( int i=0; i<MAX_CHANNELS; ++i )
		achannels[i] = default_audio_channel_position(i, channels);
	thread->window->canvas->draw();
	return 1;
}

SetChannelsCanvas::SetChannelsCanvas(MWindow *mwindow,
	SetFormatThread *thread, int x, int y, int w, int h)
 : BC_SubWindow(x, y, w, h)
{
	this->thread = thread;
	this->mwindow = mwindow;
	active_channel = -1;
	box_r = mwindow->theme->channel_position_data->get_w() / 2;
	temp_picon = new VFrame(
		mwindow->theme->channel_position_data->get_w(),
		mwindow->theme->channel_position_data->get_h(),
		mwindow->theme->channel_position_data->get_color_model(),
		0);
	rotater = new RotateFrame(mwindow->preferences->processors,
		mwindow->theme->channel_position_data->get_w(),
		mwindow->theme->channel_position_data->get_h());
}
SetChannelsCanvas::~SetChannelsCanvas()
{
	delete temp_picon;
	delete rotater;
}

int SetChannelsCanvas::draw(int angle)
{
	set_color(RED);
	//int real_w = get_w() - box_r * 2;
	//int real_h = get_h() - box_r * 2;
	//int real_x = box_r;
	//int real_y = box_r;

	draw_top_background(get_top_level(), 0, 0, get_w(), get_h());
//	draw_vframe(mwindow->theme->channel_bg_data, 0, 0);




	int x, y, w, h;
	char string[32];
	set_color(mwindow->theme->channel_position_color);
	for(int i = 0; i < thread->new_settings->session->audio_channels; i++)
	{
		get_dimensions(thread->new_settings->session->achannel_positions[i],
			x, y, w, h);
		double rotate_angle = thread->new_settings->session->achannel_positions[i];
		rotate_angle = -rotate_angle;
		while(rotate_angle < 0) rotate_angle += 360;
		rotater->rotate(temp_picon,
			mwindow->theme->channel_position_data,
			rotate_angle,
			0);

		BC_Pixmap temp_pixmap(this,
			temp_picon,
			PIXMAP_ALPHA,
			0);
		draw_pixmap(&temp_pixmap, x, y);
		sprintf(string, "%d", i + 1);
		draw_text(x + 2, y + box_r * 2 - 2, string);
	}

	if(angle > -1)
	{
		sprintf(string, _("%d degrees"), angle);
		draw_text(this->get_w() / 2 - 40, this->get_h() / 2, string);
	}

	flash();
	return 0;
}

int SetChannelsCanvas::get_dimensions(int channel_position,
		int &x, int &y, int &w, int &h)
{
	int xs10 = xS(10), ys10 = yS(10);
	int real_w = this->get_w() - box_r * 2 - xs10;
	int real_h = this->get_h() - box_r * 2 - ys10;
	float corrected_position = channel_position;
	if(corrected_position < 0) corrected_position += 360;
	Units::polar_to_xy((float)corrected_position, real_w / 2, x, y);
	x += real_w / 2 + xs10 / 2;
	y += real_h / 2 + ys10 / 2;
	w = box_r * 2;
	h = box_r * 2;
	return 0;
}

int SetChannelsCanvas::button_press_event()
{
	if(!cursor_inside()) return 0;
// get active channel
	for( int i = 0; i < thread->new_settings->session->audio_channels; i++ ) {
		int x, y, w, h;
		get_dimensions(thread->new_settings->session->achannel_positions[i], x, y, w, h);
		if( get_cursor_x() > x && get_cursor_y() > y &&
		    get_cursor_x() < x + w && get_cursor_y() < y + h ) {
			active_channel = i;
			degree_offset = (int)Units::xy_to_polar(get_cursor_x() - this->get_w() / 2, get_cursor_y() - this->get_h() / 2);
			degree_offset += 90;
			if(degree_offset >= 360) degree_offset -= 360;
			degree_offset -= thread->new_settings->session->achannel_positions[i];
			draw(thread->new_settings->session->achannel_positions[i]);
			return 1;
		}
	}
	return 0;
}

int SetChannelsCanvas::button_release_event()
{
	if(active_channel >= 0)
	{
		active_channel = -1;
		draw(-1);
		return 1;
	}
	return 0;
}

int SetChannelsCanvas::cursor_motion_event()
{
	if(active_channel >= 0)
	{
// get degrees of new channel
		int new_d;
		new_d = (int)Units::xy_to_polar(get_cursor_x() - this->get_w() / 2, get_cursor_y() - this->get_h() / 2);
		new_d += 90;
		new_d -= degree_offset;

		while(new_d >= 360) new_d -= 360;
		while(new_d < 0) new_d += 360;

		if(thread->new_settings->session->achannel_positions[active_channel] != new_d)
		{
			thread->new_settings->session->achannel_positions[active_channel] = new_d;
			int new_channels = thread->new_settings->session->audio_channels;
			memcpy(&thread->mwindow->preferences->channel_positions[new_channels - 1],
				thread->new_settings->session->achannel_positions,
				sizeof(thread->mwindow->preferences->channel_positions[new_channels - 1]));
			draw(thread->new_settings->session->achannel_positions[active_channel]);
		}
		return 1;
	}
	return 0;
}


SetFrameRateTextBox::SetFrameRateTextBox(SetFormatThread *thread, int x, int y)
 : BC_TextBox(x, y, xS(100), 1, (float)thread->new_settings->session->frame_rate)
{
	this->thread = thread;
}

int SetFrameRateTextBox::handle_event()
{
	thread->new_settings->session->frame_rate = Units::atoframerate(get_text());
	return 1;
}


//
// SetVChannels::SetVChannels(SetFormatThread *thread, int x, int y)
//  : BC_TextBox(x, y, xS(100), 1, thread->channels)
// {
// 	this->thread = thread;
// }
// int SetVChannels::handle_event()
// {
// 	thread->channels = atol(get_text());
// 	return 1;
// }




ScaleSizeText::ScaleSizeText(int x, int y, SetFormatThread *thread, int *output)
 : BC_TextBox(x, y, xS(100), 1, *output)
{
	this->thread = thread;
	this->output = output;
}
ScaleSizeText::~ScaleSizeText()
{
}
int ScaleSizeText::handle_event()
{
	*output = atol(get_text());
	*output /= 2;  *output *= 2;
	if(*output <= 0) *output = 2;
	if(*output > 10000) *output = 10000;
	*output *= -1;
	thread->update_window();
	return 1;
}



ScaleRatioText::ScaleRatioText(int x,
	int y,
	SetFormatThread *thread,
	float *output)
 : BC_TextBox(x, y, xS(100), 1, *output)
{
	this->thread = thread;
	this->output = output;
}
ScaleRatioText::~ScaleRatioText()
{
}
int ScaleRatioText::handle_event()
{
	*output = atof(get_text());
	//if(*output <= 0) *output = 1;
	if(*output > 10000) *output = 10000;
	if(*output < -10000) *output = -10000;
	*output *= -1;
	thread->update_window();
	return 1;
}


ScaleAspectAuto::ScaleAspectAuto(int x, int y, SetFormatThread *thread)
 : BC_CheckBox(x, y, thread->auto_aspect, _("Auto"))
{
	this->thread = thread;
}

ScaleAspectAuto::~ScaleAspectAuto()
{
}

int ScaleAspectAuto::handle_event()
{
	thread->auto_aspect = get_value();
	thread->update_aspect();
	return 1;
}

ScaleAspectText::ScaleAspectText(int x, int y, SetFormatThread *thread, float *output)
 : BC_TextBox(x, y, xS(70), 1, *output)
{
	this->output = output;
	this->thread = thread;
}
ScaleAspectText::~ScaleAspectText()
{
}

int ScaleAspectText::handle_event()
{
	*output = atof(get_text());
	return 1;
}


SetFormatApply::SetFormatApply(int x, int y, SetFormatThread *thread)
 : BC_GenericButton(x, y, _("Apply"))
{
	this->thread = thread;
}

int SetFormatApply::handle_event()
{
	thread->apply_changes();
	return 1;
}


FormatSwapExtents::FormatSwapExtents(MWindow *mwindow,
	SetFormatThread *thread,
	SetFormatWindow *gui,
	int x,
	int y)
 : BC_Button(x, y, mwindow->theme->get_image_set("swap_extents"))
{
	this->mwindow = mwindow;
	this->thread = thread;
	this->gui = gui;
	set_tooltip(_("Swap dimensions"));
}

int FormatSwapExtents::handle_event()
{
	int w = thread->dimension[0];
	int h = thread->dimension[1];
	thread->dimension[0] = -h;
	gui->dimension[0]->update((int64_t)h);
	gui->dimension[1]->update((int64_t)w);
	thread->update_window();
	thread->dimension[1] = -w;
	thread->update_window();
	return 1;
}

