Преглед изворни кода

Create a basic sample for a simple player list.

ShawnCZek пре 1 година
родитељ
комит
5a47483998

+ 1 - 0
Samples/basic/CMakeLists.txt

@@ -13,6 +13,7 @@ if(RMLUI_FONT_ENGINE_ENABLED)
 	add_subdirectory("load_document")
 	add_subdirectory("transform")
 	add_subdirectory("tree_view")
+	add_subdirectory("player_list")
 
 	if(RMLUI_HARFBUZZ_SAMPLE)
 		add_subdirectory("harfbuzz")

+ 12 - 0
Samples/basic/player_list/CMakeLists.txt

@@ -0,0 +1,12 @@
+set(SAMPLE_NAME "player_list")
+set(TARGET_NAME "${RMLUI_SAMPLE_PREFIX}${SAMPLE_NAME}")
+
+add_executable(${TARGET_NAME} WIN32
+	src/main.cpp
+)
+
+set_common_target_options(${TARGET_NAME})
+
+target_link_libraries(${TARGET_NAME} PRIVATE rmlui_shell)
+
+install_sample_target(${TARGET_NAME})

+ 138 - 0
Samples/basic/player_list/data/player_list.css

@@ -0,0 +1,138 @@
+* {
+    box-sizing: border-box;
+}
+
+body {
+    width: 700dp;
+    height: 600dp;
+    min-width: 500dp;
+    min-height: 200dp;
+    max-width: 100%;
+    max-height: 100%;
+    margin: auto;
+
+    background-color: #f0f0f0;
+    color: #333;
+
+    font-family: LatoLatin;
+    font-size: 15dp;
+}
+
+table {
+    box-sizing: border-box;
+    display: table;
+}
+
+tr {
+    box-sizing: border-box;
+    display: table-row;
+}
+
+td {
+    box-sizing: border-box;
+    display: table-cell;
+}
+
+thead, tbody, tfoot {
+    display: table-row-group;
+}
+
+scrollbarvertical {
+    width: 12dp;
+    cursor: arrow;
+    margin-right: -1dp;
+    padding-right: 1dp;
+}
+
+scrollbarvertical slidertrack {
+    background-color: #f0f0f0;
+}
+
+scrollbarvertical sliderbar {
+    background-color: #666;
+}
+
+input[type="text"] {
+    box-sizing: border-box;
+    width: 100%;
+    padding: 10dp;
+    border: 1dp #bbb;
+    border-radius: 3dp;
+    margin-top: 5dp;
+    margin-bottom: 20dp;
+    font-size: 1.1em;
+    line-height: 1.4;
+    cursor: text;
+}
+
+#title {
+    background-color: #CECECE;
+    padding: 4dp 20dp;
+    width: 100%;
+    display: block;
+    position: absolute;
+}
+
+#title > handle {
+    font-weight: bold;
+    font-size: 1.25em;
+}
+
+#contents {
+    margin-top: 20dp;
+    height: 100%;
+    padding: 20dp;
+    display: flex;
+    flex-direction: column;
+}
+
+#contents__footer {
+    align-self: flex-end;
+}
+
+#panel_info {
+    font-size: .95em;
+    display: flex;
+    justify-content: space-between;
+}
+
+#players {
+    margin-top: 15dp;
+    flex: auto;
+    overflow: auto;
+}
+
+table {
+    width: 100%;
+}
+
+table thead tr {
+    font-weight: bold;
+    padding-bottom: 1dp;
+}
+
+table td {
+    padding: 2dp 4dp;
+}
+
+table td.data_column {
+    width: 70dp;
+    text-align: center;
+}
+
+table tbody td.data_column {
+    font-size: .9em;
+}
+
+table td.tag_column {
+    width: 100dp;
+}
+
+#resizer {
+    position: absolute;
+    width: 12dp;
+    height: 12dp;
+    bottom: 0;
+    right: 0;
+    cursor: resize;
+}

+ 59 - 0
Samples/basic/player_list/data/player_list.rml

