unit CevoMapMain;

{***********************************************************

Project:    C-evo External Map Generator
Copyright:  1999-2024 P Blackman
License:    GPLv3+

Code for main interface form.

***********************************************************}

interface

uses
    LCLIntf, LCLType, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    StdCtrls, ExtCtrls, Spin, ComCtrls, Buttons, CevoMapFile, LCLTranslator;

type

    { TFrmInterface }

    TFrmInterface = class(TForm)
        BtnLoadTemplate:       TButton;
        BtnSaveTemplate:       TButton;
        Image1:                TImage;
        LabelNSR1:             TLabel;
        LabelNSR2:             TLabel;
        LabelEmail:            TLabel;
        LblResource:           TLabel;
        LabelLnd:              TLabel;
        LabelSmooth:           TLabel;
        LblBias:               TLabel;
        LblGain:               TLabel;
        PnlResource:           TPanel;
        PnlTemp:               TPanel;
        RG_Resource:            TRadioGroup;
        SaveDialog1:           TSaveDialog;
        SaveDialog2:           TSaveDialog;
        OpenDialog1:           TOpenDialog;
        OpenDialog2:           TOpenDialog;
        PanelMain:             TPanel;
        PageControl1:          TPageControl;
        SE_Resource:            TSpinEdit;
        TS_FileControl:        TTabSheet;
        TS_LandMass:           TTabSheet;
        TS_Weather:            TTabSheet;
        PanelStats:            TPanel;
        LabelStatsOcean:       TLabel;
        LabelStatsMountain:    TLabel;
        LabelStatsGrass:       TLabel;
        LabelStatsDesert:      TLabel;
        LabelStatsHill:        TLabel;
        LabelStatsForest:      TLabel;
        LabelStatsPrairie:     TLabel;
        LabelStatsSwamp:       TLabel;
        LabelStatsTundra:      TLabel;
        LabelStatsGlacier:     TLabel;
        LabelStatsRiver:       TLabel;
        EditStatsOcean:        TEdit;
        EditStatsMountain:     TEdit;
        EditStatsGrass:        TEdit;
        EditStatsDesert:       TEdit;
        EditStatsHill:         TEdit;
        EditStatsForest:       TEdit;
        EditStatsSwamp:        TEdit;
        EditStatsPrairie:      TEdit;
        EditStatsTundra:       TEdit;
        EditStatsGlacier:      TEdit;
        EditStatsRiver:        TEdit;
        PanelBodies:           TPanel;
        PanelMapShape:         TPanel;
        RG_LandMass:           TRadioGroup;
        PanelOceanLevel:       TPanel;
        LabelSeaLevel:         TLabel;
        SE_OceanLevel:         TSpinEdit;
        RG_Mountains:          TRadioGroup;
        PnlStatus:             TPanel;
        LblStatus:             TLabel;
        RG_Size:               TRadioGroup;
        RG_Age:                TRadioGroup;
        SpinPanelSize:         TPanel;
        SpinLabelSize:         TLabel;
        SpinPanelErosion:      TPanel;
        LabelErosion:          TLabel;
        SpinDim:               TSpinEdit;
        SpinWave:              TSpinEdit;
        PanelGo:               TPanel;
        MultiLineBtn1:         TButton;
        Button1:               TButton;
        PanelSize:             TPanel;
        SpinHeight:            TSpinEdit;
        Label1:                TLabel;
        SpinWidth:             TSpinEdit;
        Label2:                TLabel;
        LabelSize:             TLabel;
        LabelArea:             TLabel;
        RG_MapSize:            TRadioGroup;
        PanelFiles:            TPanel;
        BtnSave:               TBitBtn;
        BtnLoad:               TBitBtn;
        LabelFiles:            TLabel;
        PanelCitySquares:      TPanel;
        LabelCitySquares:      TLabel;
        LabelCitySquares2:     TLabel;
        PanelLandButons:       TPanel;
        ButtonLandDefault:     TButton;
        CheckBoxRandomLand:    TCheckBox;
        PanelWeatherButtons:   TPanel;
        ButtonDefaultWeather:  TButton;
        CheckBoxRandomWeather: TCheckBox;
        PanelPoles:            TPanel;
        LabelPoles:            TLabel;
        RG_RainPoles:          TRadioGroup;
        PanelPolesRain:        TPanel;
        TabSheetAboiut:        TTabSheet;
        PanelAboutName:        TPanel;
        PanelVersion:          TPanel;
        VersionLabel1:         TLabel;
        VersionLabel2:         TLabel;
        VersionLabel3:         TLabel;
        VersionLabel4:         TLabel;
        VersionLabel5:         TLabel;
        Templates:             TTabSheet;
        TabSheetTemperature:   TTabSheet;
        PanelEquator:          TPanel;
        RG_TempEqu:            TRadioGroup;
        SpinPanelTemp:         TPanel;
        SE_EquTemp:            TSpinEdit;
        RG_RainEqu:            TRadioGroup;
        SpinPanelRain:         TPanel;
        RG_TempPoles:          TRadioGroup;
        PanelPolesTemp:        TPanel;
        SE_PolesTemp:          TSpinEdit;
        PanelTemerature2:      TPanel;
        ButtonDefaultTemp:     TButton;
        CheckBoxRandomTemp:    TCheckBox;
        PanelrainTune:         TPanel;
        PnlRivers:             TPanel;
        LabelRiver2:           TLabel;
        RG_Rivers:             TRadioGroup;
        PanelRainVarys:        TPanel;
        LabelRainVaries:       TLabel;
        SpinWaveRain:          TSpinEdit;
        Panelrainvariation:    TPanel;
        Labelrainvaryability:  TLabel;
        SpinGainRain:          TSpinEdit;
        LabelrainTune:         TLabel;
        PanelFineTemp:         TPanel;
        PanelTempVary:         TPanel;
        LabelTempSquares:      TLabel;
        SpinWaveTemp:          TSpinEdit;
        PanelTempvariability:  TPanel;
        LabelTempVariability:  TLabel;
        SpinGainTemp:          TSpinEdit;
        LabelTempMain:         TLabel;
        LabelTempFine:         TLabel;
        LabelAboutInfo:        TLabel;
        SpinPanelImageSize:    TPanel;
        SpinLabelImageSize:    TLabel;
        SpinEditImageSize:     TSpinEdit;
        LabelScroll:           TLabel;
        LabelThumbnail:        TLabel;
        LabelGen:              TLabel;
        ProgressBar1:          TProgressBar;
        SpinWater:             TSpinEdit;
        SE_RainEqu:            TSpinEdit;
        SE_PolesRain:          TSpinEdit;
        UD_Scroll:             TUpDown;
        PanelPerf:             TPanel;
        OP_Citysquares:        TPanel;
        OP_Area:               TPanel;
        LabelAuthor:           TLabel;
        PanelMountainLevel:    TPanel;
        Label5:                TLabel;
        SE_MountainLevel:      TSpinEdit;

        SpinDimTemp:           TSpinEdit;
        SpinDimRain:           TSpinEdit;
        SpinBias:              TSpinEdit;
        SpinGain:              TSpinEdit;

        procedure BtnLoadTemplateClick;
        procedure BtnSaveTemplateClick;
        procedure Button1Click;
        procedure FormCreate;
        procedure BtnSaveClick;
        procedure RG_ResourceSelectionChanged(Sender: TObject);
        procedure SE_ResourceChange(Sender: TObject);
        procedure SpinHeightChange;
        procedure SpinWidthChange;
        procedure FormResize;
        procedure MultiLineBtn1Click;
        procedure BtnLoadClick;
        procedure RG_LandMassChanged(Sender: TObject);
        procedure RG_MountainsChanged(Sender: TObject);
        procedure RG_AgeChanged(Sender: TObject);
        procedure RG_SizeChanged(Sender: TObject);
        procedure RG_TempEquatChanged(Sender: TObject);
        procedure RG_TempPolesChanged(Sender: TObject);
        procedure AdjustMapSize;
        procedure ButtonLandDefaultClick;
        procedure ButtonDefaultWeatherClick;
        procedure RG_RainPolesChanged(Sender: TObject);
        procedure RG_RainEquatChanged(Sender: TObject);
        procedure RG_RiversChanged(Sender: TObject);
        procedure SpinEditScrollChange;
        procedure SpinEditImageSizeChange;
        procedure ButtonDefaultTempClick;
        procedure UD_ScrollClick(Sender: TObject);
    private
        procedure CopyTemplates;
    protected
        ResetNoise: Boolean;

        procedure SaveTemplate        (MyFilePath : String);

        procedure LoadFile(var Mf: TMapFile; Filename: String);
        procedure DisplayStats;
        procedure ReDisplay;
        procedure RandomCheck;
        procedure DefaultLand;
        procedure DefaultRain;
        procedure DefaultTemp;
        procedure MapDefaults;
        procedure BuildMap;
        procedure ResetScrollPosition;
        procedure SetScrollEnable;
        procedure Sizes;
        procedure SpinEditHack (Var SE : TSpinEdit);
        procedure CheckResourceWarning;

    public
        procedure CheckifLoadneeded;
    end;

