mirror of https://github.com/OpenRCT2/OpenRCT2.git
improve Theme to use List and Json
This commit is contained in:
parent
b1b9741090
commit
de17eb7279
|
@ -6,7 +6,8 @@ extern "C"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "../core/FileStream.hpp"
|
#include "../core/Json.hpp"
|
||||||
|
#include "../core/List.hpp"
|
||||||
#include "../core/Math.hpp"
|
#include "../core/Math.hpp"
|
||||||
#include "../core/Memory.hpp"
|
#include "../core/Memory.hpp"
|
||||||
#include "../core/String.hpp"
|
#include "../core/String.hpp"
|
||||||
|
@ -41,28 +42,32 @@ struct UIThemeEntry
|
||||||
WindowTheme Theme;
|
WindowTheme Theme;
|
||||||
|
|
||||||
|
|
||||||
json_t * ToJson() const;
|
json_t * ToJson() const;
|
||||||
static UIThemeEntry * FromJson(const WindowThemeDesc * wtDesc, const json_t * json);
|
static UIThemeEntry FromJson(const WindowThemeDesc * wtDesc, const json_t * json);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a user interface theme. Contains window colour schemes and appearance features.
|
* Represents a user interface theme. Contains window colour schemes and appearance features.
|
||||||
*/
|
*/
|
||||||
struct UITheme
|
class UITheme
|
||||||
{
|
{
|
||||||
utf8 * Name;
|
public:
|
||||||
UIThemeEntry * Entries;
|
utf8 * Name;
|
||||||
uint8 Flags;
|
List<UIThemeEntry> Entries;
|
||||||
|
uint8 Flags;
|
||||||
|
|
||||||
|
UITheme(const utf8 * name);
|
||||||
|
UITheme(const UITheme & name);
|
||||||
|
~UITheme();
|
||||||
|
|
||||||
|
void SetEntry(const UIThemeEntry * entry);
|
||||||
|
void RemoveEntry(rct_windowclass windowClass);
|
||||||
|
json_t * ToJson() const;
|
||||||
|
bool WriteToFile(const utf8 * path) const;
|
||||||
|
|
||||||
void SetEntry(const UIThemeEntry * entry);
|
|
||||||
void RemoveEntry(rct_windowclass windowClass);
|
|
||||||
json_t * ToJson() const;
|
|
||||||
bool WriteToFile(const utf8 * path) const;
|
|
||||||
static UITheme * Create(const utf8 * name);
|
|
||||||
static void Free(UITheme * theme);
|
|
||||||
static UITheme * FromJson(const json_t * json);
|
static UITheme * FromJson(const json_t * json);
|
||||||
static UITheme * FromFile(const utf8 * path);
|
static UITheme * FromFile(const utf8 * path);
|
||||||
|
static UITheme CreatePredefined(const utf8 * name, const UIThemeEntry * entries, uint8 flags);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -178,8 +183,13 @@ UIThemeEntry PredefinedThemeRCT2_Entries[] =
|
||||||
THEME_DEF_END
|
THEME_DEF_END
|
||||||
};
|
};
|
||||||
|
|
||||||
const UITheme PredefinedThemeRCT1 = { "RCT1", PredefinedThemeRCT1_Entries, UITHEME_FLAG_PREDEFINED };
|
const UITheme PredefinedThemeRCT1 = UITheme::CreatePredefined(
|
||||||
const UITheme PredefinedThemeRCT2 = { "RCT2", PredefinedThemeRCT2_Entries, UITHEME_FLAG_PREDEFINED };
|
"RCT1", PredefinedThemeRCT1_Entries, UITHEME_FLAG_USE_LIGHTS_RIDE |
|
||||||
|
UITHEME_FLAG_USE_LIGHTS_PARK |
|
||||||
|
UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT);
|
||||||
|
|
||||||
|
const UITheme PredefinedThemeRCT2 = UITheme::CreatePredefined(
|
||||||
|
"RCT2", PredefinedThemeRCT2_Entries, 0);
|
||||||
|
|
||||||
const UITheme * PredefinedThemes[] = {
|
const UITheme * PredefinedThemes[] = {
|
||||||
&PredefinedThemeRCT1,
|
&PredefinedThemeRCT1,
|
||||||
|
@ -238,7 +248,7 @@ json_t * UIThemeEntry::ToJson() const
|
||||||
return jsonEntry;
|
return jsonEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIThemeEntry * UIThemeEntry::FromJson(const WindowThemeDesc * wtDesc, const json_t * json)
|
UIThemeEntry UIThemeEntry::FromJson(const WindowThemeDesc * wtDesc, const json_t * json)
|
||||||
{
|
{
|
||||||
json_t * jsonColours = json_object_get(json, "colours");
|
json_t * jsonColours = json_object_get(json, "colours");
|
||||||
if (jsonColours == nullptr)
|
if (jsonColours == nullptr)
|
||||||
|
@ -249,96 +259,78 @@ UIThemeEntry * UIThemeEntry::FromJson(const WindowThemeDesc * wtDesc, const json
|
||||||
uint8 numColours = (uint8)json_array_size(jsonColours);
|
uint8 numColours = (uint8)json_array_size(jsonColours);
|
||||||
numColours = Math::Min(numColours, wtDesc->NumColours);
|
numColours = Math::Min(numColours, wtDesc->NumColours);
|
||||||
|
|
||||||
UIThemeEntry * result = Memory::Allocate<UIThemeEntry>();
|
UIThemeEntry result;
|
||||||
result->WindowClass = wtDesc->WindowClass;
|
result.WindowClass = wtDesc->WindowClass;
|
||||||
result->Theme = wtDesc->DefaultTheme;
|
result.Theme = wtDesc->DefaultTheme;
|
||||||
|
|
||||||
for (uint8 i = 0; i < numColours; i++)
|
for (uint8 i = 0; i < numColours; i++)
|
||||||
{
|
{
|
||||||
result->Theme.Colours[i] = (colour_t)json_integer_value(json_array_get(jsonColours, i));
|
result.Theme.Colours[i] = (colour_t)json_integer_value(json_array_get(jsonColours, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
UITheme * UITheme::Create(const utf8 * name)
|
|
||||||
{
|
|
||||||
UITheme * theme = Memory::Allocate<UITheme>();
|
|
||||||
theme->Name = String::Duplicate(name);
|
|
||||||
theme->Entries = Memory::AllocateArray<UIThemeEntry>(1);
|
|
||||||
theme->Entries[0].WindowClass = 255;
|
|
||||||
theme->Flags = 0;
|
|
||||||
return theme;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region UITheme
|
#pragma region UITheme
|
||||||
|
|
||||||
void UITheme::Free(UITheme * theme)
|
UITheme::UITheme(const utf8 * name)
|
||||||
{
|
{
|
||||||
assert(!(theme->Flags & UITHEME_FLAG_PREDEFINED));
|
Name = String::Duplicate(name);
|
||||||
|
Flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
Memory::Free(theme->Name);
|
UITheme::UITheme(const UITheme & copy)
|
||||||
Memory::Free(theme->Entries);
|
{
|
||||||
|
Name = String::Duplicate(copy.Name);
|
||||||
|
Flags = copy.Flags;
|
||||||
|
Entries = copy.Entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
UITheme::~UITheme()
|
||||||
|
{
|
||||||
|
Memory::Free(Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UITheme::SetEntry(const UIThemeEntry * newEntry)
|
void UITheme::SetEntry(const UIThemeEntry * newEntry)
|
||||||
{
|
{
|
||||||
// Try to replace existing entry
|
// Try to replace existing entry
|
||||||
size_t numEntries = 0;
|
for (size_t i = 0; i < Entries.GetCount(); i++)
|
||||||
for (UIThemeEntry * entry = Entries; entry->WindowClass != 0xFF; entry++)
|
|
||||||
{
|
{
|
||||||
|
UIThemeEntry * entry = &Entries[i];
|
||||||
if (entry->WindowClass == newEntry->WindowClass)
|
if (entry->WindowClass == newEntry->WindowClass)
|
||||||
{
|
{
|
||||||
*entry = *newEntry;
|
*entry = *newEntry;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
numEntries++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increase size of entry list
|
Entries.Add(*newEntry);
|
||||||
Entries = Memory::ReallocateArray(Entries, numEntries + 2);
|
|
||||||
Entries[numEntries] = *newEntry;
|
|
||||||
Entries[numEntries + 1].WindowClass = 255;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UITheme::RemoveEntry(rct_windowclass windowClass)
|
void UITheme::RemoveEntry(rct_windowclass windowClass)
|
||||||
{
|
{
|
||||||
// Remove existing entry
|
// Remove existing entry
|
||||||
bool found = false;
|
for (size_t i = 0; i < Entries.GetCount(); i++)
|
||||||
for (UIThemeEntry * entry = Entries; entry->WindowClass != 0xFF; entry++)
|
|
||||||
{
|
{
|
||||||
|
UIThemeEntry * entry = &Entries[i];
|
||||||
if (entry->WindowClass == windowClass)
|
if (entry->WindowClass == windowClass)
|
||||||
{
|
{
|
||||||
for (UIThemeEntry * entry2 = entry; entry2->WindowClass != 0xFF; entry2++)
|
Entries.RemoveAt(i);
|
||||||
{
|
|
||||||
*entry2 = *(entry2 + 1);
|
|
||||||
}
|
|
||||||
found = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) return;
|
|
||||||
|
|
||||||
// Reduce size of entry list
|
|
||||||
size_t numEntries = 0;
|
|
||||||
for (UIThemeEntry * entry = Entries; entry->WindowClass != 0xFF; entry++)
|
|
||||||
{
|
|
||||||
numEntries++;
|
|
||||||
}
|
|
||||||
Entries = Memory::ReallocateArray(Entries, numEntries);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
json_t * UITheme::ToJson() const
|
json_t * UITheme::ToJson() const
|
||||||
{
|
{
|
||||||
// Create entries
|
// Create entries
|
||||||
json_t * jsonEntries = json_object();
|
json_t * jsonEntries = json_object();
|
||||||
for (UIThemeEntry * entry = Entries; entry->WindowClass != 0xFF; entry++)
|
for (const UIThemeEntry & entry : Entries)
|
||||||
{
|
{
|
||||||
const WindowThemeDesc * wtDesc = GetWindowThemeDescriptor(entry->WindowClass);
|
const WindowThemeDesc * wtDesc = GetWindowThemeDescriptor(entry.WindowClass);
|
||||||
json_object_set_new(jsonEntries, wtDesc->WindowClassSZ, entry->ToJson());
|
json_object_set_new(jsonEntries, wtDesc->WindowClassSZ, entry.ToJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create theme object
|
// Create theme object
|
||||||
|
@ -357,26 +349,21 @@ json_t * UITheme::ToJson() const
|
||||||
|
|
||||||
bool UITheme::WriteToFile(const utf8 * path) const
|
bool UITheme::WriteToFile(const utf8 * path) const
|
||||||
{
|
{
|
||||||
const char * jsonOutput;
|
|
||||||
|
|
||||||
// Serialise theme object as JSON
|
|
||||||
json_t * jsonTheme = ToJson();
|
json_t * jsonTheme = ToJson();
|
||||||
jsonOutput = json_dumps(jsonTheme, JSON_INDENT(4));
|
bool result;
|
||||||
json_decref(jsonTheme);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto fs = FileStream(path, FILE_MODE_WRITE);
|
Json::WriteToFile(path, jsonTheme, JSON_INDENT(4));
|
||||||
size_t jsonOutputSize = String::SizeOf(jsonOutput);
|
result = true;
|
||||||
fs.Write(jsonOutput, jsonOutputSize);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
log_error("Unable to save %s: %s", path, ex.GetMessage());
|
log_error("Unable to save %s: %s", path, ex.GetMessage());
|
||||||
return false;
|
result = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
json_decref(jsonTheme);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
UITheme * UITheme::FromJson(const json_t * json)
|
UITheme * UITheme::FromJson(const json_t * json)
|
||||||
|
@ -397,7 +384,7 @@ UITheme * UITheme::FromJson(const json_t * json)
|
||||||
UITheme * result = nullptr;
|
UITheme * result = nullptr;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result = UITheme::Create(themeName);
|
result = new UITheme(themeName);
|
||||||
|
|
||||||
if (json_is_true(json_object_get(json, "useLightsRide")))
|
if (json_is_true(json_object_get(json, "useLightsRide")))
|
||||||
{
|
{
|
||||||
|
@ -420,16 +407,15 @@ UITheme * UITheme::FromJson(const json_t * json)
|
||||||
const WindowThemeDesc * wtDesc = GetWindowThemeDescriptor(jkey);
|
const WindowThemeDesc * wtDesc = GetWindowThemeDescriptor(jkey);
|
||||||
if (wtDesc == nullptr) continue;
|
if (wtDesc == nullptr) continue;
|
||||||
|
|
||||||
UIThemeEntry * entry = UIThemeEntry::FromJson(wtDesc, jvalue);
|
UIThemeEntry entry = UIThemeEntry::FromJson(wtDesc, jvalue);
|
||||||
result->SetEntry(entry);
|
result->SetEntry(&entry);
|
||||||
Memory::Free(entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
UITheme::Free(result);
|
delete result;
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -440,26 +426,8 @@ UITheme * UITheme::FromFile(const utf8 * path)
|
||||||
UITheme * result = nullptr;
|
UITheme * result = nullptr;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto fs = FileStream(path, FILE_MODE_OPEN);
|
json = Json::ReadFromFile(path);
|
||||||
|
result = UITheme::FromJson(json);
|
||||||
size_t fileLength = (size_t)fs.GetLength();
|
|
||||||
if (fileLength > MAX_THEME_SIZE)
|
|
||||||
{
|
|
||||||
throw IOException("Language file too large.");
|
|
||||||
}
|
|
||||||
|
|
||||||
utf8 * fileData = Memory::Allocate<utf8>(fileLength + 1);
|
|
||||||
fs.Read(fileData, fileLength);
|
|
||||||
fileData[fileLength] = '\0';
|
|
||||||
|
|
||||||
json_error_t jsonLoadError;
|
|
||||||
json = json_loads(fileData, 0, &jsonLoadError);
|
|
||||||
Memory::Free(fileData);
|
|
||||||
|
|
||||||
if (json != nullptr)
|
|
||||||
{
|
|
||||||
result = UITheme::FromJson(json);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -470,5 +438,19 @@ UITheme * UITheme::FromFile(const utf8 * path)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
UITheme UITheme::CreatePredefined(const utf8 * name, const UIThemeEntry * entries, uint8 flags)
|
||||||
|
{
|
||||||
|
auto theme = UITheme(name);
|
||||||
|
theme.Flags = flags | UITHEME_FLAG_PREDEFINED;
|
||||||
|
|
||||||
|
size_t numEntries = 0;
|
||||||
|
for (const UIThemeEntry * entry = entries; entry->WindowClass != 255; entry++)
|
||||||
|
{
|
||||||
|
numEntries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
theme.Entries = List<UIThemeEntry>(entries, numEntries);
|
||||||
|
return theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
Loading…
Reference in New Issue