@@ -0,0 +1,59 @@
+<rml>
+	<head>
+		<title>Player List Sample</title>
+
+		<link rel="stylesheet" type="text/rcss" href="player_list.css" />
+	</head>
+
+	<body>
+		<div id="title">
+			<handle move_target="#document">
+				<div id="title__text">Player List</div>
+			</handle>
+		</div>
+
+		<div id="contents">
+			<div>
+				<div id="panel_info">
+					<div>
+						Server: Europe #56763
+					</div>
+				</div>
+			</div>
+
+			<div id="players">
+				<table>
+					<thead>
+						<tr>
+							<td class="data_column">ID</td>
+							<td class="tag_column">Player Tag</td>
+							<td></td>
+							<td class="data_column">Ping</td>
+							<td class="data_column">Score</td>
+						</tr>
+					</thead>
+
+					<tbody data-model="player_list">
+						<tr data-for="player : players" data-attr-data-id="player.id">
+							<td class="data_column">{{player.id}}</td>
+							<td data-style-color="player.tag_color">{{player.tag_name}}</td>
+							<td>{{player.name}}</td>
+							<td class="data_column">{{player.latency}} ms</td>
+							<td class="data_column">{{player.score}}</td>
+						</tr>
+					</tbody>
+				</table>
+			</div>
+
+			<div id="contents__footer" data-model="player_list">
+				<div id="players_list_controls">
+					<div>
+						<input type="text" data-value="search_players_query" maxlength="32" />
+					</div>
+				</div>
+			</div>
+		</div>
+
+		<handle size_target="#document" id="resizer" />
+	</body>
+</rml>

+ 130 - 0
Samples/basic/player_list/data/player_list_web.css

@@ -0,0 +1,130 @@
+* {
+    box-sizing: border-box;
+}
+
+#body {
+    width: 700px;
+    height: 600px;
+    min-width: 500px;
+    min-height: 250px;
+    margin: auto;
+    position: relative;
+
+    background-color: #f0f0f0;
+    color: #333;
+
+    font-family: Arial;
+    font-size: 15px;
+
+    resize: both;
+    overflow: auto;
+}
+
+table {
+    box-sizing: border-box;
+    display: table;
+}
+
+tr {
+    box-sizing: border-box;
+    display: table-row;
+}
+
+td {
+    box-sizing: border-box;
+    display: table-cell;
+}
+
+thead, tbody, tfoot {
+    display: table-row-group;
+}
+
+scrollbarvertical {
+    width: 12px;
+    cursor: arrow;
+    margin-right: -1px;
+    padding-right: 1px;
+}
+
+scrollbarvertical slidertrack {
+    background-color: #f0f0f0;
+}
+
+scrollbarvertical sliderbar {
+    background-color: #666;
+}
+
+input[type="text"] {
+    box-sizing: border-box;
+    width: 100%;
+    padding: 10px;
+    border: 1px #bbb;
+    border-radius: 3px;
+    margin-top: 15px;
+    font-size: 1.1em;
+    line-height: 1.4;
+    cursor: text;
+}
+
+#title {
+    background-color: #CECECE;
+    padding: 4px 20px;
+    width: 100%;
+    display: block;
+    position: absolute;
+}
+
+#title > handle {
+    font-weight: bold;
+    font-size: 1.25em;
+}
+
+#contents {
+    height: 100%;
+    padding: 40px 20px 20px;
+    display: flex;
+    flex-direction: column;
+}
+
+#contents__footer {
+    width: 100%;
+    align-self: flex-end;
+}
+
+#panel_info {
+    font-size: .95em;
+    display: flex;
+    justify-content: space-between;
+}
+
+#players {
+    margin-top: 15px;
+    flex: auto;
+    overflow: auto;
+}
+
+table {
+    width: 100%;
+}
+
+table thead tr {
+    font-weight: bold;
+    padding-bottom: 1px;
+}
+
+table td {
+    padding: 2px 4px;
+}
+
+table td.data_column {
+    width: 70px;
+    text-align: center;
+}
+
+table tbody td.data_column {
+    font-size: .9em;
+}
+
+table td.tag_column {
+    width: 100px;
+}

+ 479 - 0
Samples/basic/player_list/data/player_list_web.html

@@ -0,0 +1,479 @@
+<html>
+	<head>
+		<title>Player List Sample</title>
+
+		<link rel="stylesheet" type="text/css" href="player_list_web.css" />
+	</head>
+
+	<body>
+		<div id="body">
+            <div id="title">
+                <handle move_target="#document">
+                    <div id="title__text">Player List</div>
+                </handle>
+            </div>
+
+            <div id="contents">
+                <div>
+                    <div id="panel_info">
+                        <div>
+                            Server: Europe #56763
+                        </div>
+                    </div>
+                </div>
+
+                <div id="players">
+                    <table>
+                        <thead>
+                            <tr>
+                                <td class="data_column">ID</td>
+                                <td class="tag_column">Player Tag</td>
+                                <td></td>
+                                <td class="data_column">Ping</td>
+                                <td class="data_column">Score</td>
+                            </tr>
+                        </thead>
+
+                        <tbody>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                            <tr>
+                                <td class="data_column">123</td>
+                                <td data-style-color="player.tag_color">tag</td>
+                                <td>name</td>
+                                <td class="data_column">100 ms</td>
+                                <td class="data_column">99</td>
+                            </tr>
+                        </tbody>
+                    </table>
+                </div>
+
+                <div id="contents__footer">
+                    <div id="players_list_controls">
+                        <div>
+                            <input type="text" maxlength="32" />
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+	</body>
+</html>