var
    FrmInterface: TFrmInterface;


implementation uses INIFiles, FileUtil, MapTiles, ImageForm, CevoMap, Rivers, Settings;

{$R *.lfm}

const
    Min_Map = 400;
    Lacunarity = 1.9;
    clOrange = TColor($00A5FF);

    Old_LxMax = 100;
    Old_LyMax = 96;
    OldMapMax = Old_LxMax * Old_LyMax;

var MyMap: TMap;


procedure TFrmInterface.ResetScrollPosition;
begin
    UD_Scroll.position := 0;
    FrmImage.Scroll    := 0;
end;

procedure TFrmInterface.SetScrollEnable;
begin
    UD_Scroll.Enabled := True;
end;

procedure TFrmInterface.DisplayStats;
var Rivers: Integer;
    Stats: tTerrainArray;
begin
    FrmImage.Init(SpinWidth.Value, SpinHeight.Value, SpinEditImageSize.Value);

    Rivers := 0;
    Stats  := MyMap.GetStats(Rivers);

    EditStatsOcean.Text    := IntToStr(Stats[Ocean]+Stats[Coast]) + '%';
    EditStatsMountain.Text := IntToStr(Stats[Mountain]) + '%';
    EditStatsGrass.Text    := IntToStr(Stats[Grass]) + '%';
    EditStatsDesert.Text   := IntToStr(Stats[Desert]) + '%';
    EditStatsHill.Text     := IntToStr(Stats[Hills]) + '%';
    EditStatsForest.Text   := IntToStr(Stats[Forest]) + '%';
    EditStatsPrairie.Text  := IntToStr(Stats[Prairie]) + '%';
    EditStatsSwamp.Text    := IntToStr(Stats[Swamp]) + '%';
    EditStatsTundra.Text   := IntToStr(Stats[Tundra]) + '%';
    EditStatsGlacier.Text  := IntToStr(Stats[Glacier]) + '%';
    EditStatsRiver.Text    := IntToStr(Rivers) + '%';

    if MyMap.CitySquares < 12 then
        OP_CitySquares.color := clOrange
    else
    if MyMap.CitySquares < 27 then
        OP_CitySquares.color := clYellow
    else
        OP_CitySquares.color := clBtnFace;

    OP_CitySquares.Caption := IntToStr(MyMap.CitySquares);
