Ticket #3511: ticket-3511-full.patch

File ticket-3511-full.patch, 12.8 KB (added by mimo, 8 years ago)
  • binaries/data/mods/public/gui/options/options.js

     
    11var g_hasCallback = false;
     2var g_hasChanges = false;
    23/**
    34 * This array holds the data to populate the general section with.
    45 * Data is in the form [Title, Tooltip, {ActionType:Action}, InputType].
     
    5455{
    5556    if (data && data.callback)
    5657        g_hasCallback = true;
     58    let reload = data && data.reload ? true : false;
    5759
    5860    // WARNING: We assume a strict formatting of the XML and do minimal checking.
    59     for each (var prefix in Object.keys(options))
     61    for (let prefix of Object.keys(options))
    6062    {
    61         var lastSize;
    62         for (var i = 0; i < options[prefix].length; i++)
     63        let lastSize;
     64        for (let i = 0; i < options[prefix].length; i++)
    6365        {
    64             var body = Engine.GetGUIObjectByName(prefix + "[" + i + "]");
    65             var label = Engine.GetGUIObjectByName(prefix + "Label[" + i + "]");
     66            let body = Engine.GetGUIObjectByName(prefix + "[" + i + "]");
     67            let label = Engine.GetGUIObjectByName(prefix + "Label[" + i + "]");
    6668            // Setup control.
    67             setupControl(options[prefix][i], i, prefix);
     69            setupControl(options[prefix][i], i, prefix, reload);
    6870            // Setup label.
    6971            label.caption = options[prefix][i][0];
    7072            label.tooltip = options[prefix][i][1];
     
    7173            // Move each element to the correct place.
    7274            if (i > 0)
    7375            {
    74                 var newSize = new GUISize();
     76                let newSize = new GUISize();
    7577                newSize.left = lastSize.left;
    7678                newSize.rright = lastSize.rright;
    7779                newSize.top = lastSize.bottom;
     
    8082                lastSize = newSize;
    8183            }
    8284            else
    83             {
    8485                lastSize = body.size;
    85             }
    8686            // Show element.
    8787            body.hidden = false;
    8888        }
     
    9595 * @param option Structure containing the data to setup an option.
    9696 * @param prefix Prefix to use when accessing control, for example "generalSetting" when the tickbox name is generalSettingTickbox[i].
    9797 */
    98 function setupControl(option, i, prefix)
     98function setupControl(option, i, prefix, reload)
    9999{
     100    var control;
     101    var onPress = function(){ g_hasChanges = true; };
     102
    100103    switch (option[3])
    101104    {
    102         case "boolean":
    103             // More space for the label
    104             let text = Engine.GetGUIObjectByName(prefix + "Label[" + i + "]");
    105             let size = text.size;
    106             size.rright = 87;
    107             text.size = size;
    108             var control = Engine.GetGUIObjectByName(prefix + "Tickbox[" + i + "]");
    109             var checked;
    110             var onPress = function(){};
    111             // Different option action load and save differently, so this switch is needed.
    112             for each (var action in Object.keys(option[2]))
     105    case "boolean":
     106        // More space for the label
     107        let text = Engine.GetGUIObjectByName(prefix + "Label[" + i + "]");
     108        let size = text.size;
     109        size.rright = 87;
     110        text.size = size;
     111        control = Engine.GetGUIObjectByName(prefix + "Tickbox[" + i + "]");
     112        var checked;
     113        // Different option action load and save differently, so this switch is needed.
     114        for (let action of Object.keys(option[2]))
     115        {
     116            switch (action)
    113117            {
    114                 switch (action)
     118            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)
    115124                {
    116                     case "config":
    117                         // Load initial value if not yet loaded.
    118                         if (!checked || typeof checked != "boolean")
    119                             checked = Engine.ConfigDB_GetValue("user", option[2][action]) === "true" ? true : false;
    120                         // Hacky macro to create the callback.
    121                         var callback = function(key)
    122                         {
    123                             return function()
    124                                 Engine.ConfigDB_CreateValue("user", key, String(this.checked));
    125                         }(option[2][action]);
    126                         // Merge the new callback with any existing callbacks.
    127                         onPress = mergeFunctions(callback, onPress);
    128                         break;
    129                     case "renderer":
    130                         // Load initial value if not yet loaded.
    131                         if (!checked || typeof checked != "boolean")
    132                             checked = eval("Engine.Renderer_Get" + option[2][action] + "Enabled()");
    133                         // Hacky macro to create the callback.
    134                         var callback = function(key)
    135                         {
    136                             return function()
    137                                 eval("Engine.Renderer_Set" + key + "Enabled(" + this.checked + ")");
    138                         }(option[2][action]);
    139                         // Merge the new callback with any existing callbacks.
    140                         onPress = mergeFunctions(callback, onPress);
    141                         break;
    142                     case "function":
    143                         // This allows for doing low-level actions, like hiding/showing UI elements.
    144                         onPress = mergeFunctions(eval("function(){" + option[2][action] + "}"), onPress);
    145                         break;
    146                     default:
    147                         warn("Unknown option source type '" + action + "'");
     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);
     130                break;
     131            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 + ")");
    148139                }
     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);
     154                break;
     155            case "function":
     156                // This allows for doing low-level actions, like hiding/showing UI elements.
     157                onPress = mergeFunctions(eval("function(){" + option[2][action] + "}"), onPress);
     158                break;
     159            default:
     160                warn("Unknown option source type '" + action + "'");
    149161            }
    150             // Load final data to the control element.
    151             control.checked = checked;
    152             control.onPress = onPress;
    153             break;
    154         case "number":
    155             // TODO: Slider
    156         case "string":
    157             var control = Engine.GetGUIObjectByName(prefix + "Input[" + i + "]");
    158             var caption;
    159             var onPress = function(){};
    160             for each (var action in Object.keys(option[2]))
     162        }
     163        // Load final data to the control element.
     164        control.checked = checked;
     165        control.onPress = onPress;
     166        break;
     167    case "number":
     168        // TODO: Slider
     169    case "string":
     170        control = Engine.GetGUIObjectByName(prefix + "Input[" + i + "]");
     171        var caption;
     172        for (let action of Object.keys(option[2]))
     173        {
     174            switch (action)
    161175            {
    162                 switch (action)
     176            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)
    163181                {
    164                     case "config":
    165                         // Load initial value if not yet loaded.
    166                         if (!checked || typeof checked != boolean)
    167                             caption = Engine.ConfigDB_GetValue("user", option[2][action]);
    168                         // Hacky macro to create the callback.
    169                         var callback = function(key)
    170                         {
    171                             return function()
    172                                 Engine.ConfigDB_CreateValue("user", key, String(this.caption));
    173                         }(option[2][action]);
    174                         // Merge the new callback with any existing callbacks.
    175                         onPress = mergeFunctions(callback, onPress);
    176                         break;
    177                     case "function":
    178                         // This allows for doing low-level actions, like hiding/showing UI elements.
    179                         onPress = mergeFunctions(function(){eval(option[2][action])}, onPress);
    180                         break;
    181                     default:
    182                         warn("Unknown option source type '" + action + "'");
    183                 }
     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);
     192                break;
     193            case "function":
     194                // This allows for doing low-level actions, like hiding/showing UI elements.
     195                onPress = mergeFunctions(function(){eval(option[2][action])}, onPress);
     196                break;
     197            default:
     198                warn("Unknown option source type '" + action + "'");
    184199            }
    185             control.caption = caption;
    186             control.onPress = onPress;
    187             break;
    188         default:
    189             warn("Unknown option type '" + options[3] + "', assuming string. Valid types are 'number', 'string', or 'bool'.");
    190             var control = Engine.GetGUIObjectByName(prefix + "Input[" + i + "]");
    191             break;
     200        }
     201        control.caption = caption;
     202        control.onPress = onPress;
     203        control.onMouseLeave = onPress;
     204        break;
     205    default:
     206        warn("Unknown option type '" + options[3] + "', assuming string. Valid types are 'number', 'string', or 'bool'.");
     207        control = Engine.GetGUIObjectByName(prefix + "Input[" + i + "]");
     208        break;
    192209    }
    193210    control.hidden = false;
    194211    control.tooltip = option[1];
     
    209226    };
    210227}
    211228
     229function reloadDefaults()
     230{
     231    Engine.ConfigDB_Reload("user");
     232    init({ "reload": true });
     233    g_hasChanges = false;
     234}
     235
     236function saveDefaults()
     237{
     238    g_hasChanges = false;
     239    Engine.ConfigDB_WriteFile("user", "config/user.cfg");
     240}
     241
    212242/**
    213243 * Close GUI page and call callbacks if they exist.
    214244 **/
    215245function closePage()
    216246{
    217     // Revert all changes if they were not saved on the disk
    218     Engine.ConfigDB_Reload("user");
     247    if (g_hasChanges)
     248    {
     249        let btCaptions = [translate("No"), translate("Yes")];
     250        let btCode = [null, function(){ closePageWithoutConfirmation(); }];
     251        messageBox(500, 200, translate("You have unsaved changes, are you sure you want to quit ?"),
     252            translate("Warning"), 0, btCaptions, btCode);
     253    }
     254    else
     255        closePageWithoutConfirmation();
     256}
    219257
     258function closePageWithoutConfirmation()
     259{
    220260    if (g_hasCallback)
    221261        Engine.PopGuiPageCB();
    222262    else
  • binaries/data/mods/public/gui/options/options.xml

     
    1717        <object style="ModernLabelText" type="text" size="50%-128 -16 50%+128 16">
    1818            <translatableAttribute id="caption">Game Options</translatableAttribute>
    1919        </object>
    20         <object name="GeneralSettings" type="image" sprite="ModernDarkBoxGold" size="16 16 312 100%-16">
     20        <object name="GeneralSettings" type="image" sprite="ModernDarkBoxGold" size="16 16 312 100%-52">
    2121            <object style="ModernLabelText" type="text" size="0 5 100% 25">
    2222                <translatableAttribute id="caption">General</translatableAttribute>
    2323            </object>
     
    5353                </object>
    5454            </repeat>
    5555        </object>
    56         <object name="LobbySettings" type="image" sprite="ModernDarkBoxGold" size="620 50%+4 916 100%-16">
     56        <object name="LobbySettings" type="image" sprite="ModernDarkBoxGold" size="620 50%+4 916 100%-52">
    5757            <object style="ModernLabelText" type="text" size="0 5 100% 25">
    5858                <translatableAttribute id="caption">Lobby Settings</translatableAttribute>
    5959            </object>
     
    6565                </object>
    6666            </repeat>
    6767        </object>
    68         <object type="button" style="ModernButtonRed" size="320 100%-44 50%-4 100%-16" hotkey="cancel">
    69             <translatableAttribute id="caption">Cancel</translatableAttribute>
    70             <action on="Press">closePage();</action>
     68        <object type="button" style="ModernButtonRed" size="50%-170 100%-44 50%-70 100%-16" hotkey="cancel">
     69            <translatableAttribute id="caption">Reload</translatableAttribute>
     70            <translatableAttribute id="tooltip">Reload defaults values from file</translatableAttribute>
     71            <action on="Press">reloadDefaults();</action>
    7172        </object>
    72         <object type="button" style="ModernButtonRed" size="50%+4 100%-44 612 100%-16">
     73        <object type="button" style="ModernButtonRed" size="50%-62 100%-44 50%+38 100%-16">
    7374            <translatableAttribute id="caption">Save</translatableAttribute>
    74             <action on="Press">Engine.ConfigDB_WriteFile("user", "config/user.cfg");closePage();</action>
     75            <translatableAttribute id="tooltip">Save changes on file</translatableAttribute>
     76            <action on="Press">saveDefaults();</action>
    7577        </object>
     78        <object type="button" style="ModernButtonRed" size="50%+70 100%-44 50%+170 100%-16">
     79            <translatableAttribute id="caption">Quit</translatableAttribute>
     80            <translatableAttribute id="tooltip">non-saved changes affect this session only</translatableAttribute>
     81            <action on="Press">closePage();</action>
     82        </object>
    7683    </object>
    7784</objects>