+ 303 - 0
Samples/basic/player_list/src/main.cpp

@@ -0,0 +1,303 @@
+/*
+ * This source file is part of RmlUi, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://github.com/mikke89/RmlUi
+ *
+ * Copyright (c) 2018 Michael R. P. Ragazzon
+ * Copyright (c) 2019-2024 The RmlUi Team, and contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include <RmlUi/Core.h>
+#include <RmlUi/Debugger.h>
+#include <RmlUi_Backend.h>
+#include <Shell.h>
+
+static const int GENERATED_PLAYER_COUNT = 100;
+
+class PlayerEntry {
+public:
+	bool is_local;
+	uint32_t entity_id;
+
+	uint32_t score;
+
+	uint16_t latency;
+
+	bool is_muted;
+	bool is_friend;
+
+	Rml::String name;
+
+	Rml::String tag_name;
+	Rml::Colourb tag_color;
+
+public:
+	static void InitializeDataModel(Rml::DataModelConstructor& constructor)
+	{
+		if (auto player = constructor.RegisterStruct<PlayerEntry>())
+		{
+			player.RegisterMember("id", &PlayerEntry::entity_id);
+			player.RegisterMember("score", &PlayerEntry::score);
+			player.RegisterMember("latency", &PlayerEntry::latency);
+			player.RegisterMember("is_muted", &PlayerEntry::is_muted);
+			player.RegisterMember("is_friend", &PlayerEntry::is_friend);
+			player.RegisterMember("name", &PlayerEntry::name);
+			player.RegisterMember("tag_name", &PlayerEntry::tag_name);
+			player.RegisterMember("tag_color", &PlayerEntry::tag_color);
+		}
+	}
+};
+
+class PlayerList final : public Rml::EventListener {
+public:
+	PlayerList(Rml::Context* context) : last_update(0)
+	{
+		InitializeDataModel(context);
+
+		document = context->LoadDocument("basic/player_list/data/player_list.rml");
+
+		if (document)
+		{
+			document->Show();
+		}
+	}
+
+	void Shutdown()
+	{
+		if (document)
+		{
+			document->Close();
+			document = nullptr;
+		}
+	}
+
+	void ProcessEvent(Rml::Event& event) override
+	{
+		switch (event.GetId())
+		{
+		case Rml::EventId::Keydown:
+		{
+			if (event.GetParameter<int>("key_identifier", 0) == Rml::Input::KI_ESCAPE)
+				Backend::RequestExit();
+		}
+		break;
+		default: break;
+		}
+	}
+
+	void Update(double t)
+	{
+		if (t < last_update + 0.5)
+			return;
+
+		RMLUI_ZoneScoped;
+
+		for (PlayerEntry& player : data)
+		{
+			player.score = (uint32_t)Rml::Math::RandomInteger(100);
+			player.latency = (uint16_t)Rml::Math::RandomInteger(500);
+		}
+
+		Filter();
+		Sort();
+
+		RMLUI_ASSERT(data_model);
+		data_model.DirtyVariable("players");
+
+		last_update = t;
+	}
+
+	Rml::ElementDocument* GetDocument() const { return document; }
+
+	void AddPlayer(PlayerEntry&& player) { data.emplace_back(std::move(player)); }
+
+private:
+	void InitializeDataModel(Rml::Context* context)
+	{
+		if (Rml::DataModelConstructor constructor = context->CreateDataModel("player_list"))
+		{
+			constructor.RegisterScalar<Rml::Colourb>([](const Rml::Colourb& c, Rml::Variant& variant) {
+				variant = Rml::CreateString("rgba(%u, %u, %u, %u)", c.red, c.green, c.blue, c.alpha);
+			});
+
+			constructor.Bind("search_players_query", &search_query);
+
+			PlayerEntry::InitializeDataModel(constructor);
+
+			constructor.RegisterArray<decltype(entries)>();
+			constructor.Bind("players", &entries);
+
+			data_model = constructor.GetModelHandle();
+		}
+	}
+
+	void Filter()
+	{
+		if (search_query.empty())
+		{
+			entries = data;
+			return;
+		}
+
+		const auto search = [](const PlayerEntry& player, const Rml::String& query) -> bool {
+			if (player.is_local)
+				return true;
+
+			Rml::String needle = Rml::StringUtilities::ToLower(player.name);
+			if (needle.find(query) != Rml::String::npos)
+				return true;
+
+			needle = Rml::StringUtilities::ToLower(player.tag_name);
+			if (needle.find(query) != Rml::String::npos)
+				return true;
+
+			return false;
+		};
+
+		// Dump all the current data first.
+		entries.clear();
+
+		// Use lowercase strings for querying.
+		const Rml::String query = Rml::StringUtilities::ToLower(search_query);
+
+		for (const PlayerEntry& player : data)
+			if (search(player, query))
+				entries.emplace_back(player);
+	}
+
+	void Sort()
+	{
+		auto start_it = std::partition(entries.begin(), entries.end(), [](const PlayerEntry& player) { return player.is_local; });
+		std::sort(start_it, entries.end(), [](const PlayerEntry& a, const PlayerEntry& b) { return a.score > b.score; });
+	}
+
+private:
+	Rml::ElementDocument* document;
+	Rml::DataModelHandle data_model;
+
+	double last_update;
+
+	// A collection of all player data from the players manager.
+	Rml::Vector<PlayerEntry> data;
+	// A collection of players that is used in the UI document itself. It may be sorted, filtered out, ...
+	Rml::Vector<PlayerEntry> entries;
+
+	Rml::String search_query;
+};
+
+void GenerateFakePlayerData(PlayerList* list);
+
+#if defined RMLUI_PLATFORM_WIN32
+	#include <RmlUi_Include_Windows.h>
+int APIENTRY WinMain(HINSTANCE /*instance_handle*/, HINSTANCE /*previous_instance_handle*/, char* /*command_line*/, int /*command_show*/)
+#else
+int main(int /*argc*/, char** /*argv*/)
+#endif
+{
+	const int width = 1600;
+	const int height = 900;
+
+	// Initializes the shell which provides common functionality used by the included samples.
+	if (!Shell::Initialize())
+		return -1;
+
+	// Constructs the system and render interfaces, creates a window, and attaches the renderer.
+	if (!Backend::Initialize("Player List Sample", width, height, true))
+	{
+		Shell::Shutdown();
+		return -1;
+	}
+
+	// Install the custom interfaces constructed by the backend before initializing RmlUi.
+	Rml::SetSystemInterface(Backend::GetSystemInterface());
+	Rml::SetRenderInterface(Backend::GetRenderInterface());
+
+	// RmlUi initialisation.
+	Rml::Initialise();
+
+	// Create the main RmlUi context.
+	Rml::Context* context = Rml::CreateContext("main", Rml::Vector2i(width, height));
+
+	if (!context)
+	{
+		Rml::Shutdown();
+		Backend::Shutdown();
+		Shell::Shutdown();
+		return -1;
+	}
+
+	Rml::Debugger::Initialise(context);
+	Shell::LoadFonts();
+
+	auto player_list = Rml::MakeUnique<PlayerList>(context);
+	context->AddEventListener("keydown", player_list.get());
+
+	GenerateFakePlayerData(player_list.get());
+
+	bool running = true;
+	while (running)
+	{
+		running = Backend::ProcessEvents(context, &Shell::ProcessKeyDownShortcuts);
+
+		double t = Rml::GetSystemInterface()->GetElapsedTime();
+
+		player_list->Update(t);
+		context->Update();
+
+		Backend::BeginFrame();
+		context->Render();
+		Backend::PresentFrame();
+	}
+
+	player_list->Shutdown();
+
+	// Shutdown RmlUi.
+	Rml::Shutdown();
+
+	Backend::Shutdown();
+	Shell::Shutdown();
+
+	return 0;
+}
+
+void GenerateFakePlayerData(PlayerList* list)
+{
+	const auto generate_fake_player = [](bool is_local) -> PlayerEntry {
+		PlayerEntry data{};
+		data.is_local = is_local;
+		data.entity_id = (uint32_t)Rml::Math::RandomInteger(100'000);
+		data.score = (uint32_t)Rml::Math::RandomInteger(100);
+		data.latency = (uint16_t)Rml::Math::RandomInteger(500);
+		data.is_muted = Rml::Math::RandomBool();
+		data.is_friend = Rml::Math::RandomBool();
+		Rml::FormatString(data.tag_name, "tag %d", Rml::Math::RandomInteger(1'000'000));
+		data.name = is_local ? "local player" : Rml::CreateString("player %d", data.entity_id);
+
+		const auto random_color_component = []() -> uint8_t { return (uint8_t)Rml::Math::RandomInteger(0xff); };
+		data.tag_color = Rml::Colourb(random_color_component(), random_color_component(), random_color_component());
+
+		return data;
+	};
+
+	for (int i = 0; i < GENERATED_PLAYER_COUNT; ++i)
+		list->AddPlayer(generate_fake_player(i == 0));
+}