end;

procedure TFrmInterface.RandomCheck;
begin
    if CheckBoxRandomWeather.Checked then
    begin
        RG_RainEqu.ItemIndex   := random(5);
        RG_RainPoles.ItemIndex := random(5);
    end;

    if CheckBoxRandomTemp.Checked then
    begin
        { Skew slightly towards cold pole/not equ}
        RG_TempEqu.ItemIndex   := random(4);
        RG_TempPoles.ItemIndex := 1 + random(4);
    end;

    if CheckBoxRandomLand.Checked then
    begin
        RG_Size.ItemIndex      := random(5);
        RG_Age.ItemIndex       := random(4);
        RG_Mountains.ItemIndex := random(5);
        RG_LandMass.ItemIndex  := random(6);
    end;
end;

procedure TFrmInterface.BuildMap;
var myrivers: trivers;
    J, K: Integer;
    C1, C2: Int64;

begin
    lblstatus.color       := clBtnface;
    Screen.Cursor         := CrHourGlass;
    Progressbar1.position := 10;
    RandomCheck;

    if MyMap <> nil then
        FreeAndNil (MyMap);

    MyMap := TMap.Create(
        SpinWidth.Value,
        SpinHeight.Value,
        SE_OceanLevel.Value,
        SE_MountainLevel.Value);

    LblStatus.Caption := 'Altitude';
    LblStatus.update;
    Progressbar1.position := 20;
    C1 := GetTickCount64;

    MyMap.GenMap(Altitude,
        { wavelength is double feature size }
        { ie. lake + island }
        {but reduce slightly, as features seem too big }
        1.9 * SpinWave.Value,
        (SpinDim.Value) / 10,
        Lacunarity,
        SpinBias.Value,
        SpinBias.Value,
        SpinGain.Value,
        ResetNoise);

    LblStatus.Caption := 'Rainfall';
    LblStatus.update;
    Progressbar1.position := 30;

    MyMap.GenMap(Rainfall,
        SpinWaveRain.Value,
        SpinDimRain.Value / 20,
        Lacunarity,
        SE_RainEqu.Value,
        SE_PolesRain.Value,
        SpinGainRain.Value,
        False);

    LblStatus.Caption := 'Temperature';
    LblStatus.update;
    Progressbar1.position := 40;

    MyMap.GenMap(Temperature,
        SpinWaveTemp.Value,
        SpinDimTemp.Value / 20,
        Lacunarity,
        SE_EquTemp.Value,
        SE_PolesTemp.Value,
        SpinGainTemp.Value,
        False);

    { Show performance so far }
    C2 := GetTickCount64;
    PanelPerf.Caption := IntToStr((C2 - C1));

    with MyMap do
    begin
        ClearStats;
        AltitudeSort;
        AdjustSeaLevel;
        AdjustMountainLevel;
        CullSingleTileIslands;
    end;

    if SpinWater.Value > 0 then
    begin
        LblStatus.Caption       := 'Rivers';
        LblStatus.update;
        Progressbar1.position   := 50;
        myrivers                := trivers.Create(SpinWater.Value);
        myrivers.loaddata(MyMap);
        Progressbar1.position   := 60;
        LblStatus.Caption       := 'Run Rivers';
        myrivers.Generate;
        Progressbar1.position   := 70;
        Myrivers.Free;
    end;

    LblStatus.Caption := 'Terrain';
    LblStatus.update;
    Progressbar1.position := 90;
    MyMap.MakeTerrain (SE_Resource.Value);
    LblStatus.Caption := 'OK';
    LblStatus.update;
    DisplayStats;

    if SpinEditImageSize.Value > 0 then
        {Show Thumbnail Image }
        FrmImage.DisplayMap(MyMap, SpinEditImageSize.Value)
    else
        frmImage.Hide;

    Progressbar1.position := 100;
    Screen.Cursor         := CrDefault;
