mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-12-23 10:11:54 +00:00
Implement abstract syntax tree parsing of XML layout
This commit is contained in:
parent
decff5681b
commit
0c7e6bc883
22 changed files with 391 additions and 62 deletions
99
Cargo.lock
generated
99
Cargo.lock
generated
|
|
@ -15,6 +15,15 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "andrew"
|
||||
version = "0.2.1"
|
||||
|
|
@ -334,7 +343,7 @@ dependencies = [
|
|||
"autocfg 1.0.0",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"lazy_static 1.4.0",
|
||||
"maybe-uninit",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
|
|
@ -358,7 +367,16 @@ checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
|
|||
dependencies = [
|
||||
"autocfg 1.0.0",
|
||||
"cfg-if",
|
||||
"lazy_static",
|
||||
"lazy_static 1.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "css-color-parser"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ccb6ce7ef97e6dc6e575e51b596c9889a5cc88a307b5ef177d215c61fd7581d"
|
||||
dependencies = [
|
||||
"lazy_static 0.1.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -436,7 +454,7 @@ checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.24",
|
||||
"syn 1.0.27",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
|
|
@ -540,7 +558,7 @@ dependencies = [
|
|||
"proc-macro-hack",
|
||||
"proc-macro2 1.0.17",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.24",
|
||||
"syn 1.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -681,7 +699,7 @@ dependencies = [
|
|||
"foreign-types",
|
||||
"gfx-auxil",
|
||||
"gfx-hal",
|
||||
"lazy_static",
|
||||
"lazy_static 1.4.0",
|
||||
"log",
|
||||
"metal",
|
||||
"objc",
|
||||
|
|
@ -704,7 +722,7 @@ dependencies = [
|
|||
"byteorder",
|
||||
"core-graphics 0.19.0",
|
||||
"gfx-hal",
|
||||
"lazy_static",
|
||||
"lazy_static 1.4.0",
|
||||
"log",
|
||||
"objc",
|
||||
"raw-window-handle",
|
||||
|
|
@ -780,12 +798,14 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"bytemuck",
|
||||
"cgmath",
|
||||
"css-color-parser",
|
||||
"failure",
|
||||
"futures",
|
||||
"glsl-to-spirv",
|
||||
"image",
|
||||
"palette",
|
||||
"rctree",
|
||||
"regex",
|
||||
"wgpu",
|
||||
"winit",
|
||||
"xmlparser",
|
||||
|
|
@ -879,6 +899,12 @@ dependencies = [
|
|||
"winapi-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
|
|
@ -893,9 +919,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.70"
|
||||
version = "0.2.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f"
|
||||
checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
|
|
@ -1185,7 +1211,7 @@ checksum = "0b4b5f600e60dd3a147fb57b4547033d382d1979eb087af310e91cb45a63b1f4"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.24",
|
||||
"syn 1.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1229,7 +1255,7 @@ checksum = "6fb44a25c5bba983be0fc8592dfaf3e6d0935ce8be0c6b15b2a39507af34a926"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.24",
|
||||
"syn 1.0.27",
|
||||
"synstructure",
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
|
@ -1295,7 +1321,7 @@ checksum = "e58db2081ba5b4c93bd6be09c40fd36cb9193a8336c384f3b40012e531aa7e40"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.24",
|
||||
"syn 1.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1568,7 +1594,7 @@ dependencies = [
|
|||
"crossbeam-deque",
|
||||
"crossbeam-queue",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"lazy_static 1.4.0",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
|
|
@ -1593,6 +1619,24 @@ version = "0.1.56"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"thread_local",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.2"
|
||||
|
|
@ -1688,7 +1732,7 @@ dependencies = [
|
|||
"andrew",
|
||||
"bitflags",
|
||||
"dlib",
|
||||
"lazy_static",
|
||||
"lazy_static 1.4.0",
|
||||
"memmap",
|
||||
"nix",
|
||||
"wayland-client",
|
||||
|
|
@ -1737,9 +1781,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.24"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f87bc5b2815ebb664de0392fdf1b95b6d10e160f86d9f64ff65e5679841ca06a"
|
||||
checksum = "ef781e621ee763a2a40721a8861ec519cb76966aee03bb5d00adb6a31dc1c1de"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"quote 1.0.6",
|
||||
|
|
@ -1754,7 +1798,7 @@ checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.24",
|
||||
"syn 1.0.27",
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
|
|
@ -1772,6 +1816,15 @@ dependencies = [
|
|||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiff"
|
||||
version = "0.3.1"
|
||||
|
|
@ -1848,11 +1901,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "c3972e137ebf830900db522d6c8fd74d1900dcfc733462e9a12e942b00b4ac94"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
"lazy_static 1.4.0",
|
||||
"log",
|
||||
"proc-macro2 1.0.17",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.24",
|
||||
"syn 1.0.27",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
|
@ -1874,7 +1927,7 @@ checksum = "8eb197bd3a47553334907ffd2f16507b4f4f01bbec3ac921a7719e0decdfe72a"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.24",
|
||||
"syn 1.0.27",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
|
@ -1942,7 +1995,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d94e89a86e6d6d7c7c9b19ebf48a03afaac4af6bc22ae570e9a24124b75358f4"
|
||||
dependencies = [
|
||||
"dlib",
|
||||
"lazy_static",
|
||||
"lazy_static 1.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1993,7 +2046,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "19a5051a357d071fd69c24671e0ea6d644a83c7418e47eac3511427379007403"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"lazy_static",
|
||||
"lazy_static 1.4.0",
|
||||
"libc",
|
||||
"objc",
|
||||
"parking_lot",
|
||||
|
|
@ -2069,7 +2122,7 @@ dependencies = [
|
|||
"core-video-sys",
|
||||
"dispatch",
|
||||
"instant",
|
||||
"lazy_static",
|
||||
"lazy_static 1.4.0",
|
||||
"libc",
|
||||
"log",
|
||||
"mio",
|
||||
|
|
@ -2119,7 +2172,7 @@ version = "2.18.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bf981e3a5b3301209754218f962052d4d9ee97e478f4d26d4a6eced34c1fef8"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"lazy_static 1.4.0",
|
||||
"libc",
|
||||
"maybe-uninit",
|
||||
"pkg-config",
|
||||
|
|
|
|||
|
|
@ -18,3 +18,5 @@ futures = "0.3.4"
|
|||
bytemuck = "1.2.0"
|
||||
rctree = "0.3.3"
|
||||
xmlparser = "0.13.1"
|
||||
regex = "1.3.7"
|
||||
css-color-parser = "0.1.2"
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
<box content="INNER_XML" :fill="FILL = none" :round="ROUND = 0px" :border-thickness="BORDER_THICKNESS = 0px" :border-color="BORDER_COLOR = none">
|
||||
<box content="INNER_XML: (None) = none" :fill="FILL: (Color | None) = none" :round="ROUND: (AbsolutePx) = 0px" :border-thickness="BORDER_THICKNESS: (AbsolutePx) = 0px" :border-color="BORDER_COLOR: (Color | None) = none">
|
||||
{{INNER_XML}}
|
||||
</box>
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
<col content="INNER_XML">
|
||||
<col content="INNER_XML: (None) = none">
|
||||
{{INNER_XML}}
|
||||
</col>
|
||||
|
|
@ -1,20 +1,20 @@
|
|||
<header:file-menu>
|
||||
<box height="100%" x-padding="10px">
|
||||
<text height="100%" y-align="0.5" :color="[mildwhite]">፨</text>
|
||||
<text height="100%" y-align="50%" :color="['mildwhite']">፨</text>
|
||||
</box>
|
||||
<box height="100%" x-padding="10px">
|
||||
<text height="100%" y-align="0.5" :color="[mildwhite]">File</text>
|
||||
<text height="100%" y-align="50%" :color="['mildwhite']">File</text>
|
||||
</box>
|
||||
<box height="100%" x-padding="10px">
|
||||
<text height="100%" y-align="0.5" :color="[mildwhite]">Edit</text>
|
||||
<text height="100%" y-align="50%" :color="['mildwhite']">Edit</text>
|
||||
</box>
|
||||
<box height="100%" x-padding="10px">
|
||||
<text height="100%" y-align="0.5" :color="[mildwhite]">Comp</text>
|
||||
<text height="100%" y-align="50%" :color="['mildwhite']">Comp</text>
|
||||
</box>
|
||||
<box height="100%" x-padding="10px">
|
||||
<text height="100%" y-align="0.5" :color="[mildwhite]">View</text>
|
||||
<text height="100%" y-align="50%" :color="['mildwhite']">View</text>
|
||||
</box>
|
||||
<box height="100%" x-padding="10px">
|
||||
<text height="100%" y-align="0.5" :color="[mildwhite]">Help</text>
|
||||
<text height="100%" y-align="50%" :color="['mildwhite']">Help</text>
|
||||
</box>
|
||||
</header:file-menu>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<header:window-buttons :maximized="IS_MAXIMIZED">
|
||||
<box height="100%" y-align="0.5" x-padding="18px">
|
||||
<header:window-buttons :maximized="IS_MAXIMIZED: (Bool) = false">
|
||||
<box height="100%" y-align="50%" x-padding="18px">
|
||||
<icon :src="window_minimize.svg" />
|
||||
</box>
|
||||
<box height="100%" y-align="0.5" x-padding="18px">
|
||||
<box height="100%" y-align="50%" x-padding="18px">
|
||||
<if :a="{{IS_MAXIMIZED}}">
|
||||
<icon :src="window_restore_down.svg" />
|
||||
</if>
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
<icon :src="maximize.svg" />
|
||||
</if>
|
||||
</box>
|
||||
<box height="100%" y-align="0.5" x-padding="18px">
|
||||
<box height="100%" y-align="50%" x-padding="18px">
|
||||
<icon :src="window_close.svg" />
|
||||
</box>
|
||||
</header:window-buttons>
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
<icon content="SVG_DATA" :src="SVG_SOURCE = none">
|
||||
<icon content="SVG_DATA: (None) = none" :src="SVG_SOURCE: (TemplateString | None) = none">
|
||||
|
||||
</icon>
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
<input:checkbox-with-dropdown content="OPTION_LIST" :disabled="DISABLED = false" :checked="CHECKED = false" :default="DEFAULT = 0">
|
||||
<input:checkbox-with-dropdown content="OPTION_LIST: (None) = none" :disabled="DISABLED: (Bool) = false" :checked="CHECKED: (Bool) = false" :selected-index="SELECTED_INDEX: (Integer) = 0">
|
||||
<!-- Checkbox -->
|
||||
<col width="height" height="100%">
|
||||
<box width="100%" height="100%" x-align="0.5" y-align="0.5" :fill="[accent]">
|
||||
<box width="100%" height="100%" x-align="50%" y-align="50%" :round="4px 0px 0px 4px" :fill="['accent']">
|
||||
<input:checkbox :checked="{{CHECKED}}" :disabled="{{DISABLED}}" :inverted="true" />
|
||||
</box>
|
||||
</col>
|
||||
<!-- Dropdown -->
|
||||
<col width="100%">
|
||||
<input:dropdown width="100%" :default="{{DEFAULT}}" :disabled="{{DISABLED}}">{{OPTION_LIST}}</input:dropdown>
|
||||
<input:dropdown width="100%" :selected-index="{{SELECTED_INDEX}}" :disabled="{{DISABLED}}">{{OPTION_LIST}}</input:dropdown>
|
||||
</col>
|
||||
</input:checkbox-with-dropdown>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<input:checkbox :checked="CHECKED = false" :disabled="DISABLED = false" :inverted="INVERTED = false">
|
||||
<input:checkbox :checked="CHECKED: (Bool) = false" :disabled="DISABLED: (Bool) = false" :inverted="INVERTED: (Bool) = false">
|
||||
<box width="14px" height="14px" :fill="{{BOX_COLOR}}" :round="2px">
|
||||
<if :a="{{CHECKED}}">
|
||||
<if :a="{{INVERTED}}" :b="false">
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
<input:dropdown content="OPTION_LIST" :default="DEFAULT = 0" :disabled="DISABLED = false">
|
||||
<input:dropdown content="OPTION_LIST: (TemplateString | None) = none" :selected-index="SELECTED_INDEX: (Integer) = 0" :disabled="DISABLED: (Bool) = false">
|
||||
<box width="100%" :round="4px">
|
||||
<!-- Current selection text -->
|
||||
<col width="100%" height="24px">
|
||||
<text width="100%" height="100%" x-align="0.5" y-align="0.5" :color="[mildwhite]">{{CURRENT_TEXT}}</text>
|
||||
<text width="100%" height="100%" x-align="50%" y-align="50%" :color="['mildwhite']">{{CURRENT_TEXT}}</text>
|
||||
</col>
|
||||
<!-- Dropdown arrow icon -->
|
||||
<col width="8px" height="100%">
|
||||
<icon width="8px" height="100%" x-align="0.5" y-align="0.5">
|
||||
<icon width="8px" height="100%" x-align="50%" y-align="50%">
|
||||
<svg width="7" height="5" viewBox="0 0 7 5">
|
||||
<path d="M0,.5l3.5,3L7,.5v2l-3.5,3L0,2.5Z" transform="translate(0 -0.5)" fill="#ddd" />
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
<row content="INNER_XML">
|
||||
<row content="INNER_XML: (None) = none">
|
||||
{{INNER_XML}}
|
||||
</row>
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
<text content="TEXT_STRING" :color="COLOR = [middlegray]" :size="SIZE = 12px">
|
||||
<text content="TEXT_STRING: (None) = none" :color="COLOR: (Color | None) = ['middlegray']" :size="SIZE: (AbsolutePx) = 12px">
|
||||
|
||||
</text>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<viewport:panels>
|
||||
<checkbox-with-dropdown :checked="true" :default="2">
|
||||
<dropdown-option>Option A</dropdown-option>
|
||||
<dropdown-option>Option B</dropdown-option>
|
||||
<dropdown-option>Option C</dropdown-option>
|
||||
<checkbox-with-dropdown :checked="true" :selected-index="2">
|
||||
Option A
|
||||
Option B
|
||||
Option C
|
||||
</checkbox-with-dropdown>
|
||||
</viewport:panels>
|
||||
|
|
@ -2,17 +2,17 @@
|
|||
<window:main>
|
||||
<!-- Header -->
|
||||
<row width="100%" height="28px">
|
||||
<header:file-menu height="100%" x-align="0" />
|
||||
<text height="100%" y-align="0.5" x-align="0.5" :color="[mildwhite]">Document 1* - Graphite</text>
|
||||
<header:window-buttons height="100%" x-align="1" />
|
||||
<header:file-menu height="100%" x-align="0%" />
|
||||
<text height="100%" y-align="50%" x-align="50%" :color="['mildwhite']">Document 1* - Graphite</text>
|
||||
<header:window-buttons height="100%" x-align="100%" />
|
||||
</row>
|
||||
<!-- Viewport -->
|
||||
<row width="100%" height="100@">
|
||||
<viewport:panels />
|
||||
<viewport:panels width="100%" height="100%" />
|
||||
</row>
|
||||
<!-- Footer -->
|
||||
<row width="100%" height="24px">
|
||||
<text height="100%" y-align="0.5" x-align="0" x-padding="10px" :color="[mildwhite]" :size="14px">File: 1.8 MB | Memory: 137 MB | Scratch: 0.7/12.3 GB</text>
|
||||
<text height="100%" y-align="0.5" x-align="1" x-padding="10px" :color="[mildwhite]" :size="14px">🖰 Box Select Objects | [⇧G] Move Selection | [⇧R] Rotate Selection | [⇧S] Scale Selection</text>
|
||||
<text height="100%" y-align="50%" x-align="0%" x-padding="10px" :color="['mildwhite']" :size="14px">File: 1.8 MB | Memory: 137 MB | Scratch: 0.7/12.3 GB</text>
|
||||
<text height="100%" y-align="50%" x-align="100%" x-padding="10px" :color="['mildwhite']" :size="14px">🖰 Box Select Objects | [⇧G] Move Selection | [⇧R] Rotate Selection | [⇧S] Scale Selection</text>
|
||||
</row>
|
||||
</window:main>
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ impl Application {
|
|||
let gui_rect_pipeline = Pipeline::new(&device, swap_chain_descriptor.format, vec![], &mut shader_cache, ("shaders/shader.vert", "shaders/shader.frag"));
|
||||
pipeline_cache.set("gui_rect", gui_rect_pipeline);
|
||||
|
||||
let gui_root_data = GuiNode::new(swap_chain_descriptor.width, swap_chain_descriptor.height, ColorPalette::get_color_srgb(ColorPalette::Accent));
|
||||
let gui_root_data = GuiNode::new(swap_chain_descriptor.width, swap_chain_descriptor.height, ColorPalette::Accent.into_color_srgb());
|
||||
let gui_root = rctree::Node::new(gui_root_data);
|
||||
|
||||
GuiLayout::new();
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ pub enum ColorPalette {
|
|||
|
||||
impl ColorPalette {
|
||||
#[allow(dead_code)]
|
||||
pub fn get_color_srgb(self) -> Color {
|
||||
pub fn into_color_srgb(&self) -> Color {
|
||||
let grayscale = match self {
|
||||
ColorPalette::Black => 0 * 17, // #000000
|
||||
ColorPalette::NearBlack => 1 * 17, // #111111
|
||||
|
|
@ -58,11 +58,34 @@ impl ColorPalette {
|
|||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_color_linear(self) -> Color {
|
||||
let standard_rgb = ColorPalette::get_color_srgb(self);
|
||||
pub fn into_color_linear(&self) -> Color {
|
||||
let standard_rgb = ColorPalette::into_color_srgb(self);
|
||||
|
||||
let linear = palette::Srgb::new(standard_rgb.r, standard_rgb.g, standard_rgb.b).into_linear();
|
||||
|
||||
Color::new(linear.red, linear.green, linear.blue, standard_rgb.a)
|
||||
}
|
||||
|
||||
pub fn lookup_palette_color(name_in_palette: &str) -> ColorPalette {
|
||||
match &name_in_palette.to_ascii_lowercase()[..] {
|
||||
"black" => ColorPalette::Black,
|
||||
"nearblack" => ColorPalette::NearBlack,
|
||||
"mildblack" => ColorPalette::MildBlack,
|
||||
"darkgray" => ColorPalette::DarkGray,
|
||||
"dimgray" => ColorPalette::DimGray,
|
||||
"dullgray" => ColorPalette::DullGray,
|
||||
"lowergray" => ColorPalette::LowerGray,
|
||||
"middlegray" => ColorPalette::MiddleGray,
|
||||
"uppergray" => ColorPalette::UpperGray,
|
||||
"palegray" => ColorPalette::PaleGray,
|
||||
"softgray" => ColorPalette::SoftGray,
|
||||
"lightgray" => ColorPalette::LightGray,
|
||||
"brightgray" => ColorPalette::BrightGray,
|
||||
"mildwhite" => ColorPalette::MildWhite,
|
||||
"nearwhite" => ColorPalette::NearWhite,
|
||||
"white" => ColorPalette::White,
|
||||
"accent" => ColorPalette::Accent,
|
||||
_ => panic!("Invalid color lookup of `{}` from the color palette", name_in_palette),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
use std::fs;
|
||||
use std::io;
|
||||
use crate::layout_parsed_node::*;
|
||||
use crate::layout_abstract_syntax::*;
|
||||
|
||||
pub struct GuiLayout {
|
||||
|
||||
|
|
@ -10,6 +11,7 @@ impl GuiLayout {
|
|||
pub fn new() -> GuiLayout {
|
||||
let parsed_layout_tree = Self::parse_xml_file("gui/window/main.xml").unwrap();
|
||||
Self::interpret_abstract_syntax_tree(parsed_layout_tree);
|
||||
|
||||
Self {}
|
||||
}
|
||||
|
||||
|
|
@ -115,6 +117,15 @@ impl GuiLayout {
|
|||
pub fn interpret_abstract_syntax_tree(root: rctree::Node<LayoutParsedNode>) {
|
||||
for node in root.descendants() {
|
||||
println!("{:?}", node);
|
||||
|
||||
match & *node.borrow() {
|
||||
LayoutParsedNode::Tag(tag) => {
|
||||
LayoutAbstractSyntaxNode::new(tag.namespace.clone(), tag.name.clone(), &tag.attributes);
|
||||
}
|
||||
LayoutParsedNode::Text(_) => {}
|
||||
};
|
||||
|
||||
println!();
|
||||
}
|
||||
}
|
||||
}
|
||||
150
src/layout_abstract_attributes.rs
Normal file
150
src/layout_abstract_attributes.rs
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
use crate::layout_abstract_types::*;
|
||||
use crate::color_palette::ColorPalette;
|
||||
use crate::color::Color;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Attribute {
|
||||
VariableValue(VariableValue),
|
||||
TypeValue(TypeValue),
|
||||
}
|
||||
|
||||
pub fn parse_attribute(input: &str) -> Attribute {
|
||||
// Match variables and typed values that can be in an attribute
|
||||
let regex = regex::Regex::new(
|
||||
r#"(?x)
|
||||
^\s*(\w*)\s*(:)\s*(\()\s*(\w*\s*(?:\|\s*\w*\s*?)*)\s*(\))\s*(=)\s*(\w*)\s*$ | # Parameter ?: (? | ... | ?) = ?
|
||||
^\s*(\{\{)\s*(\w*)\s*(\}\})\s*$ | # Argument {{?}}
|
||||
^\s*(-?\d+)\s*$ | # Integer ?
|
||||
^\s*(-?(?:(?:\d+\.\d*)|(?:\d*\.\d+)))\s*$ | # Decimal ?
|
||||
^\s*(-?(?:(?:\d+(?:\.\d*)?)|(?:\d*(?:\.\d+))))([Pp][Xx])\s*$ | # AbsolutePx ?px
|
||||
^\s*(-?(?:(?:\d+(?:\.\d*)?)|(?:\d*(?:\.\d+))))(%)\s*$ | # Percent ?%
|
||||
^\s*(-?(?:(?:\d+(?:\.\d*)?)|(?:\d*(?:\.\d+))))(@)\s*$ | # PercentRemainder ?@
|
||||
^\s*([Ii][Nn][Nn][Ee][Rr])\s*$ | # Inner inner
|
||||
^\s*([Ww][Ii][Dd][Tt][Hh])\s*$ | # Width width
|
||||
^\s*([Hh][Ee][Ii][Gg][Hh][Tt])\s*$ | # Height height
|
||||
^\s*`(.*)`\s*$ | # TemplateString `? ... {{?}} ...`
|
||||
^\s*(\[)(.*)(\])\s*$ | # Color [?]
|
||||
^\s*([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])\s*$ | # Bool true/false
|
||||
^\s*([Nn][Oo][Nn][Ee])\s*$ # None none
|
||||
"#
|
||||
).unwrap();
|
||||
|
||||
// Match with the regular expression
|
||||
let captures = regex.captures(input).map(|captures|
|
||||
captures
|
||||
.iter()
|
||||
.skip(1)
|
||||
.flat_map(|c| c)
|
||||
.map(|c| c.as_str())
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
// Match against the captured values as a slice
|
||||
let slices = captures.as_ref().map(|c| c.as_slice());
|
||||
match slices {
|
||||
Some([name, ":", "(", types, ")", "=", default_value]) => {
|
||||
// TODO: Extend to support a list of N types (like (AbsolutePx) (AbsolutePx) (AbsolutePx) (AbsolutePx))
|
||||
let name = String::from(*name);
|
||||
|
||||
let split_types = types.split("|").map(|piece| piece.trim());
|
||||
let valid_types = split_types.map(|type_name|
|
||||
match &type_name.to_ascii_lowercase()[..] {
|
||||
"xml" => TypeName::Xml,
|
||||
"integer" => TypeName::Integer,
|
||||
"decimal" => TypeName::Decimal,
|
||||
"absolutepx" => TypeName::AbsolutePx,
|
||||
"percent" => TypeName::Percent,
|
||||
"percentremainder" => TypeName::PercentRemainder,
|
||||
"inner" => TypeName::Inner,
|
||||
"width" => TypeName::Width,
|
||||
"height" => TypeName::Height,
|
||||
"templatestring" => TypeName::TemplateString,
|
||||
"color" => TypeName::Color,
|
||||
"bool" => TypeName::Bool,
|
||||
"none" => TypeName::None,
|
||||
invalid => panic!("Invalid type `{}` specified in the attribute `{}` when parsing XML layout", invalid, input),
|
||||
}
|
||||
).collect::<Vec<_>>();
|
||||
|
||||
let default = match parse_attribute(default_value) {
|
||||
Attribute::TypeValue(type_value) => type_value,
|
||||
Attribute::VariableValue(variable_value) => panic!("Found the variable value `{:?}` in the attribute `{}` which only allows typed values, when parsing XML layout", variable_value, input),
|
||||
};
|
||||
|
||||
Attribute::VariableValue(VariableValue::Parameter(VariableParameter {name, valid_types, default}))
|
||||
}
|
||||
Some(["{{", name, "}}"]) => {
|
||||
let name = String::from(*name);
|
||||
Attribute::VariableValue(VariableValue::Argument(name))
|
||||
}
|
||||
Some([value]) if regex::Regex::new(r"^\s*(-?\d+)\s*$").unwrap().is_match(value) => {
|
||||
let integer = value.parse::<i64>().expect(&format!("Invalid value `{}` specified in the attribute `{}` when parsing XML layout", value, input)[..]);
|
||||
Attribute::TypeValue(TypeValue::Integer(integer))
|
||||
}
|
||||
Some([value]) if regex::Regex::new(r"^\s*(-?(?:(?:\d+\.\d*)|(?:\d*\.\d+)))\s*$").unwrap().is_match(value) => {
|
||||
let decimal = value.parse::<f64>().expect(&format!("Invalid value `{}` specified in the attribute `{}` when parsing XML layout", value, input)[..]);
|
||||
Attribute::TypeValue(TypeValue::Decimal(decimal))
|
||||
}
|
||||
Some([value, px]) if px.eq_ignore_ascii_case("px") => {
|
||||
let pixels = value.parse::<f32>().expect(&format!("Invalid value `{}` specified in the attribute `{}` when parsing XML layout", value, input)[..]);
|
||||
Attribute::TypeValue(TypeValue::AbsolutePx(pixels))
|
||||
}
|
||||
Some([value, "%"]) => {
|
||||
let percent = value.parse::<f32>().expect(&format!("Invalid value `{}` specified in the attribute `{}` when parsing XML layout", value, input)[..]);
|
||||
Attribute::TypeValue(TypeValue::Percent(percent))
|
||||
}
|
||||
Some([value, "@"]) => {
|
||||
let percent_remainder = value.parse::<f32>().expect(&format!("Invalid value `{}` specified in the attribute `{}` when parsing XML layout", value, input)[..]);
|
||||
Attribute::TypeValue(TypeValue::PercentRemainder(percent_remainder))
|
||||
}
|
||||
Some([inner]) if inner.eq_ignore_ascii_case("inner") => {
|
||||
Attribute::TypeValue(TypeValue::Inner)
|
||||
}
|
||||
Some([width]) if width.eq_ignore_ascii_case("width") => {
|
||||
Attribute::TypeValue(TypeValue::Width)
|
||||
}
|
||||
Some([height]) if height.eq_ignore_ascii_case("height") => {
|
||||
Attribute::TypeValue(TypeValue::Height)
|
||||
}
|
||||
Some(["`", string, "`"]) => {
|
||||
let mut segments = Vec::<TemplateStringSegment>::new();
|
||||
let mut is_template = false;
|
||||
|
||||
let regex = regex::Regex::new(r"\{\{|\}\}").unwrap();
|
||||
for part in regex.split(string) {
|
||||
let segment = match is_template {
|
||||
true => TemplateStringSegment::String(String::from(part)),
|
||||
false => TemplateStringSegment::Argument(VariableArgument { name: String::from(part) }),
|
||||
};
|
||||
segments.push(segment);
|
||||
is_template = !is_template;
|
||||
}
|
||||
|
||||
Attribute::TypeValue(TypeValue::TemplateString(segments))
|
||||
}
|
||||
Some(["[", color_name, "]"]) => {
|
||||
let regex = regex::Regex::new(r"\s*'(.*)'\s*").unwrap();
|
||||
let color = match regex.captures(color_name) {
|
||||
Some(captures) => {
|
||||
let palette_color = captures.get(1).expect(&format!("Invalid palette color name `{}` specified in the attribute `{}` when parsing XML layout", color_name, input)[..]).as_str();
|
||||
ColorPalette::lookup_palette_color(palette_color).into_color_srgb()
|
||||
}
|
||||
None => {
|
||||
let parsed = color_name.parse::<css_color_parser::Color>();
|
||||
let css_color = parsed.expect(&format!("Invalid CSS color name `{}` specified in the attribute `{}` when parsing XML layout", color_name, input)[..]);
|
||||
Color::new(css_color.r as f32 / 255.0, css_color.g as f32 / 255.0, css_color.b as f32 / 255.0, css_color.a as f32 / 255.0)
|
||||
}
|
||||
};
|
||||
|
||||
Attribute::TypeValue(TypeValue::Color(color))
|
||||
}
|
||||
Some([true_or_false]) if true_or_false.eq_ignore_ascii_case("true") || true_or_false.eq_ignore_ascii_case("false") => {
|
||||
let boolean = true_or_false.eq_ignore_ascii_case("true");
|
||||
Attribute::TypeValue(TypeValue::Bool(boolean))
|
||||
}
|
||||
Some([none]) if none.eq_ignore_ascii_case("none") => {
|
||||
Attribute::TypeValue(TypeValue::None)
|
||||
}
|
||||
_ => panic!("Invalid attribute value `{}` when parsing XML layout", input),
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
use crate::layout_abstract_attributes::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LayoutAbstractSyntaxNode {
|
||||
pub namespace: Option<String>,
|
||||
pub name: String,
|
||||
pub attributes: Vec<Attribute>,
|
||||
}
|
||||
|
||||
impl LayoutAbstractSyntaxNode {
|
||||
pub fn new(namespace: Option<String>, tag: String, attributes: &Vec<(String, String)>) -> Self {
|
||||
for attribute in attributes {
|
||||
let parsed = parse_attribute(&attribute.1[..]);
|
||||
println!("{} : {:?} -> {:?}", attribute.0, attribute.1, parsed);
|
||||
}
|
||||
|
||||
Self {
|
||||
namespace,
|
||||
name: tag,
|
||||
attributes: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
64
src/layout_abstract_types.rs
Normal file
64
src/layout_abstract_types.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
use crate::color::Color;
|
||||
|
||||
// Variable types
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum VariableValue {
|
||||
Parameter(VariableParameter),
|
||||
Argument(String),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VariableParameter {
|
||||
pub name: String,
|
||||
pub valid_types: Vec<TypeName>,
|
||||
pub default: TypeValue,
|
||||
// pub value: TypeValue,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VariableArgument {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
// Value types
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TypeName {
|
||||
Xml,
|
||||
Integer,
|
||||
Decimal,
|
||||
AbsolutePx,
|
||||
Percent,
|
||||
PercentRemainder,
|
||||
Inner,
|
||||
Width,
|
||||
Height,
|
||||
TemplateString,
|
||||
Color,
|
||||
Bool,
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TypeValue {
|
||||
Xml(()), // TODO
|
||||
Integer(i64),
|
||||
Decimal(f64),
|
||||
AbsolutePx(f32),
|
||||
Percent(f32),
|
||||
PercentRemainder(f32),
|
||||
Inner,
|
||||
Width,
|
||||
Height,
|
||||
TemplateString(Vec<TemplateStringSegment>),
|
||||
Color(Color),
|
||||
Bool(bool),
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TemplateStringSegment {
|
||||
String(String),
|
||||
Argument(VariableArgument),
|
||||
}
|
||||
|
|
@ -17,17 +17,17 @@ impl LayoutParsedNode {
|
|||
#[derive(Debug)]
|
||||
pub struct LayoutParsedTag {
|
||||
pub namespace: Option<String>,
|
||||
pub tag: String,
|
||||
pub name: String,
|
||||
pub attributes: Vec<(String, String)>,
|
||||
}
|
||||
|
||||
impl LayoutParsedTag {
|
||||
pub fn new(namespace: String, tag: String) -> Self {
|
||||
pub fn new(namespace: String, name: String) -> Self {
|
||||
let namespace = if namespace.is_empty() { None } else { Some(namespace) };
|
||||
|
||||
Self {
|
||||
namespace,
|
||||
tag,
|
||||
name,
|
||||
attributes: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ mod gui_attributes;
|
|||
mod window_events;
|
||||
mod gui_layout;
|
||||
mod layout_parsed_node;
|
||||
mod layout_abstract_types;
|
||||
mod layout_abstract_attributes;
|
||||
mod layout_abstract_syntax;
|
||||
|
||||
use application::Application;
|
||||
use winit::event_loop::EventLoop;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue