1
0
Fork 0
fgdata/gui/dialogs/weather.xml
Roman Ludwicki 6c025f04b2 Correction of the arrangement of controls for "Weather" dialog
Remove gaps made by space characters.
Add ability to stretch the window.
Adapt to the Tortola style too.
2022-09-28 00:10:12 +02:00

721 lines
26 KiB
XML

<?xml version="1.0"?>
<PropertyList>
<nasal>
<open>
<![CDATA[
setprop("sim/gui/dialogs/metar/description[1]",
"Simple and fast weather engine that interprets METAR data " ~
"directly or a set of manually defined parameters. Recommended for use with Multiplayer.");
setprop("sim/gui/dialogs/metar/description[2]",
"Advanced weather engine that gives more detailed and realistic results based on METAR " ~
"data and a set of predefined parameters. Click on 'Apply' to run the engine, as the engine " ~
"does not automatically load upon startup.");
var normalize_string = func(src) {
if( src == nil ) src = "";
var dst = "";
for( var i = 0; i < size(src); i+=1 ) {
if( src[i] == `\n` or src[i] == `\r` )
src[i] = ` `;
if (i == 0 and src[i] == ` `)
continue;
if( i != 0 and src[i] == ` ` and src[i-1] == ` ` )
continue;
dst = dst ~ " ";
dst[size(dst)-1] = src[i];
}
return dst;
}
var GlobalWeatherDialogController = {
new : func( dlgRoot ) {
var obj = { parents: [GlobalWeatherDialogController] };
obj.dlgRoot = dlgRoot;
obj.base = "sim/gui/dialogs/metar";
obj.baseN = props.globals.getNode( obj.base, 1 );
return obj;
},
refresh : func {
var scenarioName = getprop( me.base ~ "/source-selection");
if (getprop( me.base ~ "/mode/manual-weather")) {
# In manual weather mode we have to disable live weather
# fetch so the weather can be changed by the user in the
# weather configuration dialog.
setprop( "/environment/params/metar-updates-environment", 0 );
setprop( "/environment/realwx/enabled", 0 );
setprop( "/environment/config/enabled", 1 );
} else if( scenarioName == "Live data" ) {
# If we've selected Live Data we need to force
# a refresh of the Live Data setting.
setprop( "/environment/realwx/enabled", 1 );
}
},
open : func {
# Determine the weather mode.
if ( getprop("/nasal/local_weather/enabled") == 1) {
# Local weather mode
setprop( me.base ~ "/mode/global-weather", "0" );
setprop( me.base ~ "/mode/local-weather", "1" );
setprop( me.base ~ "/mode/manual-weather", "0" );
} else if ( getprop( "environment/params/metar-updates-environment" ) == 0 ) {
# Manual weather mode
setprop( me.base ~ "/mode/global-weather", "1" );
setprop( me.base ~ "/mode/local-weather", "0" );
setprop( me.base ~ "/mode/manual-weather", "1" );
} else {
# Global weather mode
setprop( me.base ~ "/mode/global-weather", "1" );
setprop( me.base ~ "/mode/local-weather", "0" );
setprop( me.base ~ "/mode/manual-weather", "0" );
}
# initialize the METAR source selection
if( getprop( "environment/realwx/enabled" ) ) {
setprop( me.base ~ "/source-selection", "Live data" );
} else {
# preset configured scenario
var wsn = props.globals.getNode( "/environment/weather-scenarios" );
var current = getprop("/environment/weather-scenario", "");
var found = 0;
if( wsn != nil ) {
var scenarios = wsn.getChildren("scenario");
forindex (var i; scenarios ) {
var metarN = scenarios[i].getNode("metar");
metarN == nil and continue;
if( scenarios[i].getNode("name").getValue() == current ) {
setprop( me.base ~ "/source-selection", scenarios[i].getNode("name").getValue() );
found = 1;
break;
}
}
}
if( found == 0 )
setprop( me.base ~ "/source-selection", "Manual input" );
}
setprop( me.base ~ "/metar-string", normalize_string(getprop("environment/metar/data")) );
gui.findElementByName( me.dlgRoot, "metar-string-input" ).getNode("legend", 1).setValue(normalize_string(getprop("environment/metar/data")));
# fill the METAR source combo box
var combo = gui.findElementByName( me.dlgRoot, "source-selection" );
var wsn = props.globals.getNode( "/environment/weather-scenarios" );
if( wsn != nil ) {
var scenarios = wsn.getChildren("scenario");
forindex (var i; scenarios ) {
combo.getChild("value", i, 1).setValue(scenarios[i].getNode("name").getValue());
}
}
me.scenarioListenerId = setlistener( me.base ~ "/source-selection", func(n) { me.scenarioListener(n); }, 1, 1 );
me.metarListenerId = setlistener( "environment/metar/valid", func(n) { me.metarListener(n); }, 1, 1 );
# Update the dialog itself
me.refresh();
},
close : func {
removelistener( me.scenarioListenerId );
removelistener( me.metarListenerId );
},
apply : func {
var scenarioName = getprop( me.base ~ "/source-selection");
var metar = getprop( "environment/metar/data" );
var global_weather_enabled = getprop( me.base ~ "/mode/global-weather");
var local_weather_enabled = getprop( me.base ~ "/mode/local-weather");
var manual_weather_enabled = getprop( me.base ~ "/mode/manual-weather");
# General weather settings based on scenario
if (manual_weather_enabled == 1) {
setprop( "/environment/params/metar-updates-environment", 0 );
setprop( "/environment/realwx/enabled", 0 );
setprop( "/environment/config/enabled", 1 );
metar = "";
} else if( scenarioName == "Live data" ) {
setprop( "/environment/params/metar-updates-environment", 1 );
setprop( "/environment/realwx/enabled", 1 );
setprop( "/environment/config/enabled", 1 );
} else if( scenarioName == "Manual input" ) {
setprop( "/environment/params/metar-updates-environment", 1 );
setprop( "/environment/realwx/enabled", 0 );
setprop( "/environment/config/enabled", 1 );
metar = getprop( me.base ~ "/metar-string" );
setprop("/environment/weather-scenario", scenarioName);
} else {
setprop( "/environment/params/metar-updates-environment", 1 );
setprop( "/environment/realwx/enabled", 0 );
setprop( "/environment/config/enabled", 1 );
metar = getprop( me.base ~ "/metar-string" );
setprop("/environment/weather-scenario", scenarioName);
}
if( metar != nil ) {
setprop( "environment/metar/data", normalize_string(metar) );
}
# Clear any local weather that might be running
if (getprop("/nasal/local_weather/enabled")) local_weather.clear_all();
setprop("/nasal/local_weather/enabled", "false");
if (local_weather_enabled) {
# If Local Weather is enabled, re-initialize with updated
# initial tile and tile selection.
setprop("/nasal/local_weather/enabled", "true");
# Re-initialize local weather.
settimer( func {local_weather.set_tile();}, 0.2);
}
},
findScenarioByName : func(name) {
var wsn = props.globals.getNode( "/environment/weather-scenarios" );
if( wsn != nil ) {
var scenarios = wsn.getChildren("scenario");
foreach (var scenario; scenarios ) {
if( scenario.getNode("name").getValue() == name )
return scenario;
}
}
return nil;
},
scenarioListener : func( n ) {
var description = "";
var metar = "nil";
var local_weather_props = nil;
var scenario = me.findScenarioByName( n.getValue() );
if( scenario != nil ) {
description = normalize_string(scenario.getNode("description", 1 ).getValue());
metar = normalize_string(scenario.getNode("metar", 1 ).getValue());
local_weather_props = scenario.getNode("local-weather");
}
if (n.getValue() == "Live data") {
# Special case - retrieve live data
var metar = getprop( "environment/metar/data" );
}
if (n.getValue() == "Manual input") {
# Special case - retain current values
var metar = getprop( me.base ~ "/metar-string" );
}
setprop(me.base ~ "/description", description );
setprop(me.base ~ "/metar-string", metar );
# Set the wind from the METAR string.
var result = [];
var msplit = split(" ", string.uc(metar));
foreach (var word; msplit) {
if ((size(word) > 6) and string.match(word, "*[0-9][0-9]KT")) {
# We've got the wind definition word. Now to split it up.
# Format is nnnmmKT or nnnmmGppKT
# Direction is easy - the first 3 characters.
var dir = chr(word[0]) ~ chr(word[1]) ~ chr(word[2]);
if (dir == "VRB") {
setprop("/local-weather/tmp/tile-orientation-deg", 360.0 * rand());
setprop("/local-weather/tmp/gust-angular-variation-deg", 180.0);
setprop("/local-weather/tmp/gust-frequency-hz", 0.001);
} else {
setprop("/local-weather/tmp/tile-orientation-deg", dir);
setprop("/local-weather/tmp/gust-angular-variation-deg", 0.0);
setprop("/local-weather/tmp/gust-frequency-hz", 0.0);
}
# Next two are the base wind
var spd = chr(word[3]) ~ chr(word[4]);
setprop("/local-weather/tmp/windspeed-kt", spd);
var gst = 0;
if ((size(word) > 7) and (chr(word[5]) == 'G')) {
# Gusty case
gst = chr(word[6]) ~ chr(word[7]);
}
if ((gst > spd) and (spd > 0)) {
setprop("/local-weather/tmp/gust-relative-strength", (gst - spd) / spd);
setprop("/local-weather/tmp/gust-frequency-hz", 0.7);
} else {
setprop("/local-weather/tmp/gust-relative-strength", 0.0);
}
}
}
if (local_weather_props != nil) {
# The local weather properties need to be set now, so they can
# be configured by the user if they select Advanced Settings
props.copy(local_weather_props, props.globals.getNode("/local-weather/tmp", 1));
} else {
# If no local weather properties have been set, we'll read from the scenario
# METAR
setprop("/local-weather/tmp/tile-type", "manual");
setprop("/local-weather/tmp/tile-management", "METAR");
}
me.refresh();
},
metarListener : func( n ) {
var metar = getprop("environment/metar/data");
if( metar == nil or metar == "" ) metar = "NIL";
metar = normalize_string(metar);
logprint(LOG_DEBUG, "new METAR: " ~ metar );
setprop( me.base ~ "/metar-string", metar );
gui.dialog_update( "weather-conditions", "metar-string" );
},
};
var controller = GlobalWeatherDialogController.new( cmdarg() );
controller.open();
]]>
</open>
<close>
<![CDATA[
controller.close();
]]>
</close>
</nasal>
<!-- Control the weather -->
<name>weather</name>
<modal>false</modal>
<resizable>true</resizable>
<layout>vbox</layout>
<default-padding>3</default-padding>
<!-- Title bar with close button -->
<group>
<layout>hbox</layout>
<default-padding>1</default-padding>
<empty>
<stretch>true</stretch>
</empty>
<text>
<label>Weather Conditions</label>
</text>
<empty>
<stretch>true</stretch>
</empty>
<button>
<legend/>
<key>Esc</key>
<pref-width>16</pref-width>
<pref-height>16</pref-height>
<border>2</border>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
<hrule/>
<group>
<layout>hbox</layout>
<valign>fill</valign>
<stretch>true</stretch>
<group>
<layout>vbox</layout>
<valign>fill</valign>
<padding>5</padding>
<text>
<halign>left</halign>
<label>Select Weather Engine</label>
</text>
<group>
<layout>table</layout>
<radio>
<row>0</row>
<col>0</col>
<halign>left</halign>
<name>simple-weather</name>
<property>sim/gui/dialogs/metar/mode/global-weather</property>
<live>true</live>
<label>Basic Weather</label>
<binding>
<command>property-assign</command>
<property>sim/gui/dialogs/metar/mode/global-weather</property>
<value>1</value>
</binding>
<binding>
<command>property-assign</command>
<property>sim/gui/dialogs/metar/mode/local-weather</property>
<value>0</value>
</binding>
<binding>
<command>property-assign</command>
<property>sim/gui/dialogs/metar/mode/manual-weather</property>
<value>0</value>
</binding>
<binding>
<command>nasal</command>
<script>
controller.refresh();
</script>
</binding>
</radio>
<group>
<row>0</row>
<col>1</col>
<layout>hbox</layout>
<halign>right</halign>
<checkbox>
<halign>right</halign>
<name>manual-weather-config</name>
<property>sim/gui/dialogs/metar/mode/manual-weather</property>
<label>Manual Configuration</label>
<live>true</live>
<enable>
<property>sim/gui/dialogs/metar/mode/global-weather</property>
</enable>
<binding>
<command>dialog-apply</command>
<object-name>manual-weather-config</object-name>
</binding>
<binding>
<command>nasal</command>
<script>
controller.refresh();
</script>
</binding>
</checkbox>
<button>
<halign>right</halign>
<legend>Manual Configuration...</legend>
<enable>
<property>sim/gui/dialogs/metar/mode/manual-weather</property>
</enable>
<binding>
<command>dialog-show</command>
<dialog-name>weather-configuration</dialog-name>
</binding>
<!--<binding>
<command>property-assign</command>
<property>sim/gui/dialogs/metar/mode/manual-weather</property>
<value>1</value>
</binding>-->
</button>
</group>
</group>
<textbox>
<name>basic description</name>
<halign>fill</halign>
<valign>fill</valign>
<stretch>true</stretch>
<pref-height>90</pref-height>
<slider>15</slider>
<editable>false</editable>
<wrap>true</wrap>
<live>true</live>
<top-line>0</top-line>
<property>sim/gui/dialogs/metar/description[1]</property>
</textbox>
<group>
<layout>table</layout>
<radio>
<row>0</row>
<col>0</col>
<label>Detailed Weather</label>
<halign>left</halign>
<name>simple-weather</name>
<property>sim/gui/dialogs/metar/mode/local-weather</property>
<live>true</live>
<binding>
<command>property-assign</command>
<property>sim/gui/dialogs/metar/mode/local-weather</property>
<value>1</value>
</binding>
<binding>
<command>property-assign</command>
<property>sim/gui/dialogs/metar/mode/global-weather</property>
<value>0</value>
</binding>
<binding>
<command>property-assign</command>
<property>sim/gui/dialogs/metar/mode/manual-weather</property>
<value>0</value>
</binding>
<binding>
<command>nasal</command>
<script>
controller.refresh();
</script>
</binding>
</radio>
<group>
<row>0</row>
<col>1</col>
<layout>hbox</layout>
<halign>right</halign>
<button>
<halign>right</halign>
<legend>Weather help</legend>
<binding>
<command>open-browser</command>
<path>Docs/README.local_weather.html</path>
</binding>
</button>
<button>
<legend>Advanced Settings...</legend>
<halign>right</halign>
<enable>
<property>sim/gui/dialogs/metar/mode/local-weather</property>
<value>1</value>
</enable>
<binding>
<command>dialog-show</command>
<dialog-name>local-weather</dialog-name>
</binding>
</button>
</group>
</group>
<textbox>
<name>advance-description</name>
<halign>fill</halign>
<valign>fill</valign>
<stretch>true</stretch>
<pref-height>100</pref-height>
<slider>15</slider>
<editable>false</editable>
<wrap>true</wrap>
<live>true</live>
<top-line>0</top-line>
<property>sim/gui/dialogs/metar/description[2]</property>
</textbox>
</group>
</group>
<hrule/>
<group>
<layout>vbox</layout>
<valign>fill</valign>
<stretch>true</stretch>
<group>
<layout>vbox</layout>
<padding>5</padding>
<group>
<layout>table</layout>
<text>
<row>0</row>
<col>0</col>
<label>Weather Conditions</label>
<halign>left</halign>
</text>
<combo>
<row>0</row>
<col>1</col>
<name>source-selection</name>
<halign>right</halign>
<stretch>true</stretch>
<pref-width>300</pref-width>
<property>sim/gui/dialogs/metar/source-selection</property>
<enable>
<equals>
<property>sim/gui/dialogs/metar/mode/manual-weather</property>
<value>0</value>
</equals>
</enable>
<binding>
<command>dialog-apply</command>
<object-name>source-selection</object-name>
</binding>
<binding>
<command>dialog-update</command>
<object-name>metar-string-input</object-name>
</binding>
</combo>
</group>
<textbox>
<name>description</name>
<halign>fill</halign>
<valign>fill</valign>
<stretch>true</stretch>
<pref-height>100</pref-height>
<slider>15</slider>
<editable>false</editable>
<wrap>true</wrap>
<live>true</live>
<top-line>0</top-line>
<property>sim/gui/dialogs/metar/description[0]</property>
</textbox>
</group>
<group>
<layout>vbox</layout>
<padding>5</padding>
<group>
<layout>table</layout>
<text>
<row>0</row>
<col>0</col>
<label>METAR Data</label>
<halign>left</halign>
</text>
<group>
<row>0</row>
<col>1</col>
<layout>hbox</layout>
<halign>right</halign>
<text>
<label>Data is valid</label>
</text>
<checkbox>
<property>/environment/metar/valid</property>
<label/>
<live>true</live>
<enable>
<false/>
</enable>
</checkbox>
</group>
</group>
<textbox>
<name>metar-string-input</name>
<halign>fill</halign>
<valign>fill</valign>
<stretch>true</stretch>
<pref-height>70</pref-height>
<slider>15</slider>
<editable>true</editable>
<wrap>true</wrap>
<!-- <live>true</live> -->
<top-line>0</top-line>
<property>sim/gui/dialogs/metar/metar-string</property>
<enable>
<and>
<equals>
<property>sim/gui/dialogs/metar/mode/manual-weather</property>
<value>0</value>
</equals>
<equals>
<property>sim/gui/dialogs/metar/source-selection</property>
<value>Manual input</value>
</equals>
</and>
</enable>
<binding>
<command>dialog-apply</command>
<object-name>metar-string-input</object-name>
</binding>
</textbox>
<group>
<layout>hbox</layout>
<halign>left</halign>
<button>
<legend>METAR Description...</legend>
<binding>
<command>dialog-show</command>
<dialog-name>weather-metar-description</dialog-name>
</binding>
</button>
</group>
</group>
</group>
<hrule/>
<group>
<layout>hbox</layout>
<empty>
<stretch>true</stretch>
</empty>
<button>
<legend>OK</legend>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
<object-name>metar-string-input</object-name>
</binding>
<binding>
<command>nasal</command>
<script>
controller.apply();
</script>
</binding>
<binding>
<command>dialog-close</command>
</binding>
</button>
<button>
<legend>Apply</legend>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
<object-name>metar-string-input</object-name>
</binding>
<binding>
<command>nasal</command>
<script>
controller.apply();
</script>
</binding>
</button>
<button>
<legend>Close</legend>
<equal>true</equal>
<default>true</default>
<key>Esc</key>
<binding>
<command>dialog-close</command>
</binding>
</button>
<empty>
<stretch>true</stretch>
</empty>
</group>
</PropertyList>