end;

{ Same Layout }
procedure TFrmInterface.Button1Click;
begin
    ResetNoise                 := False;
    CheckBoxRandomLand.Checked := False;
    BuildMap;
    SetScrollEnable;
end;

{ New Layout }
procedure TFrmInterface.MultiLineBtn1Click;
begin
    ResetNoise := True;
    ResetScrollPosition;
    BuildMap;
    SetScrollEnable;
end;


// Lazarus 3.0 breaks SpinEdits for Qt5 (Issue #40725)
procedure TFrmInterface.SpinEditHack (Var SE : TSpinEdit);
begin
    SE.ControlStyle := SE.ControlStyle - [csCaptureMouse];
end;

procedure TFrmInterface.FormCreate;
begin
    Show;

    {$ifdef LCLQT5}
        SpinEditHack (SE_Resource);
        SpinEditHack (SE_OceanLevel);
        SpinEditHack (SpinDim);
        SpinEditHack (SpinWave);
        SpinEditHack (SpinHeight);
        SpinEditHack (SpinWidth);
        SpinEditHack (SE_EquTemp);
        SpinEditHack (SE_PolesTemp);
        SpinEditHack (SpinWaveRain);
        SpinEditHack (SpinGainRain);
        SpinEditHack (SpinWaveTemp);
        SpinEditHack (SpinGainTemp);
        SpinEditHack (SpinEditImageSize);
        SpinEditHack (SpinWater);
        SpinEditHack (SE_RainEqu);
        SpinEditHack (SE_PolesRain);
        SpinEditHack (SE_MountainLevel);
        SpinEditHack (SpinDimTemp);
        SpinEditHack (SpinDimRain);
        SpinEditHack (SpinBias);
        SpinEditHack (SpinGain);
    {$endif}
end;

{ Save current map }
procedure TFrmInterface.BtnSaveClick;
var Mf: TMapFile;
begin
    if MyMap = nil then
        { No map yet }
    else
    begin
        Mf        := TmapFile.Create;
        Mf.Height := MyMap.Height;
        Mf.Width  := MyMap.Width;

        Mf.SaveTileData(MyMap);

        SaveDialog1.InitialDir := Mf.SavePath;
        SaveDialog1.FileName   := Mf.SaveFileName;

        if (Mf.Height > Old_LyMax)
        or (Mf.Width  > Old_LxMax)
        or (SE_Resource.Value <> -1) then
            SaveDialog1.Title := 'Save C-evo Map, Distant Horizon only'
        else
            SaveDialog1.Title := 'Save C-evo Map';

        if SaveDialog1.Execute then
            Mf.SaveMFile(SaveDialog1.filename);
        Mf.Free;
    end;
