text: /*
   * Dialogue to increase map size.
   *
   * Gerd Wachsmuth
   *
   * October 2008
   */
  
  #include <string.h>
  
  #include "enlarge_map_frame_t.h"
  #include "minimap.h"
  #include "welt.h"
  #include "components/gui_divider.h"
  
  #include "../simdebug.h"
  #include "../simworld.h"
  #include "simwin.h"
  #include "../display/simimg.h"
  
  #include "../dataobj/settings.h"
  #include "../dataobj/translator.h"
  
  #include "../simcolor.h"
  
  #include "../display/simgraph.h"
  
  #include "../utils/simrandom.h"
  
  
  koord enlarge_map_frame_t::koord_from_rotation(settings_t const* const sets, sint16 const x, sint16 const y, sint16 const w, sint16 const h)
  {
  	koord offset( sets->get_origin_x(), sets->get_origin_y() );
  	switch( sets->get_rotation() ) {
  		default:
  		case 0: return offset+koord(x,y);
  		case 1: return offset+koord(y,w-x);
  		case 2: return offset+koord(w-x,h-y);
  		case 3: return offset+koord(h-y,x);
  	}
  }
  
  
  enlarge_map_frame_t::enlarge_map_frame_t() :
  	gui_frame_t( translator::translate("enlarge map") ),
  	sets(new settings_t(welt->get_settings())), // Make a copy.
  	map(MAP_PREVIEW_SIZE_X-2, MAP_PREVIEW_SIZE_Y-2)
  {
  	sets->set_size_x(welt->get_size().x);
  	sets->set_size_y(welt->get_size().y);
  
  	changed_number_of_towns = false;
  
  	// Component creation
  	set_table_layout(1,0);
  	// top part: preview, maps size
  	add_table(2,1);
  	{
  		// input fields
  		add_table(2,2);
  		{
  			// map seed number label
  			map_number_label.init();
  			map_number_label.buf().printf(translator::translate("Map number: %d"), welt->get_settings().get_map_number());
  			map_number_label.update();
  			add_component(&map_number_label);
  
  			// Map X size edit
  			inp_x_size.init( sets->get_size_x(), welt->get_size().x, 32766, sets->get_size_x()>=512 ? 128 : 64, false );
  			inp_x_size.add_listener(this);
  			add_component( &inp_x_size );
  
  			// Map size label
  			size_label.init();
  			size_label.buf().printf(translator::translate("Size (%d MB):"), 9999);
  			size_label.update();
  			add_component( &size_label );
  
  			// Map size Y edit
  			inp_y_size.init( sets->get_size_y(), sets->get_size_y(), 32766, sets->get_size_y()>=512 ? 128 : 64, false );
  			inp_y_size.add_listener(this);
  			add_component( &inp_y_size );
  		}
  		end_table();
  
  		// Map preview (will be initialized in update_preview
  		add_component( &map_preview );
  	}
  	end_table();
  
  	// specify map parameters
  	add_table(2,0);
  	{
  		// Number of towns
  		new_component<gui_label_t>("5WORLD_CHOOSE");
  		inp_number_of_towns.add_listener(this);
  		inp_number_of_towns.init(abs(sets->get_city_count()), 0, 999);
  		add_component( &inp_number_of_towns );
  
  		// Town size
  		new_component<gui_label_t>("Median Citizen per town");
  		inp_town_size.add_listener(this);
  		inp_town_size.set_limits(0,999999);
  		inp_town_size.set_increment_mode(50);
  		inp_town_size.set_value( sets->get_mean_citizen_count() );
  		add_component( &inp_town_size );
  	}
  	end_table();
  
  	new_component<gui_divider_t>();
  
  	// start game
  	start_button.init( button_t::roundbox | button_t::flexible, "enlarge map");
  	start_button.add_listener( this );
  	add_component( &start_button );
  
  	welt_gui_t::update_memory(&size_label, sets);
  	update_preview();
  
  	reset_min_windowsize();
  	set_windowsize(get_min_windowsize());
  }
  
  
  enlarge_map_frame_t::~enlarge_map_frame_t()
  {
  	delete sets;
  }
  
  
  /**
   * This method is called if an action is triggered
   * @author Hj. Malthaner
   */
  bool enlarge_map_frame_t::action_triggered( gui_action_creator_t *comp,value_t v)
  {
  	if(comp==&inp_x_size) {
  		sets->set_size_x( v.i );
  		inp_x_size.set_increment_mode( v.i>=64 ? (v.i>=512 ? 128 : 64) : 8 );
  		update_preview();
  	}
  	else if(comp==&inp_y_size) {
  		sets->set_size_y( v.i );
  		inp_y_size.set_increment_mode( v.i>=64 ? (v.i>=512 ? 128 : 64) : 8 );
  		update_preview();
  	}
  	else if(comp==&inp_number_of_towns) {
  		sets->set_city_count( v.i );
  	}
  	else if(comp==&inp_town_size) {
  		sets->set_mean_citizen_count( v.i );
  	}
  	else if(comp==&start_button) {
  		destroy_all_win( true );
  		welt->enlarge_map(sets, NULL);
  	}
  	else {
  		return false;
  	}
  	return true;
  }
  
  
  void enlarge_map_frame_t::draw(scr_coord pos, scr_size size)
  {
  	while (welt->get_settings().get_rotation() != sets->get_rotation()) {
  		// map was rotated while we are active ... => rotate too!
  		sets->rotate90();
  		sets->set_size( sets->get_size_y(), sets->get_size_x() );
  		update_preview();
  	}
  
  	gui_frame_t::draw(pos, size);
  }
  
  
  /**
   * Calculate the new Map-Preview. Initialize the new RNG!
   * @author Hj. Malthaner
   */
  void enlarge_map_frame_t::update_preview()
  {
  	// reset noise seed
  	setsimrand(0xFFFFFFFF, welt->get_settings().get_map_number());
  
  	// "welt" still knows the old size. The new size is saved in "sets".
  	uint16 old_x = welt->get_size().x;
  	uint16 old_y = welt->get_size().y;
  	uint16 pre_x = min(sets->get_size_x(), map.get_width());
  	uint16 pre_y = min(sets->get_size_y(), map.get_height());
  
  	const int mx = sets->get_size_x()/pre_x;
  	const int my = sets->get_size_y()/pre_y;
  
  	for(  int j=0;  j<pre_y;  j++  ) {
  		for(  int i=0;  i<pre_x;  i++  ) {
  			PIXVAL color;
  			koord pos(i*mx,j*my);
  
  			if(  pos.x<=old_x  &&  pos.y<=old_y  ){
  				if(  i==(old_x/mx)  ||  j==(old_y/my)  ){
  					// border
  					color = color_idx_to_rgb(COL_WHITE);
  				}
  				else {
  					const sint16 height = welt->lookup_hgt( pos );
  					color = minimap_t::calc_height_color(height, sets->get_groundwater());
  				}
  			}
  			else {
  				// new part
  				const sint16 height = karte_t::perlin_hoehe(sets, pos, koord(old_x,old_y) );
  				color = minimap_t::calc_height_color(height, sets->get_groundwater());
  			}
  			map.at(i,j) = color;
  		}
  	}
  	for(  uint j=0;  j<map.get_height();  j++  ) {
  		for(  uint i=(j<pre_y ? pre_x : 0);  i<map.get_width();   i++  ) {
  			map.at(i,j) = color_idx_to_rgb(COL_GREY1);
  		}
  	}
  	map_preview.set_map_data(&map);
  
  	sets->heightfield = "";
  
  	if(!changed_number_of_towns){// Interpolate number of towns.
  		sint32 new_area = sets->get_size_x() * sets->get_size_y();
  		sint32 old_area = old_x * old_y;
  		sint32 const towns = welt->get_settings().get_city_count();
  		sets->set_city_count( towns * new_area / old_area - towns );
  		inp_number_of_towns.set_value(abs(sets->get_city_count()) );
  	}
  
  	// guess the new memory needed
  	welt_gui_t::update_memory(&size_label, sets);
  }
  