Ticket #3511: cleanOptions.diff

File cleanOptions.diff, 8.3 KB (added by mimo, 8 years ago)
  • binaries/data/mods/public/gui/options/options.js

     
    8787            body.hidden = false;
    8888        }
    8989    }
     90    // TODO  we may have unsaved changes when opening this window
     91    g_hasChanges = false;
     92    Engine.GetGUIObjectByName("loadOptions").enabled = true;
     93    Engine.GetGUIObjectByName("saveOptions").enabled = true;
    9094}
    9195
    9296/**
     
    98102function setupControl(option, i, prefix, reload)
    99103{
    100104    var control;
    101     var onPress = function(){ g_hasChanges = true; };
    102105
    103106    switch (option[3])
    104107    {
     
    110113        text.size = size;
    111114        control = Engine.GetGUIObjectByName(prefix + "Tickbox[" + i + "]");
    112115        var checked;
    113         // Different option action load and save differently, so this switch is needed.
     116        var keyRenderer;
     117        var keyConfig;
     118        var functionBody;
     119
    114120        for (let action of Object.keys(option[2]))
    115121        {
    116122            switch (action)
    117123            {
    118124            case "config":
    119                 // Load initial value if not yet loaded.
    120                 if (!checked || typeof checked != "boolean")
    121                     checked = Engine.ConfigDB_GetValue("user", option[2][action]) === "true";
    122                 // Hacky macro to create the callback.
    123                 var callback = function(key)
    124                 {
    125                     return function()
    126                         Engine.ConfigDB_CreateValue("user", key, String(this.checked));
    127                 }(option[2][action]);
    128                 // Merge the new callback with any existing callbacks.
    129                 onPress = mergeFunctions(callback, onPress);
     125                keyConfig = option[2].config;
     126                if (checked === undefined || reload)
     127                    checked = Engine.ConfigDB_GetValue("user", keyConfig) === "true";
     128                else if ((Engine.ConfigDB_GetValue("user", keyConfig) === "true") !== checked)
     129                    Engine.ConfigDB_CreateValue("user", keyConfig, String(checked));
    130130                break;
    131131            case "renderer":
    132                 // If reloading, config values have priority, otherwise load initial value if not yet loaded
    133                 if (reload && option[2].config)
    134                 {
    135                     checked = Engine.ConfigDB_GetValue("user", option[2].config) === "true";
    136                     let rendererChecked = eval("Engine.Renderer_Get" + option[2].renderer + "Enabled()");
    137                     if (rendererChecked != checked)
    138                         eval("Engine.Renderer_Set" + option[2].renderer + "Enabled(" + checked + ")");
    139                 }
    140                 else if (!checked || typeof checked != "boolean")
    141                     checked = eval("Engine.Renderer_Get" + option[2][action] + "Enabled()");
    142                 // Hacky macro to create the callback (updating also the config value if any).
    143                 var callback = function(key, keyConfig)
    144                 {
    145                     return function()
    146                     {
    147                         eval("Engine.Renderer_Set" + key + "Enabled(" + this.checked + ")");
    148                         if (keyConfig)
    149                             Engine.ConfigDB_CreateValue("user", keyConfig, String(this.checked));
    150                     };
    151                 }(option[2][action], option[2].config);
    152                 // Merge the new callback with any existing callbacks.
    153                 onPress = mergeFunctions(callback, onPress);
     132                keyRenderer = option[2].renderer;
     133                if (checked === undefined)
     134                    checked = eval("Engine.Renderer_Get" + keyRenderer + "Enabled()");
     135                else if (eval("Engine.Renderer_Get" + keyRenderer + "Enabled()") !== checked)
     136                    eval("Engine.Renderer_Set" + keyRenderer + "Enabled(" + checked + ")");
    154137                break;
    155138            case "function":
    156139                // This allows for doing low-level actions, like hiding/showing UI elements.
    157                 onPress = mergeFunctions(eval("function(){" + option[2][action] + "}"), onPress);
     140                functionBody = option[2].function;
    158141                break;
    159142            default:
    160143                warn("Unknown option source type '" + action + "'");
    161144            }
    162145        }
     146
     147        var onPress = function(keyRenderer, keyConfig, functionBody)
     148        {
     149            return function()
     150            {
     151                if (keyRenderer)
     152                    eval("Engine.Renderer_Set" + keyRenderer + "Enabled(" + this.checked + ")");
     153                if (keyConfig)
     154                    Engine.ConfigDB_CreateValue("user", keyConfig, String(this.checked));
     155                if (functionBody)
     156                    eval(functionBody);
     157                setChanges(true);
     158            };
     159        }(keyRenderer, keyConfig, functionBody);
     160
    163161        // Load final data to the control element.
    164162        control.checked = checked;
    165163        control.onPress = onPress;
     
    169167    case "string":
    170168        control = Engine.GetGUIObjectByName(prefix + "Input[" + i + "]");
    171169        var caption;
     170        var key;
     171        var functionBody;
     172
    172173        for (let action of Object.keys(option[2]))
    173174        {
    174175            switch (action)
    175176            {
    176177            case "config":
    177                 onPress = function(){};
    178                 caption = Engine.ConfigDB_GetValue("user", option[2][action]);
    179                 // Hacky macro to create the callback.
    180                 var callback = function(key)
    181                 {
    182                     return function()
    183                     {
    184                         if (Engine.ConfigDB_GetValue("user", key) == this.caption)
    185                             return;
    186                         Engine.ConfigDB_CreateValue("user", key, String(this.caption));
    187                         g_hasChanges = true;
    188                     };
    189                 }(option[2][action]);
    190                 // Merge the new callback with any existing callbacks.
    191                 onPress = mergeFunctions(callback, onPress);
     178                key = option[2].config;
     179                caption = Engine.ConfigDB_GetValue("user", key);
    192180                break;
    193181            case "function":
    194182                // This allows for doing low-level actions, like hiding/showing UI elements.
    195                 onPress = mergeFunctions(function(){eval(option[2][action]);}, onPress);
     183                functionBody = option[2].function;
    196184                break;
    197185            default:
    198186                warn("Unknown option source type '" + action + "'");
    199187            }
    200188        }
     189
     190        // as we use MouseLeave events, we must ensure that something has been modified
     191        var onMouseLeave = function(key, functionBody)
     192        {
     193            return function()
     194            {
     195                if (Engine.ConfigDB_GetValue("user", key) === this.caption)
     196                    return;
     197                Engine.ConfigDB_CreateValue("user", key, String(this.caption));
     198                if (functionBody)
     199                    eval(functionBody);
     200                setChanges(true);
     201            };
     202        }(key, functionBody);
     203
    201204        control.caption = caption;
    202         control.onPress = onPress;
    203         control.onMouseLeave = onPress;
     205        control.onMouseLeave = onMouseLeave;
    204206        break;
    205207    default:
    206         warn("Unknown option type '" + options[3] + "', assuming string. Valid types are 'number', 'string', or 'bool'.");
     208        warn("Unknown option type '" + option[3] + "', assuming string. Valid types are 'number', 'string', or 'bool'.");
    207209        control = Engine.GetGUIObjectByName(prefix + "Input[" + i + "]");
    208210        break;
    209211    }
     
    212214    return control;
    213215}
    214216
    215 /**
    216  * Merge two functions which don't expect arguments.
    217  *
    218  * @return Merged function.
    219  */
    220 function mergeFunctions(function1, function2)
     217function setChanges(val)
    221218{
    222     return function()
    223     {
    224         function1.apply(this);
    225         function2.apply(this);
    226     };
     219    g_hasChanges = val;
     220    Engine.GetGUIObjectByName("loadOptions").enabled = val;
     221    Engine.GetGUIObjectByName("saveOptions").enabled = val;
    227222}
    228223
    229224function reloadDefaults()
     
    230225{
    231226    Engine.ConfigDB_Reload("user");
    232227    init({ "reload": true });
    233     g_hasChanges = false;
     228    setChanges(false);
    234229}
    235230
    236231function saveDefaults()
    237232{
    238     g_hasChanges = false;
    239233    Engine.ConfigDB_WriteFile("user", "config/user.cfg");
     234    setChanges(false);
    240235}
    241236
    242237/**
  • binaries/data/mods/public/gui/options/options.xml

     
    6565                </object>
    6666            </repeat>
    6767        </object>
    68         <object type="button" style="ModernButtonRed" size="50%-170 100%-44 50%-70 100%-16" hotkey="cancel">
     68        <object name="loadOptions" type="button" style="ModernButtonRed" size="50%-170 100%-44 50%-70 100%-16" hotkey="cancel">
    6969            <translatableAttribute id="caption">Reload</translatableAttribute>
    70             <translatableAttribute id="tooltip">Reload default values from file</translatableAttribute>
     70            <translatableAttribute id="tooltip">Reload previous saved settings</translatableAttribute>
    7171            <action on="Press">reloadDefaults();</action>
    7272        </object>
    73         <object type="button" style="ModernButtonRed" size="50%-62 100%-44 50%+38 100%-16">
     73        <object name="saveOptions" type="button" style="ModernButtonRed" size="50%-62 100%-44 50%+38 100%-16">
    7474            <translatableAttribute id="caption">Save</translatableAttribute>
    75             <translatableAttribute id="tooltip">Save changes to file</translatableAttribute>
     75            <translatableAttribute id="tooltip">Save changes</translatableAttribute>
    7676            <action on="Press">saveDefaults();</action>
    7777        </object>
    7878        <object type="button" style="ModernButtonRed" size="50%+70 100%-44 50%+170 100%-16">