end;

procedure TFrmInterface.CheckResourceWarning;
begin
    if SE_Resource.Value = -1 then
    begin
        labelNSR1.color := clBtnFace;
        labelNSR2.color := clBtnFace;
        SE_Resource.Color := clBtnFace;
    end
    else
    begin
        // Highlight not valid unless Distant Horizon
        labelNSR1.color := clYellow;
        labelNSR2.color := clYellow;
        labelNSR1.transparent := False;
        labelNSR2.transparent := False;
        SE_Resource.Color := clYellow;
    end;
end;


procedure TFrmInterface.SE_ResourceChange(Sender: TObject);
begin
    CheckResourceWarning;
end;

{ Load file from name, may be called from button or by file association }
procedure TFrmInterface.LoadFile(var Mf: TMapFile; Filename: String);
begin
    if Mf.OpenMFile(filename) then
        if Mf.LoadFromFile then
        begin
            ResetScrollPosition;

            { Order is critical here because of side efects of on change events }
            Spinwidth.Value  := Mf.Width;
            Spinheight.Value := Mf.Height;

            if MyMap <> nil then
                 FreeandNil (MyMap);

            MyMap := TMap.Create(
                Mf.Width,
                Mf.Height,
                SE_OceanLevel.Value,
                SE_MountainLevel.Value);

            Mf.LoadMapdata(MyMap);
            DisplayStats;
            FrmImage.Caption := ' ' + ExtractFileName(Filename);
            FrmImage.DisplayMap(MyMap, SpinEditImageSize.Value);
            SetScrollEnable;
        end;
end;

{ test command line, and load map if specified }
procedure TFrmInterface.CheckifLoadneeded;
var ll : string;
    Mf: TMapFile;
begin
    if ParamStr(1) = '' then
        // Nothing to do
    else
    if (Length (ParamStr(1)) = 5)
    and (Copy (ParamStr(1), 1,2) = '-l') then
    begin
        // language code
        ll := Copy (ParamStr(1), 4,2);
        SetDefaultLang(ll);
    end
    else
    begin
        // Map File ?
        Mf := TmapFile.Create;
        try
            LoadFile(MF, ParamStr(1));
        except
            ShowMessage ('Failed to load map ' + ParamStr(1));
        end;
        Mf.Free;
    end;
end;

{ Process Load Map button }
procedure TFrmInterface.BtnLoadClick;
var Mf: TMapFile;
begin
    Mf := TmapFile.Create;
    OpenDialog1.InitialDir := Mf.LoadPath;

    if OpenDialog1.Execute then
        LoadFile(MF, OpenDialog1.filename);

    Mf.Free;
end;

procedure TFrmInterface.Sizes;
var Area : integer;
begin
    Area := SpinHeight.Value * SpinWidth.Value;

    IF SpinHeight.Value > Old_LyMax then
        SpinHeight.Color := clYellow {Not valid in old versions}
    Else
        SpinHeight.Color := clBtnFace;

    IF SpinWidth.Value > Old_LxMax then
        SpinWidth.Color := clYellow {Not valid in old versions}
    Else
        SpinWidth.Color := clBtnFace;

    If Area > OldMapMax then
        Op_Area.Color := clYellow {Not valid in old versions}
    Else
        Op_Area.Color := clBtnFace;

    Op_Area.Caption := IntToStr(Area);
end;

procedure TFrmInterface.SpinHeightChange;
begin
    if SpinHeight.Value * SpinWidth.Value > MaxMap then
    begin
        SpinWidth.Value := MaxMap DIV SpinHeight.Value;
        if Odd(SpinWidth.Value) then
            SpinWidth.Value := PRED(SpinWidth.Value);
    end
    else if SpinHeight.Value * SpinWidth.Value < Min_Map then
    begin
        SpinWidth.Value := Round(Min_Map / SpinHeight.Value);
        if Odd(SpinWidth.Value) then
            SpinWidth.Value := SUCC(SpinWidth.Value);
    end;

    Sizes;
end;

procedure TFrmInterface.SpinWidthChange;
begin
    if SpinHeight.Value * SpinWidth.Value > MaxMap then
    begin
        SpinHeight.Value := MaxMap DIV SpinWidth.Value;
        if Odd(Spinheight.Value) then
            Spinheight.Value := PRED(Spinheight.Value);
    end
    else if SpinHeight.Value * SpinWidth.Value < Min_Map then
    begin
        SpinHeight.Value := Round(Min_Map / SpinWidth.Value);
        if Odd(Spinheight.Value) then
            Spinheight.Value := SUCC(Spinheight.Value);
    end;

    Sizes;
end;

procedure TFrmInterface.AdjustMapSize;
begin
    SpinHeight.Value := UpdateSetting(RG_MapSize.ItemIndex, sMapHeight);
    SpinWidth.Value  := UpdateSetting(RG_MapSize.ItemIndex, sMapWidth);
end;

{ Used as an initialisation point }
procedure TFrmInterface.FormResize;
begin
    Caption := 'C-evo Map Generator v39';
    MapDefaults;

    Button1.Caption         := 'Same' + LineEnding + 'Land';
    MultiLineBtn1.Caption   := 'New'  + LineEnding + 'Land';

    AdjustMapSize;
    Sizes;
    CopyTemplates;
    CheckResourceWarning;
end;

procedure TFrmInterface.RG_LandMassChanged(Sender: TObject);
begin
    SE_OceanLevel.Value := UpdateSetting((Sender AS TRadioGroup).ItemIndex, sLandMass);
end;

procedure TFrmInterface.RG_ResourceSelectionChanged(Sender: TObject);
begin
    SE_Resource.Value := UpdateSetting((Sender AS TRadioGroup).ItemIndex, sResource);
    CheckResourceWarning;
end;

procedure TFrmInterface.RG_MountainsChanged(Sender: TObject);
begin
    SE_MountainLevel.Value := UpdateSetting((Sender AS TRadioGroup).ItemIndex, sMountains);
end;

procedure TFrmInterface.RG_AgeChanged(Sender: TObject);
begin
    SpinDim.Value := UpdateSetting((Sender AS TRadioGroup).ItemIndex, sAge);
end;

procedure TFrmInterface.RG_SizeChanged(Sender: TObject);
begin
    SpinWave.Value := UpdateSetting((Sender AS TRadioGroup).ItemIndex, sSize);
end;

procedure TFrmInterface.RG_RiversChanged(Sender: TObject);
begin
    SpinWater.Value := UpdateSetting((Sender AS TRadioGroup).ItemIndex, sRivers);
end;

procedure TFrmInterface.RG_TempEquatChanged(Sender: TObject);
begin
    SE_EquTemp.Value := UpdateSetting((Sender AS TRadioGroup).ItemIndex, sTempEqat);
end;

procedure TFrmInterface.RG_TempPolesChanged(Sender: TObject);
begin
    SE_PolesTemp.Value := UpdateSetting((Sender AS TRadioGroup).ItemIndex, sTempPole);
end;

procedure TFrmInterface.RG_RainEquatChanged(Sender: TObject);
begin
    SE_RainEqu.Value := UpdateSetting((Sender AS TRadioGroup).ItemIndex, sRain);
end;

procedure TFrmInterface.RG_RainPolesChanged(Sender: TObject);
begin
    SE_PolesRain.Value := UpdateSetting((Sender AS TRadioGroup).ItemIndex, sRain);
end;

procedure TFrmInterface.ButtonLandDefaultClick;
begin
    DefaultLand;
end;

procedure TFrmInterface.ButtonDefaultWeatherClick;
begin
    DefaultRain;
end;

procedure TFrmInterface.ButtonDefaultTempClick;
begin
    DefaultTemp;
end;


procedure TFrmInterface.redisplay;
begin
    if (SpinEditImageSize.Value = 0)
        OR (mymap = nil) then
        { Nothing to do }
    else
    begin
        { Scroll works backwards! }
        FrmImage.Scroll := -UD_Scroll.position;
        FrmImage.DisplayMap(MyMap, SpinEditImageSize.Value);
    end;
end;

procedure TFrmInterface.SpinEditScrollChange;
begin
    Redisplay;
end;

procedure TFrmInterface.SpinEditImageSizeChange;
begin
    if SpinEditImageSize.Value = 0 then
        FrmImage.hide
    else if mymap <> nil then
    begin
        Redisplay;
    end;
end;

procedure TFrmInterface.UD_ScrollClick(Sender: TObject);
begin
    with Sender AS TUpDown do
        if UD_Scroll.position > 0 then
            if MyMap <> nil then
            { Wrap if position has gone positive }
                UD_Scroll.position := UD_Scroll.position - Mymap.Width;
    Redisplay;
end;

{$INCLUDE TemplateDefaults}
{$INCLUDE TemplateFiles}

end.
